function PublicSelector(ixml, straatenabled)
{
  var http = window.XMLHttpRequest ? new XMLHttpRequest() : new ActiveXObject ( "Microsoft.XMLHTTP" );
  var xml = ixml;
  var sending = false;
  var page = 1;
  var state = 1;
  var filter = 1;
  var loading = 1;
  var uAllowEvents = new Array(4, 5, 6, 13, 15, 21, 22);
  var hisListener;
  var retryTimer = null;
  var retryCount = 0;
  var maxRetryCount = 2;

  this.init = init;
  this.postData = postData;
  this.refresh = refresh;
  this.handleRefresh = handleRefresh;
  this.loadingControl = loadingControl;
  this.getPage = getPage;
  this.setPage = setPage;
  this.getFilter = getFilter;
  this.setFilter = setFilter;
  this.getState = getState;
  this.setState = setState;
  
  this.allowupdates = true;
  this.objupd = new Array(1, 0, 1, 0, 1, 1);
  if (straatenabled)
    this.request_names = new Array('modus', 'hcat', 'scat', 'prov', 'plaats', 'straat');
  else
    this.request_names = new Array('modus', 'hcat', 'scat', 'land', 'prov', 'plaats');
  
  this.objectcount = 6;
  this.objext = 'sel';
  this.objpre = 'd';

  this.REQUEST_URL = "/index.php?m=pub&o=2";
  this.SWITCH_FILTER_URL = "/index.php?m=pub&o=4";

  this.MODE_CHANGE = 1;
  this.HCAT_CHANGE = 2;
  this.SCAT_CHANGE = 3;
  this.PROV_CHANGE = 4;
  this.PLAATS_CHANGE = 5;
  this.STRAAT_CHANGE = 6;
  this.MAP_CHANGE = 7;
  this.PAGE_CHANGE = 8;
  this.SHOW_MAP = 9;
  this.SHOW_BOTH = 10;
  this.SHOW_ALBUMS = 11;
  this.DD_MAP_CHANGE = 12;
  this.POSTCODE_CHANGE = 13;
  this.SEARCH_SUBMIT = 14;
  this.SHOW_DETAILS = 15;
  this.LAND_CHANGE = 21;
  this.USERLOCATION_CHANGE = 22;

  function init()
  {
    if ((!browserDetect.isChrome) && (!browserDetect.isKhtml))
    {
      window.historyStorage.init();
  
      hisListener = new Subscriber();
    }

    var pxml = google.maps.Xml.parse(xml);

    parseAlbums(pxml, true);
    parseMap(pxml);

    var loc = "";
    loc = location.search.substring(1);
    if (loc.length > 0)
      loc = '&'+loc;
    var init = '&init=1'+loc;
    var firstrequest = "";

    if ((state == 1) || (state == 2))
    {
      var width = document.getElementById('map').offsetWidth;
      var height = document.getElementById('map').offsetHeight;

      var sw = mamap.fromContainerPixelToLatLng(new google.maps.Point(-39, height + 50));
      var ne = mamap.fromContainerPixelToLatLng(new google.maps.Point(width + 10, -10));
      var center = mamap.getCenter();

      var maptype = mamap.getMapTypes().indexOf(mamap.getCurrentMapType());
      firstrequest += "&lat="+center.lat()+"&lng="+center.lng()+"&minlat="+sw.lat()+"&minlng="+sw.lng()+"&maxlat="+ne.lat()+"&maxlng="+ne.lng()+"&zoom="+mamap.getZoom();
      firstrequest += "&maptype="+maptype;
    }

    var modus = document.getElementById('modussel').selectedIndex;
    var obj = document.getElementById('hcatsel');
    var hcat = obj.options[obj.selectedIndex].value;
    
    obj = document.getElementById('provsel');
    var prov = 0;
    if (obj != undefined)
      prov = obj.options[obj.selectedIndex].value;
    
    obj = document.getElementById('scatsel');
    var scat = 0;
    if (obj != undefined)
      var scat = parseInt(obj.options[obj.selectedIndex].value);
    if (scat == 0)
      firstrequest += "&modus="+modus+"&hcat="+hcat+"&prov="+prov+"&state="+state;
    else
      firstrequest += "&modus="+modus+"&hcat="+hcat+"&scat="+scat+"&prov="+prov+"&state="+state;      
    
    updateHeaderCat(hcat,scat);
    
    if (state < 2)
    {  
      var obj = document.getElementById('showdetails');
      if (obj != undefined)
      {
        var details = (obj.checked) ? 1 : 0;
        firstrequest += "&details="+details;
      }
      else
      {
        var obj = ReadCookie('showdetails');
        if (obj)
           firstrequest += "&details="+obj;
      }
    }

    init += firstrequest;
    
    if ((!browserDetect.isChrome) && (!browserDetect.isKhtml))
      hisListener.loadNextBookmark(init);
    
    loadingControl(false);
    document.getElementById('searchtext').focus();
  }
  
  function ReadCookie(cookieName) 
  {
   var theCookie= ""+ document.cookie;
   var ind = theCookie.indexOf(cookieName);
   if (ind == -1 || cookieName == "") return ""; 
   var ind1 = theCookie.indexOf(';',ind);
   if (ind1 == -1) ind1 = theCookie.length; 
   return unescape(theCookie.substring(ind+cookieName.length+1,ind1));
 }
 
  function retryPost()
  {
    if (retryCount < maxRetryCount)
    {
      retryCount++;
      http = window.XMLHttpRequest ? new XMLHttpRequest() : new ActiveXObject ( "Microsoft.XMLHTTP" );
      postData();
    }
  }
  
  function postData(data, url, handle, eventid)
  {
    data = (data == undefined) ? postData.data : data;
    url = (url == undefined) ? postData.url : url;
    handle = (handle == undefined) ? postData.handle : handle;
    eventid = (eventid == undefined) ? postData.eventid : eventid;
    
    postData.data = data;
    postData.url = url;
    postData.handle = handle;
    postData.eventid = eventid;
    
    var time = new Date();

    sending = true;

    if (http)
    {
      http.open('POST', url+'&time='+time.getTime());
      try
      {
        http.setRequestHeader('Content-Type','application/x-www-form-urlencoded'); 
      }
      catch(err)
      {
        http = window.XMLHttpRequest ? new XMLHttpRequest() : new ActiveXObject ( "Microsoft.XMLHTTP" );
        postData(data, url, handle, eventid);
        return;
      }
      
      if (handle == undefined)
      {
        handle = function () 
        { 
          if (retryTimer != null)
            clearTimeout(retryTimer);
          if (retryCount > 0)
            retryCount = 0;
          sending = false; 
        };
      }

      http.onreadystatechange = handle;
      http.send(data);
      if (eventid == 14)
        retryTimer = setTimeout(retryPost, 20000);
      else
        retryTimer = setTimeout(retryPost, 10000);
    }
  }

  function allowUpdates(eventid, firstcall)
  {
    if (selection.getState() != 0)
    {
      var len = uAllowEvents.length;

      for (var i = 0; i < len; i++)
      {
        if (parseInt(eventid) == parseInt(uAllowEvents[i]))
        {
          selection.allowupdates = false;
          return;
        }
      }

      if (firstcall)
      {
        if (eventid == 12)
          selection.allowupdates = false;
        return;
      }
    }
    else
    {
      selection.allowupdates = true;
      return;
    }
  }

  function refresh(id)
  {
    refresh.first = (refresh.first == undefined) ? true : false;
    
    if (!sending)
    {
      loadingControl(true);
      var request = "";
      var obj = undefined;
      var requestvalues = new Array();
      var val = '';

      if (id == this.LAND_CHANGE || id == this.USERLOCATION_CHANGE)
      {
        requestvalues['land']   = refresh.arguments[1];
        requestvalues['prov']   = refresh.arguments[2];
        requestvalues['plaats'] = refresh.arguments[3];
        requestvalues['straat'] = 0;
      }
      
      for (var i = 0; i < this.objectcount; i++)
      {
        val = undefined;
        
        if (requestvalues[this.request_names[i]] != undefined)
          val = requestvalues[this.request_names[i]];
        else {
          obj = document.getElementById(this.request_names[i]+this.objext);
          if (obj != undefined)
            val = parseInt(obj.options[obj.selectedIndex].value);
        }
        
        if (val != undefined)
          request += '&'+this.request_names[i]+'='+val;
      }

      request += '&page='+(getPage()-1);

      var state = getState();
      request += '&state='+state;

      if (id == this.POSTCODE_CHANGE)
      {
        var postcode = document.getElementById('postcode').value;
        if (postcode != "Uw Postcode")
        {
          request += '&postcode='+postcode;
          if ((!browserDetect.isChrome) && (!browserDetect.isKhtml))
            hisListener.nextfocus = 1;
        }
      }

      if (state > 0)
      {
        var width = document.getElementById('map').offsetWidth;
        var height = document.getElementById('map').offsetHeight;

        var sw = mamap.fromContainerPixelToLatLng(new google.maps.Point(-39, height + 50));
        var ne = mamap.fromContainerPixelToLatLng(new google.maps.Point(width + 10, -10));
        var center = mamap.getCenter();

        var maptype = mamap.getMapTypes().indexOf(mamap.getCurrentMapType());

        request += "&lat="+center.lat()+"&lng="+center.lng()+"&minlat="+sw.lat()+"&minlng="+sw.lng()+"&maxlat="+ne.lat()+"&maxlng="+ne.lng()+"&zoom="+mamap.getZoom();
        request += "&maptype="+maptype;
      }
      
      var searchquery = document.getElementById('searchtext').value;
      if (searchquery != '')
      {
        searchquery = makeAjaxContentSafe(searchquery);
        request += '&searchquery='+searchquery;
      }

      if (state < 2)
      {  
        var details = document.getElementById('showdetails');
        if (details != undefined)
        {
          details = (details.checked) ? 1 : 0;
          request += "&details="+details;
        }
      }

      request += '&eventid='+id;

      allowUpdates(id, refresh.first);
      
      if (this.allowupdates)
      {
        if ((!browserDetect.isChrome) && (!browserDetect.isKhtml))
          hisListener.loadNextBookmark(request);
      }
      else
        this.allowupdates = true;

      sending = true;

      postData(request, this.REQUEST_URL, handleRefresh, id);
    }
  }

  function handleRefresh()
  {
    if (http.readyState == 4)
    {
      try
      {      
        if (http.status == 200)
        {
          if (retryTimer != null)
            clearTimeout(retryTimer);
          if (retryCount > 0)
            retryCount = 0;
          
          var response = undefined;
          
          response = http.responseText;
          if (response == undefined || response == "")
            return;
          
          var xml = google.maps.Xml.parse(response);
          
          var init = (handleRefresh.init) ? true : undefined;
          if (init == undefined)
          {
            var his = (handleRefresh.his) ? true : undefined;
            if (his)
              handleRefresh.his = undefined;
          }
          else
            handleRefresh.init = undefined;
          
          parseAlbums(xml, init, his);
    
          parseMap(xml);
          loadingControl(false);
        }
        else
          loadingControl(false);
      }
      catch(err)
      {
        loadingControl(false);
      }
    }
    sending = false;    
  }

  function loadingControl(load)
  {
    if ((load) && (selection.loading == 0))
    {
      document.getElementById('loading').style.display = 'block';
      selection.loading = 1;
    }
    else if (selection.loading != 0)
    {
      document.getElementById('loading').style.display = 'none';
      selection.loading = 0;
    }
  }

  function getPage()
  {
    return page;
  }

  function setPage(nPage)
  {
    page = nPage;
  }

  function getState()
  {
    return state;
  }

  function setState(nState)
  {
    state = nState;
  }

  function getFilter()
  {
    return filter;
  }

  function setFilter(nFilter)
  {
    filter = nFilter;
  }
}

function Subscriber()
{
	var i = 0;
	var firstLoad;
	var firstHash;
	var tracker = 0;
	var allowget = true;
	this.nextfocus = 0;

	this.loadNextBookmark = function(data)
	{
  	hash = "";

  	if (firstLoad == undefined)
  	{
  	  firstLoad = false;
 		  firstHash = 'start';
 		  hash = 'start';
	  }
	  else
    	i++;

	  allowget = false;

		unFocus.History.addHistory(i);

		if (!browserDetect.isWinIE)
		{
   		if (this.nextfocus == 1)
  		{
    		this.nextfocus = 0;
    		document.getElementById('postcode').focus();
      }
	  }

		if (hash == "")
		  hash = unFocus.History.getCurrent();

		data += '&history=1';
    
    historyStorage.put(hash+'req', data);
	};

	this.historyListener = function(historyHash)
	{
		if (!allowget)
		{
		  allowget = true;
		  return;
	  }

  	i = historyHash;

    if (firstLoad == false)
    {
      var hash = "";
      if (historyStorage.hasKey(historyHash+'req'))
        hash = historyHash;
      else if (historyStorage.hasKey(firstHash+'req'))
        hash = firstHash;

      if (hash == "")
        return;

  	  var req = historyStorage.get(hash+'req');

		  if (req == null || req == "")
		    return;

		  if (hash == firstHash)
		    selection.handleRefresh.init = true;
		  else
		  {
		    selection.objupd = new Array(1, 1, 1, 1, 1, 1);
		    selection.handleRefresh.his = true;
	    }

	    var statechange = false;

	    var statebegin = req.indexOf('&state=', 0);
	    var stateend = req.indexOf('&', statebegin+7);
	    if ((statebegin != -1) && (stateend != -1))
	    {
	      var nstate = parseInt(req.substring(statebegin+7, stateend));
	      if (nstate != selection.getState())
	        statechange = true;
      }
      
      var eventid = 0;
      if (!statechange)
      {
  	    var centerinfo = new Array();

  	    var temp0 = req.indexOf('&lat=', 0);
  	    var temp00 = req.indexOf('&', temp0+5);
  	    if (temp0 != -1 && temp00 != -1)
    	    centerinfo[0] = req.substring(temp0+5, temp00);

  	    var temp1 = req.indexOf('&lng=', temp0+5);
  	    var temp10 = req.indexOf('&', temp1+5);
  	    if (temp1 != -1 && temp10 != -1)
  	      centerinfo[1] = req.substring(temp1+5, temp10);

  	    var temp2 = req.indexOf('&zoom=', temp1+5);
  	    var temp20 = req.indexOf('&', temp2+6);
  	    if (temp2 != -1 && temp20 != -1)
  	      centerinfo[2] = req.substring(temp2+6, temp20);

  	    var temp3 = req.indexOf('&eventid=', 0);
  	    var temp30 = req.indexOf('&', temp3+9);
  	    if (temp3 != -1 && temp30 != -1)
  	      eventid = parseInt(req.substring(temp3+9, temp30));

  	      
        selection.loadingControl(true);

  	    if (centerinfo.length == 3)
        {
          mapeventsenabled = false;
          mamap.setCenter(new google.maps.LatLng(centerinfo[0], centerinfo[1]), parseInt(centerinfo[2]));
          oldcenter = new google.maps.LatLng(centerinfo[0], centerinfo[1]);
          oldzoom = parseInt(centerinfo[2]);
          mapeventsenabled = true;
        }
      }
      else
        selection.loadingControl(true);

	    selection.refresh.first = undefined;
      selection.postData(req, selection.REQUEST_URL, selection.handleRefresh, eventid);
	  }
	};

	unFocus.History.addEventListener('historyChange', this.historyListener);

	this.historyListener(unFocus.History.getCurrent());
};

/** An object that uses a hidden form to store history state
    across page loads. The chief mechanism for doing so is using
    the fact that browser's save the text in form data for the
    life of the browser and cache, which means the text is still
    there when the user navigates back to the page. See
    http://codinginparadise.org/weblog/2005/08/ajax-tutorial-saving-session-across.html
    for full details. */
window.historyStorage = {
   /** If true, we are debugging and show the storage textfield. */
   /** public */ debugging: false,

   /** Our hash of key name/values. */
   /** private */ storageHash: new Object(),

   /** If true, we have loaded our hash table out of the storage form. */
   /** private */ hashLoaded: false,

   /** public */ put: function(key, value) {
       this.assertValidKey(key);

       // if we already have a value for this,
       // remove the value before adding the
       // new one
       if (this.hasKey(key)) {
         this.remove(key);
       }

       // store this new key
       this.storageHash[key] = value;

       if (!this.hasKey(key)) //try 2
       {
        //if the first try was not succesful, try again.
        this.storageHash = new Object();
        this.storageHash[key] = value;
       }

       // save and serialize the hashtable into the form
       this.saveHashTable();
   },

   /** public */ get: function(key) {
      this.assertValidKey(key);

      // make sure the hash table has been loaded
      // from the form
      this.loadHashTable();

      var value = this.storageHash[key];

      if (value == undefined)
         return null;
      else
         return value;
   },

   /** public */ remove: function(key) {
      this.assertValidKey(key);

      // make sure the hash table has been loaded
      // from the form
      this.loadHashTable();

      // delete the value
      delete this.storageHash[key];

      // serialize and save the hash table into the
      // form
      this.saveHashTable();
   },

   /** Clears out all saved data. */
   /** public */ reset: function() {
      this.storageField.value = "";
      this.storageHash = new Object();
   },

   /** public */ hasKey: function(key) {
      this.assertValidKey(key);

      // make sure the hash table has been loaded
      // from the form
      this.loadHashTable();

      if (typeof this.storageHash[key] == "undefined")
         return false;
      else
         return true;
   },

   /** Determines whether the key given is valid;
       keys can only have letters, numbers, the dash,
       underscore, spaces, or one of the
       following characters:
       !@#$%^&*()+=:;,./?|\~{}[] */
   /** public */ isValidKey: function(key) {
      // allow all strings, since we don't use XML serialization
      // format anymore
      return (typeof key == "string");
   },

   /** A reference to our textarea field. */
   /** private */ storageField: null,

   /** private */ init: function() {
     this.storageField = document.getElementById("historyStorageField");
   },

   /** Asserts that a key is valid, throwing
       an exception if it is not. */
   /** private */ assertValidKey: function(key) {
      if (this.isValidKey(key) == false) {
         throw "Please provide a valid key for "
               + "window.historyStorage, key= "
               + key;
       }
   },

   /** Loads the hash table up from the form. */
   /** private */ loadHashTable: function() {
      if (this.hashLoaded == false) {
         // get the hash table as a serialized
         // string
         var serializedHashTable = this.storageField.value;

         if (serializedHashTable != "" &&
             serializedHashTable != null) {
            // destringify the content back into a
            // real JavaScript object
            this.storageHash = serializedHashTable;
         }

         this.hashLoaded = true;
      }
   },

   /** Saves the hash table into the form. */
   /** private */ saveHashTable: function() {
      this.loadHashTable();

      // serialized the hash table
      var serializedHashTable = this.storageHash;

      // save this value
      this.storageField.value = serializedHashTable;
   }
};