/** 
 * Author and Version Information {{{
 * author: Antonio Ramirez http://webeaters.blogspot.com
 *
 * class: AutoComplete for Prototype 1.6.0
 *
 * version: 1.2.1 - 2007-11-11 
 * 		(based on AutoSuggest 2.1.3 - 2007-07-19)
 * version: 1.3.0 - 2008-01-03 by Andrew Nicols <andrew@nicols.co.uk>
 *  - Fixed incorrect title-casing - CSS is Case Sensitive!!!
 *  - Adjusted the way in which the Notifier images are loaded.
 *  - Changed json code to pass all json variables back instead of just id, value and name
 *  - Fixed 'GMAIL' code such that if valueSep is undefined, it is ignored
 *  - Changed the default for valueSep to null
 *  - Fixed the resetTimeout function
 *
 * REFERENCES AND THANKS 
 * this class is based on the work in AutoSuggest.js of
 * Timothy Groves - http://www.brandspankingnew.net
 * and adapted for use with prototype 1.6.0
 *
 * UPDATED by R��da HADJOUTI
 * GMAIL like AutoComplete (semicolon separator) Update
 *
 }}}*/

var AutoComplete = Class.create();

AutoComplete.prototype = { // {{{
  Version: '1.3.0',
  REQUIRED_PROTOTYPE: '1.6.0',

  initialize: function (id, param) { // {{{
  	// check whether we have the appropiate javascript libraries
  	this.PROTOTYPE_CHECK();
	
    // Get the field we're watching.
    // It needs to be a valid field so throw an error if it's not valid or can't be found.
    this.fld = $(id);
    if (!this.fld)
    {
      throw("AutoComplete requires a field id to initialize");
    }
	
    // Init variables
    this.sInp 	= ""; // input value 
    this.nInpC 	= 0;	// input value length
    this.aSug 	= []; // suggestions array 
    this.iHigh 	= 0;	// level of list selection 
	
  // Parameter Handling {{{
	// Set the use specified options
	this.options = param ? param : {};
	// These are the default settings {{{
  var k, def = {
    valueSep:null,
    minchars:1,
    meth:"get",
    varname:"input",
    className:"autocomplete",
    timeout:3000000,
    delay:500,
    offsety:-5,
    shownoresults: true,
    noresults: "No results were found.",
    maxheight: 250,
    cache: true,
    maxentries: 25,
    onAjaxError:null,
    setWidth: false,
    minWidth: 100,
    maxWidth: 200,
    useNotifier: true
  };
  //}}}
  // Overlay any values which weren't user specified.
	for (k in def) 
	{
		if (typeof(this.options[k]) != typeof(def[k]))
			this.options[k] = def[k];
	}
  // End of Parameter Handling }}}

  // Not everyone wants to use the Notifier. Give them the option	
	if (this.options.useNotifier)
  {
    this.fld.addClassName('ac_field');
  }

	// set keyup handler for field
	// and prevent AutoComplete from client
	var p = this;
	
	// NOTE: not using addEventListener because UpArrow fired twice in Safari
	this.fld.onkeypress 	= function(ev){ return p.onKeyPress(ev); };
	this.fld.onkeyup      = function(ev){ return p.onKeyUp(ev); };
  // ARN-DEBUG Chances are we want to reset the timeout when they lose focus, at least that's what I prefer
	this.fld.onblur			  = function(ev){ p.resetTimeout(); return true; };	
  // ARN-DEBUG Not sure what this is about!
	this.fld.setAttribute("AutoComplete","off");

  }, //}}}

  convertVersionString: function (versionString){ // {{{
      var r = versionString.split('.');
      return parseInt(r[0])*100000 + parseInt(r[1])*1000 + parseInt(r[2]);
  }, // }}}

  PROTOTYPE_CHECK: function() { // {{{
    if((typeof Prototype=='undefined') || 
       (typeof Element == 'undefined') || 
       (typeof Element.Methods=='undefined') ||
       (this.convertVersionString(Prototype.Version) < 
        this.convertVersionString(this.REQUIRED_PROTOTYPE)))
       throw("AutoComplete requires the Prototype JavaScript framework >= " +
        this.REQUIRED_PROTOTYPE);
  }, // }}}

  // set responses to keypress events in the field
  // this allows the user to use the arrow keys to scroll through the results
  // ESCAPE clears the list
  // RETURN sets the current highlighted value
  // UP/DOWN move around the list

  onKeyPress: function (e) { // {{{
  	if (!e) e = window.event;
  	var key	= e.keyCode || e.wich;
  	

    switch(key)
    {
      case Event.KEY_RETURN:
        this.setHighlightedValue();
        Event.stop(e);
        break;
      case Event.KEY_TAB:
        this.setHighlightedValue();
        //Event.stop(e);
        break;
      case Event.KEY_ESC:
        this.clearSuggestions();
        break;
    }
    return true;
  }, //}}}

  onKeyUp: function (e) { // {{{
  	if (!e) e = window.event;
  	
  	var key = e.keyCode || e.wich;
  	
  	if (key == Event.KEY_UP || key == Event.KEY_DOWN) 
  	{
  		this.changeHighlight(key);
  		Event.stop(e);
  	}
  	else this.getSuggestions(this.fld.value);
  	
	return true;
  }, //}}}

  getSuggestions: function(val) { // {{{
  	// input the same? do nothing
  	if(val==this.sInp) return false;
  	
  	// kill the old list
  	if($(this.acID)) $(this.acID).remove();
  	
  	this.sInp = val;
  	
  	// input length is less than the min required to trigger a request
  	// do nothing
  	if (val.length < this.options.minchars)
  	{
  		this.aSug 	= [];
  		this.nInpC	= val.length; 
  		return false;
  	}

  	// Here we will detect if there is a comma and the splitted value has a value to check
  	// comma stars a new search and val is converted to the new value after the comma
  	var ol	= this.nInpC; // old length
  	this.nInpC	= val.length ? val.length : 0;
  	
  	// if caching enabled, and we didn't receive the maxentries value
    // and user is typing (ie. length of input is increasing)
  	// filter results out of suggestions from last request
  	var l = this.aSug.length;
  	if( this.options.cache && ( this.nInpC > ol ) && l && ( l < this.options.maxentries ) )
  	{
  		var arr = new Array();
  		for (var i=0;i<l;i++) {
  			if (this.aSug[i].value.toLowerCase().indexOf(val.toLowerCase()) != -1)
        {
  				arr.push(this.aSug[i]);
        }
  		}
  		this.aSug = arr;
  		
  		// recreate the list
  		this.createList(this.aSug);
  	} else {
  		// do new request
  		var p = this;
  		//var input	= this.sInp; // send the converted new value (comma)
  		clearTimeout(this.ajID); // ajax id timer
  		this.ajID = setTimeout( function () {p.doAjaxRequest(p.sInp)}, this.options.delay);
  	}
    document.helper = this;	
  	return false;
  }, // }}}

  getLastInput : function(str) { // {{{
  	var ret = str;
  	if (undefined != this.options.valueSep) {
  		var idx = ret.lastIndexOf(this.options.valueSep);
      ret = idx == -1 ? ret : ret.substring(idx + 1, ret.length);
  	}
  	
  	return ret;
  }, // }}}

  doAjaxRequest: function (input) { // {{{
  	// we have to check here if there is a new splitted value (, or ;)
  	// always check against the last part of the comma and then check
  	// saved input is still the value of the field
  	if (input != this.fld.value) 
  		return false;
  	
  	// Gmail like : get only the last user's input
  	this.sInp = this.getLastInput(this.sInp);
 	
  	// create ajax request
  	// do we need to call a function to recreate the url?
  	if (typeof this.options.script == 'function')
  		var url = this.options.script(encodeURIComponent(this.sInp));
  	else
  		var url = this.options.script+this.options.varname+'='+encodeURIComponent(this.sInp);
  	
  	if(!url) return false;
  	
  	var p = this;
  	var m = this.options.meth;  // get or post?
  	
  	var options = {
  		method: m,
  		onSuccess: function (req) { // {{{
        if( p.options.useNotifier )
        {
          p.fld.removeClassName('ac_field_busy');
          p.fld.addClassName('ac_field');
        };
        p.setSuggestions(req,input);
  		}, // }}}

  		onFailure: (typeof p.options.onAjaxError == 'function')? function (status) { // {{{
        if (p.options.useNotifier)
        {
          p.fld.removeClassName('ac_field_busy');
          p.fld.addClassName('ac_field');
        }
        p.options.onAjaxError(status)
      } : // }}}

      function (status) { // {{{
        if (p.options.useNotifier)
        {
          p.fld.removeClassName('ac_field_busy');
          p.fld.addClassName('ac_field');
        }
        alert("AJAX error: "+status); 
      } // }}}
    }
  	// make new ajax request
  	new Ajax.Request(url, options);
  }, // }}}

  setSuggestions: function (req, input) { // {{{
	  // if field input no longer matches what was passed to the request
	  // don't show the suggestions
	  // here we need to check against the splitted values if any (, or ;)
    if (input != this.fld.value)
      return false;
	
    this.aSug = [];
	
    if(this.options.json) 
    { // response in json format?
      var jsondata = eval('(' + req.responseText + ')');
      this.aSug = jsondata.results;
    } else {
      // response in xml format?
      var results = req.responseXML.getElementsByTagName('results')[0].childNodes;
    
      for(var i=0;i<results.length;i++)
      {
        if(results[i].hasChildNodes())
          this.aSug.push(  { 'id':results[i].getAttribute('id'), 'value':results[i].childNodes[0].nodeValue, 'info':results[i].getAttribute('info') }  );
      }
    }
    this.acID = 'ac_'+this.fld.id;
    this.createList(this.aSug);
  }, // }}}

  createDOMElement: function ( type, attr, cont, html ) { // {{{
    var ne = document.createElement( type );
	
    if (!ne)
      return 0;
      
    for (var a in attr)
      ne[a] = attr[a];
    
    var t = typeof(cont);
    
    if (t == "string" && !html)
      ne.appendChild( document.createTextNode(cont) );
    else if (t == "string" && html)
      ne.innerHTML = cont;
    else if (t == "object")
      ne.appendChild( cont );

    return ne;
  }, // }}}

  createList:	function(arr) { // {{{
    // get rid of the old list if any  
  	if($(this.acID)) $(this.acID).remove();
  	
  	// clear list removal timeout
  	this.killTimeout();
  	
  	// if no results, and showNoResults is false, do nothing
  	if (arr.length == 0 && !this.options.shownoresults) return false;
  	
  	// create holding div
  	var div	= this.createDOMElement('div', {id:this.acID, className:this.options.className});
	if (gZindex){
		gZindex +=5;
	}else{
		gZindex = getHighestZIndex()
	}
	$(div).setStyle('z-index : ' + gZindex);

  	// create div header
  	var hcorner = this.createDOMElement('div', {className: 'ac_corner'});
  	var hbar	= this.createDOMElement('div', {className: 'ac_bar'});
  	var header	= this.createDOMElement('div', {className: 'ac_header'});
  	header.appendChild(hcorner);
  	header.appendChild(hbar);
  	div.appendChild(header);
  	
    // create and populate ul
    var ul	= this.createDOMElement('ul', {id:'ac_ul'});
    var p 	= this; // pointer that we will need later on
    // no results?
    if (arr.length == 0 && this.options.shownoresults)
    {
      var li = this.createDOMElement('li', {className: 'ac_warning'}, this.options.noresults );
      ul.appendChild(li);
    } else {
      // loop through arr of suggestions creating an LI element for each of them
      for (var i=0,l = arr.length; i<l; i++)
      {
        // format output with the input enclosed in a EM elementFromPoint
        // (as HTML not DOM)
        var val 	= arr[i].value;
        var st 		= val.toLowerCase().indexOf(this.sInp.toLowerCase()); // HERE WE CHECK AGAINST THE SPLITTED VALUE IF ANY***
        var output 	= val.substring(0,st) + '<em>' + val.substring(st,st+this.sInp.length) + '</em>' + val.substring(st+this.sInp.length);
			
        var span	= this.createDOMElement('span',{},output,true); // type of, properties, output, isHTML?
			
        if(arr[i].info != '') // do we need to add extra info?
        {
          var br	= this.createDOMElement('br',{});
          span.appendChild(br);
          
          var small = this.createDOMElement('small',{}, arr[i].info);
          span.appendChild(small);
        }
        var a 	= this.createDOMElement('a',{href:'#'});
        
        var tl	= this.createDOMElement('span',{className:'tl'},'&nbsp;',true);
        var tr	= this.createDOMElement('span',{className:'tr'},'&nbsp;',true);
        
        a.appendChild(tl);
        a.appendChild(tr);
        a.appendChild(span); // add the object span into the link
			
        a.name = i+1;
        
        a.onclick 		= function () { // {{{
          p.setHighlightedValue();
          return false; 
        }; // }}}
        a.onmouseover	= function () { // {{{
          p.setHighlight(this.name); 
        }; // }}} 
			
        var li = this.createDOMElement('li', {}, a); // add the link element to a li element
        
        // finally add the newly created li element to the ul element 
        ul.appendChild(li);
      }
    }
    
    div.appendChild(ul); // add the newly created list to the div element
    
    // create div footer
    var fcorner = this.createDOMElement('div', {className: 'ac_corner'});
  	var fbar	= this.createDOMElement('div', {className: 'ac_bar'});
  	var footer	= this.createDOMElement('div', {className: 'ac_footer'});
  	footer.appendChild(fcorner);
  	footer.appendChild(fbar);
  	div.appendChild(footer);
  	
  	// get position of target textfield
    // position holding div below it
    // set width of holding div to width of field 
    // if 
    
    var pos         = this.fld.cumulativeOffset();
    div.style.left 	= pos[0] + "px";
    div.style.top 	= pos[1] + this.fld.offsetHeight + "px";
    
    var w = 
    (
      this.options.setWidth && this.fld.offsetWidth < this.options.minWidth
    )
    ? this.options.minWidth : 
    (
      this.options.setWidth && this.fld.offsetWidth > this.options.maxWidth
    )
    ? this.options.maxWidth : 
    this.fld.offsetWidth;

    
    div.style.width 	= w + "px";
    
    // set mouseover functions for div
    // when mouse pointer leaves div, set a timeout to remove the list after an interval
    // when mouse enters div, kill the timeout so the list won't be removed
    //
    div.onmouseover 	= function(){ p.killTimeout() };
    div.onmouseout 		= function(){ p.resetTimeout() };
    
    // add DIV to document
    document.getElementsByTagName("body")[0].appendChild(div);
    
    // highlight first item
    this.iHigh = 1;
    this.setHighlight(1);
    
    // remove list after interval
    this.toID	= setTimeout(
      function () {
        p.clearSuggestions() 
      }, this.options.timeout
    );

    if( this.options.useNotifier )
    {
      this.fld.removeClassName('ac_field');
	    this.fld.addClassName('ac_field_busy');
    };

  }, // }}}

  changeHighlight:	function(key) { // {{{
  	var list = $("ac_ul");
    if (!list)
      return false;
	
    var n;

    n = (key == Event.KEY_DOWN || key == Event.KEY_TAB)? this.iHigh + 1 : this.iHigh - 1; // false assumed to be Event.KEY_UP
    
    n = (n > list.childNodes.length)? list.childNodes.length : ((n < 1)? 1 : n);	
    
    this.setHighlight(n);
  }, // }}}

  setHighlight:		function(n) { // {{{
  	var list = $('ac_ul');
  	
  	if (!list) return false;
  	
  	if (this.iHigh > 0) this.clearHighlight();
  	
  	this.iHigh = Number(n);
  	
  	list.childNodes[this.iHigh-1].className = 'ac_highlight';
  	
  	this.killTimeout();
  }, // }}}

  clearHighlight:	function() { // {{{
  	var list = $('ac_ul');
  	
  	if(!list) return false;
  	
  	if(this.iHigh > 0)
  	{
  		list.childNodes[this.iHigh-1].className = '';
  		this.iHigh = 0;
  	}
  	
  }, // }}}

  setHighlightedValue:	function() { // {{{
  	if (this.iHigh)
  	{
  		// HERE WE NEED TO IMPLEMENT THE GMAIL LIKE SPLITTED VALUE
  		if (!this.aSug[this.iHigh - 1]) return;
  		
  		// Gmail like
      if (undefined != this.options.valueSep) {
        var str = this.getLastInput(this.fld.value);
        var idx = this.fld.value.lastIndexOf(str);
        str = this.aSug[ this.iHigh -1 ].value + this.options.valueSep;
        this.sInp = this.fld.value = idx == -1 ? str : this.fld.value.substring(0, idx) + str;
      } else {
        var str = this.getLastInput(this.fld.value);
        var idx = this.fld.value.lastIndexOf(str);
        str = this.aSug[ this.iHigh -1 ].value;
        this.sInp = this.fld.value = idx == -1 ? str : this.fld.value.substring(0, idx) + str;
      }
  		
  		// move cursor to end of input (safari)
  		this.fld.focus();
  		if(this.fld.selectionStart)
  			this.fld.setSelectionRange(this.sInp.length, this.sInp.length);
  			
  		this.clearSuggestions();
  		
  		// pass selected object to callback function, if exists
  		if (typeof this.options.callback == 'function')
  			this.options.callback(this.aSug[this.iHigh-1]); // the object has the properties we want, it will depend of
  	}
  }, // }}}

  killTimeout:	function() { // {{{
  	clearTimeout(this.toID);
  }, // }}}

  resetTimeout:	function() { // {{{
  	this.killTimeout();
  	var p = this;
  	this.toID = setTimeout(
      function () { 
        p.clearSuggestions();
      }, p.options.timeout
    );
    // ARN-DEBUG Added p.options.timeout back :|
  }, // }}}

  clearSuggestions:	function () { // {{{
	
    this.killTimeout();
    if ($(this.acID))
    {
      this.fadeOut(300,function () {
        $(this.acID).remove();
      } );
    }
  }, // }}}

  fadeOut:	function (milliseconds, callback) { // {{{
  	this._fadeFrom 	= 1;
  	this._fadeTo	= 0;
  	this._afterUpdateInternal = callback;
  	
  	this._fadeDuration	= milliseconds;
  	this._fadeInterval = 50;
  	this._fadeTime = 0;
  	var p = this;
  	this._fadeIntervalID = setInterval(
      function() {
        p._changeOpacity()
      }, this._fadeInterval
    );
  
  }, // }}}

  _changeOpacity: function() { // {{{
 
    if (!$(this.acID))
    {
  		this._fadeIntervalID=clearInterval(this._fadeIntervalID);
  		return;
  	} 
  	this._fadeTime += this._fadeInterval;
  	
  	var ieop = Math.round( (this._fadeFrom + ((this._fadeTo - this._fadeFrom) * (this._fadeTime/this._fadeDuration))) * 100)
  	var op = ieop / 100;
 
  	var el = $(this.acID);
  	if (el.filters) // internet explorer
  	{
      try {
        el.filters.item("DXImageTransform.Microsoft.Alpha").opacity = ieop;
      } catch (e) { 
        // If it is not set initially, the browser will throw an error.
        // This will set it if it is not set yet.
        el.style.filter = 'progid:DXImageTransform.Microsoft.Alpha(opacity='+ieop+')';
      }
    } else	{
      el.style.opacity = op;
    }
	
    if (this._fadeTime >= this._fadeDuration)
    {
      clearInterval( this._fadeIntervalID );
      if (typeof this._afterUpdateInternal == 'function')
        this._afterUpdateInternal();
    }

  } // }}}
 
} // }}}

// vim: set filetype=javascript foldmethod=marker foldlevel=5:
/**
 * RPC-class; provides functions to do AJAX-calls 
 * This is LGPL, use it where you want to, just keep the header intact
 * 
 * @author ivo toby, internet voor Ondernemers 2005
 * @licenses lGPL
 */

	var rpc = Class.create({
		initialize:function(plugin, callBack){
			this.instID = 'rpc.' + parseInt(Math.random()*1000000);
			this.URI = '';
			this.params = new Array();
			this.rpcArgs = new Array();
			this.reserved = ['action', 'chid', 'xmlReq', 'node', 'rpc'];
			this.qs = '';
			this.xPath = ''
			this.debug = false;
			this.instID = 'wps.rpc_' + parseInt(Math.random()*1000000);
			this.async = true;
			this.waiter = this.dummyWaiter;
			this.unWaiter = this.dummyWaiter;
			this.encoding = 'UTF-8';
			this.callMethod = null;
			this.reqHeader = new Array();
			this.createCall(plugin, callBack);
		},
		
		/**
		 * Prepare AJAX-call
		 * @param plugin string = remote class/object to call
		 * @param callBack function = the function to execute when the call is completed
		 * 
		 */
		createCall : function(plugin, callBack){
			if (!this.URI) this.URI = '/include/lib/rpc.php'
			this.callBack = callBack;
			this.qs = '?action=' + plugin;
			return true;
		},
		
		/**
		 * Do the actual call to the server
		 * @params method string = the method of class "plugin" (in createCall) to be called
		 * @params args hashtable = an hashtable of arguments that should be passed to "method"
		 */
		call : function(method, args){ // (method, args)
			method = arguments[0];
			this.qs += "&method=" +method; 
			for (token in args){
				this.qs += "&" + token+ "=" +args[token];
			}
			if ( this.debug ){
				if (window.console){
					console.log(this.URI + this.qs);
	        	}else{
//					alert(this.URI + this.qs);
	        	}
	        }
			this.qs +='&rand=' + parseInt(Math.random()*1000000);
	        new Ajax.Request(this.URI, {
				    method: 		'post',
				    parameters:		this.qs,
				    requestHeaders: this.reqHeader,
				    encoding:		this.encoding,
				    onLoading:		this.waiter.bind(this.waiterObj),
				    onLoaded:		this.unWaiter.bind(this.unWaiterObj),
				    asynchronous:	this.async,
		            onException:	this.handleErr.bind(this),
		            onFailure:		this.handleErr.bind(this),
		            onComplete: 	this.callBack.bind(this.pob),
		            myRPC:			this
	                });
	         return true;
		},
		
		/**
		 * Default waiter-function
		 */
		waiter : function(){
			if (this.waiter){
				this.waiterObj[this.waiter];
			}
		},

		/**
		 * Default unwaiter-function
		 */
		unWaiter : function(){
			if (this.unWaiter){
				this.unWaiterObj[this.unWaiter];
			}
		},
		
		
		/**
		 * Attach a function to be used as "waiter" when a request is being loaded from the server
		 * @param function waiterFunc a reference to the function to be run as waiter-function
		 * @param the object in which waiterfunction is located (closure)
		 */
		attachWaiter : function(waiterFunc, obj){
			this.waiterObj = obj;
			this.waiter = waiterFunc;
		},

		/**
		 * Attach a function to be used as removal of the "waiter" when a request is finished
		 * @param function unWaiterFunc a reference to the function to be run as unwaiter
		 * @param the object in which the unwaiter is located (closure)
		 */
		attachUnWaiter : function(unWaiterFunc, obj){
			this.unWaiterObj = obj;
			this.unWaiter = unWaiterFunc;
		},	
		
		/**
		 * Handles 404 or 50X-responses from the server
		 */
		handleErr : function(){
			if (window.console){
				console.log(arguments[0] + '/' + arguments[1]);
			}else{
//				alert(arguments[0] + '/' + arguments[1]);
			}
		},
	
		/**
		 * Empty waiter, used when no waiter was assigned.
		 */
		dummyWaiter : function(){}	
	})
	/**
 * Supplies functions to upload files to server and handle a callback after uploading has finished
 */
	var jsUpload = Class.create({
		initialize : function(container, storyObj, onFinishCallBack){
			this.fileIdx =0
			this.instID = 'jsUpLoad.' + parseInt(Math.random()*1000000);
			this.uploadTryCounter = 0;
			this.onFinishCallBack = function(){};
			if (onFinishCallBack) this.onFinishCallBack = onFinishCallBack;
			
			var button = new Element('button', {id:this.instID+"startUploadButton"}).update("Upload");
			
			this.fsUploadProgress = new Element('div', {id:this.instID+'fsUploadProgress', className:'swfUploadStatus'});
			this.fsQueue = new Element('div', {id:this.instID+'fsUploadQueue', className:'swfUploadQueue'});
			var cancelButton = new Element('button', {id:this.instID+"cancelUploadButton"}).update("cancel");
			
			container.insert(button);
			container.insert(this.fsUploadProgress);
			container.insert(this.fsQueue);
			this.fsQueue.hide();
//			container.insert(cancelButton);
			this.customSettings = {
					progress_target : this.instID+'fsUploadProgress',
					progressTarget :  this.instID+'fsUploadProgress',
					cancelButtonId : this.instID+"cancelUploadButton",
					upload_successful : false
				}; 
			
			this.swfu = new SWFUpload({
				// Backend settings
				upload_url : "include/lib/rpc.php",
				file_post_name: "image",
				post_params : { 
					"action" : "album",
					"method" : "acceptUpload",
					"albumID" : storyObj.albumID,
					"storyID" : storyObj.storyID,
					"userID" : storyObj.storyObj.userID
				}, 
				// Flash file settings
				file_size_limit : "5 MB",
				file_types : "*.jpg;*.jpeg,*.JPG,*.JPEG",			// or you could use something like: "*.doc;*.wpd;*.pdf",

				file_types_description : "JPG Afbeeldingen",
				file_upload_limit : "50",
				file_queue_limit : "50",

				// Event Handler Settings (all my handlers are in the Handler.js file)
				file_dialog_start_handler : this.fileDialogStart.bind(this),
				file_queued_handler : this.fileQueued.bind(this),
				file_queue_error_handler : this.fileQueueError.bind(this),
				file_dialog_complete_handler : this.fileDialogComplete.bind(this),
				upload_start_handler : this.uploadStart.bind(this),
				upload_progress_handler : this.uploadProgress.bind(this),
				upload_error_handler : this.uploadError.bind(this),
				upload_success_handler : this.uploadSuccess.bind(this),
				upload_complete_handler : this.uploadComplete.bind(this),

				// Button Settings
				button_image_url : "/images/upload_wide.png",
				button_placeholder_id : this.instID+"startUploadButton",
				button_width: 250,
				button_height: 22,
				
				// Flash Settings
				flash_url : "/js/3rdparty/swfupload/swfupload.swf", 

				custom_settings : this.customSettings,
				
				// Debug settings
				debug: false
//				debug_handler : this.debugHandle.bind(this)
			});


			this.container = container;
	        
		},
		
		debugHandle : function(msg){
			if (window.console) console.log(msg, this.swfu)
		},
		
		fileDialogStart : function(){
		},

		
		fileQueued : function(file) {
			try {
				this.fsQueue.show();
				this.fsUploadProgress.update('Bestand wordt gecontroleerd...')
				this.addFileToQueue(file);
			} catch (ex) {
				if (window.console) console.log(ex);
			}

		},
		
		addFileToQueue : function(file){
			var filename = '<span class="swfUploadFileName">' + file.name + " (" + file.size +" bytes)</span>";
			var l = new Element('div', {className:"swfUploadFile", id:this.instID+"_" + file.index}).update(filename);
			
			var progressContainer = new Element('div', {className:"swfUploadProgressContainer"});
			//id:this.instID+"_" + file.index + "_progress"}
			var progressBar = new Element('div', {className:"swfUploadProgressBar", id:this.instID+"_" + file.index + "_progress"}).update("");
			progressContainer.insert(progressBar)
			l.insert(progressContainer);
			
			this.fsQueue.insert(l)
		},
		
		fileQueueError : function (file, errorCode, message) {
			this.debug('fileQueueError');
			try {
				if (errorCode === SWFUpload.QUEUE_ERROR.QUEUE_LIMIT_EXCEEDED) {
					this.fsUploadProgress.update("Er zijn teveel bestanden tegelijk gekozen, je kan maximaal 50 bestanden tegelijk uploaden");
					return;
				}

				switch (errorCode) {
				case SWFUpload.QUEUE_ERROR.FILE_EXCEEDS_SIZE_LIMIT:
					this.fsUploadProgress.update("Het bestand is te groot (max. 2 mb).");
					this.debug("Error Code: File too big, File name: " + file.name + ", File size: " + file.size + ", Message: " + message);
					break;
				case SWFUpload.QUEUE_ERROR.ZERO_BYTE_FILE:
					this.fsUploadProgress.update("Het bestand is leeg.");
//					progress.setStatus("Cannot upload Zero Byte files.");
					this.debug("Error Code: Zero byte file, File name: " + file.name + ", File size: " + file.size + ", Message: " + message);
					break;
				case SWFUpload.QUEUE_ERROR.INVALID_FILETYPE:
					this.fsUploadProgress.update("Dat is geen geldig bestand.");
					this.debug("Error Code: Invalid File Type, File name: " + file.name + ", File size: " + file.size + ", Message: " + message);
					break;
				case SWFUpload.QUEUE_ERROR.QUEUE_LIMIT_EXCEEDED:
					this.fsUploadProgress.update(("Je hebt teveel bestanden tegelijk gekozen, je mag  " +  message + " bestanden tegelijk kiezen."));
					break;
				default:
					if (file !== null) {
						this.fsUploadProgress.update("Onbekende error");
					}
					if (window.console) console.log("Error Code: " + errorCode + ", File name: " + file.name + ", File size: " + file.size + ", Message: " + message);
					break;
				}
			} catch (ex) {
				if (window.console) console.log(ex);
		    }
		},
		
		fileDialogComplete : function(numFilesSelected, numFilesQueued) {
			try {
				this.swfu.startUpload();
			} catch (ex)  {
				if (window.console) console.log(ex);
			}
		},
		
		uploadStart : function(file) {
			try {
				/* I don't want to do any file validation or anything,  I'll just update the UI and return true to indicate that the upload should start */
				this.fsUploadProgress.update("Bezig met uploaden");
//				$(this.instID+"startUploadButton").hide();
			}
			catch (ex) {
				if (window.console) console.log(ex);
			}
			
			return true;
		},
		
		uploadProgress : function(file, bytesLoaded, bytesTotal) {
			try {
				var percent = Math.ceil((bytesLoaded / bytesTotal) * 250);
				var progress = $(this.instID+"_" + file.index + "_progress")
//				progress.update(percent + " % ");
				progress.setStyle('width:' + percent + ";");
//				var progressWidth = 
			} catch (ex) {
				if (window.console) console.log(ex);
			}
		},
		
		uploadError : function(file, errorCode, message) {
			try {
				switch (errorCode) {
				case SWFUpload.UPLOAD_ERROR.HTTP_ERROR:
					this.fsUploadProgress.update("Upload fout: " + message);
					this.debug("Error Code: HTTP Error, File name: " + file.name + ", Message: " + message);
					break;
				case SWFUpload.UPLOAD_ERROR.MISSING_UPLOAD_URL:
					//progress.setStatus("Configuration Error");
					this.fsUploadProgress.update("Configuratie fout ");
					this.debug("Error Code: No backend file, File name: " + file.name + ", Message: " + message);
					break;
				case SWFUpload.UPLOAD_ERROR.UPLOAD_FAILED:
					this.fsUploadProgress.update("Uploaden mislukt");
					this.debug("Error Code: Upload Failed, File name: " + file.name + ", File size: " + file.size + ", Message: " + message);
					break;
				case SWFUpload.UPLOAD_ERROR.IO_ERROR:
					this.fsUploadProgress.update("Er is een server error opgetreden");
					this.debug("Error Code: IO Error, File name: " + file.name + ", Message: " + message);
					break;
				case SWFUpload.UPLOAD_ERROR.SECURITY_ERROR:
					this.fsUploadProgress.update("Er is een beveiligings error opgetreden");
					this.debug("Error Code: Security Error, File name: " + file.name + ", Message: " + message);
					break;
				case SWFUpload.UPLOAD_ERROR.UPLOAD_LIMIT_EXCEEDED:
					this.fsUploadProgress.update("Bestand is te groot");
					this.debug("Error Code: Upload Limit Exceeded, File name: " + file.name + ", File size: " + file.size + ", Message: " + message);
					break;
				case SWFUpload.UPLOAD_ERROR.SPECIFIED_FILE_ID_NOT_FOUND:
					this.fsUploadProgress.update("Upload-accept-bestand niet gevonden");
					this.debug("Error Code: The file was not found, File name: " + file.name + ", File size: " + file.size + ", Message: " + message);
					break;
				case SWFUpload.UPLOAD_ERROR.FILE_VALIDATION_FAILED:
					this.fsUploadProgress.update("Validatie mislukt");
					this.debug("Error Code: File Validation Failed, File name: " + file.name + ", File size: " + file.size + ", Message: " + message);
					break;
				case SWFUpload.UPLOAD_ERROR.FILE_CANCELLED:
					if (this.swfu.getStats().files_queued === 0) {
//						document.getElementById(this.customSettings.cancelButtonId).disabled = true;
					}
					this.fsUploadProgress.update("Upload afgebroken");
					break;
				case SWFUpload.UPLOAD_ERROR.UPLOAD_STOPPED:
					this.fsUploadProgress.update("Upload gestopt");
					break;
				default:
					this.fsUploadProgress.update("Onbekende error: " + error_code);
					this.debug("Error Code: " + errorCode + ", File name: " + file.name + ", File size: " + file.size + ", Message: " + message);
					break;
				}
			} catch (ex) {
		        this.debug(ex);
		    }
		},
		
		debug : function(msg){
			if (window.console) console.log(msg);
//			console.log(msg);
		},
		
		uploadSuccess : function(file, serverData) {
			try {
			} catch (ex) {
				this.debug(ex);
			}
		},

		uploadComplete : function(file) {
			try {
				if (this.swfu.getStats().files_queued === 0) {
					this.fsQueue.update("");
					this.fsQueue.hide();
					this.onFinishCallBack();
				} else {
					var progress = $(this.instID+"_" + file.index + "_progress");
					$(progress.parentNode).setStyle('border:none;');
					$(progress.parentNode).update(' <span class="swfUploadFinished">gereed</span> ');
					this.swfu.startUpload();
				}
			} catch (ex) {
				this.debug(ex);
			}

		}
		
		
	});
/**
 * Class to handle uploaded images
 */

	var jsAlbum = Class.create({
		initialize:function(container, storyID, storyObj){
			this.instID = 'jsAlbum_' + parseInt(Math.random()*1000000);
			if (!container){
				if (window.console){
					console.log("Error jsAlbumConroller : No container!");
				}else{
					alert("Error jsAlbumConroller : No container!");
				}
				return;
			}
			this.myCommand = "album";
			this.friendlyName = "foto";
			this.container = container;
			this.storyID = 0; // defaults to all albums of session-user
			this.albumID = 0; 
			this.storyObj = storyObj;
			if (storyID) this.storyID = storyID;
			this.scrollingContainer = $(container.parentNode); 
			this.scrollingContainer.setStyle('overflow-x:hidden;overflow-y:scroll;');
			this.load();// get data
		},
		
		/**
		 * Draws the 'normal' upload interface, and if there are any; the images that are already uploaded
		 */
		draw : function(req){
			if (req.responseJSON){
				if (req.responseJSON[0]) {
					this.albumID = req.responseJSON[0].albumID;
				}else{
					this.albumID = req.responseJSON.albumID
				}
				this.images = req.responseJSON;
			}
			// build interface:
			// set images:
			this.imagesContainer = new Element('div', {className:'images', id:this.instID+"_imagesContainer"});
			this.container.insert(this.imagesContainer);
			if (this.images.length > 0) {
				this.drawGridImages(this.imagesContainer);
			}
			
			// draw upload-interface;
			this.uploadDiv = new Element('div', {className:'upload'}); 
			this.uploadDiv.insert(new Element('div', {className:'uploadLink'}).insert("<br/>Selecteer jouw foto's (max. 2mb p/foto) op je eigen computer. Je kan meerdere foto's tegelijk selecteren en uploaden! <br/><br/><br/><br/>"));

			
			this.container.insert(this.uploadDiv);
			// DO not look at this too long; it's just a callBack in a callBack, in a callBack;)
			this.uploader = new jsUpload(this.uploadDiv, this, (function(){
				this.load( // uploader calls this.load when finished
					(function(req){this.manageImages(req)}).bind(this) // this.load calls manageimages when data is retrieved
				)
			}).bind(this));
			

			var row1 = new Element('div', {className:'rssIcons'});
			this.uploadDiv.insert(row1);
			
			// flickr:
			var icon = new Element('img', {src:'/images/flickr.png', title:'Importeer van Flickr'});
			icon.importType = 'Flickr';
			row1.insert(icon);
			icon.observe('click', this.startImport.bindAsEventListener(this));

			// hyves:
			var icon = new Element('img', {src:'/images/hyves.png', title:'Importeer van Hyves'});
			icon.importType = 'Hyves';
			row1.insert(icon);
			icon.observe('click', this.startImport.bindAsEventListener(this));

			var row = new Element('div', {className:'rssIcons'});
			this.uploadDiv.insert(row);

			// Picasa:
			var icon = new Element('img', {src:'/images/picasa.png', title:'Importeer van Picasa'});
			icon.importType = 'Picasa';
			row.insert(icon);
			icon.observe('click', this.startImport.bindAsEventListener(this));

			// facebook:
			var icon = new Element('img', {src:'/images/facebook.png', title:'Importeer van Facebook'});
			icon.importType = 'Facebook';
			row.insert(icon);
			icon.observe('click', this.startImport.bindAsEventListener(this));

		},
		
		/**
		 * Retrieves images from server with AJAX
		 */
		load:function(callBack){
			if (!callBack) callBack = (function(req){this.draw(req)}).bind(this);
			var remote = new rpc(this.myCommand, callBack);
//			remote.debug=true;
			remote.call('getUserAlbum', {storyID : this.storyID, albumID:this.albumID});
		},
		
		/**
		 * reloads images from server and redraws the interface 
		 */
		reload:function(){
			this.container.update('');
			this.load();
		},
		
		/**
		 * Draws layer with all images and input-fields to alter image-properties
		 * is a callback from jsUpload
		 */
		manageImages : function(req){
			var images = req.responseJSON;
			this.container.update('');
			var link = new Element('a').update("Nieuwe foto's toevoegen");
			link.setStyle("text-decoration:underline;");
			this.container.insert(link);
			link.observe('click', this.reload.bind(this));
			this._manageImages(images);
		},
		
		/**
		 * Private function called from manageImages
		 */
		_manageImages : function(imgObjArray){
			this.scrollingContainer.setStyle('overflow:hidden;');
			// draw management interface from uploaded images
			this.managementContainer = new Element('div', {id:this.instID+"_managementContainer", className:'managementContainer'})
			this.container.insert(this.managementContainer);
			this.managementContainer.insert('<hr class="line">')
			if (imgObjArray.length > 1){
				// loop through images to draw all interfaces
				var idx = 0;
				$A(imgObjArray).each(
					(function(imgObj){
						var layer = this.drawImageManagement(imgObj, this.managementContainer);
						layer.idx = idx;
						if (idx > 0){
							layer.hide();
						}
						idx++;
					}).bind(this)
				)
				var buttonContainer = new Element('div', {className:'saveButtonContainer'});
				this.managementContainer.insert(buttonContainer);
				if (idx > 0){
					var nextButton = new Element('img',{src:'/images/submit_arrow.jpg', className:'nextButton', id:this.instID+"nextButton"});
					buttonContainer.insert(nextButton)
					nextButton.observe('click', this.manageNextImage.bindAsEventListener(this));

					var previousButton = new Element('src', {src:'/images/submit_arrow_rev.jpg', className:'previousButton', id:this.instID+"previousButton"});
					buttonContainer.insert(previousButton);
					previousButton.show();
					previousButton.observe('click', this.managePreviousImage.bindAsEventListener(this));
				}
				
			}else{
				// draw just one management interface:
				this.drawImageManagement(imgObjArray[0], this.managementContainer);
				var buttonContainer = new Element('div', {className:'saveButtonContainer'});
				this.managementContainer.insert(buttonContainer);

				var nextButton = new Element('img', {src:'/images/submit_arrow.jpg', className:'nextButton'});
				buttonContainer.insert(nextButton)
				nextButton.observe('click', this.reload.bind(this));
			}
		},
		
		_imgPrevNext : function(plus){
			// find currIdx:
			var currIdx = 0;
			var lastIdx = 0;
			$(this.instID+"_managementContainer").select('.block').each(
				function(elem){
					if (elem.visible()) currIdx = elem.idx;
					lastIdx = elem.idx;
				}
			)
			if (plus){
				var nextIdx = currIdx + 1;
			}else{
				var nextIdx = currIdx -1;
			}
			if (nextIdx > lastIdx) nextIdx = 0;
			
			if (nextIdx == lastIdx) {
				$(this.instID+"nextButton").hide();
				var button = new Element('button', {className:'uploadOpslaan'}).update("Opslaan");
				$(this.instID+"nextButton").parentNode.insert(button);
				button.observe('click', this.reload.bind(this))
			}else{
				$(this.instID+"nextButton").show();
			}
			if ( lastIdx == 0 || nextIdx < 1  ) {
				$(this.instID+"previousButton").hide();
			}else{
				$(this.instID+"previousButton").show();
			}
			
			$(this.instID+"_managementContainer").select('.block').each(
				function(aLayer){
					if (aLayer.idx == currIdx) {
						aLayer.hide();
					}
					if (aLayer.idx == nextIdx){
						aLayer.show();
					}
				}
			)	
		},
		
		managePreviousImage: function(){
			this._imgPrevNext(false);
		},
		
		manageNextImage:function(e){
			this._imgPrevNext(true);
		},
		
		/**
		 * Draws the management-interface for a single image
		 */
		drawImageManagement : function(imgObj, container){
			this.scrollingContainer.setStyle('overflow:hidden');
			var div = new Element('div', {className:'block'});
			container.insert(div);
			
			var img = new Element('img', {className:'mgmtImg', src:'/upload/userimages/50/' + imgObj.id + '.jpg', id:imgObj.id + '_manageImageImage', height:'50px',width:'50px'});
			div.insert(img);
			
			var title = new Element('div', {className:'fieldtitle'}).update("Naam");
			var imgName = imgObj.fileName;
			if (imgObj.name) imgName = imgObj.name;
			var input = new Element('input', {type:'text', id:imgObj.id+"_name", value:imgName});
			input.imgID = imgObj.id
			input.field = 'name';
			var mDiv = new Element('div', {className:'field'}).insert(title);
			mDiv.insert(input);
			div.insert(mDiv);
			input.observe('change', this.saveProperty.bindAsEventListener(this))

			var title = new Element('div', {className:'fieldtitle'}).update("Omschrijving");
			var input = new Element('input', {type:'text', id:imgObj.id+"_description", value:imgObj.description});
			input.imgID = imgObj.id
			input.field = 'description';
			var mDiv = new Element('div', {className:'field'}).insert(title);
			mDiv.insert(input);
			div.insert(mDiv);
			input.observe('change', this.saveProperty.bindAsEventListener(this))

//			var title = new Element('div', {className:'fieldtitle'}).update("Locatie foto");
//			var input = new Element('input', {type:'button', value:"Kies een locatie",  id:imgObj.id+"_location", className:'locationButton'});
//			input.imgID = imgObj.id
//			input.field = 'location';
//			var mDiv = new Element('div', {className:'field'}).insert(title);
//			mDiv.insert(input);
//			div.insert(mDiv);
//			input.observe('click', this.openGMapsPositioner.bindAsEventListener(this))
			
			var title = new Element('div', {className:'fieldtitle'}).update("Zoekwoorden");
			var input = new Element('input', {type:'text', id:imgObj.id+"_tags", value:imgObj.tags});
			input.imgID = imgObj.id
			input.field = 'tags';
			var mDiv = new Element('div', {className:'field'}).insert(title);
			mDiv.insert(input);
			div.insert(mDiv);
			input.observe('change', this.saveProperty.bindAsEventListener(this))

			var title = new Element('div', {className:'fieldtitle'}).update("Datum");
			var mDiv = new Element('div', {className:'field'}).insert(title);
			div.insert(mDiv);
            mDiv.insert(calendarDropDown(imgObj.id));
            $(imgObj.id + '_day').imgID = imgObj.id;
            $(imgObj.id + '_year').imgID = imgObj.id;
            $(imgObj.id + '_month').imgID = imgObj.id;
            
            if (imgObj.dateTaken != '' && (imgObj.dateTaken !='0000-00-00 00:00:00' ) ) {
            	var dateTaken = imgObj.dateTaken.split(' ');
            	dateTaken = dateTaken[0];
            	dateTaken = dateTaken.split('-');
            	$A($(imgObj.id + '_year').options).each(
            		function(year){
            			if (year.value == dateTaken[0]) year.selected = true; 
            		}
            	)
            	$A($(imgObj.id + '_month').options).each(
            		function(year){
            			if (year.value == dateTaken[1]) year.selected = true; 
            		}
            	)
            	$A($(imgObj.id + '_day').options).each(
            		function(year){
            			if (year.value == dateTaken[2]) year.selected = true; 
            		}
            	)
            }else{
            	var currDate = new Date();
            	
            	$A($(imgObj.id + '_year').options).each(
            		function(year){
            			if (year.value == currDate.getYear()) year.selected = true; 
            		}
            	)
            	$A($(imgObj.id + '_month').options).each(
            		function(year){
            			if (year.value == (currDate.getMonth() + 1) ) year.selected = true; 
            		}
            	)
            	$A($(imgObj.id + '_day').options).each(
            		function(year){
            			if (year.value ==  currDate.getDate() ) year.selected = true; 
            		}
            	)
            }
            $(imgObj.id + '_year').observe('change', this.setDateField.bindAsEventListener(this));
            $(imgObj.id + '_day').observe('change', this.setDateField.bindAsEventListener(this));
            $(imgObj.id + '_month').observe('change', this.setDateField.bindAsEventListener(this));

            return div;
		},
		
		/**
		 * Callback from jsCalendar ( kind of onclick )
		 */
		setDateField : function(event){
			var elem = event.element();
			var id = parseInt(elem.id);
			var date = $(id + '_year').getValue() + '/' + $(id + '_month').getValue() + '/'  + $(id + '_day').getValue() ; 
			var remote = new rpc(this.myCommand, (function(req){this.saved(req, elem)}).bind(this));
			remote.debug=true;
			remote.call('saveProperty', {'imgID' : elem.imgID, 'field':'dateTaken', 'value':date });
		},
		
		/** 
		 * Saves a image-property (but NOT the date)
		 */
		saveProperty : function(e){
			var elem = e.element();
			if (elem.id.indexOf('_description') > -1){
				if (elem.getValue().stripTags().length > 70){
					alert('Omschrijving te lang, max. 70 karakters')
					elem.value = elem.getValue().stripTags().substring(0, 69);
					return;
				}
			}
			elem.setStyle('background:url(\'/images/waiter.gif\') no-repeat right;');
			// get imgID
			var imgID = elem.imgID;
			var field = elem.field;
			var remote = new rpc(this.myCommand, (function(req){this.saved(req, elem)}).bind(this));
			var value = escape(elem.getValue().stripTags());
			remote.call('saveProperty', {'imgID' : imgID, 'storyID':this.storyID, 'field':field, 'value':value});
		},
		
		/**
		 * Callback from saveProperty; changes status
		 */
		saved : function(req, elem){
			if (elem){
				elem.setStyle('background:none;border:1px green solid');
				setTimeout(
					function(){
						elem.setStyle('border:1px #3399CC solid');
					},
					2000
				)
			}
			control.getByInstanceID('homepageWidget').each(
					function(widget){
						widget.getStories();
					}
				)
			
		},
		
		/**
		 * Renders a list of already uploaded images from an album
		 */
		drawGridImages : function(container){
			this.scrollingContainer.setStyle('overflow:auto');
			this.images.each(
				(function(image){
					this.drawGridImage(image, container);
				}).bind(this)
			)
		},
		
		/**
		 * Renders a single image, called from drawGridImages
		 */
		drawGridImage : function(image, container){
			var div = new Element('div', {className:'imageItem'})
			container.insert(div);
			
			var img = new Element('img', {src:'/upload/userimages/50/' + image.id + '.jpg', id:image.id + '_userImage', height:'50px',width:'50px'});
			div.insert(img);
			img.imgObj = image;
			
			img.observe('click', this.editImage.bindAsEventListener(this));
			
			var deleteDiv = new Element('div', {className:'deleteImg'}).update("[delete]");
			div.insert(deleteDiv);
			deleteDiv.imgObj = image;
			deleteDiv.observe('click', this.deleteFromAlbum.bindAsEventListener(this));
			
			return img;
		},
		
		deleteFromAlbum : function(e){
			if (confirm('Weet je zeker dat je deze ' + this.friendlyName + ' wilt verwijderen?')){
				var func = (function(){
					this.container.update(''); 
					this.load();
					control.getByInstanceID('homepageWidget').each(
							function(widget){
								widget.getStories();
							}
						)					
				}).bind(this)
				var elem = e.element();
				var imgObj = elem.imgObj;
				
				var remote = new rpc(this.myCommand, func);
//				remote.debug=true;
				remote.call('removeFromAlbum', {albumID:imgObj.albumID, imgID:imgObj.id});
				
			}
		},
		
		/**
		 * Called from drawGridImage;
		 * renders the management-interface for a single image
		 */
		editImage : function(e){
			var elem = e.element();
			var images = [elem.imgObj];
			this.container.update('');

			var link = new Element('a').update('Terug');
			this.container.insert(link);
			link.observe('click', this.reload.bind(this));
			
			this._manageImages(images);
		},
		
		/**
		 * DANGEROUS
		 * Deletes a complete album at a story; currently NOT used 
		 */
		deleteAlbum: function(e){
			if (confirm("Weet je het zeker?")){
				e.element().update('bezig...');
				var remote = new rpc(this.myCommand, this.reset.bind(this));
//				remote.debug=true;
				remote.call('deleteAlbum', 
						{
							albumID : this.albumID
						}
				);
			}
		},
		
		openGMapsPositioner : function(event){
			gmc.view.mapSwitch.close();
			gmc.view.mapSwitch = new gm_ReisVerhaalFotoMapSwitch(gmc, this.setSpot.bind(this));
			gmc.view.mapSwitch.hideTrans();
			this.mappingImgID = event.element().imgID;
		},
		
		setSpot : function(overlay, latlng){
			var myHtml = "Deze plaats heb je gekozen!";
			gmc.map.openInfoWindow(latlng, myHtml);
			
			var remote = new rpc(this.myCommand, (function(req){this.saved(req, '')}).bind(this));
			remote.call('saveProperty', {'imgID' : this.mappingImgID, 'field':'coordsX', 'value':latlng.x});

			var remote = new rpc(this.myCommand, (function(req){this.saved(req, '')}).bind(this));
			remote.call('saveProperty', {'imgID' : this.mappingImgID, 'field':'coordsY', 'value':latlng.y});
			
			var remote = new rpc(this.myCommand, (function(req){this.saved(req, '')}).bind(this));
			remote.call('saveProperty', {'imgID' : this.mappingImgID, 'field':'zoomLevel', 'value':gmc.map.getZoom()});
			
//			gmc.view.mapSwitch.hideMap();
//			gmc.view.mapSwitch.close();
//			gmc.view.mapSwitch = new gm_MapSwitch(gmc);
			this.mappingImgID = 0;
		},		
		
		/** 
		 * Can probably be removed
		 */
		reset : function(){
		},  

		/**
		 * Can probably be removed
		 */
		dummy:function(){},
		
		
		// RSS IMPORT functions:
		
		startImport: function(e, type){
			if (!type){
				var elem = e.element();
				this.importType = elem.importType;
			}else{
				this.importType = type;
			}

			this.container.update('');
			
			var rssExplain = new Element('div', {className:'rssExplain'})
			this.container.insert(rssExplain);
			
			rssExplain.insert("<h1>Importeren van " + this.importType + "</h1>");
			// parse uitleg;
			rssExplain.insert(this.getUitleg(this.importType));

			if (this.rssInput){
				var currValue = this.rssInput.getValue();
			}else{
				var currValue = '';
			}
			this.rssInput = new Element('input', {type:'text', value:currValue});
			rssExplain.insert(this.rssInput);
			
			var submitter = new Element('img', {src:'/images/searcharrow_next.png', id:"importSubmit"});
			rssExplain.insert(submitter);
			
			submitter.observe('click', this.fetchImages.bindAsEventListener(this));
		},
		
		getUitleg: function(type){
			switch (type) {
			case "Flickr":
				return "<p>Ga naar je Photostream op Flickr.com, scroll naar de onderkant van de pagina en zoek naar 'Subscribe to [je gebruikersnaam ]photostream – Latest | geoFeed | KML' Klik op 'Latest', kopieer het adres getoond in de adresbalk en plak dit adres in het onderstaande vakje </p>";	
				break;
			case "Hyves":
				return '<p>Ga naar <a href="http://picasaweb.google.com/home" target="_blank">http://picasaweb.google.com/home</a>  en meld je aan met je Gmail-gebruikersnaam & wachtwoord. Klik op je Picasa-homepage op het album wat je wilt importeren en zoek naar “RSS”. Klik op de RSS-link, kopieer het adres in de adresbalk en plak dit adres in het onderstaande vakje </p>';
				break;
			case "Picasa":
				return '<p>Login op Hyves en ga naar je profiel-pagina. Scroll helemaal naar beneden en klik op “More RSS-feeds” onder het kopje “RSS Feeds”.  Klik onder “My Private Feeds” op “Photos & Video\'s”, kopieer het adres in de adresbalk en plak dit adres in het onderstaande vakje.</p>';
				break;
			case "Facebook":
				return '<p>Meld je aan op facebook en ga daarna naar : <a href="http://apps.facebook.com/photostorss/" target="_blank">http://apps.facebook.com/photostorss/</a>. Installeer de Facebook-applicatie. Klik op “My Albums” en klik op een van de getoonde albums. Onder het overzicht met foto\'s staat een RSS-Icoontje, klik daarop met de rechter-muisknop en selecteer “Copy Link Location” of “Kopieer link”. Plak dit adres in het onderstaande vakje..</p>';
				break;
			default:
				return '<p></p>';
				break;
			}
		},
		
		fetchImages : function(e){
			var elem = e.element();

			if (!this.rssInput.getValue() || this.rssInput.getValue().indexOf('http') == -1 ){
				alert("Vul het adres van een RSS-feed in aub.");
				return;
			}
			this.rssURI = encodeURIComponent(this.rssInput.getValue());
			
			this.container.update('');
			var rssExplain = new Element('div', {className:'rssExplain'})
			this.container.insert(rssExplain);
			
			var spinner = new Element('img', {src:'/images/large_spinner.gif', id:'largeSpinner'});
			rssExplain.insert(spinner);

			var spinnerText = new Element('div', {id:'spinnerText'}).update("Even geduld, we zijn je foto's aan het opzoeken");
			rssExplain.insert(spinnerText);
			
			var remote = new rpc('imageImport', this.handleFetchedImages.bind(this));
			remote.debug = true;
			remote.call('fetchRSS', {type:this.importType, uri:this.rssURI});
	
		},
		
		handleFetchedImages : function(req){
			if (!req.responseJSON){
				// throw error:
				alert('Er is een error opgetreden bij het ophalen van je foto\'s, kijk of het ingevulde adres correct is of neem contact op met de helpdesk');
				this.startImport('', this.importType);
				return;
			}
			// draw grid:
			this.container.update('');
			
			var gridContainer = new Element('div', {className:'rssImportGrid'});
			this.container.insert(gridContainer);
			
			this.importedImages = req.responseJSON;
			$A(this.importedImages).each(
				(function(img){
					this.drawImportedImage(img, gridContainer);
				}).bind(this)
			)
			this.container.insert(new Element('div', {style:'clear:both;'}));
			
			var submit = new Element('img', {src:'/images/donker_blauwe_pijl.jpg', id:'storeImportedImages'});
			this.container.insert(submit);
			submit.observe('click', this.storeImportedImages.bind(this));
		},
		
		drawImportedImage : function(imgObj, container){
			var div = new Element('div', {className:'importedImageContainer'});
			container.insert(div);
			var border = new Element('div', {className:'border'});
			div.insert(border);
			
			var img = new Element('img', {src:imgObj.uri, id:imgObj.id});
			border.insert(img);
			
			var checkbox = new Element('input', {type:'checkbox', className:'rssCheckbox', checked:'checked'});
			checkbox.imgID = imgObj.id;
			border.insert(checkbox);
			
		},
		
		storeImportedImages : function(){

			// gather images:
			var selectedImages = '';
			$$('.rssCheckbox').each(
				function(checkbox){
					if (checkbox.checked){
						selectedImages += checkbox.imgID+',';
					}
				}
			)

			this.container.update('');
			var rssExplain = new Element('div', {className:'rssExplain'})
			this.container.insert(rssExplain);
			
			var spinner = new Element('img', {src:'/images/large_spinner.gif', id:'largeSpinner'});
			rssExplain.insert(spinner);

			var spinnerText = new Element('div', {id:'spinnerText'}).update("Even geduld, we zijn je foto's aan het importeren");
			rssExplain.insert(spinnerText);

			var remote = new rpc('imageImport', this.handleImported.bind(this));
			remote.debug = true;
			remote.call('import', {type:this.importType, uri:this.rssURI, images:selectedImages, albumID:this.albumID, storyID:this.storyID});

		},
		
		handleImported : function(){
			this.load( // uploader calls this.load when finished
				(function(req){this.manageImages(req)}).bind(this) // this.load calls manageimages when data is retrieved
			)
		}
		
	}) /**
 * Class to handle uploaded images
 */

	var jsVideoAlbum = Class.create(jsAlbum,{
		
		initialize:function(container, storyID){
			this.instID = 'jsVideoAlbum_' + parseInt(Math.random()*1000000);
			if (!container){
				if (window.console){
					console.log("Error jsVideoAlbumConroller : No container!");
				}else{
					alert("Error jsVideoAlbumConroller : No container!");
				}
				return;
			}
			this.myCommand = "videoalbum";
			this.friendlyName = "video";
			this.container = container;
			this.storyID = 0; // defaults to all albums of session-user
			this.albumID = 0; 
			if (storyID) this.storyID = storyID;
			this.load();// get data
			
		},
		
		/**
		 * Draws the 'normal' upload interface, and if there are any; the images that are already uploaded
		 */
		draw : function(req){
			if (req.responseJSON){
				if (req.responseJSON[0]) {
					this.albumID = req.responseJSON[0].albumID;
				}else{
					this.albumID = req.responseJSON.albumID
				}
				this.images = req.responseJSON;
			}
			// build interface:
			// set images:
			this.imagesContainer = new Element('ul', {className:'editVideoList', id:this.instID+"_imagesContainer"});
			this.container.insert(this.imagesContainer);
			if (this.images.length > 0) {
				this.images.each(
					(function(img){
						if (img.name){
							var imgName = img.name;	
						}else{
							var imgName = img.URI;
						}
						var li = new Element('li').update(imgName)
						li.imgObj = img;
						this.imagesContainer.insert(li);
						
						var deleteDiv = new Element('span').update(" [delete]");
						li.insert(deleteDiv);
						deleteDiv.imgObj = img;
						deleteDiv.observe('click', this.deleteFromAlbum.bindAsEventListener(this));
						
						li.observe('click', this.editImage.bindAsEventListener(this));
					}).bind(this)
				)
			}
			
			// draw upload-interface;
//			this.uploadDiv = new Element('div', {className:'upload', style:'cursor:pointer;'}).insert("Voeg " + this.friendlyName + "'s toe aan dit reisverhaal<br/>");
//			this.container.insert(this.uploadDiv);
//
//			var func = (function(){
////					var imgObj = {id:0, albumID:this.albumID, name:"Nieuwe youtube video", URI:'', description:'', tags:''};
////					this.drawImageManagement(imgObj, this.uploadDiv)
//					this.addEmptyVideoToAlbum();
//			}).bind(this)
			
			this.addEmptyVideoToAlbum();
//			this.uploadDiv.observe('click', func)
			
			this.uploadDiv = new Element('div');			
//			// DO not look at this too long; it's just a callBack in a callBack, in a callBack;)
//			this.uploader = new jsUpload(this.uploadDiv, this, (function(){
//				this.load( // uploader calls this.load when finished
//					(function(req){this.manageImages(req)}).bind(this) // this.load calls manageimages when data is retrieved
//				)
//			}).bind(this));
			
		},
		
		addEmptyVideoToAlbum : function(){
			var func = (function(req){
				var imgObj = {id:req.responseJSON.imgID, albumID:this.albumID, name:"Nieuwe youtube video", URI:'', description:'', tags:''}
				this.managementContainer = new Element('div', {id:this.instID+"_managementContainer", className:'managementContainer'})
				this.container.insert(this.managementContainer)
				this.drawImageManagement(imgObj, this.managementContainer);
				
				var buttonContainer = new Element('div', {className:'saveButtonContainer'});
				this.managementContainer.insert(buttonContainer);

				var nextButton = new Element('img', {src:'/images/submit_arrow.jpg', className:'nextButton'});
				buttonContainer.insert(nextButton)
				
//				var nextButton = new Element('button', {className:'nextButton'}).update('opslaan');
//				buttonContainer.insert(nextButton)
				nextButton.observe('click', this.reload.bind(this));				
			}).bind(this)
			
			var remote = new rpc(this.myCommand, func);
			remote.call('addVideoToAlbum', {storyID : this.storyID, albumID:this.albumID});
		},
		
		editImage : function(e){
			var elem = e.element();
			var images = [elem.imgObj];
			this.container.update('');

			var link = new Element('a').update('Terug');
			this.container.insert(link);
			link.observe('click', this.reload.bind(this));
			this.managementContainer = new Element('div', {id:this.instID+"_managementContainer", className:'managementContainer'})
			this.container.insert(this.managementContainer);
			this.managementContainer.insert('<hr class="line">');			
			this.drawImageManagement(images, this.managementContainer);
			
			var buttonContainer = new Element('div', {className:'saveButtonContainer'});
			this.managementContainer.insert(buttonContainer);
			
			var nextButton = new Element('img', {src:'/images/submit_arrow.jpg', className:'nextButton'});
			buttonContainer.insert(nextButton)

//			var nextButton = new Element('button', {className:'nextButton'}).update('opslaan');
//			buttonContainer.insert(nextButton)
			nextButton.observe('click', this.reload.bind(this));
			
			
		},
		
		/**
		 * Draws the management-interface for a single image
		 */
		drawImageManagement : function(imgObj, container){
			if (imgObj[0]) imgObj = imgObj[0];
			var div = new Element('div', {className:'block'});
			container.insert(div);
			
			var title = new Element('div', {className:'fieldtitle'}).update("Naam");
			var imgName = imgObj.name;
			var input = new Element('input', {type:'text', id:imgObj.id+"_name", value:imgName});
			input.imgID = imgObj.id
			input.field = 'name';
			var mDiv = new Element('div', {className:'field'}).insert(title);
			mDiv.insert(input);
			div.insert(mDiv);
			input.observe('change', this.saveProperty.bindAsEventListener(this))
			
			var title = new Element('div', {className:'fieldtitle'}).update("URL van <a href=\"http://www.youtube.com\" target=\"_blank\">YouTube</a>");
			var imgName = imgObj.URI;
			var input = new Element('input', {type:'text', id:imgObj.id+"_name", value:imgName});
			input.imgID = imgObj.id
			input.field = 'URI';
			var mDiv = new Element('div', {className:'field'}).insert(title);
			mDiv.insert(input);
			this.youtubeLink = new Element('span', {className:"youtubeLink"});
			mDiv.insert(this.youtubeLink)
			if (imgName){
//				var link = new Element('a', {href:imgName, target:"_blank"}).update('[bekijken]');
//				this.youtubeLink.insert(link) 	
			}
			
			div.insert(mDiv);
			input.observe('change', this.saveProperty.bindAsEventListener(this))
			

			var title = new Element('div', {className:'fieldtitle'}).update("Omschrijving");
			var input = new Element('input', {type:'text', id:imgObj.id+"_description", value:imgObj.description});
			input.imgID = imgObj.id
			input.field = 'description';
			var mDiv = new Element('div', {className:'field'}).insert(title);
			mDiv.insert(input);
			div.insert(mDiv);
			input.observe('change', this.saveProperty.bindAsEventListener(this))

//			var title = new Element('div', {className:'fieldtitle'}).update("Locatie foto");
//			var input = new Element('input', {type:'button', value:"Kies een locatie",  id:imgObj.id+"_location", className:'locationButton'});
//			input.imgID = imgObj.id
//			input.field = 'location';
//			var mDiv = new Element('div', {className:'field'}).insert(title);
//			mDiv.insert(input);
//			div.insert(mDiv);
//			input.observe('click', this.openGMapsPositioner.bindAsEventListener(this))
			
			var title = new Element('div', {className:'fieldtitle'}).update("Zoekwoorden");
			var input = new Element('input', {type:'text', id:imgObj.id+"_tags", value:imgObj.tags});
			input.imgID = imgObj.id
			input.field = 'tags';
			var mDiv = new Element('div', {className:'field'}).insert(title);
			mDiv.insert(input);
			div.insert(mDiv);
			input.observe('change', this.saveProperty.bindAsEventListener(this))

			var title = new Element('div', {className:'fieldtitle'}).update("Datum");
			var mDiv = new Element('div', {className:'field'}).insert(title);
			div.insert(mDiv);
            mDiv.insert(calendarDropDown(imgObj.id));
            $(imgObj.id + '_day').imgID = imgObj.id;
            $(imgObj.id + '_year').imgID = imgObj.id;
            $(imgObj.id + '_month').imgID = imgObj.id;
            if (imgObj.dateTaken != '' && (imgObj.dateTaken !='0000-00-00 00:00:00' ) ) {
            	var dateTaken = imgObj.dateTaken.split(' ');
            	dateTaken = dateTaken[0];
            	dateTaken = dateTaken.split('-');
            	$A($(imgObj.id + '_year').options).each(
            		function(year){
            			if (year.value == dateTaken[0]) year.selected = true; 
            		}
            	)
            	$A($(imgObj.id + '_month').options).each(
            		function(year){
            			if (year.value == dateTaken[1]) year.selected = true; 
            		}
            	)
            	$A($(imgObj.id + '_day').options).each(
            		function(year){
            			if (year.value == dateTaken[2]) year.selected = true; 
            		}
            	)
            }else{
            	var currDate = new Date();
            	
            	$A($(imgObj.id + '_year').options).each(
            		function(year){
            			if (year.value == currDate.getYear()) year.selected = true; 
            		}
            	)
            	$A($(imgObj.id + '_month').options).each(
            		function(year){
            			if (year.value == (currDate.getMonth() + 1) ) year.selected = true; 
            		}
            	)
            	$A($(imgObj.id + '_day').options).each(
            		function(year){
            			if (year.value ==  currDate.getDate() ) year.selected = true; 
            		}
            	)
            }
            $(imgObj.id + '_year').observe('change', this.setDateField.bindAsEventListener(this));
            $(imgObj.id + '_day').observe('change', this.setDateField.bindAsEventListener(this));
            $(imgObj.id + '_month').observe('change', this.setDateField.bindAsEventListener(this));

//			var title = new Element('div', {className:'title'}).update("Datum");
//			var calDiv = new Element('div', {id:imgObj.id+ "_date"});
//			calDiv.imgID = imgObj.id
//			calDiv.field = 'dateTaken';
//			var mDiv = new Element('div', {className:'field'}).insert(title);
//			mDiv.insert(calDiv);
//			div.insert(mDiv);
//			
//            var localDate = new Date();
//            if (imgObj.dateTaken = '') imgObj.dateTaken = new Date();
//            localDate.setDate(imgObj.dateTaken);
//
//            Calendar.setup(
//                {
//                    flat: imgObj.id+"_date",
//                    flatCallback : this.setDateField.bind(this),
//                    date : localDate
//                }
//            );	
		},
		
		
		saveProperty : function($super, e){
			$super(e);
			var elem = e.element();
			if (elem.id.indexOf('_name') > -1){
//				var link = new Element('a', {href:elem.getValue(), target:"_blank"}).update('[bekijken]');
//				this.youtubeLink.insert(link) 	
			}
		},
		
		/**
		 * Callback from saveProperty; changes status
		 */
		saved : function(req, elem){
//			if (req.responseJSON && req.responseJSON.imgID ) this.
			if (elem){
				elem.setStyle('background:none;border:1px green solid');
				setTimeout(
					function(){
						elem.setStyle('border:1px #3399CC solid');
					},
					2000
				)
			}
		}	
	})/**
*/

	var simpleZoom = Class.create({
		initialize : function(thumb, srcImg, noEvents){
			this.instID = 'simpleZoom.' + parseInt(Math.random()*1000000);
			if (noEvents == '') noEvents = false;
			this.srcImg = srcImg;
			if (noEvents){
				// zoom immediately;
				this.zoom();
			}else{
				$(thumb).observe('click', this.zoom.bind(this))
			}
		},
	
		zoom : function(){
			// draw srcImg to screen:
			var img = new Element('img', {src:this.srcImg});
			var firstNode = $(this.filteredFirstNode($(document.body)));
			// add absolute layer:
			this.transLayer = new Element('div', {className:'zoomTrans', id:this.instID+"zoomTrans"});
			$(document.body).insertBefore(this.transLayer, firstNode);
			this.transLayer.observe('click', this.close.bindAsEventListener(this))
			
			this.imgLayer = new Element('div', {className:'zoomContents', id:this.instID+"zoomContents"});
			$(document.body).insertBefore(this.imgLayer, firstNode);
			
			this.topBar = new Element('div', {className:'topBar'}).update("&nbsp;");
			this.imgLayer.insert(this.topBar);

			this.bottomBar = new Element('div', {className:'bottomBar'}).update("&nbsp;");
			this.imgLayer.insert(this.bottomBar);

			this.imgLayer.observe('click', this.close.bindAsEventListener(this));

			this.img = new Element('img', {src:this.srcImg});
			this.imgLayer.insert(this.img);
			this.img.observe('click', this.close.bindAsEventListener(this));
			this.resize();
		},
		
		resize: function(){
			if (!this.isImageLoaded()){
				setTimeout(this.resize.bind(this), 400);
				return;
			}
			setTimeout(this._resize.bind(this), 500);
		},
		
		_resize:function(){
			var screenWidth = $(document.body).getWidth() - 40;
			var screenHeight = $(document.body).getHeight() - 40;
			var imgWidth = this.img.getWidth();
			var imgHeight = this.img.getHeight();
			var resizeWidth =  (imgWidth > screenWidth);
			var resizeHeight = (imgHeight > screenHeight);
			var diff = 100;
			if (resizeWidth && resizeHeight){
				// prefer height-resize over width;
				this.img.setStyle({height :(screenHeight - diff), width:'auto'});
				this.setBars();
				return;
			}
			if (resizeHeight){
				// again prefer height-resize over width;
				this.img.setStyle({height :(screenHeight - diff), width:'auto'});
				this.setBars();
				return;
			}
			if (resizeWidth){
				// resize width, height is already OK
				this.img.setStyle({width :(screenWidth  - diff), heigth:'auto'});
				this.setBars();
				return;
			}
			this.setBars();
		},
		
		setBars : function(){
			this.img.absolutize();
			this.topBar.style.width = this.img.getWidth();
			this.topBar.style.top= this.img.offsetTop;
			if (!Prototype.Browser.IE) this.topBar.style.left = this.img.style.left;
			this.topBar.insert(new Element('img', {src:'/images/blackcloser.gif', align:'right'}));

			this.bottomBar.style.width = this.img.getWidth();
			this.bottomBar.style.top = this.img.offsetTop + this.img.getHeight();
			if (!Prototype.Browser.IE) this.bottomBar.style.left = this.img.style.left;
//			var link = new Element('a', {href:'http://www.backpackers.nl/site/content/australie/895.html', target:"_blank"}).update(new Element('img', {src:'/images/ads/ad_1.gif', border:'0', align:'left'}));
			if (gZoomAd) this.bottomBar.insert(gZoomAd);

		},
		
		close : function(){
			new Effect.Fade(this.transLayer, {duration:'0.2'});
			new Effect.Fade(this.imgLayer, {duration:'0.2'});
			setTimeout(
				(function(){
					try{
						if (this.transLayer) this.transLayer.remove();
						if (this.imgLayer) this.imgLayer.remove();
					}catch(e){
						if (window.console) console.log(e);
					}
				}).bind(this),
				200
			)
		},
		
		filteredFirstNode : function(DOM, blackList){
			if ((Prototype.Browser == 'WebKit')){ // dunno exactly why, but Safari seems to barf on the prototype $A function in this context 
				var blackList = ['#text', '#comment'];
				for (var i=0;i<DOM.childNodes.length;i++){
					var aNode = DOM.childNodes.item(i);
					if ( blackList.indexOf(aNode.nodeName) ==  -1 ){
						return aNode
					}
				}
				return null;
			}else{
				if (!blackList) var blackList = ['#text', '#comment'];
				var retNode = $A(DOM.childNodes).find(
									function(aNode){
										if ( blackList.indexOf(aNode.nodeName) ==  -1 ){
											return true;
										}
									}
							   );
				return retNode;
			}
		},
		
		isImageLoaded : function() {
		    if (!this.img.complete) {
		        return false;
		    }

		    if (typeof this.img.naturalWidth != "undefined" && this.img.naturalWidth == 0) {
		        return false;
		    }
		    // No other way of checking: assume it's ok.
		    return true;
		}
		
	})
var defaultReisverhaal = [
	 {
		 	"id":"136",
		 	"title":"ZET HIER JE REISVERHAAL EN MAAK KANS OP DIE GEWELDIGE WERELDREIS",
		 	"bbCode":"Schrijf <a href=\"#\" onclick=\"control.getContentWidget(9);\">hier</a> je reisverhaal kort, lang, maakt niet uit, al je ervaringen zijn welkom. <a href=\"#\" onclick=\"control.getContentWidget(9);\">Zet je foto\'s erbij</a> en koppel zowel je verhaal als je foto\'s aan de kaart via de \'geef locatie aan\' knop. Hierdoor verschuift de achtergrond naar jouw plekje op de wereldkaart, veraf of dichtbij, wat jij wilt.\n\n Heb je al <a href=\"#\" onclick=\"control.getContentWidget(9);\">youtube filmpjes</a> online die hier bij passen? Plaats dan deze link en de video staat erbij, incl. je gewenste locatie op de wereldkaart.\n\n Heel veel succes.\n En wie weet win jij wel die wereldreis!  \n\n\n\n",
		 	"dtAdded":"2009-04-27 14:19:54",
		 	"location":"",
		 	"tags":"",
		 	"coordsX":"133.8972473144531200",
		 	"coordsY":"-23.7564386990494800",
		 	"zoomLevel":"5",
		 	"userID":"73",
		 	images:[
			        {
			        	"albumname":"Nieuw Album",
			        	"id":"0",
			        	"albumID":"59",
			        	"fileName":"default.jpg",
			        	"name":"",
			        	"description":"",
			        	"tags":"",
			        	"coordsX":"0",
			        	"coordsY":"0",
			        	"zoomLevel":"7",
			        	"dateAdded":"2009-04-20 18:08:12",
			        	"dateTaken":"0000-00-00 00:00:00",
			        	"aID":"59"
			        }
		      ], 
		 	userData:{"first_name":"Australian Backpackers","middle_name":"","last_name":""},
		 	videos:{albumID:104}
	 }
	];
	var reisverhaal_form = function(parentContainer){
		parentContainer.insert(new Element('span', {className:'lineSpacer'}));
		parentContainer.insert(new Element('hr', {className:'line'}));
		
		var currID = gContentBlocks[(gContentBlocks.length - 1)];
		var container = new Element('div', {className:'storyForm', id:currID+'_storyForm'});
		parentContainer.insert(container);
		
		var titleBlock = this.getFormBlock("Titel  max. 90 tekens", new Element('input', {className:'title', name:'title', id:currID+'_title'})); 
		container.insert(titleBlock)
		titleBlock.observe('keyup', function(e){
			if (e.element().getValue().length > 90){
				e.element().value = e.element().getValue().substring(0,89);
				alert("Titel is te lang");
				return false;
			}
		})

		var tmpInput = new Element('button', {className:'locationLink', name:'locationName', id:currID+'_locationName', style:'text-align:center;'}).update("geef locatie aan");
		container.insert(
			this.getFormBlock("Waar?", tmpInput )
		)		
		if (Prototype.Browser.IE){
			tmpInput.setStyle({width:'135px'});
		}else{
			tmpInput.setStyle({width:'140px'});	
		}
		
		
		
		container.insert(this.getFormBlock("Zoektermen", new Element('input', {className:'tags', name:'tags', id:currID+'_tags'})) );
		
		container.insert(this.getFormBlock("Schrijf hier je verhaal", new Element('textarea', {className:"bbCode", id:currID+'_bbCode'}), 'blockingRowTitle', 'highRow' ));
		container.insert(
					this.getFormBlock("", 
							new Element('button', {className:'fotoLink', name:'fotoLink', id:currID+'_addAlbumLink'}).update('foto\'s')
					)
		);
		container.insert(
				this.getFormBlock("", 
						new Element('button', {className:'fotoLink', name:'videoLink', id:currID+'_addVideoLink'}).update('video\'s')
				)
		);
		container.insert(new Element('div', {className:'formError storyErrors', id:currID+'_storyErrors', style:'display:none;'}))
		
//		var img = new Element('img', {id:currID+'_storySubmit', src:'/images/submit_arrow.jpg', align:'right'});
		var img = new Element('input', {id:currID+'_storySubmit', type:'button', className:'storySubmit', value:'opslaan'});

		var div = new Element('div', {className:'formRow'}).insert(img);
		container.insert(div)
//		container.insert(
//					this.getFormBlock("", 
//							new Element('button', {className:'fotoLink', name:'fotoLink', id:currID+'_storySubmit'}).update('reisverhaal opslaan')
//					)
//		);

		return container;
	}
	
	var getFormBlock = function(title, input, className, rowClassName, inputClassName){
		if (!className) className = 'rowTitle';
		if (!rowClassName) rowClassName = 'formRow';
		if (!inputClassName) inputClassName = 'rowInput';
		
		if (!title) title = '';
		var div = new Element('div', {className:rowClassName});
		if (title) div.insert(new Element('label', {className:className}).update(title));
		
		var inputContainer = new Element('div', {className:inputClassName}).update(input);
		div.insert(inputContainer);
		return div;
	}
	var gLowest = 0;
	var gZoomAd = new Element('a', {href:'http://www.backpackers.nl/abp.php?rand=54wo9545#Aanbieding China Airlines', target:"_blank"}).insert(new Element('img', {src:'/images/ads/ad_1_black.png', border:'0', align:'left'}));
	var gShouldFocus = true;
	
	hideTrans = function(e){
		control.hideAll();
		$('mapSwitch').show();
		new Effect.Fade($('mapTrans'), {duration:'0.2'});
	}
	
	hideMap = function(){
		$('mapTrans').show();
		$('mapSwitch').hide();
		window.control.showAll();		
	}
	
	openGMapsPersonalPositioner = function(){
		if (gmc.view instanceof gm_ProfileOwnerView){
			gmc.view.mapSwitch.close();
			gmc.view.mapSwitch = new gm_PositieMapSwitch(gmc, setMyPosition);
			gmc.view.mapSwitch.hideTrans();
		}
	}

	setMyPosition = function(overlay, latlng){
		var myHtml = "Deze plaats heb je gekozen!";
		gmc.map.openInfoWindow(latlng, myHtml);
		var remote = new rpc('profile', positionDummy);
		remote.call('saveProfileProperties', {coordsX:latlng.x, coordsY:latlng.y, zoomLevel:gmc.map.getZoom()})
	}

	positionDummy = function(){
	}
	
	openABPContentWidget = function(name){
		if (control.get('newsWidget')){
			control.get('newsWidget').closeMe();
			var contentWidget = getContentWidget();
			control.add(contentWidget, true);
			control.render();
			contentWidget.shadow.style.zIndex = 4;
			contentWidget.container.style.zIndex = 5;
		}
		if (!control.contentWidget){
			var contentWidget = getContentWidget();
			control.add(contentWidget, true);
			control.render();
			contentWidget.shadow.style.zIndex = 4;
			contentWidget.container.style.zIndex = 5;
		}
		control.contentWidget.options.ajax.uri = '/include/lib/rpc.php?action=content&method=getContentByButtonName&name=' + name;
		control.contentWidget.show();
		control.contentWidget.reload();
	}
	
	getContentWidget = function(){
		var contentWidget = new abpContentWidget(
				{
						name : 'contentWidget',
						position:{left:50, top:250}, 
						size:{width:660, height:456},
						containerClassName:'orangeWidget', 
						useIFrame:false,
						scrolling:true,
						showClose:true, 
						canHide:true,
						ajax:{uri : '/include/lib/rpc.php?action=content&method=getContent&id=24'},
						zIndex:5
				}
			) 
		return contentWidget;
	}

	openNewsPage = function(){
		window.location.href= 'http://' + window.location.hostname + '/abp.php';
		
	}
	
	openEmailWidget = function(userData){
//		var topMargin = '15px';
//		if (Prototype.Browser.IE) var topMargin = '20px';
		control.get('profile').closeMe();
		control.add(
			new emailWidget(
    				{
						id:'profile',
						position:{left:50, top:20}, 
						size:{width:350, height:325},
						containerClassName:'whiteWidget', 
						useIFrame:false,
						scrolling : false,
						showClose:true,
						framePadding : '0px',
						canHide:true
    				}, userData
    			)
			);
		control.render();
	}
	
	openBrochureWidget = function(){
		var topMargin = '15px';
		if (Prototype.Browser.IE) var topMargin = '20px';
		var widget = new shadowedWidget(
    				{
						id:'brochureWidget',
						position:{left:50, top:20}, 
						size:{width:665, height:680},
						containerClassName:'whiteWidget', 
						useIFrame:true,
						scrolling : false,
						frameMargin : {top:topMargin}, 
						ajax:{uri:'/include/inhoud_brochure.php'},
						showClose:false,
						framePadding : '0px',
						canHide:true
    				}
    			)
		control.add( widget );
		control.render();
		widget.toFG();
	}		
	
	openInsuranceWidget = function(){
		var topMargin = '15px';
		if (Prototype.Browser.IE) var topMargin = '20px';
		var widget = new shadowedWidget(
    				{
						id:'insuranceWidget',
						position:{left:50, top:20}, 
						size:{width:660, height:500},
						containerClassName:'whiteWidget', 
						useIFrame:true,
						scrolling : true,
						frameMargin : {top:topMargin}, 
						ajax:{uri:'http://www.australianbackpackers.nl/_includes/verzekering_bponly.php'},
						showClose:false,
						framePadding : '0px',
						canHide:true
    				}
    			)
		control.add( widget );
		control.render();
		setTimeout(function(){widget.toFG();}, 500);
	}	
	
	openTicketsWidget = function(){
		var topMargin = '15px';
		if (Prototype.Browser.IE) var topMargin = '20px';
		control.add(
				new shadowedWidget(
					{
						id:'ticketsWidget',
						position:{left:90, top:45}, 
						size:{width:700, height:600}, 
						containerClassName:'whiteWidget',
						frameMargin : {top:topMargin}, 
						scrolling : false,
						showClose:true,
						useIFrame:true, 
						ajax:{uri : 'http://flight1.onlinetravel.ch/cgi-bin/flightmore?agentc=ausnl&language=nl&mode=0&mask=fastbook'},
						canHide :true
					}
				)
			);
		control.render();
	}

	openGroepsreizenWidget = function(directUri){
		if (!directUri) directUri = '/include/inhoud_groepsreizen.php';
		control.add(
    			new shadowedWidget(
    				{
    						id:'GroepsreizenWidget',
    						position:{left:50, top:20}, 
    						size:{width:665, height:680},
    						containerClassName:'whiteWidget', 
    						useIFrame:true, 
    						ajax:{uri:directUri},
    						showClose:true,
    						framePadding : '0px',
    						canHide:true
    				}
    			)
			);
		control.render();
	}
	
	
	openOpendageWidget = function(){
		control.add(
    			new shadowedWidget(
    				{
    						id:'opendagenWidget',
    						position:{left:50, top:20}, 
    						size:{width:665, height:680},
    						containerClassName:'whiteWidget', 
    						useIFrame:true, 
    						ajax:{uri:'/include/inhoud_opendag.php'},
    						showClose:true,
    						framePadding : '0px',
    						canHide:true
    				}
    			)
			);
		control.render();
	}	
	
	getEmptyHomepageWidget = function(callBack){
		if (!callBack) callBack = function(){};
		var widget = new homepageWidget(
				{
					id:'homepageWidget',
					position:{left:90, top:45}, 
					size:{width:660, height:520}, 
					containerClassName:'tabbedWidget',
					scrolling : false,
					showClose:false,
					canHide :true
				},
				'','',
				new Element('a', {href:'http://www.backpackers.nl/abp.php?rand=54wo9545#Aanbieding China Airlines', target:"_blank"}).insert(new Element('img', {src:'/images/ads/ad_1.png', border:'0'}))
			);
		widget.widgetCallBack = callBack;
		return widget;
	}

	function nl2br(str, is_xhtml) {
	    var breakTag = '';

	    breakTag = '<br />';
	    if (typeof is_xhtml != 'undefined' && !is_xhtml) {
	        breakTag = '<br>';
	    }

	    return (str + '').replace(/([^>]?)\n/g, '$1'+ breakTag +'\n');
	}
	
	function replaceABPImage(img, idx){
		if (!$$('.abpHeaderImage'+idx)[0]){
			setTimeout(
				function (){
					replaceABPImage(img, idx)
				},
				500
			)
			return;
		}
		$$('.abpHeaderImage'+idx)[0].src = img;
	}
	
	function replaceABPImages(imgs){
		$$('.abpHeaderImage1')[0].src = imgs[0];
		$$('.abpHeaderImage2')[0].src = imgs[1];
		$$('.abpHeaderImage3')[0].src = imgs[2];
	}
	
	function setAlgemeenPositioning(widget){
		if (Prototype.Browser.IE){
			$(widget.instID+'mainNav').setStyle("left:6px");
			$(widget.instID+'_contentContainer').select('.shadow')[0].setStyle("left:20px;bottom:-49px;")
			
			if ($(widget.instID+'_contentContainer').select('.subnavigationContainer')[0]){
				$(widget.instID+'_contentContainer').select('.subnavigationContainer')[0].setStyle("margin-left:7px;");
				$(widget.instID+'_contentContainer').select('.navShadow').each(function(elem){elem.setStyle("left:26px;")});
			}
		}else{
			$(widget.instID+'mainNav').setStyle("left:6px");
			$(widget.instID+'_contentContainer').select('.shadow')[0].setStyle("left:21px")
			if ($(widget.instID+'_contentContainer').select('.subnavigationContainer')[0]){
				$(widget.instID+'_contentContainer').select('.subnavigationContainer')[0].setStyle("margin-left:6px;");
				$(widget.instID+'_contentContainer').select('.navShadow').each(function(elem){elem.setStyle("left:27px;")});
			}			
		}
	}
	
	function setWerkenPositioning(widget){
		if (Prototype.Browser.IE){
			$(widget.instID+'mainNav').setStyle("left:35px");
			$(widget.instID+'_contentContainer').select('.shadow')[0].setStyle("left:50px");
			if ($(widget.instID+'_contentContainer').select('.subnavigationContainer')[0]){
				$(widget.instID+'_contentContainer').select('.subnavigationContainer')[0].setStyle("margin-left:36px;");
				$(widget.instID+'_contentContainer').select('.navShadow').each(function(elem){elem.setStyle("left:27px;")});
			}							
		}else{
			$(widget.instID+'mainNav').setStyle("left:35px");
			$(widget.instID+'_contentContainer').select('.shadow')[0].setStyle("left:50px");
			if ($(widget.instID+'_contentContainer').select('.subnavigationContainer')[0]){
				$(widget.instID+'_contentContainer').select('.subnavigationContainer')[0].setStyle("margin-left:35px;");
				$(widget.instID+'_contentContainer').select('.navShadow').each(function(elem){elem.setStyle("left:27px;")});
			}
		}
	}
	
	function setTicketsPositioning(widget){
		if (Prototype.Browser.IE){
			$(widget.instID+'mainNav').setStyle("left:20px");
			$(widget.instID+'_contentContainer').select('.shadow')[0].setStyle("left:33px")
			if ($(widget.instID+'_contentContainer').select('.subnavigationContainer')[0]){
				$(widget.instID+'_contentContainer').select('.subnavigationContainer')[0].setStyle("margin-left:21px;");
				$(widget.instID+'_contentContainer').select('.navShadow').each(function(elem){elem.setStyle("left:26px;")});
			}
		}else{
			$(widget.instID+'mainNav').setStyle("left:20px");
			$(widget.instID+'_contentContainer').select('.shadow')[0].setStyle("left:35px")
			if ($(widget.instID+'_contentContainer').select('.subnavigationContainer')[0]){
				$(widget.instID+'_contentContainer').select('.subnavigationContainer')[0].setStyle("margin-left:20px;");
				$(widget.instID+'_contentContainer').select('.navShadow').each(function(elem){elem.setStyle("left:27px;")});
			}
		}
	}
	
	function setReizenPositioning(widget){
		if (Prototype.Browser.IE){
			$(widget.instID+'mainNav').setStyle("left:15px");
			$(widget.instID+'_contentContainer').select('.shadow')[0].setStyle("left:30px")
			if ($(widget.instID+'_contentContainer').select('.subnavigationContainer')[0]){
				$(widget.instID+'_contentContainer').select('.subnavigationContainer')[0].setStyle("margin-left:16px;");
				$(widget.instID+'_contentContainer').select('.navShadow').each(function(elem){elem.setStyle("left:27px;")});
			}
		}else{
			$(widget.instID+'mainNav').setStyle("left:15px");
			$(widget.instID+'_contentContainer').select('.shadow')[0].setStyle("left:30px")
			if ($(widget.instID+'_contentContainer').select('.subnavigationContainer')[0]){
				$(widget.instID+'_contentContainer').select('.subnavigationContainer')[0].setStyle("margin-left:15px;");
				$(widget.instID+'_contentContainer').select('.navShadow').each(function(elem){elem.setStyle("left:27px;")});
			}
		}
	}

	function moveABPMapSwitch(){
		if (!$('abpLogo')){
			setTimeout(moveABPMapSwitch, 400);
			return;
		}
		var parent = $('abpLogo').parentNode;
		$(parent).insert($('mapSwitch'));
		$('mapSwitch').addClassName('abpMapSwitch');
	}    		 

	function getSocialBookMarks(container, url, text){
		if (!text) text='';
		text = encodeURIComponent(text);
		url = encodeURIComponent(url);
		var sbmContainer = new Element('div', {className:'sbmContainer'});
		container.insert(sbmContainer);
		sbmContainer.insert(getSBMLink('http://www.google.com/bookmarks/mark?op=add&&bkmk=' +url + "&title=" + text, '/images/sbm/bookmark_google_bookmark.png', 'Save to Google Bookmark', 'Google Bookmarks'));
		sbmContainer.insert(getSBMLink('http://del.icio.us/post?url=' +url + "&title=" + text, '/images/sbm/bookmark_del_icio_us.png', 'Save to Delicious', 'del.icio.us'));
		sbmContainer.insert(getSBMLink('http://twitter.com/home?status=Currently reading ' +text + ' ' + url, '/images/sbm/bookmark_twitter.png', 'Share on Twitter', 'Twitter'));
		sbmContainer.insert(getSBMLink('http://www.facebook.com/sharer.php?u=' +url + '&t=' + text, '/images/sbm/bookmark_facebook.png', 'Share on Facebook', 'Facebook'));
		//sbmContainer.insert(getSBMLink('http://www.bloglines.com/sub//' +url, '/images/sbm/bookmark_bloglines.png', 'Share on BlogLines', 'BlogLines'));
		sbmContainer.insert(getSBMLink('http://digg.com/submit?phase=2&url=' +url, '/images/sbm/bookmark_digg.png', 'Share on Digg', 'Digg'));
		sbmContainer.insert(getSBMLink('http://www.stumbleupon.com/submit?url=' +url + "&title=" + text, '/images/sbm/bookmark_stumbleupon.png', 'Save to StumbleUpon', 'StumbleUpon'));
		sbmContainer.insert(getSBMLink('http://www.diigo.com/post?url=' +url + "&title=" + text, '/images/sbm/bookmark_diigo.png', 'Save to Diigo', 'Diigo'));
		sbmContainer.insert(getSBMLink('http://www.hyves.nl/profilemanage/add/tips/?name=Backpackers&text=' +text+ " " + url, '/images/sbm/bookmark_hyves.png', 'Share on Hyves', 'Hyves'));
		sbmContainer.insert(getSBMLink('http://technorati.com/faves?add=' + url,'/images/sbm/bookmark_technorati.png', 'Share on Technorati', 'Technorati'));
		sbmContainer.insert(getSBMLink('http://myweb2.search.yahoo.com/myresults/bookmarklet?t=' + text + '&d=&tag=&u=' + url,'/images/sbm/bookmark_yahoo.png', 'Save to Yahoo MyWeb', 'Yahoo MyWeb'));
		sbmContainer.insert(getSBMLink('http://www.newsgator.com/ngs/subscriber/subext.aspx?url=' + url,'/images/sbm/bookmark_newsgator.png', 'Save to Newsgator', 'Newsgator'));
		sbmContainer.insert(getSBMLink('http://www.furl.net/storeIt.jsp?u=' + url + '&keywords=&t=' + text ,'/images/sbm/bookmark_furl.png', 'Save to FURL', 'Newsgator'));
		sbmContainer.insert(getSBMLink('http://www.netscape.com/submit/?U=' + url + '&T=' + text ,'/images/sbm/bookmark_netscape.png', 'Save to Netscape', 'Netscape'));
		sbmContainer.insert(getSBMLink('http://www.google.com/reader/preview/*/feed/' + url ,'/images/sbm/bookmark_google_reader.png', 'Save to Google Reader', 'Google Reader'));
		//sbmContainer.insert(getSBMLink('http://de.lirio.us/rubric/post?uri=' + url,'/images/sbm/bookmark_de.lirio.us.png', 'Save to de.lirio.us', 'de.lirio.us'));
		sbmContainer.insert(getSBMLink('http://www.spurl.net/spurl.php?v=3&tags=&title=' + text + '&url=' + url ,'/images/sbm/bookmark_spurl.png', 'Save to spurl.net', 'spurl.net'));
		sbmContainer.insert(getSBMLink('http://www.newsvine.com/_wine/save?popoff=1&u=' + url + '&tags=&blurb=' + text ,'/images/sbm/bookmark_newsvine.png', 'Save to newsvine', 'newsvine'));
		sbmContainer.insert(getSBMLink('http://www.simpy.com/simpy/LinkAdd.do?href=' + url,'/images/sbm/bookmark_simpify.png', 'Save to SIMPIFY', 'SIMPIFY'));
		sbmContainer.insert(getSBMLink('http://linkarena.com/bookmarks/addlink/?url=' + url,'/images/sbm/bookmark_linkarena.png', 'Save to Linkarena', 'Linkarena'));
		sbmContainer.insert(getSBMLink('http://www.folkd.com/submit/' + url,'/images/sbm/bookmark_folkd.png', 'Save to folkd.com', 'folkd.com'));
		sbmContainer.insert(getSBMLink('http://reddit.com/submit?url=' + url + '&title=' + text,'/images/sbm/bookmark_reddit.png', 'Save to reddit', 'reddit'));
		sbmContainer.insert(getSBMLink('http://slashdot.org/bookmark.pl?url=' + url + '&title=' + text,'/images/sbm/bookmark_slashdot.png', 'Save to Slashdot', 'Slashdot'));
		sbmContainer.insert(getSBMLink('http://www.blinklist.com/index.php?Action=Blink/addblink.php&Description=&Tag=&Url=' + url + '&Title=' + text,'/images/sbm/bookmark_blinklist.png', 'Save to blinklist', 'blinklist'));
		sbmContainer.insert(getSBMLink('http://blogmarks.net/my/new.php?mini=1&simple=1&url=' + url + '&content=&public-tags=&title=' + text,'/images/sbm/bookmark_blogmarks.png', 'Save to blogmarks', 'blogmarks'));
		sbmContainer.insert(getSBMLink('http://www.blinkbits.com/bookmarklets/save.php?v=1&title=' + text + '&source_url=' + url + '&source_image_url=&rss_feed_url=&rss_feed_url=&rss2member=&body=','/images/sbm/bookmark_blinkbits.png', 'Save to blinkbits', 'blinkbits'));
		sbmContainer.insert(getSBMLink('http://ma.gnolia.com/bookmarklet/add?url=' + url + '&title=' + text + '&description=&tags=','/images/sbm/bookmark_magnolia.png', 'Save to ma.gnolia', 'ma.gnolia'));
		sbmContainer.insert(getSBMLink('http://smarking.com/editbookmark/?url=' + url + '&description=' + text + '&tags=','/images/sbm/bookmark_smarking.png', 'Save to smarking.com', 'smarking.com'));
		sbmContainer.insert(getSBMLink('http://www.netvouz.com/action/submitBookmark?url=' + url + '&description=&tags=&title=' + text + '&popup=yes','/images/sbm/bookmark_netvouz.png', 'Save to netvouz', 'netvouz'));
		sbmContainer.insert(getSBMLink('http://co.mments.com/track?url=' + url,'/images/sbm/bookmark_co.mments.png', 'Save to co.mments', 'co.mments'));
		sbmContainer.insert(getSBMLink('http://www.connotea.org/addpopup?continue=confirm&uri=' + url,'/images/sbm/bookmark_connotea.png', 'Save to connotea', 'connotea'));
		sbmContainer.insert(getSBMLink('http://www.mister-wong.de/add_url/' ,'/images/sbm/bookmark_mister_wong.png', 'Save to MISTER WONG', 'MISTER WONG'));
		sbmContainer.insert(getSBMLink('http://beta.oneview.de:80/quickadd/neu/addBookmark.jsf?URL=' + url + '&title=' + text,'/images/sbm/bookmark_oneview.png', 'Save to oneview', 'oneview')); 
		sbmContainer.insert(getSBMLink('http://yigg.de/neu?exturl=' + url + '','/images/sbm/bookmark_yigg.png', 'Save to yigg.de', 'yigg.de')); 
		sbmContainer.insert(getSBMLink('http://www.icio.de/add.php?url=' + url,'/images/sbm/bookmark_icio.png', 'Save to icio.de', 'icio.de')); 
		sbmContainer.insert(getSBMLink('http://www.webnews.de/einstellen?url=' + url + '&title=' + text,'/images/sbm/bookmark_webnews.png', 'Save to webnews', 'webnews')); 		
	}
	
	function getSBMLink(url, image, imgTitle, textTitle){
		if (!textTitle) textTitle ='';
		var container = new Element('div', {className:"sbmLinkContainer"});
		var img = new Element('img', {src:image, title:imgTitle, alt:imgTitle, className:"sbmImage"});
		var txt = new Element('div', {className:'sbmText'}).update(textTitle);
		var link = new Element("a", {href:url, target:"_blank",title:imgTitle, alt:imgTitle}).insert(img);
		link.insert(txt);
		container.insert(link);
		return container;
	}
	
	function checkLogin(elem){
		// disallowed chars:
		var ok = true;
		var username = $(elem).getValue();
		var disallowed = [' ', '@', ',', '.', '/', '\\'];
		var foundChar = '';
		disallowed.each(
			function(char){
				if (username.toString().indexOf(char) > -1){
					ok = false;
					foundChar = char;
				}
			}
		)
		if (!ok){
			alert("Het karakter '" +foundChar+ "' is niet toegestaan");
			elem.value = username.replace(foundChar, "");
			return false;
		}
		return true;
	}
	
	getHighestZIndex = function(){
		var z = 0;
		$$("*").each(
			function(elem){
				if (parseInt(elem.style.zIndex) > z){
					z = parseInt(elem.style.zIndex);
				}
			})
		return parseInt(z);
	}
	
	getLowestItem = function(){
		gLowest = 0;
		$A($('demoContainer').childNodes).each(
			function(elem){
				var top = parseInt(elem.offsetTop);
				var height = parseInt($(elem).getHeight());
				var bottom = top + height;
				if (bottom > gLowest) gLowest = bottom;
			}
		)
		var wHeight = windowSize();
		wHeight = wHeight[1];
		if ( wHeight > gLowest) return wHeight;  
		return gLowest;
	}
	
	windowSize = function(){
		var myWidth = 0; 
		var myHeight = 0;
		
		if( typeof( window.innerWidth ) == 'number' ) {
			  //Non-IE
			myWidth = window.innerWidth;
			myHeight = window.innerHeight;
		} else if( document.documentElement && ( document.documentElement.clientWidth || document.documentElement.clientHeight ) ) {
			//IE 6+ in 'standards compliant mode'
			myWidth = document.documentElement.clientWidth;
			myHeight = document.documentElement.clientHeight;
		} else if( document.body && ( document.body.clientWidth || document.body.clientHeight ) ) {
			//IE 4 compatible
			myWidth = document.body.clientWidth;
			myHeight = document.body.clientHeight;
		}
		myHeight = parseInt(myHeight);
		myWidth = parseInt(myWidth);
		return [myWidth, myHeight];
	}
	function calendarDropDown(id){
		var html = '<div class="calSelect"><select name="day" id="' + id + '_day">';
		html+='<option value="1">1</option>';
		html+='<option value="2">2</option>';
		html+='<option value="3">3</option>';
		html+='<option value="4">4</option>';
		html+='<option value="5">5</option>';
		html+='	<option value="6">6</option>';
		html+='<option value="7">7</option>';
		html+='<option value="8">8</option>';
		html+='<option value="9">9</option>';
		html+='<option value="10">10</option>';
		html+='<option value="11">11</option>';
		html+='<option value="12">12</option>';
		html+='	<option value="13">13</option>';
		html+='<option value="14">14</option>';
		html+='<option value="15">15</option>';
		html+='<option value="16">16</option>';
		html+='<option value="17">17</option>';
		html+='<option value="18">18</option>';
		html+='<option value="19">19</option>';
		html+='	<option value="20">20</option>';
		html+='<option value="21">21</option>';
		html+='<option value="22">22</option>';
		html+='<option value="23">23</option>';
		html+='<option value="24">24</option>';
		html+='<option value="25">25</option>';
		html+='<option value="26">26</option>';
		html+='<option value="27">27</option>';
		html+='<option value="28">28</option>';
		html+='<option value="29">29</option>';
		html+='<option value="30">30</option>';
		html+='<option value="31">31</option>';
		html+='</select>';
		html+='<select name="month" id="' + id + '_month">';
		html+='<option value="1">January</option>';
		html+='<option value="2">February</option>';
		html+='<option value="3">March</option>';
		html+='<option value="4">April</option>';
		html+='<option value="5">May</option>';
		html+='<option value="6">June</option>';
		html+='	<option value="7">July</option>';
		html+='<option value="8">August</option>';
		html+='<option value="9">September</option>';
		html+='<option value="10">October</option>';
		html+='<option value="11">November</option>';
		html+='<option value="12">December</option>';
		html+='</select>';
		html+='<select name="year" id="' + id + '_year">';
		html+='<option value="2008">2008</option>';
		html+='	<option value="2009">2009</option>';
		html+='<option value="2010">2010</option>';
		html+='<option value="2011">2011</option>';
		html+='<option value="2012">2012</option>';
		html+='<option value="2013">2013</option>';
		html+='<option value="2014">2014</option>';
		html+='</select></div>';		
		return html;
	}
	

	function calendarDropDownMonthYear(id){
		var html = '<div class="calSelect">';
		html+='<select name="month" id="' + id + '_month">';
		html+='<option value="1">January</option>';
		html+='<option value="2">February</option>';
		html+='<option value="3">March</option>';
		html+='<option value="4">April</option>';
		html+='<option value="5">May</option>';
		html+='<option value="6">June</option>';
		html+='	<option value="7">July</option>';
		html+='<option value="8">August</option>';
		html+='<option value="9">September</option>';
		html+='<option value="10">October</option>';
		html+='<option value="11">November</option>';
		html+='<option value="12">December</option>';
		html+='</select>';
		html+='<select name="year" id="' + id + '_year">';
		html+='<option value="2008">2008</option>';
		html+='	<option value="2009">2009</option>';
		html+='<option value="2010">2010</option>';
		html+='<option value="2011">2011</option>';
		html+='<option value="2012">2012</option>';
		html+='<option value="2013">2013</option>';
		html+='<option value="2014">2014</option>';
		html+='</select></div>';		
		return html;
	}
	
		
	function openAlbumWidget(){
		alert('postStoryInstance ' + postStoryInstance);
		postStoryInstance.openAlbumWidget();
	}

	
	var postStory = Class.create({
		initialize: function(container, userID){
			this.instID = 'postStory.' + parseInt(Math.random()*1000000);
			this.storyID = 0;
			this.coordsX = 0;
			this.coordsY = 0;
			this.zoom = 0;
			this.userID = userID;
			this.changed = false;
			this.container = container;
			this.myWidget = container.parentNode.widget;
			this.myWidget.options.closeEvent = this.canClose.bind(this);
			this.uniqueID = parseInt(container.getAttribute('id'));
			// assign event:
			$(this.uniqueID + "_storySubmit").observe('click', this.post.bindAsEventListener(this));
			$(this.uniqueID + '_addAlbumLink').observe('click', (function(){this.openAlbumWidget();}).bind(this));
			$(this.uniqueID + '_addVideoLink').observe('click', this.openVideoAlbumWidget.bind(this));
			$(this.uniqueID + '_locationName').observe('click', this.openGMapsPositioner.bind(this));
			
			// set input events;
			$(this.uniqueID + '_title').observe('change', this.setChanged.bind(this));
			$(this.uniqueID + '_tags').observe('change', this.setChanged.bind(this));
			$(this.uniqueID + '_bbCode').observe('change', this.setChanged.bind(this));
			
			// handle zIndex
			this.myWidget.toFG();
			gShouldFocus = false;

		},
		
		post : function(){
			// check values:
			var ok = true;
			var err = '';
			if ($(this.uniqueID + "_title").getValue() =='' && $(this.uniqueID + "_title").getValue().replace(' ', '') == ''){
				ok = false;
				err += "Het veld titel is verplicht.<br/>";
				$(this.uniqueID + "_title").setStyle({border:'1px red solid'})
			}else{
				$(this.uniqueID + "_title").setStyle({border:'1px black solid'})
			}
			if ($(this.uniqueID + "_bbCode").getValue() =='' && $(this.uniqueID + "_bbCode").getValue().replace(' ', '') == ''){
				ok = false;
				err += "Het veld 'wat heb je meegemaakt' is verplicht.<br/>";
				$(this.uniqueID + "_bbCode").setStyle({border:'1px red solid'})
			}else{
				$(this.uniqueID + "_bbCode").setStyle({border:'1px black solid'})
			}
			if (!ok){
				$(this.uniqueID + '_storyErrors').update(err);
				new Effect.Appear($(this.uniqueID + '_storyErrors'), {duration:'0.2'});
				return false;
			}else{
				new Effect.Fade($(this.uniqueID + '_storyErrors'), {duration:'0.2'});
				//setTimeout(function(){$(this.uniqueID + '_storyErrors').update('')}, 170);
				this.doPost();
				return true;
			}
		},
		
		canClose : function(){
			if (this.changed){
				if (this.post()) {
					gShouldFocus = true;
					return true;
				}
				return false;
			} 
			gShouldFocus = true;
			return true;
		},
		
		setChanged : function(e){
			if (e.element().getValue() != ''){
				this.changed = true;
			}else{
				if (
						($(this.uniqueID + '_title').getValue() == '') 
					&& 
						($(this.uniqueID + '_tags').getValue() == '') 
					&&
						($(this.uniqueID + '_bbCode').getValue() == '')
					){
						this.changed = false;
					}
			}
		},
		
		doPost:function(){
			var remote = new rpc('story', this.handlePost.bind(this));
			remote.debug=true;
			if (this.storyID > 0){
				remote.call('saveStory', 
					{
						title : this.safeValue($(this.uniqueID + "_title").getValue()),
						bbCode : this.safeValue($(this.uniqueID + "_bbCode").getValue()),
						tags : this.safeValue($(this.uniqueID + "_tags").getValue()),
						storyID : this.storyID,
						coordsX : this.coordsX,
						coordsY : this.coordsY,
						zoom : this.zoom,
						publish : 1
					}
				);
			}else{
				remote.call('saveStory', 
						{
							title : this.safeValue($(this.uniqueID + "_title").getValue()),
							bbCode : this.safeValue($(this.uniqueID + "_bbCode").getValue()),
							tags : this.safeValue($(this.uniqueID + "_tags").getValue()),
							coordsX : this.coordsX,
							coordsY : this.coordsY,
							zoom : this.zoom,
							publish : 1
						}
					);
			}
		},
		
		safeValue : function(value){
			return encodeURIComponent(value.stripTags());
		},
		
		virtualPost : function(callBack){
			// only creates a record ID for a story, without publishing it;
			if (this.storyID) {
				callBack({storyID:this.storyID});
				return;
			}
			var func = (function(req){
				this.setStoryID(req);
				callBack(req);
			}).bind(this);
			
			var remote = new rpc('story', func);
//			remote.debug=true;
			remote.call('saveStory', 
					{
						title : this.safeValue($(this.uniqueID + "_title").getValue()),
						bbCode : this.safeValue($(this.uniqueID + "_bbCode").getValue()),
						tags : this.safeValue($(this.uniqueID + "_tags").getValue()),
						coordsX : this.coordsX,
						coordsY : this.coordsY,
						zoom : this.zoom,
						publish : 0
					}
			);
			
		},
		
		setStoryID : function(req){
			this.storyID = req.responseJSON.storyID;
			var userID = req.responseJSON.userID;
			this.storyObj = {
				storyID : this.storyID,
				userID : userID
			}
			
		},
		
		handleDelete : function(req){
			if (req.responseJSON.message == 'true'){
				//$(this.uniqueID + '_storyForm').update('Je reisverhaal is verwijderd!');
				this.myWidget.closeMe();
				control.getByInstanceID('homepageWidget').each(
					function(widget){
						widget.getStories();
					}
				)
				alert("Je reisverhaal is verwijderd!");
			}else{
				alert("Er is iets mis gegaan bij het verwijderen van je reisverslag, probeer het nog een keer, en als dat niet lukt neem dan contact op met de webmaster");
			}
		},
		
		handlePost : function(req){
			this.changed = false;
			if (req.responseJSON.message == 'true'){
				// reload profielfoto-widget:
				var profielFoto = control.get('profielFoto');
				if (profielFoto){
					profielFoto.closeMe();
				}
				control.getByInstanceID('homepageWidget').each(
					function(widget){
						widget.getStories();
					}
				)
//				if ($(this.uniqueID + '_storyForm')) $(this.uniqueID + '_storyForm').update('Je reisverhaal is opgeslagen!');
				this.myWidget.closeMe();
				alert("Je reisverhaal is opgeslagen!");
			}else{
				alert("Er is iets mis gegaan bij het opslaan van je reisverslag, probeer het nog een keer, en als dat niet lukt neem dan contact op met de webmaster");
			}
		},
		
		openVideoAlbumWidget : function(){
			if (!this.storyID){
				this.virtualPost(this._openVideoAlbumWidget.bind(this));
				return;
			}else{
				this._openVideoAlbumWidget();
			}
		},
		
		
		openAlbumWidget : function(){
			if (!this.storyID){
				this.virtualPost(this._openAlbumWidget.bind(this));
				return;
			}
			this._openAlbumWidget();
		},
		
		_openVideoAlbumWidget : function(){
			this.albumWidget = new borderedWidget(
				{
						position:{left:100, top:25}, 
						size:{width:300, height:400}, 
						useIFrame:false, 
						containerClassName:'whiteWidget',
						canHide : true
				}
			) 
			
			window.parent.control.add( this.albumWidget);
			window.parent.control.render();
			this.albumWidget.contentContainer.insert('<h1>Video\'s</h1>');
			this.jsAlbum = new jsVideoAlbum(this.albumWidget.contentContainer, this.storyID);
		},
		
		_openAlbumWidget : function(){
			this.albumWidget = new shadowedWidget(
				{
						position:{left:100, top:25}, 
						size:{width:300, height:410}, 
						useIFrame:false, 
						containerClassName:'whiteWidget',
						canHide : true
				}
			) 
			window.parent.control.add( this.albumWidget);
			window.parent.control.render();
			
			this.albumWidget.contentContainer.insert(new Element('img', {src:'/include/smallTitle.php?text=FOTO-ALBUM'}));
			this.albumWidget.contentContainer.insert('<hr class="line">');
			this.jsAlbum = new jsAlbum(this.albumWidget.contentContainer, this.storyID, this.storyObj);
			setTimeout(
					(function(){
						this.albumWidget.container.setStyle('overflow-x:hidden;overflow-y:scroll;');
					}).bind(this), 500);
		},

		openGMapsPositioner : function(){
			gmc.view.mapSwitch.close();
			gmc.view.mapSwitch = new gm_ReisVerhaalMapSwitch(gmc, this.setSpot.bind(this));
			gmc.view.mapSwitch.hideTrans();
		},
		
		setSpot : function(overlay, latlng){
			var myHtml = "Deze plaats heb je gekozen!)";
			gmc.map.openInfoWindow(latlng, myHtml);
			this.coordsX = latlng.x;
			this.coordsY = latlng.y;
			this.zoom = gmc.map.getZoom();
//			gmc.view.mapSwitch.hideMap();
//			gmc.view.mapSwitch.close();
//			gmc.view.mapSwitch = new gm_MapSwitch(gmc);
		}
		
		
	})
	

	var editStory = Class.create(postStory, {
		initialize : function($super, storyObj){
			this.instID = 'editStory.' + parseInt(Math.random()*1000000);
			this.storyObj = storyObj;
			this.coordsX = 0;
			this.coordsY = 0;
			this.zoom = 0;
			this._init(); // there could be a small timeout on loading the container, so check and recheck until it's found
		},
		
		_init : function(){
			if (!$('editStory')){
				setTimeout(this._init.bind(this), 200);
				return;
			}
			var container = reisverhaal_form($('editStory'));
			this.myWidget = container.parentNode.widget;
			this.myWidget.options.closeEvent = this.canClose.bind(this);
			this.uniqueID = parseInt(container.getAttribute('id'));

//			var div = new Element('div', {className:'formRow'}).insert(new Element('label', {className:"rowTitle"}).update(" "));
//			div.insert(getFormBlock("", );
			//var del= new Element('a', {className:'removeStory', id:this.uniqueID+'_storySubmit'}).update('Verwijderen');
			var del = new Element('input', {id:this.uniqueID+'_storyDelete', type:'button', className:'removeStory', value:'verwijderen'});
			container.insert(del);
			del.observe('click', this.removeStory.bindAsEventListener(this));
			
			$(this.uniqueID + "_storySubmit").observe('click', this.post.bindAsEventListener(this));
			$(this.uniqueID + '_addAlbumLink').observe('click', this.openAlbumWidget.bind(this));
			$(this.uniqueID + '_addVideoLink').observe('click', this.openVideoAlbumWidget.bind(this));
			$(this.uniqueID + '_locationName').observe('click', this.openGMapsPositioner.bind(this));
			
			// set input events;
			$(this.uniqueID + '_title').observe('change', this.setChanged.bind(this));
			$(this.uniqueID + '_tags').observe('change', this.setChanged.bind(this));
			$(this.uniqueID + '_bbCode').observe('change', this.setChanged.bind(this));
			
			this.storyID = this.storyObj.id;
			this.setValues();

			// handle zIndex
			this.myWidget.toFG();
			gShouldFocus = false;
		},
		
		canClose : function(){
			if (this.post()){
				gShouldFocus = true;
				return true;
			}
			return false;
		},
		
		removeStory : function(){
			if (confirm("Weet je zeker dat je dit reisverhaal wilt verwijderen?")){
				var remote = new rpc('story', this.handleDelete.bind(this));
				remote.debug=true;
				remote.call('removeStory', {storyID : this.storyID});					
			}
			
		},
		
		setValues : function(){
			var bbCode = this.storyObj.bbCode;
			bbCode = bbCode.toString().replace(/<br\/>/g, "\n"); 
			if (this.storyObj.title) $(this.uniqueID + '_title').setValue(this.storyObj.title);
//			if (this.storyObj.location) $(this.uniqueID + '_locationName').setValue(this.storyObj.location);
			if (this.storyObj.bbCode) $(this.uniqueID + '_bbCode').setValue(bbCode);
			if (this.storyObj.tags) $(this.uniqueID + '_tags').setValue(this.storyObj.tags);
			if (this.storyObj.coordsX) this.coordsX = this.storyObj.coordsX;
			if (this.storyObj.coordsY) this.coordsY = this.storyObj.coordsY;
			if (this.storyObj.zoomLevel) this.zoom = this.storyObj.zoomLevel;
		},
		
		setChanged : function(e){
			var elem = e.element();
			var internalToken = elem.id.toString().replace(this.uniqueID + "_", '');
			var internalValue = this.storyObj[internalToken];
			if (internalValue != elem.getValue){
				this.changed = true;
				
			}
		},		
		
		doPost : function(){
			var remote = new rpc('story', this.handlePost.bind(this));
//			remote.debug=true;
			remote.call('saveStory', 
					{
						title : this.safeValue($(this.uniqueID + "_title").getValue()),
						bbCode : this.safeValue($(this.uniqueID + "_bbCode").getValue()),
						tags : this.safeValue($(this.uniqueID + "_tags").getValue()),
						coordsX : this.coordsX,
						coordsY : this.coordsY,
						zoom : this.zoom,
						storyID : this.storyID,
						publish : 1
					}
				);			
		},
		
		virtualPost : function(callBack){
			callBack({storyID:this.storyID});
			return;
			
		}
		
	})
	

	var gridStory = Class.create({
		initialize: function(container){
			this.instID = 'gridStory.' + parseInt(Math.random()*1000000);
			this.container = container;
			this.getUserStories();
		},
		
		getUserStories : function(){
			var remote = new rpc('story', this.draw.bind(this));
//			remote.debug=true;
			remote.call('getUserStories', {});			
		},
		
		draw : function(req){
			var storiesContainer = new Element('ul');
			this.container.insert(storiesContainer);
			var stories = $A(req.responseJSON);
			stories.each(
				(function(story){
					var li = new Element('li')
					storiesContainer.insert(li);
					
					var link =  new Element('a', {id:story.id+"_storyLink", className:'storyLink'}).update(this.getTitle(story))
					link.story = story; // attach complete story object; you never know;)
					li.insert(link);
					link.observe('click', this.openStory.bindAsEventListener(this));
				}).bind(this)
			)
		},

		openStory : function(e){
			var elem = e.element();
			var story = elem.story;
			var func = (function(){
				this.editting = new editStory(story);
			}).bind(this)
			
			window.parent.control.getContentWidget(11, '',  '', func);
		},
		
		getTitle : function(story){
			var dateValue = story.dtAdded.split(' ')[0];
			dateValue = dateValue.split('-');
			dateValue = dateValue[2] + '-' + dateValue[1] + '-'+dateValue[0];
			return story.title + ' [' + dateValue + "]";
		}
		
	})
	
	
	var gm_AbstractMapSwitch = Class.create({ 
		initialize:function(controller){
			$('mapTrans').observe('click', this.hideFunc);
			$('mapSwitch').setStyle('height:70px;');
			$('mapSwitch').update("<span id=\"" + this.instID + "message\">" + this.defaultText + "</span>");

			var buttonContainer = new Element('div', {className:'mapSwitchButtonContainer'});
			$('mapSwitch').insert(buttonContainer);
//			this.selectButton = new Element('button').update("Bevestig");
//			buttonContainer.insert(this.selectButton);
//			this.selectButton.observe('click', this.selectSpot.bind(this));
			
			this.cancelButton = new Element('button', {className:''}).update("Annuleren");
			buttonContainer.insert(this.cancelButton);
			this.cancelButton.hide();
			this.cancelButton.observe('click', this.cancel.bind(this));
			
			var link = new Element('button').update("Terug");
			buttonContainer.insert(link);
			link.observe('click', this.hideMap.bind(this));
			
		},

		hideTrans : function(e){
			control.hideAll();
			this.zoomMapControls = new GLargeMapControl();
			this.controller.map.addControl(this.zoomMapControls);
			this.controller.map.enableScrollWheelZoom();
			$('mapSwitch').show();
			new Effect.Fade($('mapTrans'), {duration:'0.2'});
		},
	
		hideMap : function(){
			this.controller.map.removeControl(this.zoomMapControls );
			$('mapTrans').show();
			$('mapSwitch').hide();
			window.control.showAll();		
			this.close();
			gmc.view.mapSwitch = new gm_MapSwitch(gmc);			
			GEvent.removeListener(this.mapsEvent);
		},

		selectSpot : function(){
//			this.cancelButton.show();
//			this.selectButton.hide();
//			$(this.instID + "message").update("Klik nu een locatie aan op de kaart, deze locatie wordt opgeslagen.");
			this.mapsFunc = (function(overlay, latlng){this.setSpot(overlay, latlng)}).bind(this)
			this.mapsEvent = GEvent.addListener(this.controller.map,"dblclick", this.mapsFunc);
		},
		
		setSpot : function(overlay, latlng) {
			this.callBack(overlay, latlng);
			this.hideMap();
		},
		
		cancel : function(){
			this.selectButton.show();
			this.cancelButton.hide();
			$(this.instID + "message").update(this.defaultText);
		},
		
		close:function(){
			$('mapTrans').stopObserving('click', this.hideFunc);
			$('mapSwitch').stopObserving('click', this.switchFunc);
			$('mapSwitch').update("");
		},
		
		getXHair : function(){
			//return '<div id="xhair"><img src="/images/crosshair_left.png" class="xhairleft"/><div class="xhair"><div class="top"><img width="35" src="/images/xhair/top_left.png"/><img width="58" src="/images/xhair/top_middle.png"/><img width="32" src="/images/xhair/top_right.png"/></div><div class="middle"><img width="35" src="/images/xhair/middle_left.png"/><div class="empty">&nbsp;</div><img width="32" src="/images/xhair/middle_right.png"/></div><div class="bottom"><img width="35" src="/images/xhair/bottom_left.png"/><img width="58" src="/images/xhair/bottom_middle.png"/><img width="32" src="/images/xhair/bottom_right.png"/></div></div></div>';			
			return '<img src="/images/crosshair.png" id="xhair"/>';
		}
		

	})	
	var gm_MapSwitch = Class.create(gm_AbstractMapSwitch, { 
		initialize:function(controller){
			this.instID = 'gm_MapSwitch.' + parseInt(Math.random()*1000000);
			// needs an internal reference to hideTrans and hideMap because of stopObserving in this.close::
			this.controller = controller;
			this.hideFunc = (function(){this.hideTrans()}).bindAsEventListener(this);
			this.switchFunc = (function(){this.hideMap()}).bindAsEventListener(this);
			$('mapTrans').observe('click', this.hideFunc);
			$('mapSwitch').observe('click', this.switchFunc);
			$('mapSwitch').update("Terug");
			$('mapSwitch').currHeight = $('mapSwitch').getHeight();
			$('mapSwitch').setStyle('height:40px;');
		},

		hideMap : function(){
			this.controller.map.removeControl(this.zoomMapControls );
			$('mapTrans').show();
			$('mapSwitch').hide();
			window.control.showAll();		
			this.controller.map.disableScrollWheelZoom();
		}
		
	})
		
	var gm_PositieMapSwitch = Class.create(gm_AbstractMapSwitch,{ 
		initialize:function($super, controller, callBack){
			this.instID = 'gm_PositieMapSwitch.' + parseInt(Math.random()*1000000);
			// needs an internal reference to hideTrans and hideMap because of stopObserving in this.close::
			this.hideFunc = (function(){this.hideTrans()}).bindAsEventListener(this);
			this.controller = controller;
			this.callBack = callBack;
			this.defaultText = "";
			$super(controller);
		},
		
		hideTrans : function(e){
			control.hideAll();
			if (Prototype.Browser.IE){
				var position = new GControlPosition('', new GSize(483,360));	
			}else{
				var position = new GControlPosition('', new GSize(478,360));
			}
			this.controller.map.enableScrollWheelZoom();
			
			this.zoomMapControls = new GLargeMapControl();
			this.controller.map.addControl(this.zoomMapControls, position );
			$('mapSwitch').show();
			new Effect.Fade($('mapTrans'), {duration:'0.2'});
			$('map').insert(this.getXHair());
			setTimeout(function(){
				$$('.gmnoprint').each(function(elem){elem.setStyle('z-index:100;')})
			}, 500);
			this.selectSpot();
		},

		hideMap : function(){
			this.controller.map.removeControl(this.zoomMapControls );
			$('mapTrans').show();
			$('mapSwitch').hide();
			$('xhair').hide();
			window.control.showAll();		
			this.close();
			gmc.view.mapSwitch = new gm_MapSwitch(gmc);			
			GEvent.removeListener(this.mapsEvent);
			this.controller.map.disableScrollWheelZoom();
		},
		
		cancel:function($super){
			$super();
			$('xhair').hide();
		}
	})
		
	var gm_ReisVerhaalMapSwitch = Class.create(gm_AbstractMapSwitch,{ 
		initialize:function($super, controller, callBack){
			this.instID = 'gm_ReisVerhaalMapSwitch.' + parseInt(Math.random()*1000000);
			// needs an internal reference to hideTrans and hideMap because of stopObserving in this.close::
			this.hideFunc = (function(){this.hideTrans()}).bindAsEventListener(this);
			this.controller = controller;
			this.callBack = callBack;
			this.defaultText = "";
			$super(controller);

		},
		
		hideTrans : function(e){
			control.hideAll();
			
			if (Prototype.Browser.IE){
				var position = new GControlPosition('', new GSize(483,360));	
			}else{
				var position = new GControlPosition('', new GSize(478,360));
			}
			this.controller.map.enableScrollWheelZoom();
			
			this.zoomMapControls = new GLargeMapControl();
			this.controller.map.addControl(this.zoomMapControls, position );
			$('mapSwitch').show();
			new Effect.Fade($('mapTrans'), {duration:'0.2'});
			$('map').insert(this.getXHair());
			setTimeout(function(){
				$$('.gmnoprint').each(function(elem){elem.setStyle('z-index:100;')})
			}, 500);
			this.selectSpot();
		},

		hideMap : function(){
			this.controller.map.removeControl(this.zoomMapControls );
			$('mapTrans').show();
			$('mapSwitch').hide();
			$('xhair').hide();
			window.control.showAll();		
			this.close();
			gmc.view.mapSwitch = new gm_MapSwitch(gmc);			
			GEvent.removeListener(this.mapsEvent);
			this.controller.map.disableScrollWheelZoom();
		},
		
		cancel:function($super){
			$super();
			$('xhair').hide();
		}
	})
		
	var gm_ReisVerhaalFotoMapSwitch = Class.create(gm_AbstractMapSwitch,{ 
		initialize:function($super, controller, callBack){
			this.instID = 'gm_ReisVerhaalMapSwitch.' + parseInt(Math.random()*1000000);
			// needs an internal reference to hideTrans and hideMap because of stopObserving in this.close::
			this.hideFunc = (function(){this.hideTrans()}).bindAsEventListener(this);
			this.controller = controller;
			this.callBack = callBack;
			this.defaultText = "";
			$super(controller);
		},
		hideTrans : function(e){
			control.hideAll();
			
			if (Prototype.Browser.IE){
				var position = new GControlPosition('', new GSize(483,360));	
			}else{
				var position = new GControlPosition('', new GSize(478,360));
			}
			this.zoomMapControls = new GLargeMapControl();
			this.controller.map.addControl(this.zoomMapControls, position );
			this.controller.map.enableScrollWheelZoom();
			$('mapSwitch').show();
			new Effect.Fade($('mapTrans'), {duration:'0.2'});
			$('map').insert(this.getXHair());
			setTimeout(function(){
				$$('.gmnoprint').each(function(elem){elem.setStyle('z-index:100;')})
			}, 500);
			this.selectSpot();
		},

		hideMap : function(){
			this.controller.map.removeControl(this.zoomMapControls );
			$('mapTrans').show();
			$('mapSwitch').hide();
			$('xhair').hide();
			window.control.showAll();		
			this.close();
			gmc.view.mapSwitch = new gm_MapSwitch(gmc);			
			GEvent.removeListener(this.mapsEvent);
			this.controller.map.disableScrollWheelZoom();
		},
		
		cancel:function($super){
			$super();
			$('xhair').hide();
		}


	})
	
	var gm_controller = Class.create({
		initialize:function(mapContainer){
			this.instID = 'gm_controller.' + parseInt(Math.random()*1000000);
			this.mapContainer = mapContainer;
			if (Prototype.Browser.IE){
				var bodyWidth = ($(document.body).getWidth() -300 );
				$('demoContainer').setStyle({width:'auto'});
				$('demoContainer').setStyle({zIndex:10})
				if (bodyWidth > 1000){
					$('demoContainer').setStyle({position:'absolute', left: parseInt(bodyWidth/4) + 'px', top:'0px', zIndex:10})
				}
			}else{
				$('demoContainer').relativize();
			}

			if (GBrowserIsCompatible()) {
				this.map = new GMap2(this.mapContainer);
				//this.map.enableScrollWheelZoom();
				this.map.setMapType(G_HYBRID_MAP);
//				this.map.setMapType(G_SATELLITE_MAP);
			}else{
				alert('Your browser is not capable of rendering the Google Maps application, please upgrade to the latest version of your browser or get a real browser like Firefox (www.getfirefox.com)');
				return;
			}
			
			// resize mapcontainer;
//			this.resizeMap();
//			window.onresize = this.resizeMap.bind(this);
		},
		
		renderView : function(viewObj){
			this.view = viewObj;
			this.view.render();
		},
		
		resizeMap : function(){
			if (parseInt(this.mapContainer.getHeight()) < getLowestItem()){
				this.mapContainer.setStyle('height:' + getLowestItem() + 'px');
				$('mapTrans').setStyle('height:' + getLowestItem() + 'px');
			}	
		}
	
		
	})	/**
	 * Google Maps Abstract View; Base-class for googlemaps-views
	 * Contains basic methods for other googlemaps-views
	 */

	var gm_AbstractView = Class.create({
		
		initialize:function(controller){
			this.instID = 'gm_AbstractView.' + parseInt(Math.random()*1000000);
			this.controller = controller;
			this.myCommand = '';
			this.markers = [];
			if (!$('mapSwitch')){
				var mapSwitch = new Element('div', {className:"mapSwitch", id:"mapSwitch", style:"display:none;"});
				$(document.body).insert(mapSwitch);
			}
		},
		
		render:function(){
			// defaults to full view of oz:
			this.controller.map.setCenter(new GLatLng(-25.274398,133.775136), 2);
			this.mapSwitch = new gm_MapSwitch(this.controller);
			this.markerManager = new MarkerManager(this.controller.map, { trackMarkers: false });
			this.loadMarkers();
		},

		loadMarkers : function(){
			if (this.markerManager){
				var remote = new rpc(this.myCommand, this.handleReq.bind(this));
				remote.debug = true;
				remote.call('getMarkers', {all:1});
			}
		},
		
		handleReq : function(req){
			this.markers = [];
			this.users = req.responseJSON.users;
			this.stories = req.responseJSON.stories;
			this.images = req.responseJSON.images;
			this.videos = req.responseJSON.videos;
			if (this.users){
				this.users.each(
					(function(userObj){
						var tmp = this.createUserMarker(userObj);
						if (tmp) this.markers.push(tmp);
					}).bind(this)
				);
			}
			if (this.stories){
				this.stories.each(
					(function(storyObj){
						if (storyObj.bbCode.toString().length > 40){
							var tmp = this.createStoryMarker(storyObj);
							if (tmp) this.markers.push(tmp);
						}
					}).bind(this)
				);
			}
			if (this.images){
				this.images.each(
					(function(imgObj){
						var tmp = this.createImageMarker(imgObj);
						if (tmp) this.markers.push(tmp);
					}).bind(this)
				);
			}
			if (this.videos){
				this.videos.each(
					(function(imgObj){
						var tmp = this.createVideoMarker(imgObj);
						if (tmp) this.markers.push(tmp);
					}).bind(this)
				);
			}
			if (this.markers.length > 0) {
				this.markerManager.addMarkers(this.markers, 1);
				this.markerManager.refresh();
			}else if (window.console) {
				console.log("No markers found!", req.responseJSON);
			}
		},

		createStoryMarker : function(obj){
			if (obj.coordsX == 0 || obj.coordsY == 0 ) return false;
			var user = this.users.find(
				function(userObj){
					if (userObj.userID == obj.userID) {
						return true;
					}
				}
			)
			if (!user) user  = {first_name:'', last_name:''}
			var lg = new GLatLng(obj.coordsY, obj.coordsX);
			var marker = new GMarker(lg, 
					{
						title: obj.title + "(" + user.first_name + " " + user.last_name + ")",
						icon:this.createGIcon("/images/text.png", 12, 17, true), 
						draggable:false
					});
			GEvent.addListener(marker, 'click', (function() { this.openStoryMarker(marker, arguments[0])}).bind(this) );
			marker.srcObj = obj;
			return marker;
		},		
		
		getFirstImageFromStory : function(storyObj){
			var images = this.images.findAll(
				function(imgObj){
					if (imgObj.storyID == storyObj.storyID) return storyObj;
				}
			)
			if (images && images.length > 1){
				images = images.sort(this.sortById.bind(this));
				return images[0];
			}
		},
		
		sortById : function(a,b){
			return b.imgID - a.imgID;
		},
		
		getOwnerName : function(storyObj){
			var user = this.users.find(
				function(user){
					if (user.userID == storyObj.userID) return user;
				}
			)
			if (user) return user.first_name + ' ' + user.last_name;
			return '';
		},
		
		openStoryMarker : function(marker, latlng){
			// check for image:
			var firstImg = this.getFirstImageFromStory(marker.srcObj);
			var html ='<div class="googleBalloon">';
			if (firstImg) html += '<img src="/upload/userimages/100/' + firstImg.imgID + '.jpg" class="googleBaloonImage"/>';
			html += '<span class="googleBaloonOwner">' + this.getOwnerName(marker.srcObj) + '</span>';
			html += '<span class="googleBaloonTitle">' + marker.srcObj.title.substring(0,12) + '</span>';
			html += '<span class="googleBaloonIntro">'  + marker.srcObj.bbCode.substring(0,56) + '...</span>';
//			html += '<a class="googleBaloonLink" id="' + marker.srcObj.storyID + '_markerLink">[meer]</a>';
			html += '<a class="googleBaloonLink" href="/userHome.php?rand=' + parseInt(Math.random()*1000000) + '&userID=' + marker.srcObj.userID+ '#story='+marker.srcObj.storyID+'">[meer]</a>';
			html += '</div>';
			gmc.map.openInfoWindow(latlng, html);
			//this._openStoryMarker(marker);// set private function with timer
		},
		
		_openStoryMarker : function(marker,callBack){
			if (!$(marker.srcObj.storyID + '_markerLink')){
				setTimeout((function(){ this._openStoryMarker(marker,callBack) }).bind(this), 200);
				return;
			}
			if (!callBack) callBack = function(){};
			$(marker.srcObj.storyID + '_markerLink').observe('click', (function(e){this.openStory(e, callBack)}).bind(this) )
			$(marker.srcObj.storyID + '_markerLink').marker = marker;
		},
		
		openStory : function(e, callBack){
			var storyID = parseInt(e.element().id);
			// show widgetlayer:
			if (storyID){
				//control.showAll();
				this.mapSwitch.hideMap();
				

				// check if homepagewidget is available and remove it:
				control.widgets.values().each(
					(function(widget){
						if (widget.instID.toString().indexOf('homepageWidget') > -1){
							 control.remove(widget);
						}
					}).bind(this)
				)
	
				var homepageWidget = getEmptyHomepageWidget();
				homepageWidget.userID =  e.element().marker.srcObj.userID;
				control.add(homepageWidget);
				control.render();
				this._openStory(homepageWidget,storyID , callBack);
			}
			
		},
		
		_openStory : function(homepageWidget, storyID, callBack){
			if (!homepageWidget.stories || homepageWidget.stories.length ==0){
				setTimeout(
					(function(){
						this._openStory(homepageWidget, storyID, callBack);
					}).bind(this),
					200
				)
				return;
			}
			homepageWidget._openStory(storyID);
			if (callBack) {
//				homepageWidget[callBack]();
			}
			
		},
		
		createUserMarker : function(obj){
			if (obj.coordsX == 0 || obj.coordsY == 0 ) return false;
			var lg = new GLatLng(obj.coordsY, obj.coordsX);
			this.createGIcon("/upload/profile/20/" + obj.userID + ".jpg")
			var marker = new GMarker(lg, 
					{
						title: obj.first_name + " " + obj.last_name, 
						icon:this.createGIcon("/images/msn.png", 19, 19, true),
						draggable:false
					});
			GEvent.addListener(marker, 'click', (function() { this.openUserMarker(marker, arguments[0])}).bind(this) );
			marker.srcObj = obj;
			return marker;
		},

		getFirstStoryFromUser : function(userID){
			var stories = this.stories.findAll(
				function(story){
					if (story.userID == userID) return story; 
				}
			)
			if (stories){
				stories = stories.sort(this.sortStory.bind(this))
				return stories[0];
			}
		},
		
		sortStory : function(a,b){
			return b.storyID - a.storyID;
		},
			
		openUserMarker : function(marker, latlng){
			var firstStory = this.getFirstStoryFromUser(marker.srcObj.userID);
			var html ='<div class="googleBalloon">';
			if (marker.srcObj.hasImage == 'true') html += '<img src="/upload/profile/' + marker.srcObj.userID + '.jpg" class="googleBaloonImage" width="100" />';
			html += '<span class="googleBaloonOwner">' + marker.srcObj.first_name +" " + marker.srcObj.last_name + '</span>';
			if (firstStory){
				html += '<span class="googleBaloonTitle">' + firstStory.title.substring(0,12) + '</span>';
				html += '<span class="googleBaloonIntro">'  + firstStory.bbCode.substring(0,56) + '...</span>';
				html += '<a class="googleBaloonLink" href="/userHome.php?rand=' + parseInt(Math.random()*1000000) + '&userID=' + marker.srcObj.userID+ '#story='+firstStory.storyID+'">[meer]</a>';
			}else{
				html += '<a class="googleBaloonLink" href="/userHome.php?rand=' + parseInt(Math.random()*1000000) + '&userID=' + marker.srcObj.userID+ '">[meer]</a>';
			}
			html += '</div>';
			gmc.map.openInfoWindow(latlng, html);
			if (firstStory){
				this._openStoryMarker({srcObj:firstStory});// set private function with timer
			}
		},

		createImageMarker : function(obj){
			if (obj.coordsX == 0 || obj.coordsY == 0 ) return false;
			
			var lg = new GLatLng(obj.coordsY, obj.coordsX);
			var marker = new GMarker(lg, 
					{
						title: obj.name, 
						icon:this.createGIcon("/upload/userimages/25/" + obj.imgID + ".jpg", 20,20,true),
						draggable:false
					});
			marker.srcObj = obj;
			GEvent.addListener(marker, 'click', (function() { this.openImageMarker(marker, arguments[0])}).bind(this) ); 
			return marker;
		},
		
		openImageMarker : function(marker, latlng){
			var story = this.stories.find(
				function(st){
					if (st.storyID == marker.srcObj.storyID) return true;
				}
			)
			var user = this.users.find(
				function(user){
					if (user.userID == marker.srcObj.userID) return true;
				}
			)
			var html ='<div class="googleBalloon">';
			html += '<img id="' + marker.srcObj.imgID + '_googleImg" src="/upload/userimages/100/' + marker.srcObj.imgID + '.jpg" class="googleBaloonImage" width="100" />';
			html += '<span class="googleBaloonOwner">' + user.first_name +" " + user.last_name + '</span>';
			if (marker.srcObj.name){
				html += '<span class="googleBaloonTitle">' + marker.srcObj.name.substring(0,12) + '</span>';
			}else{
				if (story) html += '<span class="googleBaloonTitle">' + story.title.substring(0,12) + '</span>';
			}
			if (marker.srcObj.description){
				html += '<span class="googleBaloonIntro">'  + marker.srcObj.description.substring(0,56) + '...</span>';
			}else if (story){
				html += '<span class="googleBaloonIntro">'  + story.bbCode.substring(0,56) + '...</span>';
			}
//			if (story) html += '<a class="googleBaloonLink" id="' + story.storyID + '_markerLink">[meer]</a>';
			if (story) {
				html += '<a class="googleBaloonLink" href="/userHome.php?rand=' + parseInt(Math.random()*1000000) + '&userID=' + marker.srcObj.userID + '#story='+story.storyID+':photo=' +marker.srcObj.imgID + '">[meer]</a>';
			}else{
				html += '<a class="googleBaloonLink" href="/userHome.php?rand=' + parseInt(Math.random()*1000000) + '&userID=' + marker.srcObj.userID+ '#photo=' +marker.srcObj.imgID + '">[meer]</a>';
			}
			html += '</div>';
			gmc.map.openInfoWindow(latlng, html);

//			this._openStoryMarker({srcObj:story});// set private function with timer
//			this._openImageMarker(marker.srcObj);
//			var myHtml = '<a target="_blank" href="http://' + window.location.hostname+ '/upload/userimages/originals/' + marker.srcObj.imgID + '.jpg">';
//			myHtml += '<img src="upload/userimages/100/' + marker.srcObj.imgID + '.jpg" width="100" border="none"/>';
//			myHtml += '</a>';
//			gmc.map.openInfoWindow(latlng, myHtml);			
		},
		
		_openImageMarker : function(imgObj){
			if (!$(imgObj.imgID + '_googleImg')){
				setTimeout((function(){ this._openImageMarker(imgObj) }).bind(this), 200);
				return;
			}
			var func = function(){
				var sZoom = new simpleZoom('', '/upload/userimages/originals/' + imgObj.imgID + '.jpg', true);	
			}
			$(imgObj.imgID + '_googleImg').observe('click', func)
			
		},
		
		createVideoMarker : function(obj){
			if (obj.coordsX == 0 || obj.coordsY == 0 ) return false;
			var lg = new GLatLng(obj.coordsY, obj.coordsX);
			var marker = new GMarker(lg, 
					{
						title: obj.name, 
						icon:this.createGIcon("/images/youtube.gif", 42, 21, true),
						draggable:false
					});
			GEvent.addListener(marker, 'click', (function() { this.openVideoMarker(marker, arguments[0])}).bind(this) );
			marker.srcObj = obj;
			return marker;
		},

		openVideoMarker : function(marker, latlng){
			var story = this.stories.find(
				function(st){
					if (st.storyID == marker.srcObj.storyID) return true;
				}
			)
			var user = this.users.find(
				function(user){
					if (user.userID == marker.srcObj.userID) return true;
				}
			)

			var html ='<div class="googleBalloon">';
			html += '<img src="/images/youtube_large.png" class="googleBaloonImage" width="100" />';
			html += '<span class="googleBaloonOwner">' + user.first_name +" " + user.last_name + '</span>';
			if (marker.srcObj.name){
				html += '<span class="googleBaloonTitle">' + marker.srcObj.name.substring(0,12) + '</span>';
			}else{
				html += '<span class="googleBaloonTitle">' + story.title.substring(0,12) + '</span>';
			}
			if (marker.srcObj.description){
				html += '<span class="googleBaloonIntro">'  + marker.srcObj.description.substring(0,56) + '...</span>';
			}else{
				html += '<span class="googleBaloonIntro">'  + story.bbCode.substring(0,56) + '...</span>';
			}
			html += '<a class="googleBaloonLink" href="/userHome.php?rand=' + parseInt(Math.random()*1000000) + '&userID=' + marker.srcObj.userID+ '#story='+ story.storyID +':video=' +marker.srcObj.imgID + '">[meer]</a>';
			html += '</div>';
			gmc.map.openInfoWindow(latlng, html);
//			this._openStoryMarker({srcObj:story}, 'showVideo');// set private function with timer
						
		},
		
		createGIcon : function(img, sizeX, sizeY, hasShadow){
			if (!img){
				var aIcon = new GIcon();
				aIcon.image = "/images/default_icon.png";
				aIcon.iconSize = new GSize(20, 20);
				aIcon.iconAnchor = new GPoint(20, 20);
				aIcon.shadow = "/images/general_shadow.png";
				aIcon.shadowSize = new GSize(sizeX, sizeY);
			}else{
				var aIcon = new GIcon();
				aIcon.image = img;
				if (sizeX && sizeY) aIcon.iconSize = new GSize(sizeX, sizeY);
				if (sizeX && sizeY) aIcon.iconAnchor = new GPoint(sizeX, sizeY);
				if (hasShadow) aIcon.shadow = "/images/general_shadow.png";
				if (sizeX && sizeY) aIcon.shadowSize = new GSize(sizeX *2, sizeY *2) ;
			}
			return aIcon;
		},
		
		close : function(){
			this.markerManager.clearMarkers();
			this.mapSwitch.close();
		}
		
		
	})
	/**
	 * Google Maps Global View; inherited from gm_abstractView;
	 * retrieves global markers from database and renders them to a global view
	 * Only used when there's no user selected or no session['userID'] is available
	 */


	var gm_GlobalView = Class.create(gm_AbstractView, {
		initialize:function($super, controller){
			$super(controller);
			this.instID = 'gm_GlobalView.' + parseInt(Math.random()*1000000);
			this.myCommand = 'googlemaps_global';
		},
		
		handleReq : function(req){
			this.markers = [];
			this.users = req.responseJSON.users;
			this.stories = req.responseJSON.stories;
			this.images = req.responseJSON.images;
			this.videos = req.responseJSON.videos;
			if (this.users){
				this.users.each(
					(function(userObj){
						var tmp = this.createUserMarker(userObj);
						if (tmp) this.markers.push(tmp);
					}).bind(this)
				);
			}
			if (this.stories){
				this.stories.each(
					(function(storyObj){
						if (storyObj.bbCode.toString().length > 40){
							var tmp = this.createStoryMarker(storyObj);
							if (tmp) this.markers.push(tmp);
						}
					}).bind(this)
				);
			}
//			if (this.images){
//				this.images.each(
//					(function(imgObj){
//						var tmp = this.createImageMarker(imgObj);
//						if (tmp) this.markers.push(tmp);
//					}).bind(this)
//				);
//			}
//			if (this.videos){
//				this.videos.each(
//					(function(imgObj){
//						var tmp = this.createVideoMarker(imgObj);
//						if (tmp) this.markers.push(tmp);
//					}).bind(this)
//				);
//			}
			if (this.markers.length > 0) {
				this.markerManager.addMarkers(this.markers, 1);
				this.markerManager.refresh();
			}else if (window.console) {
				console.log("No markers found!", req.responseJSON);
			}
		}
		
	})
	
	var gm_ProfileView = Class.create(gm_AbstractView, {
		initialize:function($super, controller, userID){
			$super(controller);
			this.instID = 'gm_ProfileView.' + parseInt(Math.random()*1000000);
			this.myCommand = 'googlemaps_profile';
			this.userID = userID;
		},

		render:function(){
			var remote = new rpc(this.myCommand, this._render.bind(this));
			remote.call('getUserView', {userID:this.userID});
		},
		
		_render : function(req){
			var x = req.responseJSON.users[0].coordsX;
			var y = req.responseJSON.users[0].coordsY;
			var zoom = req.responseJSON.users[0].zoomLevel;
			if (x != 0 && y!=0 && zoom){
				this.controller.map.setCenter(new GLatLng(y, x), parseInt(zoom));
			}else{
				//default oz
				this.controller.map.setCenter(new GLatLng(-25.274398,133.775136), 2);
			}
			this.mapSwitch = new gm_MapSwitch(this.controller);
			this.markerManager = new MarkerManager(this.controller.map, { trackMarkers: false });
			this.loadMarkers();
		},
		
		loadMarkers : function(){
			if (this.markerManager){
				var remote = new rpc(this.myCommand, this.handleReq.bind(this));
//				remote.debug=true;
				remote.call('getMarkers', {userID:this.userID});
			}
		}
		
	})
	var gm_ProfileOwnerView = Class.create(gm_ProfileView, {
		initialize:function($super, controller, userID){
			$super(controller);
			this.instID = 'gm_ProfileOwnerView.' + parseInt(Math.random()*1000000);
			this.myCommand = 'googlemaps_profileowner';
			this.userID = userID;
		}
	})
	var gm_CommercialView = Class.create(gm_AbstractView, {
		initialize:function($super, controller,  page){
			$super(controller);
			this.instID = 'gm_CommercialView.' + parseInt(Math.random()*1000000);
			this.myCommand = 'googlemaps_commercial';
			this.userID = 0;
			this.page ='';
			if (page) this.page = page;
		},
		
		loadMarkers : function(){
			if (this.markerManager){
				var remote = new rpc(this.myCommand, this.handleReq.bind(this));
				remote.debug = true;
				remote.call('getMarkers', {all:1, page:this.page});
			}
		},
	
		handleReq : function(req){
			req.responseJSON.each(
					(function(marker){
						var tmp = this.createCommercialMarker(marker);
						if (tmp) this.markers.push(tmp);
					}).bind(this)
				);
			if (this.markers.length > 0) {
				this.markerManager.addMarkers(this.markers, 1);
				this.markerManager.refresh();
			}else if (window.console) {
				console.log("No markers found!", req.responseJSON);
			}
			
		},
		
		createCommercialMarker : function(obj){
			if (obj.coordsX == 0 || obj.coordsY == 0 ) return false;
			var lg = new GLatLng(obj.coordsY, obj.coordsX);
			var marker = new GMarker(lg, 
					{
						icon:this.createGIcon("/db/" + obj.WAS_file_ID + "/" + obj.image, obj.width, obj.height, false),
						draggable:false
					});
			GEvent.addListener(marker, 'click', (function() {
				if (obj.link.indexOf("javascript") > -1){
					var str = obj.link.toString();
					str = str.replace('javascript:', '');
					eval(str);
				}else{
					window.open(obj.link)	
				}
				 
			}).bind(this) );
			marker.srcObj = obj;
			return marker;
		}
	})	/**
	 * Google Maps Global View; inherited from gm_abstractView;
	 * retrieves global markers from database and renders them to a global view
	 * Only used when there's no user selected or no session['userID'] is available
	 */


	var gm_ABPView = Class.create(gm_AbstractView, {
		initialize:function($super, controller){
			$super(controller);
			this.instID = 'gm_ABPView.' + parseInt(Math.random()*1000000);
			this.myCommand = 'googlemaps_global';
		},
		
		render:function(){
			// defaults to full view of oz:
//			this.controller.map.setCenter(new GLatLng(-25.274398,140.775136), 5);
			this.controller.map.setCenter(new GLatLng(-25.874398,142.775136), 5);
			this.mapSwitch = new gm_MapSwitch(this.controller);
			this.markerManager = new MarkerManager(this.controller.map, { trackMarkers: false });
			this.loadMarkers();
		}
		
	})
	var fotoBrowser = Class.create({
			
		initialize:function(photoContainer,commentContainer, floatBlock, storyObj){
			this.instID = 'fotoBrowser.' + parseInt(Math.random()*1000000);
			this.photoContainer = photoContainer;
			this.commentContainer = commentContainer;
			this.floatBlock = floatBlock;
			this.story = storyObj;
			this.idx = 0;
//			this.defaultWidth = 622;
//			this.defaultHeight = 456;
			this.defaultWidth = 622;
			this.defaultHeight = 426;

			this.doResizing = false;
		},
		
		draw : function(fotoID){
			if (this.story.images.length == 0) return;
			if (fotoID == 0) {
				this.currPhoto = this.story.images[0];
			}else{
				var tmpIdx = 0;
				this.story.images.each(
					(function(image){
						tmpIdx++;
						if (image.id == fotoID){ 
							this.currPhoto = image;
							this.idx = tmpIdx-1;
						}
						
					}).bind(this)
				)
			}
			this.drawFoto();
			
		},
		
		drawFoto:function(){
			var photoContainer = new Element('div', {className:'photoMainContainer'});
			this.photoContainer.update(photoContainer);
			
			if (this.doResizing){
				var photo = new Element('img', {src:'/upload/userimages/originals/' + this.currPhoto.id + '.jpg', className:'currPhoto'});
				photoContainer.insert(photo);
				// resize image:
				if (parseInt(this.currPhoto.width) > parseInt(this.currPhoto.height)){
					// horizontal orientated; max_width
					photo.setStyle('width:' + this.defaultWidth+ 'px;');
	
					// set margin to center the height;
					var newHeight = (this.defaultWidth / parseInt(this.currPhoto.width)) * parseInt(this.currPhoto.height)
					var diffHeight = (this.defaultHeight-parseInt(newHeight)) / 2;
					photo.setStyle('margin-top:' + diffHeight + "px;");
				}else{
					photo.setStyle('height:' + this.defaultHeight + 'px;');
				}
			}else{
				if (parseInt(this.currPhoto.width) > parseInt(this.currPhoto.height)){
					// horizontal orientated, resize to height and cut off sides
					var border = new Element('div', {className:'photoBorderWide'});
					photoContainer.insert(border);
					var whiteBorder = new Element('div', {className:'photoBorderWhite'});
					border.insert(whiteBorder);
					
					var photo = new Element('img', {src:'/upload/userimages/originals/' + this.currPhoto.id + '.jpg', className:'currPhoto'});
					whiteBorder.insert(photo);

					var newWidth = (this.defaultHeight / parseInt(this.currPhoto.height)) * parseInt(this.currPhoto.width);
					if (newWidth < this.defaultWidth){
						// resize to match viewport:
						photo.setStyle('width:' + this.defaultWidth + "px;");
						if (Prototype.Browser.IE){
							// calculate new height;
							var newHeight = (this.defaultWidth / parseInt(this.currPhoto.width)) * parseInt(this.currPhoto.height);
							photo.setStyle('height:' + this.defaultHeight + "px;");
						}
					}else{
						if (Prototype.Browser.IE){
							photo.setStyle('width:' + newWidth + "px;");
						}
						photo.setStyle('height:' + this.defaultHeight + "px;");
					}
					
				}else{
					// vertical
					var border = new Element('div', {className:'photoBorderHigh'});
					photoContainer.insert(border);
					var whiteBorder = new Element('div', {className:'photoBorderWhite'});
					border.insert(whiteBorder);
					
					var photo = new Element('img', {src:'/upload/userimages/originals/' + this.currPhoto.id + '.jpg', className:'currPhoto'});
					whiteBorder.insert(photo);
					
					photo.setStyle('height:' + this.defaultHeight + "px;");
					//calculate width
					var newWidth = (this.defaultHeight / parseInt(this.currPhoto.height)) * parseInt(this.currPhoto.width);
					if (Prototype.Browser.IE){
						photo.setStyle('width:' + newWidth + "px;");
						border.setStyle('width:' + (parseInt(newWidth)) + "px;");
					}else{
						border.setStyle('width:' + (parseInt(newWidth)+8) + "px;");
					}
					whiteBorder.setStyle('width:' + (parseInt(newWidth)) + "px;");
				}
				
			}
			
			if (!this.isFirst(this.currPhoto.id)){
				var arrow= new Element('img', {src:'/images/searcharrow_previous.png', className:"arrowPrevious"})
				photoContainer.insert(arrow);
				arrow.observe('click', this.showPrevious.bind(this));
				arrow = '';
			}

			var container = new Element('div', {className:'fotoInfo'});
			photoContainer.insert(container);
			if (this.currPhoto.name) container.insert('<strong>' + this.currPhoto.name + "</strong> ");
			if (this.currPhoto.dateTaken !='0000-00-00 00:00:00'){
				container.insert("<i>" + this.getFriendlyDate(this.currPhoto.dateTaken) + "</i> ");
			}else{
				container.insert("<i>" + this.getFriendlyDate(this.currPhoto.dateAdded) + "</i> ");
			}
			if (this.currPhoto.description) container.insert(' <strong> ' + nl2br(this.currPhoto.description.substring(0, 60)) + '</strong>');

			// set position of description
			if (parseInt(this.currPhoto.width) > parseInt(this.currPhoto.height)){
				// horizontal oriented
				container.setStyle('width:' + this.defaultWidth + ";");
			}else{
				container.setStyle('width:' + newWidth + ";");
			}
			
			
			if (!this.isLast(this.currPhoto.id)){
				var arrow = new Element('img', {src:'/images/searcharrow_next.png', className:"arrowNext"})
				photoContainer.insert(arrow);
				arrow.observe('click', this.showNext.bind(this))
//				// reposition next-arrow to match width of image:
//				if (parseInt(this.currPhoto.height) > parseInt(this.currPhoto.width)){
//					var newWidth = (this.defaultHeight / parseInt(this.currPhoto.height)) * parseInt(this.currPhoto.width)
//					arrow.setStyle('left:' + (newWidth -17) + 'px');
//				}
			}
			// update commentcontainer:
//			this.floatBlock.hide();
			
		},
		
		showPrevious:function(){
			this.idx--;
			this.currPhoto = this.story.images[this.idx]; 
			this.drawFoto();
			
		},
		
		showNext:function(){
			this.idx++;
			this.currPhoto = this.story.images[this.idx]; 
			this.drawFoto();
		},
		
		isFirst : function(fotoID){
			if (this.story.images[0].id == fotoID) return true;
			return false;
			
		},
		isLast : function(fotoID){
			if (this.story.images[(this.story.images.length -1)].id == fotoID) return true;
			return false;
			
		},
		getFriendlyDate : function(dbDate){
			var dateValue = dbDate;
			dateValue = dateValue.split(' ');
			dateValue = dateValue[0].split('-');
			dateValue = dateValue[2] + '/' + dateValue[1] + '/'+dateValue[0];
			return dateValue ;			
		}
		
	});	var bpStoryReactie = Class.create({
		
		initialize:function(container, story, loggedOnUserID, callBack){
			this.instID = 'bpStoryReactie_' + parseInt(Math.random()*1000000)
			this.container = container;
			this.story = story;
			this.loggedOnUserID = loggedOnUserID;
			if (!callBack){
				this.callBack = function(){}
			}else{
				this.callBack = callBack;
			}
			
			// set form-texts;
			this.defaultBorderColor = '#1E3066';
			this.defaultVoornaam = 'voornaam';
			this.defaultEmail = 'e-mail';
			this.defaultMessage = 'Schrijf hier je reactie...';
			this.defaultCaptcha = 'Vul hier de code in';
			
			// set default form-values;
			this.voornaam = '';
			this.email = '';
			this.message = '';
			this.captchaCode = '';
			
			this.getReactions();
			
		},	
	
		getReactions : function(){
			var remote = new rpc('reisverhaalReactie', this.draw.bind(this));
			remote.debug=true;
			remote.call('getReactions', {storyID : this.story.id});
		},
		
		draw: function(req){
			this.reactions = req.responseJSON;
			
			// setup header:
			this.header = new Element('div', {className:'reactionHeader'});
			this.container.insert(this.header);
			
			// set up form:
			this.drawForm(this.header);
			
			this.drawMessages();
			this.callBack();
		},
		
		drawMessages : function(){
			var container = new Element('div', {className:'reactions'});
			this.container.insert(container);
			this.reactions.each(
				(function(reaction){
					this.drawMessage(reaction, container);
				}).bind(this)
			)
		},
		
		drawMessage : function(reaction, parentContainer){
			var container = new Element('div', {className:'reaction'});
			parentContainer.insert(container);

			var userImage = new Element('div', {className:'reactionUserImage'});
			container.insert(userImage);
			if (reaction.hasImage == '1'){
				var img = new Element('img', {src:'/upload/profile/' + reaction.userID + '.jpg'});
			}else{
				var img = new Element('img', {src:'/images/dummy_user_img_small.jpg'});
			}
			userImage.insert(img);
			
			
			var title = new Element('div', {className:'reactionTitle'}).update('<span class="reactionTitleUserName">' + reaction.name + '</span> <span class="reactionTitleDate">' + reaction.postedFriendly + '</span>');
			container.insert(title);
			
			var body = nl2br(reaction.body)
			var msg = new Element('div', {className:'reactionMessage'}).update(body);
			container.insert(msg);
			
		},
		
		drawForm : function(container){
			container.insert('<span class="reactionHeadTitle">Reageer op dit reisverhaal:</span>');
			
			if (this.loggedOnUserID > 0){
				// draw ONLY text-input
				var formContainer = new Element('div', {className:'simpleForm'})
				container.insert(formContainer);

				var col1 = new Element('div', {className:'formCol1'});
				formContainer.insert(col1);
				this.inputMessage = new Element('textarea', {className:'inputMessage'}).update(this.defaultMessage);
				col1.insert(this.inputMessage);
				this.inputMessage.observe('focus', (function(){
					if (this.inputMessage.getValue() == this.defaultMessage) this.inputMessage.value = '';
				}).bind(this))
				this.inputMessage.observe('blur', (function(){
					if (this.inputMessage.getValue() == '') this.inputMessage.value = this.defaultMessage;
				}).bind(this) );

				var col2 = new Element('div', {className:'formCol2'});
				formContainer.insert(col2);
				var submit = new Element('img', {src:'/images/donker_blauwe_pijl.jpg', className:'reactionSubmit'})
				col2.insert(submit);
				submit.observe('click', this.validate.bind(this));
			}else{
				// draw full form with CAPTCHA;
				var formContainer = new Element('div', {className:'fullForm'});
				container.insert(formContainer);
				// form is setup into 3 columns;
				
				// COLUMN 1
				var col1 = new Element('div', {className:'formCol1'});
				formContainer.insert(col1);

				this.inputVoornaam = new Element('input', {type:'text', className:'inputVoornaam', value:this.defaultVoornaam});
				col1.insert(this.inputVoornaam);
				this.inputVoornaam.observe('focus', (function(){
					if (this.inputVoornaam.getValue() == this.defaultVoornaam) this.inputVoornaam.value = '';
				}).bind(this))
				this.inputVoornaam.observe('blur', (function(){
					if (this.inputVoornaam.getValue() == '') this.inputVoornaam.value = this.defaultVoornaam;
				}).bind(this) );

				
				this.inputEmail = new Element('input', {type:'text', className:'inputEmail', value:this.defaultEmail});
				col1.insert(this.inputEmail);
				this.inputEmail.observe('focus', (function(){
					if (this.inputEmail.getValue() == this.defaultEmail) this.inputEmail.value = '';
				}).bind(this))
				this.inputEmail.observe('blur', (function(){
					if (this.inputEmail.getValue() == '') this.inputEmail.value = this.defaultEmail;
				}).bind(this) );
				

				this.inputMessage = new Element('textarea', {className:'inputMessage'}).update(this.defaultMessage);
				col1.insert(this.inputMessage);
				this.inputMessage.observe('focus', (function(){
					if (this.inputMessage.getValue() == this.defaultMessage) {
						this.inputMessage.value = '';
					}
				}).bind(this))
				this.inputMessage.observe('blur', (function(){
					if (this.inputMessage.getValue() == '') this.inputMessage.value = this.defaultMessage;
				}).bind(this) );

				this.hiddenField = new Element('input', {type:'text', name:'email', value:'', className:'hiddenField'});
				formContainer.insert(this.hiddenField);
					
				// \\COLUMN 1				
				
				// COLUMN 2
//				var col2 = new Element('div', {className:'formCol2'});
//				formContainer.insert(col2);
//				// insert captcha:
//				var img = new Element('img', {src:"include/lib/3rdparty/captcha/CaptchaSecurityImages.php"});
//				col2.insert(img);
//			
//				this.inputCaptcha = new Element('input', {type:'text', className:'inputCaptcha', value:this.defaultCaptcha});
//				col2.insert(this.inputCaptcha);
//				this.inputCaptcha.observe('focus', (function(){
//					if (this.inputCaptcha.getValue() == this.defaultCaptcha) this.inputCaptcha.value = '';
//				}).bind(this))
//				this.inputCaptcha.observe('blur', (function(){
//					if (this.inputCaptcha.getValue() == '') this.inputCaptcha.value = this.defaultCaptcha;
//				}).bind(this) );
					
				
				// \\COLUMN 2
					
				// COLUMN 3
				var col3 = new Element('div', {className:'formCol3'});
				formContainer.insert(col3);
				var submit = new Element('img', {src:'/images/donker_blauwe_pijl.jpg', className:'reactionSubmit'})
				col3.insert(submit);
				submit.observe('click', this.validate.bind(this));
				// \\COLUMN 3				
			}
			
		},
		
		validate : function(){
			if (this.loggedOnUserID == 0){
				//Check captcha
//				var captchaValue = this.inputCaptcha.getValue();
//				if (captchaValue == this.defaultCaptcha){
//					var captchaValue = '';
//				}else{
//					var captchaValue = this.inputCaptcha.getValue().replace(' ', '');
//				}
//				
//				if (captchaValue == ''){
//					var ok = false;
//					this.inputCaptcha.setStyle("border-color:red;");
//					this._validate('',false);
//					return;
//				}else{
//					this.inputCaptcha.setStyle("border-color:" + this.defaultBorderColor + ";");
//					captchaValue = this.inputCaptcha.getValue();
//				}
//				var func = (function(req){
//					this._validate(req, true)
//				}).bind(this)
//				var remote = new rpc('reisverhaalReactie', func);
//				remote.debug=true;
//				remote.call('checkCaptcha', {captcha : captchaValue});
				if (this.hiddenField.getValue() !=''){
					return false;
				}else{
					this._validate('', true)
				}
			}else{
				this._validate('', true)
			}
		},
		
		_validate : function(req, captchaOK){
			if (!captchaOK){
				var ok = false;
			}else{
				var ok = true;
			}
			if (this.loggedOnUserID == 0){
				// interpret ajax call for captcha code
//				if (req.responseJSON.message == '0'){
//					ok = false;
//					this.inputCaptcha.setStyle("border-color:red;");
//				}else{
//					this.inputCaptcha.setStyle("border-color:" + this.defaultBorderColor + ";");
//				}				
				// check name/email/message 
				var voornaamValue = this.inputVoornaam.getValue();
				if (voornaamValue == this.defaultVoornaam) {
					var voornaamValue = '';
				}else{
					var voornaamValue = this.inputVoornaam.getValue().replace(' ', '');
				}
				if (voornaamValue == ''){
					var ok = false;
					this.inputVoornaam.setStyle("border-color:red;");
				}else{
					this.inputVoornaam.setStyle("border-color:" + this.defaultBorderColor + ";");
					voornaamValue = this.inputVoornaam.getValue();
				}

				var emailValue = this.inputEmail.getValue();
				if (emailValue == this.defaulEmail) {
					var emailValue = '';
				}else{
					var emailValue = this.inputEmail.getValue().replace(' ', '');
				}
				if (emailValue != '' && this.checkEmailValue(emailValue)){
					this.inputEmail.setStyle("border-color:" + this.defaultBorderColor + ";");
				}else{
					var ok = false;
					this.inputEmail.setStyle("border-color:red;");
				}
			}

			var msgValue = this.inputMessage.getValue();
			if (msgValue == this.defaultMessage) {
				var msgValue = '';
			}else{
				var msgValue = this.inputMessage.getValue().replace(' ', '');
			}
			if (msgValue == ''){
				var ok = false;
				this.inputMessage.setStyle("border-color:red;");
			}else{
				this.inputMessage.setStyle("border-color:" + this.defaultBorderColor + ";");
				msgValue = this.inputMessage.getValue();
			}
			if (ok){
				this.postMessage();
			}
		},
		
		postMessage : function(){
			var func = (function(req){
				this.container.update('');
				alert("Je bericht is opgeslagen!");
				this.draw(req);
			}).bind(this)
			
			var remote = new rpc('reisverhaalReactie', func);
			remote.debug=true;

			var msgValue = this.safeValue(this.inputMessage.getValue());
			var storyID = this.story.id;

			// gather values:
			if (this.loggedOnUserID == 0 || this.loggedOnUserID == ''){
//				var captchaValue = this.safeValue(this.inputCaptcha.getValue());
				var emailValue = this.safeValue(this.inputEmail.getValue());
				var voornaamValue = this.safeValue(this.inputVoornaam.getValue());
				remote.call('saveMessage', {
					"storyID" : storyID,
					"name" : voornaamValue,
					"email" : emailValue,
					"message" : msgValue
				});	
			}else{
				remote.call('saveMessage', {
					"storyID" : storyID,
					"message" : msgValue,
					"userID" : this.loggedOnUserID
				});	
				
			}
		},
		
		checkEmailValue : function(emailStr){
			var checkTLD=1;
			var knownDomsPat=/^(com|net|org|edu|int|mil|gov|arpa|biz|aero|name|coop|info|pro|museum)$/;
			var emailPat=/^(.+)@(.+)$/;
			var specialChars="\\(\\)><@,;:\\\\\\\"\\.\\[\\]";
			var validChars="\[^\\s" + specialChars + "\]";
			var quotedUser="(\"[^\"]*\")";
			var ipDomainPat=/^\[(\d{1,3})\.(\d{1,3})\.(\d{1,3})\.(\d{1,3})\]$/;
			var atom=validChars + '+';
			var word="(" + atom + "|" + quotedUser + ")";
			var userPat=new RegExp("^" + word + "(\\." + word + ")*$");
			var domainPat=new RegExp("^" + atom + "(\\." + atom +")*$");
			var matchArray=emailStr.match(emailPat);

			if (matchArray==null) {
				return false;
			}

			var user=matchArray[1];
			var domain=matchArray[2];

			for (i=0; i<user.length; i++) {
				if (user.charCodeAt(i)>127) {
					return false;
				}
			}

			for (i=0; i<domain.length; i++) {
				if (domain.charCodeAt(i)>127) {
					return false;
				}
			}
			
			if (user.match(userPat)==null) {
				return false;
			}

			var IPArray=domain.match(ipDomainPat);
			
			if (IPArray!=null) {
				for (var i=1;i<=4;i++) {
					if (IPArray[i]>255) {
						return false;
			   		}
				}
				return true;
			}
			
			 
			var atomPat=new RegExp("^" + atom + "$");
			var domArr=domain.split(".");
			var len=domArr.length;

			for (i=0;i<len;i++) {
				if (domArr[i].search(atomPat)==-1) {
					return false;
			   }
			}

			if (checkTLD && domArr[domArr.length-1].length!=2 && domArr[domArr.length-1].search(knownDomsPat)==-1) {
				return false;
			}

			if (len<2) {
				return false;
			}
			
			return true;			
		},

		safeValue : function(value){
			return encodeURIComponent(value.stripTags());
		}

	
		
		
	})/**
 * WidgetController, controls (behaviours of) widgets
 * Widgets each get an instance of the controller so they can reference other widgets.
 * Usage:
 * 	- create an instance of the controller, and assign the container it should use, and optional the rootPath of the website (for inclusion of stylesheets);
 * 		var control = new widgetController($('demoContainer'), rootPath);
 * @author Ivo Toby, ivo@i-v-o.nl
 */

	var widgetController = Class.create({
		/**
		 * Attempt to define an interface for the widgets, this is NOT standard javascript, javascript doesn't know interfaces
		 */
		iWidget : ['render', 'load', 'remove'],
		
		/**
		 * Constructor: 
		 * @param element Container : the container in which the widgets should be rendered.
		 * @param (optional) string : rootPath for CSS/images
		 */
		initialize : function(container, rootPath){
			this.instID = 'widgetController.' + parseInt(Math.random()*1000000); // each Object coded I-V-O style has this variable; use it as a kind of resource-ID (like PHP): great for debugging:)
			if (rootPath) {
				this.rootPath = rootPath; // widgets CAN use this variable
			}else{
				this.rootPath = '';
			}
			this.container = container;
			this.widgets = $H({}); // HASH-table in which widgets are contained
			this.cssFiles = []; //  contains CSS-files (to be sure each CSS file is included only ONCE.
			this.moveBy = {x:0,y:0};
			this.isChecking = false;
			this.zIndex = 2;
			this.contentWidget = null;
			this.isRetrieving = false;
			this.ajaxCalls = [];
		},
		
		
		/**
		 * Used to add a widget to the controller;
		 * Widgets are checked to make sure they comply to a (still simple) interface and they get an instance of the controller (done in isWidget)
		 * 
		 * If you add a widget AFTER controller::render(), you should initialize rendering yourself by calling widget.render();
		 * 
		 * @param widgetObject widget  
		 * @return widgetObject widget (initialized).
		 * @access public
		 */
		add : function(widget, isContentWidget){
			if (!isContentWidget) isContentWidget = false;
			var widgetObject = this.isWidget(widget);
			if (widgetObject) {
				if (this.widgets.get(widget.id)){
					if (window.console) {
						console.log(widget.id + " already exists!", widget, this)
					}else{
//						alert(widget.id + " already exists!");
					}
				}else{
					widget.controller = this;
					this.widgets.set(widget.options.id, widget);
					if (isContentWidget) this.contentWidget = widget;
				}
			}else{
				if (window.console) {
					console.log(widget.instID  + " is not a valid widget", widget, 	this)
				}else{
//					alert(widget.instID  + " is not a valid widget");
				}
			}
			return widget;
		},
		
		/** 
		 * Removes a widget from the widget-hash-table and removes it's output 
		 */
		remove : function(widget){
//			this.widgets.get(widget.options.id).remove();
			return this.widgets.unset(widget.options.id);
		},
		
		/**
		 * get a widget by it's ID
		 */
		get : function(id){
			return this.widgets.get(id);
		},
		
		getByInstanceID : function(searchFor){
			return this.widgets.values().findAll(
				function (widget){
					if (widget.instID.indexOf(searchFor) > -1) return widget
				}
			)
		},
		
		/**
		 * Recursively find a widgetobject from an element
		 */
		getByElement : function(elem){
			if (!elem) return;
			if (!elem.getAttribute('id')){
				return this.getByElement(elem.parentNode);
			}
			if (elem.getAttribute('id').toString().indexOf('__widgetContainer') > -1){
				return elem.widget;
			}else{
				return this.getByElement(elem.parentNode);				
			}
		},
		
		/**
		 * public function to start rendering the widgets
		 */
		render : function(callBack){
			if (!callBack) callBack = function(){};
			this.widgets.values().each(
				(function(widget){
					if (!widget.rendered){
						widget.options.zIndex = this.zIndex;
						widget.render(this.container, callBack);
						if (widget.options.closeOther == '1') this.hideAll(widget);
						this.zIndex +=10;

					}
				}).bind(this)
			)
			if (!this.isChecking){
				this.isChecking = true;
			}
//			this.widgets.values().each(
//				(function(widget){
//					console.log($(widget.container).select('h1'))
////					var titleText = $(widget.contentContainer).select('h1')[0].innerHTML; 
////					$(widget.contentContainer).select('h1')[0].innerHTML = titleText.toUpperCase();
//				}).bind(this)
//			)
			//setTimeout(function(){sifrInstance.replace();}, 200);
		},
		
		/**
		 * Private function to check an widget for interface and pass the controller to it (so a widget can be aware of other widgets).
		 */

		isWidget : function(widgetObj){
			// check widget against predefined interface, pass the controller into it and return true if it's valid
			if (!(widgetObj instanceof abstractWidget)) return false;
			var ok = true;
			this.iWidget.each(
				function(method){
					if (! (widgetObj[method] instanceof Function) ) ok = false;
				}
			)
			if (ok){
				widgetObj.controller = this;
				return widgetObj;
			}
			return false;
		},
		
		
		/**
		 * Invokes widget to hide themselves if their option canHide = true, and except currWidget
		 * currWidget is optional 
		 */
		hideAll : function(currWidget){
			if (!currWidget) currWidget=''
			this.widgets.values().each(
					(function(widget){
						if (widget.rendered && (widget.options.canHide > 0) ){
							if (currWidget){ 
								if (currWidget.instID != widget.instID){
									widget.hide();
								}
							}else{
								widget.hide();
							}
						}
					}).bind(this)
				)			
		},

		/**
		 * Shows all available widgets if options.canHide was true (or else the widget could render itself twice)
		 */
		showAll : function(){
			this.widgets.values().each(
					(function(widget){
						if (widget.rendered && (widget.options.canHide > 0) ){
							widget.show();
						}
					}).bind(this)
				)			
		},
		
		/**
		 * Public function to get a widget from database (MAIN_texts)
		 * Order of business; 
		 * 	- Get Widget-options from an AJAX-call and callback _getContentWidget
		 *  - _getContentWidget will add it to the collection of widgets in this (controller) and render the widget
		 *  - the widget itself will get the content from the database and render it in it's contentcontainer (implementation in abtractWidget) 
		 */
		getContentWidget : function(cID, contentName, qs, callBack){
			if (!contentName) contentName = '';
			if (!cID) cID = '';
			if (!callBack) callBack = function(){}
			var func = (function(req){
				this._getContentWidget(req, qs, callBack);
			}).bind(this);
			var remote = new rpc('content', func);
//			remote.debug=true;
			remote.call('getWidget', {'contentID' : cID, 'contentName':contentName});
		},
		
		/** 
		 * Private function, see getContentWidget
		 */
		_getContentWidget : function(req, qs, callBack, zIndex){
			if (!zIndex) zIndex ='';
			var widget ='';
			req.responseJSON.each(
				(function(aWidget){
					widget = aWidget.widgetClass;
					if (!widget){
						widget = 'shadowedWidget';
					}
					var widgetClassName = aWidget.widgetClassName;
					if (!widgetClassName) widgetClassName = 'whiteWidget'
					if (!qs) qs='';
					widget = new window[widget]({
						position:{
							left:aWidget.widgetLeft, 
							top:aWidget.widgetTop
						}, 
						size:{	
							width:aWidget.widgetWidth, 
							height:aWidget.widgetHeight
						}, 
						useIFrame:false, 
						containerClassName:widgetClassName,
						showClose:aWidget.widgetShowClose,
						ajax:{uri:'/include/lib/rpc.php?action=content&method=getContent&id=' + aWidget.contentID + "&buttonID=" + aWidget.buttonID +"&"+qs},
						onloadCallback : aWidget.widgetOnloadCallback,
						closeOther : aWidget.widgetCanCloseOther,
						canHide : aWidget.widgetCanHide
					});
					if (aWidget.widgetID) widget.options.id = aWidget.widgetID; 
					this.add(widget);
				}).bind(this)
			);
			this.render(callBack);
			this.isRetrieving = false;
//			setTimeout(function(){callBack(req, widget);}, 100);
			this.setAjaxTimeout();
		},
		
		getStaticAds : function(currPage){
			var remote = new rpc('ads', this.setStaticAdWidgets.bind(this));
			remote.debug=true;
			remote.call('getWidgets', {'page' : currPage});
		},
		
		setStaticAdWidgets: function(req){
			req.responseJSON.each(
					(function(aWidget){
						widget = new staticAdWidget({
								position:{
									left:aWidget.widgetLeft, 
									top:aWidget.widgetTop
								}, 
								size:{	
									width:aWidget.widgetWidth, 
									height:aWidget.widgetHeight
								}, 
								useIFrame:false, 
								containerClassName:'whiteWidget',
								showClose:false,
								closeOther : false,
								canHide : true
							}, 
							'http://' + window.location.hostname +'/db/' + aWidget.WAS_file_ID + '/' + aWidget.image,
							aWidget.id,
							aWidget
						);
						this.add(widget);
					}).bind(this)
				);
			this.render();
		},
		
		getNavigationWidget : function(cID, buttonName, qs, callBack){
			if (this.isRetrieving){
				var call = {'cID':cID, 'buttonName':buttonName, 'qs':qs, 'callBack':callBack};
				this.ajaxCalls.push(call);
				return;
			}
			this.isRetrieving = true;
			if (!buttonName) buttonName = '';
			if (!cID) cID = '';
			if (!callBack) callBack = function(){}
			var func = (function(req){
				this._getContentWidget(req, qs, callBack);
			}).bind(this);
			var remote = new rpc('navigation', func);
			remote.call('getWidget', {'navID' : cID, 'navName':buttonName});			
		},
		
		setAjaxTimeout : function(){
//			if (this.isRetrieving){
//				setTimeout(this.setAjaxTimeout.bind(this), 250)
//				return;
//			}
			if (this.ajaxCalls.length > 0){
				var call = this.ajaxCalls.pop();
				this.getNavigationWidget(call.cID, call.buttonName, call.qs, call.callBack)
			}
		}
			
	});
/**
 * Abstract widget: 
 * base-class which forms a basic widget; 
 * SHOULD be extended to implementation 
 * (but; javascript doesn't support REAL abstract classes, so you can initialize an abstractWidget, but you shouldn't.. really.. don't)
 * @param object options: anonymous object with options, will always fallback to defaults as defined in this class. 
 * @return null :D
 * @author Ivo Toby, ivo@i-v-o.nl
 */
	var abstractWidget = Class.create({
		/** 
		 * Constructor;
		 * @param object options: anonymous object with options, will always fallback to defaults as defined in this class.
		 * NOTICE: if you make your own implementation of a widgetObject, ALWAYS start with initialize($super) ($super is same as parent:: in PHP).
		 * @access public
		 */
		initialize : function(options){
			this.instID = 'abstractWidget.' + parseInt(Math.random()*1000000);
			this.cssInserted = false; 
			
			// the default widget options
			this.options = {
				size : 					{height:100, width:100}, 			/* Size of widget */
				position : 				{left : 100, top : 100}, 			/* position of widget */
				containerClassName : 	'widget',							/* classname of the widget-container */
				cssFile : 				'css/widgets/abstractWidget.css',	/* Css-file used to render this widget */
				useIFrame : 			false,								/* Boolean to determine if this widget renders content from another website (in an IFRAME) */
				zIndex :				2,									/* Default z-Index, IS MANIPULATED from the controller.*/
				overrideZIndex : 		0,									/* used to override zindex from controller */
				id	:					this.instID,   						/* Identifier for widgets, falls back to a widgets' instID, SHOULD BE UNIQUE!!! */
				scrolling :				true,								/* Enable or disable scrolling within widget (overflow will be hidden on false) */
				ajax:														/* RPC/Iframe options */
					{
						ajaxRequestMethod : 'post',							/* Request method, possible values : post/get */
						requestParams : $H({}),								/* Params (querystring) used in POST-requests */
						reqHeader : [],										/* additional array with special headers sent with the request */
						encoding : 'UTF-8',									/* Encoding-type in which the request is sent */
						async:true,											/* Boolean indicating the asynchronious nature of the call (you prolly do not want to change this*/
						uri:'',												/* URL to which the request is made, if you use the IFRAME this is the src-attribute of the IFRAME, in case of AJAX-requests; DO NOT try to request from another Domain (SOP) */
						ajaxRequestMethod:'post'							/* Default method of requesting */
					},
				framePadding : '',											/* New since 03-04-09: override padding of iframe */
				frameMargin : {},											/* New since 01-07-09: override margin of iframe */
				showClose : true,											/* New since 22-01-09: show close-button */
				closeImg : '/images/Witkruis.png',							/* New since 22-01-09: close-button-image */
				canHide : false,											/* New, determines if widget can be made hidden by other widgets or hide-all*/
				closeOther : false,											/* New, hides all other widgets on initialization (except those with canHide : false) */
				title : false,												/* new since 07-03-09-> iframed widgets do not support the replacement of H1-titles due to browser-security*/
				closeEvent : function(){return true}						/* New since 17-11-09-> extra event-handler before closing the widget (returns true/false) */
			}
			this.mergeOptions(options);										/* merges received options with the default options */
			this.rendered = false;
			this.widgetCallBack = function(){}
		},
		
		/**
		 * Rendering function, inserts CSS, makes up elements to be inserted in parent-container
		 * @param element container : the parent container
		 * @access public (but prolly not used as a public function)
		 */
		render : function(container, callBack){
			if (!callBack) callBack = function(){};
			this.widgetCallBack = callBack;
			if (this.rendered) return;
			
			var elem = new Element('div', 
					{
						id:this.instID + "_widgetContainer", 
						className:this.options.containerClassName
					});
			container.insert(elem);
			
			elem.widget = this;
			// add waiter-animation:
			this.waiterElem = new Element('img',{align:'right', style:'display:none;', className:'waiter', src:this.controller.rootPath+ '/images/waiter.gif', id:this.instID+"_waiter"})
			
			// add closer (sluitkruis)
			if (this.options.showClose == 1){
				this.closeElem = new Element('img',{className:'closer', src:this.controller.rootPath+ this.options.closeImg, id:this.instID+"_closer"})
				
				elem.insert(this.closeElem);
				this.closeElem.observe('click', this.closeMe.bind(this));
			}
			elem.absolutize(); // prototype-function to make the element absolute
			
			var localOverflow = 'auto';
			if (!this.options.scrolling || this.options.useIFrame) {
				localOverflow = 'hidden';
			}
			if (this.options.overrideZIndex) this.options.zIndex = this.options.overrideZIndex; 
			elem.setStyle(
					{
						width:this.options.size.width + 'px',
						height:this.options.size.height + 'px',
						left:this.options.position.left + 'px',
						top:this.options.position.top+ 'px',
						zIndex:this.options.zIndex
					}
			);
			// overflow needs more styling on MSIE:
			if (Prototype.Browser.IE){
				if (localOverflow == 'hidden'){
					elem.setStyle('overflow:hidden;');
				}else{
					elem.setStyle('overflow-x:hidden;overflow-y:auto;');
				}
			}else{
				if (localOverflow == 'hidden'){
					elem.setStyle('overflow:hidden;');
				}else{
					elem.setStyle('overflow-x:hidden;overflow-y:auto;');	
				}
				
			}
			this.container = elem;
			// THIS IS IMPORTANT, the contentContainer is the actual container in which any kind of content is placed.
			this.contentContainer = new Element('div', {id:this.instID+"_contentContainer", className:'content'});
			this.container.insert(this.waiterElem);
			elem.insert(this.contentContainer);
			this.load(); // start loading content
			this.rendered = true;		
		},
		
		/**
		 * Private : Loads content into this.contentContainer, either a 'normal' AJAX-request of just an iFRAME
		 * @param string uri: optional URI for the request (in normal cases this is taken from this.options.ajax
		 * @param string params : (prototype) hash-table with key-value-pairs  (only really applicable in ajax-POSTs)
		 * @access private
		 */
		load: function(uri, params){
			if (!uri) uri = this.options.ajax.uri;
			if (!params) params = this.options.ajax.requestParams;
			if (!params) params = $H({});
			if (this.options.useIFrame){
				// load iframe src;
				if (this.options.title){
					this.contentContainer.insert(new Element('img', {src:'/include/smallTitle.php?text=' + this.options.title.toUpperCase()}));
				}
				var localScrolling = 'auto';
				if (!this.options.scrolling) localScrolling = "no";
				if (this.options.framePadding) {
					this.iframe = new Element('iframe', {id:this.instID + "_iframe", width: (parseInt(this.options.size.width)), height:parseInt(this.options.size.height) + parseInt(this.options.framePadding),frameborder:0, scrolling:localScrolling,src:this.options.ajax.uri, className:'iframe'});
					this.iframe.setStyle('padding:' + this.options.framePadding);
				}else if (this.options.frameMargin.top || this.options.frameMargin.left || this.options.frameMargin.bottom ||this.options.frameMargin.right){
					this.iframe = new Element('iframe', {id:this.instID + "_iframe", width: (parseInt(this.options.size.width)), height:parseInt(this.options.size.height) - 20,frameborder:0, scrolling:localScrolling,src:this.options.ajax.uri, className:'iframe'});
					for (type in this.options.frameMargin){
						this.iframe.setStyle('margin-'+type+':' + this.options.frameMargin[type]);	
					}
				}else{
					this.iframe = new Element('iframe', {id:this.instID + "_iframe", width: (parseInt(this.options.size.width)), height:parseInt(this.options.size.height) - 20,frameborder:0, scrolling:localScrolling,src:this.options.ajax.uri, className:'iframe'});
				}
				this.container.setStyle({overflow:'hidden'});
				this.contentContainer.insert(this.iframe);
				this.contentContainer.setStyle({padding:'0px'});
			}else{
				if (uri){
					// get content by Ajax-call:
					new Ajax.Request(
							uri, 
							{
								method: 		this.options.ajax.ajaxRequestMethod,
								parameters : 	params.toQueryString(),
							    requestHeaders: this.options.ajax.reqHeader,
							    encoding: 		this.options.ajax.encoding,
							    onLoading: 		this.waiter.bind(this),
							    onLoaded: 		this.unWaiter.bind(this),
							    asynchronous:	this.options.ajax.async,
					            onException:	this.handleErr.bind(this),
					            onFailure:		this.handleErr.bind(this),
					            onComplete: 	this._load.bind(this),// CALLBACK! 
					            evalScripts : 	true
					            
							}
					);
				}
			}
		},
		
		
		/**
		 * Private function : callback from this.load in case of a realy AJAX-call, can be overridden to support more functionality after an ajax-request.
		 * @param httpRequestObject req:
		 * @access private 
		 */
		_load:function(req){
			if (this.options.title){
				this.contentContainer.insert(new Element('img', {src:'/include/smallTitle.php?text=' + this.title}));
			}
			this.contentContainer.insert(req.responseText);
			this.assignMyself(this.contentContainer);
			if (!this.options.title){
				this.contentContainer.select('h1').each(// loop through h1-nodes to invoke sifr (and maybe manipulate contents of H1-tags
						function(elem){
							var elemText = elem.innerHTML;
							elemText = elemText.toUpperCase();
							var img = new Element('img', {className:'titleImg', src:'/include/smallTitle.php?text=' + elemText});
							elem.update(img);
						}
					)
			}
			if (this.widgetCallBack) this.widgetCallBack(this);
		},
		
		reload : function(){
			this.contentContainer.update('');
			this.load();
		},
		
		/**
		 * This function assigns the instance of this object recursively to all nodes in the contentContainer.
		 * Why? Could be handy if you write your own javascript and need to access the widget-object (for closing, getting the container etc)
		 * You can access the widgetObject from any node in contentContainer by accessing elem.widget 
		 * 
		 * this is recursive hell; DO NOT TOUCH UNLESS YOU WANT TO SPEND THE REST OF THE DAY DEBUGGING
		 *  
		 **/
		assignMyself : function(node){
			$(node).siblings().each(
				(function(elem){
					if (elem.widget) return;
					if (elem.nodeName.toLowerCase() == 'iframe'){
						elem.widget = this;
						elem.contentWindow.widget = this;
					}else{
						elem.widget = this;
					}
				}).bind(this)
			)
			$(node).descendants().each(
				(function(elem){
					if (elem.widget) return;
					if (elem.nodeName.toLowerCase() == 'iframe'){
						elem.widget = this;
						elem.contentWindow.widget = this;
					}else{
						this.assignMyself(elem);
						elem.widget = this;
					}
				}).bind(this)
			)
		},

		
		/**
		 * Private function to merge the default options with the ones supplied in object-creation
		 * calls itself to merge option-objects:)
		 * @access private
		 */
		mergeOptions: function(options, parentToken){
			if (!parentToken) parentToken = '';
			for (token in options){
				if ((options[token] instanceof Object)){
					this.mergeOptions(options[token], token)
				}
				if (parentToken){
					this.options[parentToken][token]=options[token];	
				}else{
					this.options[token]=options[token];
				}
			}
		},
		
		/**
		 * Experimental!
		 * Function to move a widget, relative to it's current position
		 * you must pass an object with properties x and y,ie:
		 * {x:20,y:300}
		 */
		move : function(xy){
			new Effect.Move(this.container, { x:xy.x, y:xy.y, mode: 'relative', duration:'0.2' });
		},
		
		/**
		 * Private function to insert a widget's CSS-file in the head of your document. Check's the controller's cssFile-array to make sure the CSS isn't inserted yet
		 * @access private
		 * DISABLED !!! -> this function is NOT used anymore, but maybe handy some day
		 */
		insertCSS : function(){
			if (!this.cssInserted){
				var cssFile  = this.options.cssFile;
				if (this.controller.cssFiles.indexOf(cssFile) ==-1){
					var cssLink = new Element('link', {rel:'stylesheet', type:'text/css', href:cssFile});
					$$('head')[0].insert(cssLink);
					this.controller.cssFiles.push(cssFile);
				}
				this.cssInserted = true;
			}
		},		
		
		/** 
		 * Hide widget
		 */
		hide : function(){
			this.container.hide();
		},
		
		/** 
		 * Show widget
		 */
		show : function(){
			this.container.show();
		},
		
		/** 
		 * Reset a widget (which will cause it to render itself again if the controller asks it to)
		 */

		reset : function(){
			this.rendered = false;
		},
		
		/**
		 * closeMe will remove the widget from DOM (if you'd like to render it again use reset after closeMe
		 */
		closeMe : function(){
			var closeEvent = this.options.closeEvent;
			if (closeEvent()){
				this.controller.remove(this);
				this.remove();
			}
		},
		
		/**
		 * Remove's widget's output from the DOM.
		 * left here for backwards-compatibility (and the facts it's a natural way of removing stuff)
		 */
		remove : function(){
			try{
				this.container.remove();
			}catch(e){
				if (window.console) {
					console.log("Error in abstractWidget Line 326", e);
				}
			}
		},
		
		/** 
		 * Waiter-function ; used in AJAX-calls to show user the object is busy 
		 */
		waiter : function(){
//			if (this.waiterElem) $(this.waiterElem).show();
		},

		/** 
		 * unWaiter; used in AJAX-calls to show user the object is ready with something
		 */
		unWaiter : function(){
//			if (this.waiterElem) $(this.waiterElem).hide();
			if (this.onloadCallback) this.onloadCallback(); // execute callback if there is any
		},
		
		/**
		 * Error-handling function; used in AJAX-requests if the server returns 4xx or 5xx.
		 */
		handleErr : function(e){
			if (window.console){
				console.log("Error in abstractWidget Line 351", e, arguments);
			}else{
//				alert('Unfortunately an error occurred in widget ' + this.options.id + '. Please contact support.');
			}
			return;
		},
		
		toFG : function(){
			if (!gShouldFocus) return;
			this.originalZIndex = this.container.style.zIndex;
			if (gZindex){
				gZindex++;
			}else{
				gZindex = getHighestZIndex()
			}
			this.container.setStyle('z-index : ' + gZindex);
		},
		
		toBG : function(){
			if (!gShouldFocus) return;
			if (this.originalZIndex) this.container.setStyle('z-index : ' + this.originalZIndex);
		}
		
	})/**
 * Implementation of a standard widget
 * This is only an instance of AbstractWidget.
 * Please notice the constructor: a reference to the abstractWidget-Class is supplied ($super)
 */

	var stdWidget = Class.create(abstractWidget,{
		initialize : function($super, options){
			$super(options);
			this.instID = 'stdWidget.' + parseInt(Math.random()*1000000);	
		}
	});/**
 * Implementation of a widget with a shadow-like-background
 * you can change the offset of the shadow by altering:
 * 		this.options.offsetLeft = int-value
 * 		this.options.offsetTop = int-value
 * @author Ivo Toby, ivo@i-v-o.nl 
 */

	var shadowedWidget= Class.create(abstractWidget,{
		
		initialize : function($super, options){
			$super(options);// run initialize of abstractWidget.js 
			this.options.position.offsetLeft = 15; // horizontal offset of shadow layer
			this.options.position.offsetTop = 16; // vertical offset of shadow layer
			this.instID = 'shadowedWidget.' + parseInt(Math.random()*1000000);	
		},
		
		render:function($super, container){
			this.options.scrolling = false;
			$super(container); // render widget as normal
			
			// add shadow:
			var newzIndex = -1;
			if (parseInt(this.container.style.zIndex) >0){
				var newzIndex = parseInt(this.container.style.zIndex) - 1;
			}
			var shadow = new Element('div', {className:'shadow', id:this.instID+"_shadow"});
			this.shadow = shadow;
			shadow.absolutize();
			shadow.setStyle(
					{
						width: this.options.size.width + 'px',
						height: this.options.size.height + 'px',
						left:( parseInt(this.options.position.left) + parseInt(this.options.position.offsetLeft) ) + 'px',
						top: ( parseInt(this.options.position.top) + parseInt(this.options.position.offsetTop) )+ 'px',
						zIndex : newzIndex
					}
			);
			container.insert(shadow);
			this.container.observe(gDefaultFocusEvent, this.toFG.bind(this))
			if (gDefaultFocusEvent == 'mouseover') this.container.observe('mouseout', this.toBG.bind(this))
			
		},
		
		
		move : function(xy){
			// extended because this widget has to outer-layers
			new Effect.Move(this.container, { x:xy.x, y:xy.y, mode: 'relative', duration:'0.2' });
			new Effect.Move(this.shadow, { x:xy.x, y:xy.y, mode: 'relative', duration:'0.2' });
		},
		
		hide : function(){
			// extended because this widget has to outer-layers
			this.container.hide();
			if (this.shadow) this.shadow.hide();
		},
		
		show : function(){
			// extended because this widget has to outer-layers			
			this.container.show();
			if (this.shadow) this.shadow.show();
		},
		

		/**
		 * Remove's widget's output from the DOM.
		 * @access public
		 */
		remove : function(){
			// extended because this widget has to outer-layers
			try{
				this.container.remove();
				$(this.instID+"_shadow").remove();
			}catch(e){
				if (window.console) console.log(e)
			}
		},
		
		toFG : function(){
			if (!gShouldFocus) return;
			this.originalZIndex = this.container.style.zIndex;
			this.originalShadowZIndex = $(this.instID+"_shadow").style.zIndex;
			if (gZindex){
				gZindex +=5;
			}else{
				gZindex = getHighestZIndex()
			}
			this.container.setStyle('z-index : ' + gZindex);
			$(this.instID+"_shadow").setStyle('z-index : ' + (gZindex -1) );
		},
		
		toBG : function(){
			if (!gShouldFocus) return;
			if (this.originalZIndex) this.container.setStyle('z-index : ' + this.originalZIndex);
			if (this.originalShadowZIndex) $(this.instID+"_shadow").setStyle('z-index : ' + this.originalShadowZIndex);
		}
		
	});/**
 * Implementation of navigation widget, draws basic vertical oriented navigation-bar with submenu's
 * 
 * @author Ivo Toby, ivo@i-v-o.nl
 */

	var navigationWidget = Class.create(shadowedWidget,{
		initialize : function($super, options){
			options.scrolling = false;
			options.overflow = 'visible';
			$super(options);
			this.instID = 'navigationWidget.' + parseInt(Math.random()*1000000);	
		},
		
		
		/**
		 * Rendering function, inserts CSS, makes up elements to be inserted in parent-container
		 * @param element container : the parent container
		 * @access public (but prolly not used as a public function)
		 */
		render : function(container, callBack){
			if (!callBack) callBack = function(){};
			this.widgetCallBack = callBack;
			var elem = new Element('div', 
					{
						id:this.instID + "_widgetContainer", 
						className:this.options.containerClassName
					});
			this.waiterElem = new Element('img',{align:'right', style:'display:none;', className:'waiter', src:this.controller.rootPath+ '/images/waiter.gif', id:this.instID+"_waiter"})
			elem.absolutize(); // prototype-function to make the element absolute
			elem.setStyle(
					{
						width:this.options.size.width + 'px',
						height:this.options.size.height + 'px',
						left:this.options.position.left + 'px',
						top:this.options.position.top+ 'px',
						zIndex:this.options.zIndex,
						overflow:'visible'
					}
			)
			container.insert(elem);
			this.container = elem;
			this.contentContainer = new Element('div', {id:this.instID+"_contentContainer", className:'content'});
//			this.contentContainer = new Element('div', {id:this.instID+"_contentContainer", className:'scrollerContent'});
			this.container.insert(this.waiterElem);
			elem.insert(this.contentContainer);
			
			// add shadow:
			var newzIndex = -1;
			if (parseInt(this.container.style.zIndex) >0){
				var newzIndex = parseInt(this.container.style.zIndex) - 1;
			}
			var shadow = new Element('div', {className:'shadow'});
			this.shadow = shadow;
			shadow.absolutize();
			shadow.setStyle(
					{
						width: this.options.size.width + 'px',
						height: this.options.size.height + 'px',
						left:( parseInt(this.options.position.left) + parseInt(this.options.position.offsetLeft) ) + 'px',
						top: ( parseInt(this.options.position.top) + parseInt(this.options.position.offsetTop) )+ 'px',
						zIndex : newzIndex
					}
			);
			container.insert(shadow);
			this.load(); // start loading content
			this.rendered = true;
		},

		/**
		 * Private function : callback from this.load in case of a realy AJAX-call, can be overridden to support more functionality after an ajax-request.
		 * @param httpRequestObject req:
		 * @access private 
		 */
		_load:function(req){
			this.contentContainer.insert(req.responseText);
			// handle navigation HOOKS
			this.setNavHooks();
		},
		
		setNavHooks : function(){
			this.resetSubNav();
			
			this.contentContainer.select('.navigationContainer').each(
				(function(elem){
					elem.id = this.instID+"mainNav";		
				}).bind(this)
			)
			this.contentContainer.select('.navigationContainer .item').each(this.setNavEvents.bind(this));
			// set events on children:
			this.contentContainer.select('.subnavigationContainer .item').each(
				(function (elem){
					elem.observe('mouseover', this.resetTimeout.bind(this));
					elem.observe('mouseout', this.startTimeout.bind(this));
					this.setNavEvents(elem);
				}).bind(this)
			)
			if (this.widgetCallBack) this.widgetCallBack(this);
		},
		
		setNavEvents : function(elem){
			// check if item has subnavigation:
			var subNavItems = this.hasSubNav(elem.getAttribute('id'));
			if (subNavItems.length > 0){
				// element should open children
				elem.observe('mouseover', this.openSubNav.bindAsEventListener(this))
			}else{
				// element should open a widget
				elem.observe('click', this.openWidget.bindAsEventListener(this));
			}
		},
		
		hasSubNav : function(buttonID){
			return this.contentContainer.select('.subnavigationContainer .item').findAll(
				(function(elem){
					if (elem.getAttribute('buttonID') == buttonID) return elem;
				}).bind(this)
			)
		},
		
		openWidget : function(e){
			// check if item has subnavigation:
			var subNavItems = this.hasSubNav(e.element().getAttribute('id'));
			if (this.controller.contentWidget){
				this.controller.contentWidget.options.ajax.uri = '/include/lib/rpc.php?action=content&method=getContentByButtonID&id=' + e.element().id;
				this.controller.contentWidget.reload();
			}else{			
				// rpc call!
				var buttonID = e.element().id;
				var remote = new rpc('content', this.getContent.bind(this));
				remote.call('getWidget', {'buttonID' : buttonID});
			}
			this.resetTimeout();
			this.resetSubNav();
		},
		
		getContent : function(req){
			var widget = req.responseJSON[0].widgetClass;
			if (!widget) widget = 'shadowedWidget'
			if (widget){
				var widgetClassName = req.responseJSON[0].widgetClassName;
				if (!widgetClassName) widgetClassName = 'whiteWidget'
				widget = new window[widget]({
					position:{
						left:req.responseJSON[0].widgetLeft, 
						top:req.responseJSON[0].widgetTop
					}, 
					size:{	
						width:req.responseJSON[0].widgetWidth, 
						height:req.responseJSON[0].widgetHeight
					}, 
					useIFrame:false, 
					showClose:req.responseJSON[0].widgetShowClose,
					containerClassName:widgetClassName,
					ajax:{uri:'/include/lib/rpc.php?action=content&method=getContent&id=' + req.responseJSON[0].contentID},
					onloadCallback : req.responseJSON[0].widgetOnloadCallback,
					closeOther : req.responseJSON[0].widgetCanCloseOther,
					canHide : req.responseJSON[0].widgetCanHide
				});
				this.controller.add(widget);
				this.controller.render();
			}
		},
		
		openSubNav : function(e){
			this.resetTimeout();
			this.resetSubNav();
			var clicked = e.element();
			var subContainer = $$('.subnavigationContainer')[0];
			subContainer.absolutize();
			subContainer.setStyle({top:clicked.offsetTop + 'px', left:this.getSubOffset()+'px', width:this.options.size.width+'px'});
			
			subContainer.show();
			var children = this.hasSubNav(clicked.id)
			children.each(
					function(elem){
						$(elem.id + "_shadow").show();
						elem.show();
					}
			)
			this.startTimeout();
		},
		
		resetSubNav : function(){
			$$('.subnavigationContainer')[0].hide();
			this.contentContainer.select('.subnavigationContainer .item').each(
				(function(elem){
					$(elem.id + "_shadow").hide();
					elem.hide();
				}).bind(this)
			)
		},
		
		getSubOffset : function(){
			// determine who to open the subnavcontainer
			var vpWidth = document.viewport.getWidth();
			vpWidth = parseInt(vpWidth/2);
			
			if (parseInt(this.options.position.left) < vpWidth){
//				return parseInt(this.options.position.left) - this.options.size.width;
				return this.options.size.width + 5;
			}
			//return parseInt(this.options.position.left) + this.options.size.width;
			return (this.options.size.width * -1) -5 ;
		},
		
		startTimeout : function(){
			this.navTimeout = setTimeout(this.resetSubNav.bind(this), 2500);
		},
		
		resetTimeout : function(){
			if (this.navTimeout)  clearTimeout(this.navTimeout)
		}
	});/**
 * Implementation of a widget with a transparent background
 */

	var framelessWidget= Class.create(abstractWidget,{
		initialize : function($super, options){
			options.containerClassName = 'transparent';
			$super(options);
			this.instID = 'framelessWidget.' + parseInt(Math.random()*1000000);	
		}
	});/**
 * semi-transparent widget, with shadow and navigation
 */

	var logoWidget = Class.create(navigationWidget,{
		initialize : function($super, options){
			options.scrolling = false;
			options.overflow = 'visible';
			$super(options);
			this.instID = 'logoWidget.' + parseInt(Math.random()*1000000);	
		},
		
		
		/**
		 * Rendering function, inserts CSS, makes up elements to be inserted in parent-container
		 * @param element container : the parent container
		 * @access public (but prolly not used as a public function)
		 */
		render : function(container, callBack){
			if (!callBack) callBack = function(){}
			this.widgetCallBack = callBack;
			
			this.options.containerClassName = 'transparent';
//			$super(container); // render widget as normal
			var elem = new Element('div', 
					{
						id:this.instID + "_widgetContainer", 
						className:this.options.containerClassName
					});
			this.waiterElem = new Element('img',{align:'right', style:'display:none;', className:'waiter', src:this.controller.rootPath+ '/images/waiter.gif', id:this.instID+"_waiter"})
			elem.absolutize(); // prototype-function to make the element absolute
			elem.setStyle(
					{
						width:this.options.size.width + 'px',
						height:this.options.size.height + 'px',
						left:this.options.position.left + 'px',
						top:this.options.position.top+ 'px',
						zIndex:this.options.zIndex,
						overflow:'visible'
					}
			)
			
			container.insert(elem);
			this.container = elem;
			this.contentContainer = new Element('div', {id:this.instID+"_contentContainer", className:'content'});
			this.container.insert(this.waiterElem);
			elem.insert(this.contentContainer);
			
			var mapSwitch = new Element('div', {className:"mapSwitch", id:"mapSwitch", style:"display:none;"});
			this.contentContainer.insert(mapSwitch);
			
			var logo =new Element('img', {src:'/images/logo.png', id:this.instID +"_logo"});
			this.contentContainer.insert(logo);

			logo.observe('click', function(){
				hideMap();
			})
			

			// add shadow:
			var newzIndex = -1;
			if (parseInt(this.container.style.zIndex) >0){
				var newzIndex = parseInt(this.container.style.zIndex) - 1;
			}
			var shadow = new Element('div', {className:'shadow', id:this.instID+"_shadow"});
			this.shadow = shadow;
			shadow.absolutize();
			shadow.setStyle(
					{
						width: this.options.size.width - 9 + 'px',
						height: (this.options.size.height -30 )+ 'px',
						left:( parseInt(this.options.position.left + 10) + parseInt(this.options.position.offsetLeft) ) + 'px',
						top: (( parseInt(this.options.position.top) + parseInt(this.options.position.offsetTop) ) + 43 )+ 'px',
						zIndex : newzIndex
					}
			);
			container.insert(shadow);
			this.load(); // start loading content
			this.rendered = true;

			this.container.observe(gDefaultFocusEvent, this.toFG.bind(this))
//			this.container.observe('mouseout', this.toBG.bind(this))
			
		},

		/**
		 * Private function : callback from this.load in case of a realy AJAX-call, can be overridden to support more functionality after an ajax-request.
		 * @param httpRequestObject req:
		 * @access private 
		 */
		_load:function(req){
			this.contentContainer.insert(req.responseText);
			this.setNavHooks();
		},
		
		/**
		 * Assigns show-hide events to retrieved subnavigation 
		 */
		setNavHooks : function(){
			this.resetSubNav();
			this.contentContainer.select('.navigationContainer .item').each(this.setNavEvents.bind(this));
			// set events on children:
			this.contentContainer.select('.subnavigationContainer .item').each(
				(function (elem){
					elem.observe('mouseover', this.resetTimeout.bind(this));
					elem.observe('mouseout', this.startTimeout.bind(this));
					this.setNavEvents(elem);
				}).bind(this)
			)
			if (this.widgetCallBack) this.widgetCallBack(this);
			if (window.location.search.toString().indexOf('refererDestination') > -1){
				// assume page was opened from reisgenotenforum, create a link back
				var item = new Element('a', {className:'item', id:this.instID+'_backtoReisgenoten'}).update("terug naar reisgenoten forum");
				this.contentContainer.select('.navigationContainer')[0].insert(item);
				item.observe('click', function(){
					// split the qs:
					var items = window.location.search.toString().split("&");
					var qs = $H({});
					items.each(
						function(token){
							token = token.toString().replace("?", "");
							token = token.toString().split("=");
							qs.set(token[0], token[1]);
						}
					)
					window.location.href="http://" + window.location.hostname + '/index.php#forumDestination=' + qs.get('refererDestination') +":forumDate=" + qs.get('refererDate') 
				})
				
			}
		},
		
		/**
		 * Assigns click-events to navigation-nodes
		 */
		setNavEvents : function(elem){
			// check if item has subnavigation:
			var subNavItems = this.hasSubNav(elem.getAttribute('id'));
			if (subNavItems.length > 0){
				// element should open children, doesn't do anything else!!
				elem.observe('mouseover', this.openSubNav.bindAsEventListener(this))
			}else{
				if (elem.getAttribute('url')){
					// elem should redirect to another page;
					elem.observe('click', function(e){
							window.location.href = e.element().getAttribute('url');
						} 
					);
				}else if (elem.getAttribute('onclick')){
					// elem has it's own event
				}else{
					// element should open a widget
					elem.observe('click', this.openWidget.bindAsEventListener(this));
				}
			}
		},
		
		/**
		 * Determines if a navigation-node has subnavigation (and returns subnavigation-nodes as an array)
		 */
		hasSubNav : function(buttonID){
			return $$('.subnavigationContainer .item').findAll(
				(function(elem){
					if (elem.getAttribute('buttonID') == buttonID) return elem;
				}).bind(this)
			)
		},
		
		/**
		 * Opens another widget
		 * TODO: Check if this can be done from the controller
		 */
		openWidget : function(e){
			// rpc call!
			var buttonID = e.element().id;
			var remote = new rpc('content', this.getContent.bind(this));
//			remote.debug=true;
			remote.call('getWidget', {'buttonID' : buttonID});
		},
		
		
		/** 
		 * Shows subnavigation (which was already rendered)
		 */
		openSubNav : function(e){
			this.resetTimeout();
			this.resetSubNav();
			var clicked = e.element();
			var subContainer = $$('.transparent .subnavigationContainer')[0];
			
			
			subContainer.show();
			var children = this.hasSubNav(clicked.id)
			children.each(
					function(elem){
						elem.show();
					}
			)
			if (Prototype.Browser.IE){
				subContainer.setStyle({top:(clicked.offsetTop) + 'px', left:clicked.offsetLeft+'px'});
				try{
					subContainer.relativize();
				}catch(e){
					// weird stuff, ie...
					if (window.console) console.log(e);
				}
			}else{
				subContainer.absolutize();
				subContainer.setStyle({top:(clicked.offsetTop + 15) + 'px', left:clicked.offsetLeft+'px'});
			}
			
			this.startTimeout();
		},
		
		/**
		 * Hides subnavigation (called from timeout)
		 */
		resetSubNav : function(){
			$$('.subnavigationContainer')[0].hide();	
			this.contentContainer.select('.subnavigationContainer .item').each(
				(function(elem){
					elem.hide();
				}).bind(this)
			)
		},
		
		/**
		 * determines where to open the subnavcontainer
		 */
		getSubOffset : function(){
			var vpWidth = document.viewport.getWidth();
			vpWidth = parseInt(vpWidth/2);
			
			if (parseInt(this.options.position.left) < vpWidth){
//				return parseInt(this.options.position.left) - this.options.size.width;
				return this.options.size.width + 5;
			}
			//return parseInt(this.options.position.left) + this.options.size.width;
			return (this.options.size.width * -1) -5 ;
		},
		
		/** 
		 * Starts timeout for hiding subnavigation
		 */
		startTimeout : function(){
			this.navTimeout = setTimeout(this.resetSubNav.bind(this), 1500);
		},
		
		/**
		 * Clears timeout for hiding subnavigation
		 */
		resetTimeout : function(){
			if (this.navTimeout)  clearTimeout(this.navTimeout)
		}
		
	});/**
 * This widget is drawn, but not shown; kind of remote javascripting, because you can execute javascript from the database
 */

	var hiddenWidget = Class.create(abstractWidget,{
		initialize : function($super, options){
			$super(options);
			this.instID = 'hiddenWidget.' + parseInt(Math.random()*1000000);	
		},

		render : function($super, container, callBack){
			$super(container, callBack);
			this.container.setStyle("display:none;");
		}
	
	});
	var tabbedWidget = Class.create(shadowedWidget,{
		initialize : function($super, options, tabs){
			$super(options);
			this.instID = 'tabbedWidget.' + parseInt(Math.random()*1000000);
			this.options.containerClassName = "tabbedWidget" 
			this.tabs = $H({});
			if (tabs.length> 0){
				$A(tabs).each(
					(function(tab){
						this.tabs.set(tab.id, tab);
					}).bind(this)
				)
			}
		},
		
		render : function($super, container, callBack){
			$super(container, callBack); // render widget as normal
			var tabsContainer = new Element('div', {className:'tabs', id:this.instID+"_tabsContainer"});
			this.container.insert(tabsContainer);
			
			this.tabsController = new jsTabsController(tabsContainer);
			this.tabsController.tabs = this.tabs;
			this.tabsController.render();
		}
		
	});/**
 * Implementation of the widget used as homepage -> REISVERHALEN
 * Extends upon shadowedWidget, but is prolly 99% on it's own
 * @author Ivo Toby, ivo@i-v-o.nl
 */

	var homepageWidget = Class.create(shadowedWidget,{

		/**
		 * Params; 
		 * $super = function of base-class (in this case shadowedWidget)
		 * options = hash-table of options
		 * userID = the userID of the reisverhalen-user
		 * clientIsOwner = boolean indicating the current user owns the reisverhalen (this is NOT a leak; the RPC-calls are checked!)
		 */
		initialize : function($super, options, userID, clientIsOwner, ad){
			if (userID) this.userID = userID;
			$super(options, this.controlTabs);
			this.instID = 'homepageWidget.' + parseInt(Math.random()*1000000);
			this.page = 0;
			this.loggedOnUserID = 0;
			if (clientIsOwner) this.clientIsOwner = clientIsOwner;
			if (ad){
				this.ad = ad;
			}else{
				this.ad = '';
			}
			this.widgetCallBack = function(){};
		},
		
		/** 
		 * Large parts of render are copied from shadowedWidget
		 */
		render : function($super, container, dummyCallBack, callBack){
//			callBack = '';
			this.callingContainer = container;
			if (this.rendered) return;
    		if (Prototype.Browser.IE){
//    			$(container).relativize(); // BUG// BUG// BUG// BUG// BUG// BUG// BUG// BUG// BUG// BUG// BUG// BUG MSIE
//    			$('demoContainer').absolutize();
//    			$('demoContainer').setStyle({left:'50%'});
    		}else{
				$('demoContainer').relativize();
    		}
			
			var elem = new Element('div', 
					{
						id:this.instID + "_widgetContainer", 
						className:this.options.containerClassName
					});
			container.insert(elem);
			this.baseContainer = elem;
			
			elem.widget = this;
			this.waiterElem = new Element('img',{align:'right', style:'display:none;', className:'waiter', src:this.controller.rootPath+ '/images/waiter.gif', id:this.instID+"_waiter"})
			elem.absolutize(); // prototype-function to make the element absolute
			elem.setStyle(
					{
						width:this.options.size.width + 'px',
						height:this.options.size.height + 'px',
						left:this.options.position.left + 'px',
						top:this.options.position.top+ 'px',
						zIndex:this.options.zIndex
					}
			);
			this.originalContainer = elem;
			this.container = elem;
			this.container.insert(this.waiterElem);
			this.load(); // start loading content

			// add shadow:
			var newzIndex = -1;
			if (parseInt(this.container.style.zIndex) >0){
				var newzIndex = parseInt(this.container.style.zIndex) - 1;
			}
			var shadow = new Element('div', {className:'shadow', id:this.instID+"_shadow"});
			this.shadow = shadow;
			shadow.absolutize();
			shadow.setStyle(
					{
						width: this.options.size.width + 'px',
						height: this.options.size.height + 'px',
						left:( parseInt(this.options.position.left) + parseInt(this.options.position.offsetLeft) ) + 'px',
						top: ( parseInt(this.options.position.top) + parseInt(this.options.position.offsetTop) )+ 'px',
						zIndex : newzIndex
					}
			);
			container.insert(shadow);			
			if (!this.userID){
				// get and build userlist:
				var remote = new rpc('story', this.setUserlist.bind(this));
//				remote.debug=true;
				remote.call('getUserList');
			}else{
				
				var closer = new Element('img', {className:'homePageCloser', src:'/images/closer.gif', style:'z-index:99;'});
				this.container.insert(closer); 
				closer.observe('click', this.closeMe.bind(this))

				var topContainer = new Element('div', {className:'topVertical'}); // enkelvoudige TAB
				this.container.insert(topContainer);
				
//				this.terugLink = new Element('a', {className:'terugLink'}).update('terug');
//				topContainer.insert(this.terugLink);
//				this.terugLink.observe('click', this.redrawStory.bind(this))
//				this.terugLink.hide();

				this.imgBlock = new Element('div', {className:'imgBlock'}); 
				this.container.insert(this.imgBlock);
				this.videoLink = new Element('img', {src:'/images/tab_video_off.png'});
				this.imgLink = new Element('img', {src:'/images/tab_foto_on.png'});
				var videoLink = new Element('a', {className:'fotoblockLink', id:'videoLink'}).update(this.videoLink);
				var imgLink = new Element('a', {className:'fotoblockLink', id:'fotoLink'}).update(this.imgLink);
				
				this.imgBlock.insert(imgLink);
				this.imgBlock.insert(videoLink);

				videoLink.observe('click', this.showVideo.bindAsEventListener(this));
				imgLink.observe('click', this.showReisVerhaalFotos.bindAsEventListener(this));

//				videoLink.observe('mouseover', (function(){
//					this.imgBlock.setStyle("background:transparent url(../images/full_tab_reverse.png) no-repeat scroll 0 0;")	
//				}).bind(this));
//
//				videoLink.observe('mouseout', (function(){
//					this.imgBlock.setStyle("background:transparent url(../images/full_tab.png) no-repeat scroll 0 0;")	
//				}).bind(this));
				
				
				this.terugLink = new Element('img', {src:'/images/left_tab.png', className:'leftTab'});
				this.container.insert(this.terugLink);
				this.terugLink.observe('click', this.redrawStory.bind(this))

				var fakeScroller = new Element('div', {className:'fakeScroller', id:'fakeTabbedScroller'});
				this.container.insert(fakeScroller);

				var scrollContainer = new Element('div', {className:'makeScroll', id:'makeScroll'});
				this.container.insert(scrollContainer);

				this.fotoContents = new Element('div', {className:'fotoContents', id:this.instID+"_fotoContents"});
//				this.imgBlock.insert(this.fotoContents);
				scrollContainer.insert(this.fotoContents);
				


				this.content = new Element('div', {className:'tabbedContent', id: this.instID + '_tabbedContent'});
				scrollContainer.insert(this.content);
				
				this.photoLayer = new Element('div', {className:"photoLayer"});
				scrollContainer.insert(this.photoLayer);
				this.photoLayer.hide();

				
				var head = new Element('div', {className:'tabHead'})
				this.content.insert(head);

				this.headRightTop = new Element('div', {className:'top'});
				head.insert(this.headRightTop);
	
				head.insert(new Element('div', {className:'thickLine'}));
				
				var titleContainer = new Element('div', {className:'bottom'});
				head.insert(titleContainer);
				
				this.title = new Element('span', {className:'largeTitle'});
				titleContainer.insert(this.title);
			
				var linksContainer = new Element('div', {className:'tabbedLinks'});
				this.content.insert(linksContainer);
				
				this.linksRight = new Element('div', {className:'right'});
				linksContainer.insert(this.linksRight);

				var linksLeft = new Element('div', {className:'left'});
				linksContainer.insert(linksLeft);
				
				var loginLink = new Element('a').update('Login');
				linksLeft.insert(loginLink);
				loginLink.observe('click', (function(){
						control.getContentWidget(2);
						this.closeMe();
					}).bind(this)
				);
	
//				var reactLink = new Element('a').update('  /  Reageer');
//				linksLeft.insert(reactLink);
//				reactLink.observe('click', this.openReactionWidget.bind(this))
				
				
				this.actualContent = new Element('div', {className:'actualContent'});
				this.content.insert(this.actualContent);
				
				var footer = new Element('div', {className:'tabbedFooter'});
				this.container.insert(footer);

				var div = new Element('div', {className:'topLine'});
				footer.insert(div);

				var div = new Element('div', {className:'tabbedScroller'});
				footer.insert(div);

				this.ads = new Element('div', {className:'ads'});
				footer.insert(this.ads);
				if (!this.ad){
//					var someAd = new Element('a', {href:'javascript:openGroepsreizenWidget(\'/include/inhoud_groepsreizen.php?keus=e\')'}).insert(new Element('img', {src:'/images/ads/ad_1.png', border:'0'}));
				}else{
					var someAd = this.ad;
				}
				this.ads.insert(someAd);

				this.floatBlock = new Element('div', {className:'floatBlock'});
				footer.insert(this.floatBlock);
				
				this.infoPanel = new Element('div', {className:'floatBlock'});
				footer.insert(this.infoPanel);
				this.infoPanel.hide();
//	// ASSIGN EVENT!

	// \\LINKS			
				
	// CONTENT:
	// \\CONTENT
	
	// FOOTER
	// ASSIGN ID OR FILL WITH LIST
				
				// temp:
				
				if (this.clientIsOwner){
					var editLink = new Element('a').update("Reisverhaal toevoegen");
					this.floatBlock.insert(editLink);
					editLink.observe('click', (function(){
							control.getContentWidget(9);
						}).bind(this)
					);
					this.floatBlock.insert('<br/>');
					this.editLink = new Element('a', {id:this.instID+"_editStoryLink"}).update("Dit reisverhaal bewerken");
					this.floatBlock.insert(this.editLink);
					this.editLink.observe('click', this.editStory.bind(this))
				}
//	
//				var floatBlock = new Element('div', {className:'floatBlock'});
//				footer.insert(floatBlock);
	// ASSIGN ID OR FILL WITH LIST

				this.rendered = true;
				if (!callBack) {
					this.getStories();
				}else{
					callBack();
				}
			}
			this.container.observe(gDefaultFocusEvent, this.toFG.bind(this))
			if (gDefaultFocusEvent == 'mouseover') this.container.observe('mouseout', this.toBG.bind(this))
			
		},
		
		/**
		 * Opens another widget to allow user to edit the currently shown reisverhaal
		 */
		editStory:function(e){
			var story = this.story;
			var func = (function(){
				this.editting = new editStory(story);
			}).bind(this)
			this.localContentWidget(11, '',  '', func);
		},
		
		/**
		 * Retrieves all stories from user 
		 */
		getStories : function(){
			var remote = new rpc('story', this.setStory.bind(this));
			remote.debug=true;
			remote.call('getUserStories', {userID : this.userID});
		},
		
		
		/** 
		 * Callback from getStories; stores retrieved stories in memory (this.stories)
		 */
		setStory : function(req){
			this.stories = req.responseJSON;
			if (!this.stories || !this.stories.length ){
				if (this.clientIsOwner){
					this.stories = defaultReisverhaal;
					this.isDefaultStory = true;
					if (this.editLink) this.editLink.hide();
				}else{
					this.closeMe();
				}
			}else{
				this.isDefaultStory = false;
				if (this.editLink) this.editLink.show();
			}
			this.story = this.stories[0];
			this.createStoryList();
			var hash = window.location.hash;
			if (hash){
				var commands = $H({});
				hash = hash.replace("#","");
				// split hash:
				hash = hash.split(":");
				hash.each(
					function(token){
						token = token.split('=');
						commands.set(token[0], token[1]);
					}
				)
				// always open a story:
				this._openStory(commands.get('story'));
				// check if there's a photo in commands
				if (commands.get('photo')){
					this.showReisVerhaalFotos('', commands.get('photo'));
					// zoom foto:
//					var sZoom = new simpleZoom('', '/upload/userimages/originals/' + commands.get('photo') + '.jpg', true);
				}
				if (commands.get('video')){
					// search video obj by ID:
					var videoObj = '';
					this.story.videos.each(
						function(vid){
							if (vid.id == commands.get('video')) videoObj = vid; 
						}
					)
					if (videoObj){
						this.showVideo('', videoObj);
					}else{
						alert("Video niet gevonden of verwijderd");
					}
				}
				
			}else{
				this.drawStory();
			}
			this.profielFoto = control.get('profielFoto');
			
			if (!this.profielFoto){
				this.profielFoto = new profielFotoWidget(
    				{
    						id:'profielFoto',
    						position:{left:50, top:225}, 
    						canHide:true,
    						scrolling:false,
    						showClose:false,
    						overrideZIndex : 10
    				},
    				this.userID,
    				this
    			);
				control.add(this.profielFoto);
				control.render();
			}
		},
		
		/**
		 * Renders a story
		 */
		drawStory : function(){
			// reset fields
//			if (!this.story){
//				if (this.editLink) this.editLink.hide();
//			}else{
//				if (this.editLink) this.editLink.show();
//			}
			this.title.update('');
			this.actualContent.update('');
			this.fotoContents.update('');
			this.linksRight.update('');
//			this.ads.update('');
			if (this.story.images.length > 0){
				var img = new Element('img', {className:'headerImage', align:'left', src:'/upload/userimages/191/' + this.story.images[0].id + '.jpg'})
				this.fotoContents.update(img);			
				img.observe('click', this.showReisVerhaalFotos.bindAsEventListener(this));
			}else{
				var img = new Element('div', {className:'fakeImage'})
				this.fotoContents.update(img);
			}
//			this.story.title = 
			var storyTitle = this.story.title.toUpperCase();
			var endTitleText = '';
			var thirdRowTitleText = '';
			if (storyTitle.length > 24){
				// THIS IS NASTY STUFF;; rule of thumb; if it ain't broken, do not fix it!
				// create 2 rows from text:
				var titleText = storyTitle;
				var startTitleText = titleText.substring(0, 24);
				// first check if current break is on a space
				// sentence break in the midst of a word, loop from char 32 to 0 until a space if found:
				var newIdx =0;
				for(var i = 24;i>0;i--){
					var char = titleText.substring(i-1, i);
					if (char == ' '){
						newIdx = i;
						break;
					}
				}
				// break startTitle:
				startTitleText = titleText.substring(0, newIdx);
				endTitleText = titleText.substring(newIdx, titleText.length);

				// now check if a 3rd row is needed;
				if (endTitleText.length > 24){
					// yup!
					titleText = endTitleText;// reassign and do it again
					// sentence break in the midst of a word, loop from char 32 to 0 until a space if found:
					var newIdx =0;
					for(var i = 24;i>0;i--){
						var char = titleText.substring(i-1, i);
						if (char == ' '){
							newIdx = i;
							break;
						}
					}
					// break startTitle:
					endTitleText = titleText.substring(0, newIdx);
					// determine last allowed char on third row:
					thirdRowTitleText = titleText.substring(newIdx, titleText.length);
					if (thirdRowTitleText.length > 20){
						thirdRowTitleText = thirdRowTitleText.substring(0,20) + '...'
					}
				}
				
				var img = new Element('img', {className:'titleImg', src:'/include/largeTitle.php?text=' + startTitleText});
				this.title.update( img );				
				var img = new Element('img', {className:'titleImg', src:'/include/largeTitle.php?text=' + endTitleText});
				this.title.insert( img );
				if (thirdRowTitleText){
					var img = new Element('img', {className:'titleImg', src:'/include/largeTitle.php?text=' + thirdRowTitleText});
					this.title.insert( img );
				}
			}else{
				var img = new Element('img', {className:'titleImg', src:'/include/largeTitle.php?text=' + this.story.title});
				this.title.update( img );				
			}
			this.actualContent.update('');
			this.actualContent.insert(new Element('img', {src:'/images/pijlen/right_large.gif', className:'textArrow'}));
			this.actualContent.insert(nl2br(this.story.bbCode));
			
			var lastName = this.story.userData.last_name;
			this.linksRight.update('<font style="font-weight:bold;">' + this.story.userData.first_name + ' ' + lastName + '</font><font style="font-style:italic;"> ' + this.story.location + ' ' + this.getFriendlyDate(this.story.dtAdded) + '</font>');

			getSocialBookMarks(this.actualContent, 'http://' + window.location.hostname +'/userHome.php' + window.location.search + "#story=" + this.story.id, this.story.title);
			
			if (this.userID && !this.isDefaultStory){
//				/// draw reaction-iframe:
//				var iframe = new Element('iframe', {scrolling:"no", frameborder:"0",  height:'100000px', className:'reactionIframe',id:this.story.id + "_reactions", src:'/modules/reactions/index.php?list=1&tableID=PROFILE_stories&recordID=' + this.story.id});
//				var iframeDiv = new Element('div', {className:'reactContainer', id:this.story.id+'_reactionIframeContainer'}).insert(iframe);
//				window.reactionContainer = iframeDiv;
				var reactionContainer = new Element('div', {className:'homepageReactions'});
				this.actualContent.insert(reactionContainer);
				try{
					var func = 	function(){$j('#makeScroll').jScrollPane({animateTo:true,scrollbarWidth:20, scrollbarMargin:10, dragMaxHeight:16, dragMinHeight:16, showArrows:false})};
					this.reactions = new bpStoryReactie(reactionContainer, this.story, this.loggedOnUserID, func);
				}catch(e){
					if (window.console) console.log(e)
				}
				$j('#makeScroll').jScrollPane({animateTo:true,scrollbarWidth:20, scrollbarMargin:10, dragMaxHeight:16, dragMinHeight:16, showArrows:false});
			}else{
				$j('#makeScroll').jScrollPane({animateTo:true,scrollbarWidth:20, scrollbarMargin:10, dragMaxHeight:16, dragMinHeight:16, showArrows:false});
			}

				// set map to position of story:
			if (this.story.coordsX != 0 && this.story.coordsY != 0){
				if (this.story.zoomLevel) {
					gmc.map.panTo(new GLatLng(this.story.coordsY, this.story.coordsX));
					setTimeout(
						(function(){
							gmc.map.setZoom(parseInt(this.story.zoomLevel))
						}).bind(this), 
						2500
					)
				}else{
					gmc.map.panTo(new GLatLng(this.story.coordsY, this.story.coordsX));
				}
			}
			this.widgetCallBack();

		},

		
		/**
		 * Renders a list of other stories 
		 */
		createStoryList: function(){
			if (this.isDefaultStory) return;
			this.headRightTop.update('');
			var storyCount = this.stories.length;
			var pageCount = Math.round(storyCount/8);
			
			// create 2 lists
			var ul1 = new Element('ul', {className:'leftList'});
			var ul2 = new Element('ul', {className:'rightList'});
			this.headRightTop.insert(ul1);
			this.headRightTop.insert(ul2);
			var start = (this.page * 8) ;
			var end = start+8;
			var rightArrow = new Element('img', {src:'/images/pijlen/right_large.gif', className:'navArrowRight', style:'display:none;'});
			this.headRightTop.insert(rightArrow);
			rightArrow.observe('click', this.nextPage.bind(this))
			
			var leftArrow = new Element('img', {src:'/images/pijlen/left_large.gif', className:'navArrowLeft', style:'display:none;'});
			this.headRightTop.insert(leftArrow);
			leftArrow.observe('click', this.prevPage.bind(this))
			
			if (pageCount > 0 && ( this.page < pageCount-1 ) ){
				rightArrow.show();
			}
			if (this.page > 0){
				leftArrow.show();
			}
			for (var i=start;i<end;i++){
				var story = this.stories[i];
				if ( (story) ) { //&& (story.id != this.story.id)
					var titleText = story.title;
					if (titleText.length > 25){
						titleText = titleText.substring(0, 22) + '...';
					}
					var li = new Element('li').update(titleText);
					li.storyID = story.id;
					if (i%2 == 0){
						ul1.insert(li);
					}else{
						ul2.insert(li);					
					}
					li.observe('click', this.openStory.bind(this));
				}
			}

		},
		
		/**
		 * Renders the previous page of the story-list, 
		 */
		prevPage : function(){
			this.page--;			
			this.createStoryList();
		},

		/**
		 * Renders the next page of the story-list, 
		 */
		nextPage : function(){
			this.page++;
			this.createStoryList();
		},
		
		hideContentLayer:function(){
			if ($(this.instID+"_fotoContents")) $(this.instID+"_fotoContents").hide();
//			this.imgBlock.hide();
			this.content.hide();
			this.photoLayer.update('');
			this.photoLayer.show();
		},

		/**
		 * Needs implementation!
		 */
		showVideo : function(e, videoObj){
			if (this.story.videos && this.story.videos.length > 0){
				this.imgLink.src = this.imgLink.src.replace('on', 'off');
				this.videoLink.src = this.videoLink.src.replace('off', 'on');
				
				this.currVideoIdx= 0;
				if (e) e.element().src = e.element().src.replace('off', 'on'); 
				this.hideContentLayer();
				this.floatBlock.hide();
				this.infoPanel.show();
				this.videoInfoPanel = new Element('div', {className:'videoInfoPanel'});
				this.infoPanel.update(this.videoInfoPanel);
				
				if (this.story.videos.length > 0){
					this.videoRightArrow = new Element('img', {src:'/images/pijlen/right_large.gif', className:'videoArrowRight'});
					this.videoRightArrow.hide();
					this.infoPanel.insert(this.videoRightArrow);
					this.videoRightArrow.observe('click', this.nextVideo.bindAsEventListener(this))
					
					this.videoLeftArrow = new Element('img', {src:'/images/pijlen/left_large.gif', className:'videoArrowLeft'});
					this.infoPanel.insert(this.videoLeftArrow);
					this.videoLeftArrow.observe('click', this.prevVideo.bindAsEventListener(this))
					this.videoArrows();
				}
				if (!videoObj) videoObj = this.story.videos[0];
				this.playVideo('', videoObj);
				$j('#makeScroll').jScrollPane({animateTo:true,scrollbarWidth:20, scrollbarMargin:10, dragMaxHeight:16, dragMinHeight:16, showArrows:false});
			}else{
				alert("Geen video's beschikbaar");
			}			
		},
		
		nextVideo:function(){
			if (this.currVideoIdx < this.story.videos.length){
				this.currVideoIdx++;
			}else{
				return;
			}
			this.videoArrows();
			this.playVideo('', this.story.videos[this.currVideoIdx]);
		},
		
		prevVideo:function(){
			if (this.currVideoIdx > 0){
				this.currVideoIdx--;
			}else{
				return;
			}
			this.videoArrows();
			this.playVideo('', this.story.videos[this.currVideoIdx]);
		},
		
		videoArrows : function(){
			// more than 1 video, show arrows
			if (this.currVideoIdx == 0){
				// hide back arrow
				this.videoLeftArrow.hide();
			}else{
				//show back arrow
				this.videoLeftArrow.show();
			}
			if (this.currVideoIdx < (this.story.videos.length -1)){
				// show forward arrow
				this.videoRightArrow.show();
			}else{
				// hide forward arrow
				this.videoRightArrow.hide();
			}			
		},
		
		playVideo : function(e, imgObj){
			if (!imgObj ) imgObj = e.element().imgObj;

			this.photoLayer.update('');
			
			var movieContainer = new Element('div', {id:imgObj.id + '_videoContainer', className:'videoContainer'});
			this.photoLayer.insert(movieContainer);
//			var so = new SWFObject('/js/3rdparty/mediaplayer.swf', imgObj.id + '_video', (parseInt(this.photoLayer.getWidth()) - 20),'468','0');
			var so = new SWFObject('/js/3rdparty/mediaplayer/player.swf', imgObj.id + '_video', '630','468','0');
			so.addVariable("javascriptid",imgObj.id + '_video');

			so.addParam('allowscriptaccess','always');
            so.addParam('allowfullscreen','false');

            so.addVariable('displayheight', '469')
            so.addVariable('autostart', 'true');
            so.addVariable('file',imgObj.URI);
			so.write(imgObj.id + '_videoContainer');
			
			var metaBlock = new Element('div', {className:'videoMetaData'});
//			this.photoLayer.insert(metaBlock);
			var dateVal = '';
			if (imgObj.dateTaken) {
				dateVal = imgObj.dateTaken.toString();
				dateVal = dateVal.split(' ');
				dateVal = dateVal[0].split('-');
				dateVal = dateVal[2] + '-' + dateVal[1] + '-' + dateVal[0];
			}
			
			if (imgObj.name) metaBlock.insert(new Element('span').update("<b>" + imgObj.name +"</b> <i>" + dateVal + "</i>"))
//			if (imgObj.description) metaBlock.insert(imgObj.description)

			this.videoInfoPanel.update(metaBlock);

			if (imgObj.coordsX != 0 && imgObj.coordsY != 0){
				if (imgObj.zoomLevel) {
					gmc.map.panTo(new GLatLng(imgObj.coordsY, imgObj.coordsX));
					setTimeout(
						(function(){
							gmc.map.setZoom(parseInt(imgObj.zoomLevel))
						}).bind(this), 
						2500
					)
				}else{
					gmc.map.panTo(new GLatLng(imgObj.coordsY, imgObj.coordsX));
				}
			}				
		},
		
		/**
		 * Called from the storylist; renders the contents of a story
		 */
		openStory : function(e){
			this.baseContainer.remove();
			this.shadow.remove();
			this.rendered = false;
			var func = (function(){
				$j('#makeScroll').jScrollPaneRemove();
				var elem = e.element();
				var storyID = elem.storyID;
				this.createStoryList();
				this._openStory(storyID);
			}).bind(this)

			this.render(this.callingContainer, '', func);
//			var elem = e.element();
//			var storyID = elem.storyID;
//			this._openStory(storyID);			
		},
		
		_openStory : function(storyID){
			var localStory = this.stories.find(
				(function(st){
					if (st.id == storyID){
						return st;
					}
				}).bind(this)
			)
			this.story = localStory;
			this.drawStory();
		},
		
		/**
		 * returns a human-readable date from a database-date-value
		 */
		getFriendlyDate : function(dbDate){
			var dateValue = dbDate;
			dateValue = dateValue.split(' ');
			dateValue = dateValue[0].split('-');
			dateValue = dateValue[2] + '/' + dateValue[1] + '/'+dateValue[0];
			return dateValue ;			
		},
		
		redrawStory : function(){
//			this.photoLayer.hide();
//			this.photoLayer.update('');
//			this.imgBlock.show();
//			this.content.show();
//			$(this.instID+"_fotoContents").show();
//			this.videoLink.src = this.videoLink.src.replace('on', 'off');
//			this.imgLink.src = this.imgLink.src.replace('off', 'on');
//			// reset footer;
//			this.floatBlock.show();
//			this.infoPanel.hide();
//			this.infoPanel.update('');
			this.baseContainer.remove();
			this.shadow.remove();
			this.rendered = false;
			var func = (function(){
				$j('#makeScroll').jScrollPaneRemove();
				this.createStoryList();
				this._openStory(this.story.id);
			}).bind(this)

			this.render(this.callingContainer, '', func);			
		},
		
		/**
		 * Renders reisverhalen-foto's
		 */
		showReisVerhaalFotos : function(e, photoID){
			if (!photoID) photoID = 0;
			if (this.story.images && this.story.images.length > 0){
				this.imgLink.src = this.imgLink.src.replace('off', 'on');
				this.videoLink.src = this.videoLink.src.replace('on', 'off');
				this.hideContentLayer();
				var flashLayer = new Element('div', {id:this.instID+"_flashFotoGallery"});
				this.photoLayer.insert(flashLayer);
				var obj = new fotoBrowser(flashLayer, this.infoPanel, this.floatBlock, this.story);
				obj.draw(photoID);
				$j('#makeScroll').jScrollPane({animateTo:true,scrollbarWidth:20, scrollbarMargin:10, dragMaxHeight:16, dragMinHeight:16, showArrows:false});
			}else{
				alert("Geen afbeeldingen beschikbaar");
			}
			
		},
		
		
		showReisVerhaalFotosFlash : function(e){
			if (this.story.images && this.story.images.length > 0){
				this.imgLink.src = this.imgLink.src.replace('off', 'on');
				this.videoLink.src = this.videoLink.src.replace('on', 'off');
				this.hideContentLayer();
				var flashLayer = new Element('div', {id:this.instID+"_flashFotoGallery"});
				this.photoLayer.insert(flashLayer);
				
//				var flashvars = {XMLFile: "/js/3rdparty/StackPhotoGallery/gallery.xml"};
//				var flashvars = {XMLFile: "/include/albumXMLZen.php?storyID=" + this.story.id};
				var flashvars = {XMLFile: "/include/albumXMLBox.php?storyID=" + this.story.id};
				var params = {bgcolor: "#ffffff"};
				//swfobject.embedSWF("/js/3rdparty/StackPhotoGallery/StackPhotoGalleryDemo.swf", this.instID+"_flashFotoGallery", "600", "460", "9.0.0",false, flashvars, params);
//				swfobject.embedSWF("/js/3rdparty/ZenFlashGallery/ZenGalleryDemo.swf", this.instID+"_flashFotoGallery", "630", "460", "9.0.0",false, flashvars, params);
				swfobject.embedSWF("/js/3rdparty/BoxFlashGallery/BoxFlashGalleryDemo.swf", this.instID+"_flashFotoGallery", "630", "460", "9.0.0",false, flashvars, params);
				
			}else{
				alert("Geen afbeeldingen beschikbaar");
			}
		},
		
		_showReisVerhaalFotos : function(e, photoID){
			if (photoID){
				this.zoomImg('', photoID);
			}else{
				if (this.story.images && this.story.images.length > 0){
					this.imgLink.src = this.imgLink.src.replace('off', 'on');
					this.videoLink.src = this.videoLink.src.replace('on', 'off');
					this.hideContentLayer();
					this.story.images.each(
						(function(imgObj){
							var div = new Element('div', {className:'storyImage'});
							var img = new Element('img', {src:'upload/userimages/50/' + imgObj.id + ".jpg"})
							img.imgID = imgObj.id;
							img.imgObj = imgObj;
							div.insert(img);
	//						var span = new Element('span', {className:'imgDescription'}).update(imgObj.description);
	//						div.insert(span);
							this.photoLayer.insert(div);
							img.observe('click', this.zoomImg.bindAsEventListener(this))
							img.observe('mouseover', this.showImgInfo.bindAsEventListener(this));
							img.observe('mouseout', this.hideImgInfo.bindAsEventListener(this))
						}).bind(this)
					)
					$j('#makeScroll').jScrollPane({scrollbarWidth:20, scrollbarMargin:10, dragMaxHeight:20, dragMinHeight:20, showArrows:false});
				}else{
					alert("Geen afbeeldingen beschikbaar");
				}
			}				
		},
		
		showImgInfo: function(e){
			var imgObj = e.element().imgObj;
			this.floatBlock.hide();
			var container = new Element('div', {className:'fotoInfo'});
			this.infoPanel.insert(container);
			if (imgObj.name) container.insert('<b>' + imgObj.name + "</b>");
//			if (imgObj.tags) this.infoPanel.insert(imgObj.tags);
			if (imgObj.dateTaken !='0000-00-00 00:00:00'){
				container.insert("<i>" + this.getFriendlyDate(imgObj.dateTaken) + "</i>");
			}else{
				container.insert("<i>" + this.getFriendlyDate(imgObj.dateAdded) + "</i>");
			}
			if (imgObj.description) container.insert(' ' + imgObj.description.substring(0, 69));
			this.infoPanel.show();
		},
		
		hideImgInfo: function(){
			this.floatBlock.show();
			this.infoPanel.hide();
			this.infoPanel.update('');
		},
		
		/** 
		 * Renders a list of users that have reisverhalen
		 */
		setUserlist : function(req){
			this.container.insert(new Element('h1').update("Kies een gebruiker:"));
			var list = new Element('ul',{className:'userList'});
			this.container.insert(list);
			req.responseJSON.each(
				function(user){
					var userName = user.first_name;
					userName += " " +user.last_name;
					var li = new Element('li').update(userName);
					li.userID = user.userID;
					list.insert(li);
					li.observe('click', function(e){
						window.location = 'http://' + window.location.hostname + '/userHome.php?userID='+e.element().userID;
					})
				}
			)
			
		},
		
		/**
		 * called when a user clicks an image when reisverhalen-images are shown,
		 * could/should be rewritten for lightbox or something in the likes of lightbox
		 */
		zoomImg : function(e, imgID){
			if (!imgID) imgID = e.element().imgID;
			var sZoom = new simpleZoom('', '/upload/userimages/originals/' + imgID + '.jpg', true);
//			window.open('/upload/userimages/originals/' + imgID + '.jpg');
		},
		
		/**
		 * Because of the shadow-layer this widget has it's own implementation of hide
		 */
		hide : function(){
			this.originalContainer.hide();
			if (this.shadow) this.shadow.hide();
		},
		
		/**
		 * Because of the shadow-layer this widget has it's own implementation of show
		 */
		show : function(){
			this.originalContainer.show();
			if (this.shadow) this.shadow.show();
		},
		
		localContentWidget : function(cID, contentName, qs, callBack){
			if (!contentName) contentName = '';
			if (!cID) cID = '';
			if (!callBack) callBack = function(){}
			var func = (function(req){
				this._localContentWidget(req, qs, callBack);
			}).bind(this);
			var remote = new rpc('content', func);
//			remote.debug=true;
			remote.call('getWidget', {'contentID' : cID, 'contentName':contentName});
		},
		
		/** 
		 * Private function, see getContentWidget
		 */
		_localContentWidget : function(req, qs, callBack, zIndex){
			if (!zIndex) zIndex ='';
			var widget ='';
			req.responseJSON.each(
				(function(aWidget){
					widget = aWidget.widgetClass;
					if (!widget){
						widget = 'shadowedWidget';
					}
					var widgetClassName = aWidget.widgetClassName;
					if (!widgetClassName) widgetClassName = 'whiteWidget'
					if (!qs) qs='';
					widget = new window[widget]({
						position:{
							left:aWidget.widgetLeft, 
							top:aWidget.widgetTop
						}, 
						size:{	
							width:aWidget.widgetWidth, 
							height:aWidget.widgetHeight
						}, 
						useIFrame:false, 
						containerClassName:widgetClassName,
						showClose:aWidget.widgetShowClose,
						ajax:{uri:'/include/lib/rpc.php?action=content&method=getContent&id=' + aWidget.contentID + "&buttonID=" + aWidget.buttonID +"&"+qs},
						onloadCallback : aWidget.widgetOnloadCallback,
						closeOther : aWidget.widgetCanCloseOther,
						canHide : aWidget.widgetCanHide
					});
					if (aWidget.widgetID) widget.options.id = aWidget.widgetID; 
					window.parent.control.add(widget);
//					this.add(widget);
				}).bind(this)
			);
			window.parent.control.render();
			this.isRetrieving = false;
			setTimeout(function(){callBack(req, widget);}, 100);
		}
		
	});/**
 * Implementation of the widget used as homepage -> REISVERHALEN
 * Extends upon shadowedWidget, but is prolly 99% on it's own
 * @author Ivo Toby, ivo@i-v-o.nl
 */

	var profielFotoWidget = Class.create(shadowedWidget,{

		/**
		 * Params; 
		 * $super = function of base-class (in this case shadowedWidget)
		 * options = hash-table of options
		 * userID = the userID of the reisverhalen-user
		 * clientIsOwner = boolean indicating the current user owns the reisverhalen (this is NOT a leak; the RPC-calls are checked!)
		 */
		initialize : function($super, options, userID, homepageWidget){
			if (userID) this.userID = userID;
			$super(options);
			this.instID = 'profielFotoWidget.' + parseInt(Math.random()*1000000);
			this.page = 0;
			this.images = [];
			this.maxImages = 15;
			this.maxRetries = 2;
			this.retries = 0;
			this.checked = false;
			this.rendered = false;
			this.options.containerClassName = 'whiteWidget';
			if (Prototype.Browser.IE){
				this.options.size = {width:208, height:258};
			}else{
				this.options.size = {width:210, height:258};
			}

			this.itemsPerPage = 16;
			this.page = 0;
			this.navigatorPage = 0;
			this.navigatorItemsPerPage = 4;
			this.startFrom = 0;
			this.endOn = 16;
			this.homepageWidget = homepageWidget;
		},
		
		render : function($super, container, callBack){
			// first check for images:
			if (this.checkForImages()){
				$super(container, callBack);
				this.imagesDiv = new Element('div', {className:'profielImagesContainer', id:this.instID+"_profielImagesContainer"});
				this.contentContainer.insert(this.imagesDiv);
				
				this.controlDiv = new Element('div', {className:'controlContainer', id:this.instID+"_controlContainer"});
				this.contentContainer.insert(this.controlDiv);
	
				this.navigator = new Element('div', {id:this.instID + '_navigator', className:'navigator'});
				this.controlDiv.insert(this.navigator);
				this.drawImages();
			}
		},

		checkForImages : function(){
			if (!this.homepageWidget.stories){
				return false;
			}
			if(this.homepageWidget.stories.length < 1){
				return false;
			}
			this.homepageWidget.stories.each(
					(function(story){
						this.addImagesFromStory(story);
					}).bind(this)
			)
			if (this.images.length > 3){
				return true;
			}else{
				return false;
			}
			return true;
		},
		
		addImagesFromStory : function(story){
			if (!story.images) return;
			try{
				story.images.each(
					(function(image){
						image.srcStory = story;
						this.images.push(image);
					}).bind(this)
				)
			}catch(e){
//				this.images.push(story.images);
			}
		},
		
		drawImages : function(){
			if (this.images.length > 1){
				for (var i=this.startFrom;i<this.endOn;i++){
					var img = this.images[i];
					if (img){
						var imgElement = new Element('img', {src:'/upload/userimages/50/' + img.id + '.jpg', className:'profileImage'});
						imgElement.setStyle("border:1px white solid;");
						imgElement.imgObj = img;
						imgElement.storyObj = img.srcStory;
						imgElement.imgID = img.id;
						this.imagesDiv.insert(imgElement);
						imgElement.observe('mouseover', this.highlite.bindAsEventListener(this));
						imgElement.observe('mouseout', this.unhighlite.bindAsEventListener(this));
						imgElement.observe('click', this.zoomImg.bindAsEventListener(this));
					}
				}
			}
			this.drawNavigator();
		},
		
		highlite : function(e){
			var elem = e.element();
			elem.setStyle("border:1px #1e3066 solid;");
			this.highlited = elem;
		},

		unhighlite : function(e){
			if (this.highlited) this.highlited.setStyle("border:1px white solid;")
		},
		
		zoomImg : function(e){
//			var imgID = e.element().imgID;
//			var sZoom = new simpleZoom('', '/upload/userimages/originals/' + imgID + '.jpg', true);
			if (!this.homepageWidget || !control.widgets.get('homepageWidget')){
				this.openNewReisverhalenWidget(e.element().storyObj, e.element().imgID);
			}else{
				this.homepageWidget.story = e.element().storyObj;
				this.homepageWidget.showReisVerhaalFotos('', e.element().imgID);
			}
			
		},
		
		openNewReisverhalenWidget : function(storyObj, imgID){
    		var homepage = getEmptyHomepageWidget();
    		homepage.userID = this.userID;
    		control.add(homepage);
			control.render();
			homepage.story = storyObj;
			homepage.showReisVerhaalFotos('', imgID);
			this.homePageWidget = homepage;
			return homepage;
		},
		
		openReisverhalenWidget : function(){
			if (!callBack) callBack = function(){}
    		var homepage = getEmptyHomepageWidget();
    		homepage.userID = this.userID;
    		this.homePageWidget = homepage;
			control.add(homepage);
			control.render();
			return homepage;
		},
		
		drawNavigator : function(){
			var container = new Element('div', {className:'navCont'});
			this.navigator.update(container);
			
			var pageCount = Math.ceil(this.images.length/this.itemsPerPage);
			if (pageCount  < 2) return;
			var start = this.navigatorPage;
			var end = this.navigatorPage + this.navigatorItemsPerPage;
			
			if (end > pageCount){
				end = pageCount;
			}
			if (start > 0){
				var prevNavPage = new Element('img', {src:'/images/searcharrow_previous.png', className:'profileFotoPrevious'});
				container.insert(prevNavPage);
				prevNavPage.observe('click', this.prevNavigatorPage.bindAsEventListener(this));
			}else{
				var prevNavPage = new Element('div', {className:'profileFotoPrevious'});
				container.insert(prevNavPage);
			}
			
			var navigatorRow = new Element('div', {className:'navigatorRow'});
			container.insert(navigatorRow);

			for (var i=start;i<end;i++){
				var item = new Element('span').update((i+1) + '/');
				if (i==this.page) {
					item.className ='active';
				}else{
					item.className ='inactive';
				}
				item.page = i;
				navigatorRow.insert(item);
				item.observe('click', this.goToPage.bindAsEventListener(this));
			}
			if (pageCount > end){
				navigatorRow.insert(' ... ');
				var nextNavPage = new Element('img', {src:'/images/searcharrow_next.png', className:'profileFotoNext'});
				container.insert(nextNavPage);
				nextNavPage.observe('click', this.nextNavigatorPage.bindAsEventListener(this));
			}else{
				var nextNavPage = new Element('div', {className:'profileFotoNext'});
				container.insert(nextNavPage);
			}
		},
		
		prevNavigatorPage : function(e){
			this.navigatorPage = this.navigatorPage - this.navigatorItemsPerPage;
			this.drawNavigator();
		},
		
		nextNavigatorPage : function(e){
			this.navigatorPage = this.navigatorPage + this.navigatorItemsPerPage;
			this.drawNavigator();
		},
		
		goToPage : function(e){
			var page = e.element().page;
			this.page = page;
			this.startFrom = this.page * 16;
			this.endOn = this.startFrom + 16;
			this.imagesDiv.update('');
			this.drawImages();
		}


	});/**
 * Implementation of a widget with a shadow-like-background
 * you can change the offset of the shadow by altering:
 * 		this.options.offsetLeft = int-value
 * 		this.options.offsetTop = int-value
 * @author Ivo Toby, ivo@i-v-o.nl 
 */

	var borderedWidget= Class.create(shadowedWidget,{
		
		initialize : function($super, options){
			$super(options);// run initialize of abstractWidget.js 
			this.options.position.offsetLeft = 15; // horizontal offset of shadow layer
			this.options.position.offsetTop = 16; // vertical offset of shadow layer
			this.instID = 'borderedWidget.' + parseInt(Math.random()*1000000);
			this.options.containerClassName = 'borderedWidget'
		},

		render:function($super, container){
			$super(container);
			if (Prototype.Browser.IE){
				this.container.setStyle({paddingTop:'1px'});
				this.contentContainer.setStyle({height:parseInt(this.options.size.height)-2});
			}else{
				this.contentContainer.setStyle({height:parseInt(this.options.size.height)-24});
			}
		}
		
	});/**
 * Implementation of a widget with a shadow-like-background
 * you can change the offset of the shadow by altering:
 * 		this.options.offsetLeft = int-value
 * 		this.options.offsetTop = int-value
 * @author Ivo Toby, ivo@i-v-o.nl 
 */

	var reactieWidget= Class.create(borderedWidget,{
		
		initialize : function($super, options){
			$super(options);// run initialize of abstractWidget.js 
			this.options.position.offsetLeft = 15; // horizontal offset of shadow layer
			this.options.position.offsetTop = 16; // vertical offset of shadow layer
			this.instID = 'reactieWidget.' + parseInt(Math.random()*1000000);
			this.options.containerClassName = 'reactieWidget';
		},

		render:function($super, container){
			$super(container);
			if (Prototype.Browser.IE){
				this.container.setStyle({paddingTop:'1px'});
				this.contentContainer.setStyle({height:parseInt(this.options.size.height)-2});
			}else{
				this.contentContainer.setStyle({height:parseInt(this.options.size.height)-4});
			}
		},
		
		getStories : function(){
			var remote = new rpc('story', this.setStory.bind(this));
//			remote.debug=true;
			remote.call('getUserStories', {userID : this.userID});
		}
		
		
	});/**
 * Implementation of the widget used as homepage -> REISVERHALEN
 * Extends upon shadowedWidget, but is prolly 99% on it's own
 * @author Ivo Toby, ivo@i-v-o.nl
 */
	var searchWidget = Class.create(shadowedWidget,{

		/**
		 * Params; 
		 * $super = function of base-class (in this case shadowedWidget)
		 * options = hash-table of options
		 * userID = the userID of the reisverhalen-user
		 * clientIsOwner = boolean indicating the current user owns the reisverhalen (this is NOT a leak; the RPC-calls are checked!)
		 */
		initialize : function($super, options, searchSelect, searchStr, userID){
			$super(options);
			this.instID = 'searchWidget.' + parseInt(Math.random()*1000000);
			this.page = 0;
			this.images = [];
			this.userID = userID;
			if (searchSelect) this.selected = searchSelect;
			if (searchStr) {
				this.searchStr = searchStr;
			}else{
				this.searchStr = 'Wat zoek ik...';
			}
			this.itemsPerPage = 5;
			this.page = 0;
			this.navigatorPage = 0;
			this.navigatorItemsPerPage = 4;
		},
		
		render : function($super, container, callBack){
			$super(container,callBack);
			this.searchDiv = new Element('div', {className:'searchFieldContainer', id:this.instID+"_searchFieldContainer"});
			this.contentContainer.insert(this.searchDiv);
			this.contentContainer.insert(new Element('div', {className:'searchLine'}));
			this.resultsDiv = new Element('div', {className:'resultsContainer', id:this.instID+"_resultsContainer"});
			this.contentContainer.insert(this.resultsDiv);
			
			this.navigator = new Element('div', {id:this.instID + '_navigator', className:'navigator'});
			this.contentContainer.insert(this.navigator);
			
			// draw searchbox
			this.select = new Element('select', {className:'searchSelect'});
			this.searchDiv.insert(this.select);
			this.addOption('', 'Ik zoek in...');
			this.addOption('searchStories', 'reisverhalen');
			this.addOption('searchFotos', 'foto\'s');
			this.addOption('searchVideos', 'video\'s');
//			this.addOption('searchAanbiedingen', 'aanbiedingen');
//			this.addOption('searchInsurance', 'reisverzekeringen');
			this.addOption('searchPersons', 'personen');
			this.addOption('searchTickets', 'tickets');
			this.addOption('searchReisgenoten', 'reisgenoten');
			this.addOption('setDefaults', 'De nieuwste');
			this.select.observe('change', (function(e){
				if (this.select.getValue()=='setDefaults') {
					this.getDefaults();
					this.searchField.value='';
				}else if (this.select.getValue() == 'searchReisgenoten'){
					// open reisgenoten widget:
					control.add(
							new reisgenotenWidget(
								{
									id:'reisgenotenWidget',
									position:{left:90, top:37}, 
									size:{width:660, height:520}, 
									containerClassName:'reisgenotenWidget',
									scrolling : false,
									showClose:true,
									canHide :true
								}, this.userID
							)
						);
					control.render();
				}else if (this.select.getValue() == 'searchTickets'){
					// close profielwidget:
					control.get('profile').closeMe();
					// open tickets widget:
					var tickets = new inlineTickets($('ticketsContainer'));
				}else if (this.select.getValue() == 'searchInsurance'){
					openInsuranceWidget();
				}
			}).bindAsEventListener(this));

			this.searchField = new Element('input', {type:'text', className:'searchField', value:this.searchStr});
			this.searchDiv.insert(this.searchField);
			this.searchField.observe('click', function(e){
				if (e.element().getValue()=="Wat zoek ik...") e.element().value="";
			})
			this.searchField.observe('keydown', (function(e){
					if (e.keyCode == Event.KEY_RETURN){
						this.doSearch();
					}
				}).bindAsEventListener(this)
			);
			
			var submit = new Element('input', {type:'image', className:'searchSubmit', src:'/images/searchSubmit.png'});
			this.searchDiv.insert(submit);
			submit.observe('click', this.doSearch.bindAsEventListener(this));
			if (this.selected && this.searchStr){
				this.doSearch();
			}else{
				this.getDefaults();
			}
			this.container.observe(gDefaultFocusEvent, this.toFG.bind(this))
//			this.container.observe('mouseout', this.toBG.bind(this))
		},
		
		getDefaults : function(){
			// get defaults
			var remote = new rpc('search', this.setResults.bind(this));
			remote.debug=true;
			remote.call('getDefaults');
		},
		
		addOption : function(where, text){
			var option = new Element('option', {value:where}).update(text);
			this.select.insert(option);
			if (this.selected == where) {
				option.selected = true;
			}
		},

		doSearch : function(){
			// check values:
			if (this.searchField.getValue() == ''){
				alert("Voer a.u.b. een zoekwoord in");
				this.searchField.setStyle("border:1px red solid");
				return;
			}else{
				this.searchField.setStyle("border:1px #1E3167 solid");
			}

			if (this.select.getValue() == ''){
				alert("Selecteer waarin je wilt zoeken");
				this.select.setStyle("border:1px red solid");
				return;
			}else{
				this.select.setStyle("border:1px #1E3167 solid");
			}
			if (this.select.getValue() == 'setDefaults'){
				this.getDefaults();
			}else{
				// execute search on server
				var remote = new rpc('search', this.setResults.bind(this));
				remote.debug=true;
				remote.call('doSearch', {where:this.select.getValue(), what:this.searchField.getValue()});
			}
		},

		setResults : function(req){
			if (req) this.req = req.responseJSON;
			
			// build results & navigator:
			this.resultsDiv.update('');
			this.count = this.req.length;
			if (this.req.length ==0){
				this.resultsDiv.insert("Geen resultaten");
			}else{
				var start = this.page*this.itemsPerPage; 
				var end = start + this.itemsPerPage;
				for (var i=start;i<end;i++ ){
					var row = this.req[i]; 
					this.drawResultRow(row);
				}
			}
			this.resultsDiv.insert(new Element('div', {className:'resultsLine'}));
			this.drawNavigator();
		},
		
		drawNavigator : function(){
			var navigatorRow = new Element('div', {className:'navigatorRow'});
			this.navigator.update(navigatorRow);
			
			var pageCount = parseInt(this.count/this.itemsPerPage);
			var start = this.navigatorPage;
			var end = this.navigatorPage + this.navigatorItemsPerPage;
			if (end * this.navigatorItemsPerPage > this.count){
				end = this.count/this.navigatorItemsPerPage;
			}
			if (start > 0){
				var prevNavPage = new Element('img', {src:'/images/searcharrow_previous.png', className:'searchArrowPrevious'});
//				var prevNavPage = new Element('span', {className:'nextNavigatorPage'}).update('vorige/');
				this.navigator.insert(prevNavPage);
				prevNavPage.observe('click', this.prevNavigatorPage.bindAsEventListener(this));
			}
			for (var i=start;i<end;i++){
				var item = new Element('span').update((i+1) + '/');
				if (i==this.page) {
					item.className ='active';
				}else{
					item.className ='inactive';
				}
				item.page = i;
				navigatorRow.insert(item);
				item.observe('click', this.goToPage.bindAsEventListener(this));
			}
			if (pageCount > end){
				navigatorRow.insert(' ... ');
				var nextNavPage = new Element('img', {src:'/images/searcharrow_next.png', className:'searchArrowNext'});
				this.navigator.insert(nextNavPage);
				nextNavPage.observe('click', this.nextNavigatorPage.bindAsEventListener(this));
			}
		},
		
		prevNavigatorPage : function(e){
			this.navigatorPage = this.navigatorPage - this.navigatorItemsPerPage;
			this.drawNavigator();
		},
		
		nextNavigatorPage : function(e){
			this.navigatorPage = this.navigatorPage + this.navigatorItemsPerPage;
			this.drawNavigator();
		},
		
		goToPage : function(e){
			var page = e.element().page;
			this.page = page;
			this.setResults();
		},
		
		setDefaults : function(req){
			this.resultsDiv.update('');
			req.responseJSON.each(
				(function(res){
					this.drawResultRow(res);
				}).bind(this)
			)
			this.resultsDiv.insert(new Element('div', {className:'resultsLine'}));
		},
		
		drawResultRow : function(result){
			if (!result) return;
			var onclick = ' onclick="window.location.href=\'' + result.link + '\'" ';
			if (result.text){
				var text = result.text;
			}else if (result.alttext){
				var text = result.alttext;
			}else{
				var text = '';
			}
			if (Prototype.Browser.IE){
				text = text.substring(0,12);
			}else{
				text = text.substring(0,13);	
			}
			
			
			var html = '<div class="row" '+onclick+'>';
			html 	+= '<div class="image" '+onclick+'>';
			if (result.image){
				html 	+= '<img src="' + result.image + '" '+onclick+'>';
			}
			html 	+= '</div>';
			html 	+= '<div class="content" '+onclick+'>';
			html 	+= '<div class="part" '+onclick+'>' + result.part + '</div>';
			html 	+= '<div class="text" '+onclick+'>' + text + '</div>';
			html 	+= '<img src="/images/searcharrow.png" class="arrow" '+onclick+'>';
			html 	+= '</div>';
			html 	+= '</div>';
			this.resultsDiv.insert(html);
		}


	});/**
 * Implementation of the widget used as homepage -> REISVERHALEN
 * Extends upon shadowedWidget, but is prolly 99% on it's own
 * @author Ivo Toby, ivo@i-v-o.nl
 */

	var staticAdWidget = Class.create(shadowedWidget,{

		/**
		 * Params; 
		 * $super = function of base-class (in this case shadowedWidget)
		 * options = hash-table of options
		 * userID = the userID of the reisverhalen-user
		 * clientIsOwner = boolean indicating the current user owns the reisverhalen (this is NOT a leak; the RPC-calls are checked!)
		 */
		initialize : function($super, options, image, id,data){
			$super(options);
			this.instID = 'staticAdWidget.' + parseInt(Math.random()*1000000);
			this.image = image;
			this.adID = id;
			this.options.containerClassName = 'adWidget';
			this.options.scrolling = false;
			this.options.useIFrame = false;
			this.options.position.offsetTop = 10;
			this.options.position.offsetLeft = 10;
			this.data = data;
			
		},
		
		render : function($super, container, callBack){
			this.options.zIndex = 2;
			$super(container, callBack);
			var img = new Element('img', {src:this.image, border:'0'});
			if (this.data.url.substring(0,4) != 'http'){
				var link = new Element('a', {href:this.data.url}).insert(img);
			}else{
				var link = new Element('a', {href:'/include/adclick.php?id=' + this.adID, target:"_blank"}).insert(img);
			}
			this.contentContainer.insert(link);
		}
		

	});/**
 * Implementation of the widget used as homepage -> REISVERHALEN
 * Extends upon shadowedWidget, but is prolly 99% on it's own
 * @author Ivo Toby, ivo@i-v-o.nl
 */

	var slideshowWidget = Class.create(shadowedWidget,{

		/**
		 * Params; 
		 * $super = function of base-class (in this case shadowedWidget)
		 * options = hash-table of options
		 * userID = the userID of the reisverhalen-user
		 * clientIsOwner = boolean indicating the current user owns the reisverhalen (this is NOT a leak; the RPC-calls are checked!)
		 */
		initialize : function($super, options, images){
			$super(options);
			this.options.containerClassName = 'slideShowWidget';
			this.options.scrolling = false;
			this.options.useIFrame = false;
			this.options.position.offsetTop = 10;
			this.options.position.offsetLeft = 10;
			this.instID = 'slideshowWidget.' + parseInt(Math.random()*1000000);
			this.pause = options.pause;
			this.transduration = options.transduration;
			this.images = images;
			this.imgIdx = 0;
		},
		
		render : function($super, container, callBack){
			this.options.zIndex = 2;
			$super(container, callBack);
			// preload images;
			var imgTemp = [];
			this.images.each(
				(function(imgArr){
					var img = new Element('img', {src:imgArr[0], className:'slideShowImage', border:0});
					var link = new Element('a', {href:imgArr[1], target:imgArr[2]});
					link.insert(img);
					link.hide();
					this.contentContainer.insert(link);
					imgTemp.push(link);
				}).bind(this)
			);
			this.images = imgTemp;
			this.currImage = this.images[0];
			this.currImage.show();
			setTimeout(this.next.bind(this), this.pause);
		},
		
		next : function(){
			if (this.imgIdx == this.images.length-1){
				this.imgIdx = 0;
			}else{
				this.imgIdx++;
			}
			new Effect.Fade(this.currImage, {duration:this.transduration});
			this.currImage = this.images[this.imgIdx];
			this.currImage.show();
			setTimeout(this.next.bind(this), this.pause);
		}
		

	});/**
 * Implementation of the widget used as homepage -> REISVERHALEN
 * Extends upon shadowedWidget, but is prolly 99% on it's own
 * @author Ivo Toby, ivo@i-v-o.nl
 */

	var reisgenotenWidget = Class.create(shadowedWidget,{

		/**
		 * Params; 
		 * $super = function of base-class (in this case shadowedWidget)
		 * options = hash-table of options
		 * userID = the userID of the reisverhalen-user
		 * clientIsOwner = boolean indicating the current user owns the reisverhalen (this is NOT a leak; the RPC-calls are checked!)
		 */
		initialize : function($super, options, userID){
			if (userID) this.userID = userID;
			$super(options, this.controlTabs);
			this.instID = 'reisgenotenWidget.' + parseInt(Math.random()*1000000);
			this.dateValue = 'Selecteer datum';
			this.destination = 'Selecteer plaats';
			this.defaultComment = "Start dan nu eenvoudig een nieuw forum door je bericht hier achter te laten ...";
			this.loadedFromHash = false;
		},
		
		/** 
		 * Large parts of render are copied from shadowedWidget
		 */
		render : function($super, container, callBack){
			if (!callBack) callBack = function(){}
			this.widgetCallBack = callBack;
			
			this.callingContainer = container;
			if (this.rendered) return;
    		if (Prototype.Browser.IE){
//    			$(container).relativize(); // BUG// BUG// BUG// BUG// BUG// BUG// BUG// BUG// BUG// BUG// BUG// BUG MSIE
//    			$('demoContainer').absolutize();
//    			$('demoContainer').setStyle({left:'50%'});
    		}else{
				$('demoContainer').relativize();
    		}
			
			var elem = new Element('div', 
					{
						id:this.instID + "_widgetContainer", 
						className:this.options.containerClassName
					});
			container.insert(elem);
			this.baseContainer = elem;
			
			elem.widget = this;
			elem.absolutize(); // prototype-function to make the element absolute
			elem.setStyle(
					{
						width:this.options.size.width + 'px',
						height:this.options.size.height + 'px',
						left:this.options.position.left + 'px',
						top:this.options.position.top+ 'px',
						zIndex:this.options.zIndex
					}
			);
			this.originalContainer = elem;
			this.container = elem;

			// add shadow:
			var newzIndex = -1;
			if (parseInt(this.container.style.zIndex) >0){
				var newzIndex = parseInt(this.container.style.zIndex) - 1;
			}
			var shadow = new Element('div', {className:'shadow', id:this.instID+"_shadow"});
			this.shadow = shadow;
			shadow.absolutize();
			shadow.setStyle(
					{
						width: this.options.size.width + 'px',
						height: this.options.size.height + 'px',
						left:( parseInt(this.options.position.left) + parseInt(this.options.position.offsetLeft) ) + 'px',
						top: ( parseInt(this.options.position.top) + parseInt(this.options.position.offsetTop) )+ 'px',
						zIndex : newzIndex
					}
			);
			container.insert(shadow);			
				
			var closer = new Element('img', {className:'homePageCloser', src:'/images/closer.gif', style:'z-index:99;'});
			this.container.insert(closer); 
			closer.observe('click', this.closeMe.bind(this))

			var fakeScroller = new Element('div', {className:'fakeScroller', id:'fakeTabbedScroller'});
			this.container.insert(fakeScroller);

			var scrollContainer = new Element('div', {className:'makeScroll', id:'makeScroll'});
			this.container.insert(scrollContainer);
			this.scrollContainer = scrollContainer;
			this.drawHome();
			this.rendered = true;
			this.container.observe(gDefaultFocusEvent, this.toFG.bind(this))
//			this.container.observe('mouseout', this.toBG.bind(this))
			
		},
		
		drawHome : function(){
			this.scrollContainer.update('');
			var topContainer = new Element('div', {className:'reisgenotenTopContainer', id:'reisgenotenTopContainer'}); 
			this.scrollContainer.insert(topContainer);
			
			var title = new Element('img', {className:'title', src:'/include/middleTitle.php?text=BACKPACKERS MEETINGPOINT'});
			topContainer.insert(title);
			
			var formContainer = new Element('div', {className:'reisverhalenFormContainer'});
			topContainer.insert(formContainer);
			
			var search = new Element('div', {className:'reisverhalenSearchContainer'});
			formContainer.insert(search);
			
			var calendar = new Element('div', {className:"dateSelection"}).insert(calendarDropDownMonthYear('date_'+this.instID));
			search.insert(calendar);
			var dtNow = new Date();

        	$A($('date_'+this.instID + '_month').options).each(
        			function(year){
            			if (year.value == (dtNow.getMonth() + 1) ) year.selected = true; 
            		}
            	)

        	$A($('date_'+this.instID + '_year').options).each(
        			function(year){
            			if (year.value == dtNow.getFullYear()) year.selected = true; 
            		}
            	)

			this.travelDestination = new Element('input', {type:'text', id:this.instID+"travelDestination", value:this.destination});
			search.insert(this.travelDestination);
			
			this.goHome = new Element('span', {style:"cursor:pointer"}).update('home');
			search.insert(this.goHome);
			this.goHome.hide();
			this.goHome.observe('click', this.drawHome.bind(this));
			
			var autoCompleteLayer = new Element('div', {id:this.instID+"autocompleter", className:'autocomplete'});
			search.insert(autoCompleteLayer);
			this.travelDestination.observe('click',
				(function(){
					if (this.travelDestination.getValue() == this.destination) this.travelDestination.value = '';
				}).bind(this)
			)
			

			var submitArrow = new Element('img', {src:'/images/reisgenoten_pijl_small.jpg', className:'reisgenotenSearchSubmit'});
			search.insert(submitArrow);
			submitArrow.observe('click', this.searchForum.bind(this))

			this.commentContainer = new Element('div');
			formContainer.insert(this.commentContainer);
			this.commentContainer.hide();

			this.drawCommentSection();
			$$('.reisverhalenFormContainer')[0].setStyle('height:30px');

			this.forumContents = new Element('div', {className:'reisverhalenContents'});
			this.scrollContainer.insert(this.forumContents);

			var footer = new Element('div', {className:'reisgenotenFooter'});
			this.container.insert(footer);

			this.ads = new Element('div', {className:'reisgenotenAds'});
			footer.insert(this.ads);
			var someAd = new Element('a', {href:'http://www.backpackers.nl/site/content/australie/895.html', target:'_blank'}).insert(new Element('img', {src:'/images/ads/ad_1.gif', border:'0'}));
			this.ads.insert(someAd);
			
//			var footerScroller = new Element('div', {className:'footerScroller'});
//			footer.insert(footerScroller);
//			/include/lib/rpc.php?action=reisgenoten&method=search&date=2009/4/28&destination=Sydney
			new Ajax.Autocompleter(this.instID+"travelDestination", this.instID+"autocompleter", '/include/lib/rpc.php', {parameters:'action=reisgenoten&method=autocomplete', paramName:'searchText'});

			var remote = new rpc('reisgenoten', this.drawDefaults.bind(this));
			remote.debug=true;
			remote.call('getDefaults');
		},
		
		drawCommentSection : function(){
			if (!this.userID){
				this.commentContainer.update('<span class="reisgenotenFormQuestion" >Is er nog geen reisgenotenforum voor de opgegeven maand + plaats?</span>');
				this.commentContainer.insert('<span style="font-size:10px;">' + this.defaultComment + '</span>');
				this.travelComment = new Element('textarea', {value:this.defaultComment}).update(this.defaultComment); // just to be safe
				var loginLayer = new Element('div', {className:'inlineLogin'}).update("<strong>Hiervoor moet je wel ingelogd zijn:</strong><br/>");
				this.commentContainer.insert(loginLayer);
				
				var loginLayerSpan = new Element('span');
				loginLayer.insert(loginLayerSpan);
				loginLayerSpan.insert('Gebruikersnaam : ');
				var loginName = new Element('input', {type:"text", id:this.instID + 'username', className:'login', value:'login'});
				loginLayerSpan.insert(loginName);
				loginName.observe('click', function(e){
					if (e.element().getValue() == 'login' ) e.element().value = '';
				})
				loginLayerSpan.insert('Wachtwoord : ');
				var passWord = new Element('input', {type:'password', id:this.instID + 'password', className:'login', value:'login'});
				loginLayerSpan.insert(passWord);
				passWord.observe('click', function(e){
					e.element().value = '';
				})

				var submitArrow = new Element('img', {src:'/images/reisgenoten_pijl_small.jpg', className:'arrow'});
				loginLayerSpan.insert(submitArrow);
				submitArrow.observe('click', this.login.bind(this))
				
				var createAccount = new Element('div', {className:'inlineCreateAccount'}).update('<img src="/images/reisgenoten_pijl_smaller.jpg" align="left"/><span class="destination">Heb je nog geen account?</span> Maak dan eerst je profiel aan');
				this.commentContainer.insert(createAccount);
				$$('.reisverhalenFormContainer')[0].setStyle('height:175px');
				createAccount.observe('click', this.openRegistrationWidget.bind(this));
			}else{
				this.commentContainer.update('<span class="reisgenotenFormQuestion" >Is er nog geen reisgenotenforum voor de opgegeven maand + plaats?</span>');
				this.travelComment = new Element('textarea', {value:this.defaultComment}).update(this.defaultComment);
				this.commentContainer.insert(this.travelComment);
				this.travelComment.observe('click',
						(function(){
							if (this.travelComment.getValue() == this.defaultComment) this.travelComment.value = '';
						}).bind(this)
					)
				var submitArrow = new Element('img', {src:'/images/reisgenoten_pijl_small.jpg', className:'reisgenotenSubmit'});
				this.commentContainer.insert(submitArrow);
				submitArrow.observe('click', this.storePost.bind(this))
				$$('.reisverhalenFormContainer')[0].setStyle('height:143px');
			}			
		},
		
		openRegistrationWidget : function(){
			control.getContentWidget(1);
		},
		
		login: function(){
			var username = $(this.instID + "username");
			var password = $(this.instID+"password");
			if (username.getValue() == '' || username.getValue() == 'login'){
				alert("Vul a.u.b een geldige gebruikersnaam in")
				return;
			}
			if (password.getValue() == ''){
				alert("Vul a.u.b een geldig wachtwoord in")
				return;
			}
			var remote = new rpc('login', this.handleLogin.bind(this));
			remote.debug=true;
			remote.call('doLogin', {'username':username.getValue(), 'password':password.getValue()});				

		},
		
		handleLogin : function (req){
			if (req.responseJSON.uid == false){
				alert("Aanmelden is mislukt, probeer het nog een keertje.");
				return;
			}
			this.userID = req.responseJSON.uid;
			$$('.inlineLogin')[0].remove();
			this.drawCommentSection();
		},
		
		drawDefaults : function(req){
			var hash = window.location.hash;
			if (hash && !this.loadedFromHash){
				var commands = $H({});
				hash = hash.replace("#","");
				// split hash:
				hash = hash.split(":");
				hash.each(
					function(token){
						token = token.split('=');
						commands.set(token[0], token[1]);
					}
				)
				this.setSearchValues(commands.get('forumDate'), commands.get('forumDestination'), 'searchForum');
				this.loadedFromHash = true;
			}else{
				var posts = req.responseJSON;
	//			this.commentContainer.show();
				if (posts.length == 0){
					var line = new Element('div', {className:'reisverhalenContentsLine'});
					this.forumContents.update(line);
					this.forumContents.insert('<div class="reisgenotenNoResults">Geen reisgenoten gevonden op ' + this.getFriendlyDate() + ' naar ' + this.selectedDestination + "</div>");
					return;
				}else{
					var line = new Element('div', {className:'reisverhalenContentsLine'});
					this.forumContents.update(line);
					
					posts.each(
						(function(post){
							this.drawDefaultPost(post);
						}).bind(this)
					)
					$j('#makeScroll').jScrollPane({animateTo:true,scrollbarWidth:20, scrollbarMargin:10, dragMaxHeight:16, dragMinHeight:16, showArrows:false});
				}
			}
			
		},
		
		drawDefaultPost : function(post){
			if (post.destination == '' || post.destination == "Selecteer plaats") return;
			var container = new Element('div', {className:'postRow'});
			this.forumContents.insert(container);
			
			var left =  new Element('div', {className:'left'});
			container.insert(left);
			var imgContainer = new Element('div', {className:'imgContainer'});
			left.insert(imgContainer);
			if (post.hasImage != 0){
				var img = new Element('img', {src:post.hasImage, className:'postImage'});
			}else{
				var img = new Element('img', {src:'/images/dummy_user_img_small.jpg', className:'postImage'});
			}
			imgContainer.insert(img);
			img.observe('click', function(){
				this.setSearchValues(post.dateTravel, post.destination, 'searchForum');
//				this.searchForum();
			}.bind(this))
			var middle =  new Element('div', {className:'middle'});
			container.insert(middle);

			var arrow = new Element('img', {src:'/images/reisgenoten_pijl_small.jpg', className:'postArrow'});
			middle.insert(arrow);
			arrow.observe('click', function(){
				this.setSearchValues(post.dateTravel, post.destination, 'searchForum');
//				this.searchForum();
			}.bind(this))
			
			var titleRow = new Element('div', {className:'titleRow'}).update("<b>"+post.name + ' / ' + post.destination + ' / ' + this.getFriendlyShortDisplayDate(post.dateTravel) + " / " + post.count + " posts </b>");
			middle.insert(titleRow);
			titleRow.observe('click', function(){
				this.setSearchValues(post.dateTravel, post.destination, 'searchForum');
//				this.searchForum(post.dateTravel, post.destination);
			}.bind(this))
			var titleRow = new Element('div', {className:'messageRowOverview'}).update("Laatste bericht: " + this.getFriendlyDisplayDate(post.posted));
			middle.insert(titleRow);
			if (post.body == 'Vertrek jij ook deze datum? Laat dan hier van je horen...' || post.body == ''){
				var body =  '';
			}else{
				var body = nl2br(post.body.toString().substring(0, 72)) + '...';
			}
			var bodyRow = new Element('div', {className:'bodyRow'}).update(body);
			middle.insert(bodyRow);			
//			var right =  new Element('div', {className:'right'});
//			container.insert(right);
		},
		
		setSearchValues : function(date, dest, callBack){
			var month = date.split('-');
			var localYear = month[0];
			var localMonth = month[1];
			if (localMonth.indexOf(0) == '0') localMonth = localMonth.substring(1,2);
        	$A($('date_'+this.instID + '_month').options).each(
        			function(month){
            			if (month.value == localMonth ) {
            				month.selected = true;
            			}else{
            				month.selected = false;
            			}
            		}
            	)
        	$A($('date_'+this.instID + '_year').options).each(
        			function(year){
            			if (year.value == localYear) {
            				year.selected = true;
            			}else{
            				year.selected = false;
            			}
            		}
            	)
            this.travelDestination.value = dest;
        	$j('#makeScroll').jScrollPane({animateTo:true,scrollbarWidth:20, scrollbarMargin:10, dragMaxHeight:16, dragMinHeight:16, showArrows:false});
        	$j('#makeScroll')[0].scrollTo(0)
        	this[callBack]();
		},
		
		searchForum : function(){
			this.travelComment.value = this.defaultComment;
			this.selectedDate = this.getDBDate() ;
			this.selectedDestination = this.travelDestination.getValue();
			if (this.selectedDestination == 'Selecteer plaats'){
				this.selectedDestination = '';
				//alert("Vul aub. een plaats in");
				//return;
			}
			var remote = new rpc('reisgenoten', this.drawPosts.bind(this));
			remote.debug=true;
			remote.call('search', 
				{
					date : this.selectedDate,
					destination : this.selectedDestination
				}
			);			
		},
		
		getDBDate : function(date){
			return $('date_'+this.instID + '_year').getValue() + "/"+$('date_'+this.instID + '_month').getValue()+'/01';
		},

		getFriendlyDate : function(){
			return $('date_'+this.instID + '_month').getValue() + '-' + $('date_'+this.instID + '_year').getValue();
		},

		drawPosts : function(req){
			this.goHome.show();
			var posts = req.responseJSON;
			this.drawCommentSection();
			this.commentContainer.show();
			if (posts.length == 0){
				var line = new Element('div', {className:'reisverhalenContentsLine'});
				this.forumContents.update(line);
				this.forumContents.insert('<div class="reisgenotenNoResults">Geen reisgenoten gevonden op ' + this.getFriendlyDate() + ' naar ' + this.selectedDestination + "</div>");
				return;
			}else{
				var line = new Element('div', {className:'reisverhalenContentsLine'});
				this.forumContents.update(line);
				
				posts.each(
					(function(post){
						this.drawPost(post);
					}).bind(this)
				)
				$j('#makeScroll').jScrollPane({animateTo:true,scrollbarWidth:20, scrollbarMargin:10, dragMaxHeight:16, dragMinHeight:16, showArrows:false});
			}
		},

		drawPost : function(post){
			var container = new Element('div', {className:'postRow'});
			this.forumContents.insert(container);
			
			var left =  new Element('div', {className:'left'});
			container.insert(left);
			var imgContainer = new Element('div', {className:'imgContainer'});
			left.insert(imgContainer);
			if (post.hasImage != 0){
				var img = new Element('img', {src:post.hasImage, className:'postImage'});
			}else{
				var img = new Element('img', {src:'/images/dummy_user_img_small.jpg', className:'postImage'});
			}
			imgContainer.insert(img);
			img.observe('click', (function(){
				//window.location.href="http://" + window.location.hostname + '/userHome.php?userID=' + post.userID;
				this.redirectToProfile(post)
			}).bind(this))
			var middle =  new Element('div', {className:'middle'});
			container.insert(middle);

			var arrow = new Element('img', {src:'/images/reisgenoten_pijl_small.jpg', className:'postArrow'});
			middle.insert(arrow);
			arrow.observe('click', (function(){
				//window.location.href="http://" + window.location.hostname + '/userHome.php?userID=' + post.userID;
				this.redirectToProfile(post)
			}).bind(this))
			
			if (this.selectedDestination == ''){
				var titleRow = new Element('div', {className:'titleRow'}).update("<b>"+post.name + ' </b> / <i>' + post.destination + ' / ' + this.getFriendlyShortDisplayDate(post.dateTravel) + "</i>");
			}else{
				var titleRow = new Element('div', {className:'titleRow'}).update("<b>"+post.name + '</b> <i>' + this.getFriendlyDisplayDate(post.posted) + "</i>");
			}
//			
			middle.insert(titleRow);
			titleRow.observe('click', (function(){
				//window.location.href="http://" + window.location.hostname + '/userHome.php?userID=' + post.userID;
				this.redirectToProfile(post)
			}).bind(this))
			var titleRow = new Element('div', {className:'messageRow'}).update(nl2br(post.body));
			middle.insert(titleRow);
			
//			var right =  new Element('div', {className:'right'});
//			container.insert(right);
			
		},

		
		redirectToProfile : function(post){
			window.location.href="http://" + window.location.hostname + '/userHome.php?userID=' + post.userID + "&refererDestination=" + post.destination + "&refererDate=" + post.dateTravel;
		},
		
		storePost : function(){
			if ( (this.travelDestination.getValue() == this.destination) || this.travelDestination.getValue() == ''){
				this.travelDestination.setStyle('border-color:red;');
				alert("Vul a.u.b. je bestemming in");
				return;
			}
			var travelComment =this.travelComment.getValue(); 
			if ( travelComment == this.defaultComment){
				travelComment = '';
			}
			travelComment = encodeURIComponent(travelComment.stripTags()); 
			var remote = new rpc('reisgenoten', this.drawPosts.bind(this));
			remote.debug=true;
			remote.call('store', 
				{
					date : this.getDBDate(),
					destination : this.travelDestination.getValue(),
					message : travelComment
				}
			);			

		},

		getFriendlyShortDisplayDate : function(dbDate){
			var dateValue = dbDate;
			dateValue = dateValue.split(' ');
			dateValue = dateValue[0].split('-');
			switch (dateValue[1]) {
			case '01':
				var month = " Jan. "
				break;
			case '02':
				var month = " Feb. "
				break;
			case '03':
				var month = " Maart "
				break;
			case '04':
				var month = " Apr. "
				break;
			case '05':
				var month = " Mei "
				break;
			case '06':
				var month = " Jun. "
				break;
			case '07':
				var month = " Jul. "
				break;
			case '08':
				var month = " Aug. "
				break;
			case '09':
				var month = " Sept. "
				break;
			case '10':
				var month = " Okt. "
				break;
			case '11':
				var month = " Nov. "
				break;
			case '12':
				var month = " Aug. "
				break;
			}
			return month + ' ' + dateValue[0];			
		},
		
		getFriendlyDisplayDate : function(dbDate){
			var dateValue = dbDate;
			dateValue = dateValue.split(' ');
			var time = dateValue[1];
			dateValue = dateValue[0].split('-');
			dateValue = dateValue[2] + '/' + dateValue[1] + '/'+dateValue[0] + ' ' + time; 
			return dateValue;			
		},		
		
		/**
		 * Because of the shadow-layer this widget has it's own implementation of hide
		 */
		hide : function(){
			this.originalContainer.hide();
			if (this.shadow) this.shadow.hide();
		},
		
		/**
		 * Because of the shadow-layer this widget has it's own implementation of show
		 */
		show : function(){
			this.originalContainer.show();
			if (this.shadow) this.shadow.show();
		}
		
	});/**
 * Implementation of the widget used as homepage -> REISVERHALEN
 * Extends upon shadowedWidget, but is prolly 99% on it's own
 * @author Ivo Toby, ivo@i-v-o.nl
 */

	var emailWidget = Class.create(shadowedWidget,{

		/**
		 * Params; 
		 * $super = function of base-class (in this case shadowedWidget)
		 * options = hash-table of options
		 * userID = the userID of the reisverhalen-user
		 * clientIsOwner = boolean indicating the current user owns the reisverhalen (this is NOT a leak; the RPC-calls are checked!)
		 */
		initialize : function($super, options, userData){
			$super(options, this.controlTabs);
			this.instID = 'emailWidget.' + parseInt(Math.random()*1000000);
			this.widgetCallBack = function(){};
			this.userData = userData;
			this.defaultVoornaam = 'Voornaam';
			this.defaultEmail = 'Email';
			this.defaultMessage = 'Schrijf hier je reactie';
			this.defaultCaptcha = 'Vul hier de code in';
			this.defaultBorderColor = '#1E3066';
		},
		
		/** 
		 * Large parts of render are copied from shadowedWidget
		 */
		render : function($super, container, dummyCallBack, callBack){
			$super(container);
			this.drawUserInfo();
		},
		
		drawUserInfo : function(){
			var html = '';
			html += '<div class="profielWidget">';	
			html += '	<div class="profielWidgetFoto">';
			html += '		<img src="' + this.userData.image + '" alt="" height="150" width="150" border="0">';
			html += '	</div>';
//			html += '	<div class="profielWidgetSubTitle">';
//			html += '		<p class="widgets_subsubsubtekst">' + this.userData.dateStr + '</p>';
//			html += '	</div>';
			html += '	<div class="profielWidgetTitle">';
			html += '		<img src="' + this.userData.titleImage + '"/>';
			html += '	</div>';
			html += '	<div class="emailUserForm" id="' + this.instID + '_formTop">';
			html += '	</div>';
			html += '</div>';
			this.contentContainer.insert(html)
			// draw form:
			var container = new Element('div', {className:'formTop'}); 
			$(this.instID + '_formTop').insert(container);
			
			this.inputVoornaam = new Element('input', {type:'text', id:this.instID+'_name', value:this.defaultVoornaam});
			container.insert(this.inputVoornaam);
			this.inputVoornaam.observe('focus', (function(){
				if (this.inputVoornaam.getValue() == this.defaultVoornaam) {
					this.inputVoornaam.value = '';
				}
			}).bind(this))
			this.inputVoornaam.observe('blur', (function(){
				if (this.inputVoornaam.getValue() == '') this.inputVoornaam.value = this.defaultVoornaam;
			}).bind(this) );			


			this.inputEmail = new Element('input', {type:'text', id:this.instID+'_email', value:this.defaultEmail});
			container.insert(this.inputEmail);
			this.inputEmail.observe('focus', (function(){
				if (this.inputEmail.getValue() == this.defaultEmail) {
					this.inputEmail.value = '';
				}
			}).bind(this))
			this.inputEmail.observe('blur', (function(){
				if (this.inputEmail.getValue() == '') this.inputEmail.value = this.defaultEmail;
			}).bind(this) );			

			
			var container = new Element('div', {className:'formBottom'}); 
			$(this.instID + '_formTop').insert(container);

			this.inputMessage = new Element("textarea", {id:this.instID+'_message'}).update(this.defaultMessage);
			container.insert(this.inputMessage);
			this.inputMessage.observe('focus', (function(){
				if (this.inputMessage.getValue() == this.defaultMessage) {
					this.inputMessage.value = '';
				}
			}).bind(this))
			this.inputMessage.observe('blur', (function(){
				if (this.inputMessage.getValue() == '') this.inputMessage.value = this.defaultMessage;
			}).bind(this) );
			
			
//			var img = new Element('img', {src:"include/lib/3rdparty/captcha/CaptchaSecurityImages.php?type=email&width=152"});
//			var captchaContainer = new Element('div', {className:'captchaContainer'}).insert(img);
//			container.insert(captchaContainer);
//
//			this.inputCaptcha = new Element('input', {type:'text', id:this.instID+'_captcha', value:this.defaultCaptcha});
//			container.insert(this.inputCaptcha);
//			this.inputCaptcha.observe('focus', (function(){
//				if (this.inputCaptcha.getValue() == this.defaultCaptcha) this.inputCaptcha.value = '';
//			}).bind(this))
//			this.inputCaptcha.observe('blur', (function(){
//				if (this.inputCaptcha.getValue() == '') this.inputCaptcha.value = this.defaultCaptcha;
//			}).bind(this) );
			
			
			var arrow = new Element('img', {src:'/images/submitEmail.jpg', className:'submitEmail'});
			container.insert(arrow);
			arrow.observe('click', this.validate.bind(this));
		},
		
		validate : function(){
			this._validate('',true);
			
			//Check captcha
//			var captchaValue = this.inputCaptcha.getValue();
//			if (captchaValue == this.defaultCaptcha){
//				var captchaValue = '';
//			}else{
//				var captchaValue = this.inputCaptcha.getValue().replace(' ', '');
//			}
//			
//			if (captchaValue == ''){
//				var ok = false;
//				this.inputCaptcha.setStyle("border-color:red;");
//				this._validate('',false);
//				return;
//			}else{
//				this.inputCaptcha.setStyle("border-color:" + this.defaultBorderColor + ";");
//				captchaValue = this.inputCaptcha.getValue();
//			}
//			var func = (function(req){
//				this._validate(req, true)
//			}).bind(this)
//			var remote = new rpc('emailUser', func);
//			remote.debug=true;
//			remote.call('checkCaptcha', {captcha : captchaValue});
		},
		
		_validate : function(req, captchaOK){
			if (!captchaOK){
				var ok = false;
			}else{
				var ok = true;
			}
			// interpret ajax call for captcha code
//			if (req.responseJSON.message == '0'){
//				ok = false;
//				this.inputCaptcha.setStyle("border-color:red;");
//			}else{
//				this.inputCaptcha.setStyle("border-color:" + this.defaultBorderColor + ";");
//			}				
			// check name/email/message 
			var voornaamValue = this.inputVoornaam.getValue();
			if (voornaamValue == this.defaultVoornaam) {
				var voornaamValue = '';
			}else{
				var voornaamValue = this.inputVoornaam.getValue().replace(' ', '');
			}
			if (voornaamValue == ''){
				var ok = false;
				this.inputVoornaam.setStyle("border-color:red;");
			}else{
				this.inputVoornaam.setStyle("border-color:" + this.defaultBorderColor + ";");
				voornaamValue = this.inputVoornaam.getValue();
			}

			var emailValue = this.inputEmail.getValue();
			if (emailValue == this.defaulEmail) {
				var emailValue = '';
			}else{
				var emailValue = this.inputEmail.getValue().replace(' ', '');
			}
			if (emailValue != '' && this.checkEmailValue(emailValue)){
				this.inputEmail.setStyle("border-color:" + this.defaultBorderColor + ";");
			}else{
				var ok = false;
				this.inputEmail.setStyle("border-color:red;");
			}

			var msgValue = this.inputMessage.getValue();
			if (msgValue == this.defaultMessage) {
				var msgValue = '';
			}else{
				var msgValue = this.inputMessage.getValue().replace(' ', '');
			}
			if (msgValue == ''){
				var ok = false;
				this.inputMessage.setStyle("border-color:red;");
			}else{
				this.inputMessage.setStyle("border-color:" + this.defaultBorderColor + ";");
				msgValue = this.inputMessage.getValue();
			}
			if (ok){
				this.postMessage();
			}
		},
				
		postMessage : function(){
			var func = (function(req){
				this.closeMe();
				alert("Je email is verzonden!");
				
				control.add(
	    			new shadowedWidget(
	    				{
	    						id:'profile',
	    						position:{left:50, top:20}, 
	    						size:{width:350, height:155},
	    						containerClassName:'whiteWidget', 
	    						useIFrame:true, 
	    						ajax:{uri:'/include/profiel.php?showUser=' + this.userData.userID},
	    						showClose:false,
	    						framePadding : '0px',
	    						canHide:true
	    				}
	    			)
				);
				control.render();
				
			}).bind(this)
			
			var remote = new rpc('emailUser', func);
			remote.debug=true;

			var msgValue = this.safeValue(this.inputMessage.getValue());

			// gather values:
//			var captchaValue = this.safeValue(this.inputCaptcha.getValue());
			var emailValue = this.safeValue(this.inputEmail.getValue());
			var voornaamValue = this.safeValue(this.inputVoornaam.getValue());
			remote.call('sendMessage', {
//				"captcha" : captchaValue,
				"name" : voornaamValue,
				"email" : emailValue,
				"message" : msgValue,
				"userID" : this.userData.userID
			});	
		},		
		
		checkEmailValue : function(emailStr){
			var checkTLD=1;
			var knownDomsPat=/^(com|net|org|edu|int|mil|gov|arpa|biz|aero|name|coop|info|pro|museum)$/;
			var emailPat=/^(.+)@(.+)$/;
			var specialChars="\\(\\)><@,;:\\\\\\\"\\.\\[\\]";
			var validChars="\[^\\s" + specialChars + "\]";
			var quotedUser="(\"[^\"]*\")";
			var ipDomainPat=/^\[(\d{1,3})\.(\d{1,3})\.(\d{1,3})\.(\d{1,3})\]$/;
			var atom=validChars + '+';
			var word="(" + atom + "|" + quotedUser + ")";
			var userPat=new RegExp("^" + word + "(\\." + word + ")*$");
			var domainPat=new RegExp("^" + atom + "(\\." + atom +")*$");
			var matchArray=emailStr.match(emailPat);

			if (matchArray==null) {
				return false;
			}

			var user=matchArray[1];
			var domain=matchArray[2];

			for (i=0; i<user.length; i++) {
				if (user.charCodeAt(i)>127) {
					return false;
				}
			}

			for (i=0; i<domain.length; i++) {
				if (domain.charCodeAt(i)>127) {
					return false;
				}
			}
			
			if (user.match(userPat)==null) {
				return false;
			}

			var IPArray=domain.match(ipDomainPat);
			
			if (IPArray!=null) {
				for (var i=1;i<=4;i++) {
					if (IPArray[i]>255) {
						return false;
			   		}
				}
				return true;
			}
			
			 
			var atomPat=new RegExp("^" + atom + "$");
			var domArr=domain.split(".");
			var len=domArr.length;

			for (i=0;i<len;i++) {
				if (domArr[i].search(atomPat)==-1) {
					return false;
			   }
			}

			if (checkTLD && domArr[domArr.length-1].length!=2 && domArr[domArr.length-1].search(knownDomsPat)==-1) {
				return false;
			}

			if (len<2) {
				return false;
			}
			
			return true;			
		},

		safeValue : function(value){
			return encodeURIComponent(value.stripTags());
		},
		
		closeMe:function($super){
			var uid = this.userData.userID;
			$super();
			control.add(
	    			new shadowedWidget(
	    				{
	    						id:'profile',
	    						position:{left:50, top:20}, 
	    						size:{width:350, height:155},
	    						containerClassName:'whiteWidget', 
	    						useIFrame:true, 
	    						ajax:{uri:'/include/profiel.php?showUser='+ uid},
	    						showClose:false,
	    						framePadding : '0px',
	    						canHide:true
	    				}
	    			)
				);
			control.render();
		}

	});	/** THIS IS NOT A WIDGET!!!!! **/

	var gTicketHTML = '';
	 gTicketHTML =' <div class="smallForm" id="smallForm">'; 
	 gTicketHTML +='	<img src="/images/form_header.jpg" class="formHeader"/>'; 
	 gTicketHTML +='	<form method="POST" action="http://flight1.onlinetravel.ch/cgi-bin/flightmore" id="onlinetravelForm" target="_blank">'; 
	 gTicketHTML +='		<input type="hidden" name="agentc" value="ausnl">'; 
	 gTicketHTML +='		<input type="hidden" name="language" value="nl">'; 
	 gTicketHTML +='		<input type="hidden" name="mode" value="3">'; 
	 gTicketHTML +='		<input type="hidden" name="mask" value="fastbook">'; 
	 gTicketHTML +='		<input type="hidden" name="flugart" value="R">'; 
	 gTicketHTML +='		<input type="hidden" name="onlyavail" value="">'; 
	 gTicketHTML +='		<input type="hidden" name="fromt" id="fromt"/>'; 
	 gTicketHTML +='		<input type="hidden" name="destt" id="destt"/>'; 
	 gTicketHTML +='		<div class="row">'; 
	 gTicketHTML +='			<div class="fieldElementWide">'; 
	 gTicketHTML +='				<span class="ac_holder">'; 
	 gTicketHTML +='					<input type="text" name="from" id="ticketFrom" value="Dusseldorf">'; 
	 gTicketHTML +='				</span>'; 
	 gTicketHTML +='			</div>'; 
	 gTicketHTML +='			<img src="/images/form_wereldbol.jpg" class="wereldbol"/>'; 
	 gTicketHTML +='			<div class="fieldElementWide">'; 
	 gTicketHTML +='				<span class="ac_holder">'; 
	 gTicketHTML +='					<input type="text" name="dest" id="ticketDest" value="naar"/>'; 
	 gTicketHTML +='				</span>						'; 
	 gTicketHTML +='			</div>'; 
	 gTicketHTML +='			<img src="/images/form_wereldbol.jpg" class="wereldbol"/>'; 
	 gTicketHTML +='		</div>'; 
	 gTicketHTML +='		<div class="row">'; 
	 gTicketHTML +='			<div class="fieldTitle">Van</div>'; 
	 gTicketHTML +='			<div class="fieldElementSmall">'; 
	 gTicketHTML +='				<select name="hdate1" id="hdate1" class="selectDay">'; 
	 gTicketHTML +='				</select>'; 
	 gTicketHTML +='				<select name="hdate2" id="hdate2" class="selectMonthYear">'; 
	 gTicketHTML +='				</select>'; 
	 gTicketHTML +='			</div>'; 
	 gTicketHTML +='			<div class="fieldTitleBetween"><sup>t</sup><sub>m</sub></div>'; 
	 gTicketHTML +='			<div class="fieldElementSmall">'; 
	 gTicketHTML +='				<select name="rdate1" id="rdate1" class="selectDay">'; 
	 gTicketHTML +='				</select>'; 
	 gTicketHTML +='				<select name="rdate2" id="rdate2" class="selectMonthYear">'; 
	 gTicketHTML +='				</select>					'; 
	 gTicketHTML +='			</div>				'; 
	 gTicketHTML +='			<div class="fieldElementSmall">'; 
	 gTicketHTML +='				<input type="text" id="amount" class="formAmount" value="2" onchange="if ( parseInt($(this).getValue()) > 4) { alert(\'Het max. aantal is 4 personen\') ;this.value = 4; }"/>'; 
	 gTicketHTML +='			</div>'; 
	 gTicketHTML +='			<div class="fieldElementWide">'; 
	 gTicketHTML +='				<select id="agegroup" class="agegroup">'; 
	 gTicketHTML +='					<option value="youth">Jongeren (18-25)</option>'; 
	 gTicketHTML +='					<option value="student">Studenten (12-36)</option>'; 
	 gTicketHTML +='					<option value="adult">Volwassenen</option>'; 
	 gTicketHTML +='					<option value="child">Kinderen (2-11)</option>'; 
	 gTicketHTML +='					<option value="infant">Babies (0-2)</option>'; 
	 gTicketHTML +='				</select>						'; 
	 gTicketHTML +='			</div>'; 
	 gTicketHTML +='		</div>'; 
	 gTicketHTML +='		<div class="row">'; 
	 gTicketHTML +='			<input type="button" class="btnVoorwaarden" onclick="window.open(\'http://www.goedkopervliegen.nl/algemene_voorwaarden\')" value="Voorwaarden"/>'; 
	 gTicketHTML +='			<input type="button" class="btnUitgebreid" onclick="window.open(\'http://flight1.onlinetravel.ch/cgi-bin/flightmore?agentc=ausnl&language=nl&mode=0&mask=fastbook\')" value="Uitgebreid"/>'; 
	 gTicketHTML +='			<input type="button" id="ticketbtnZoek" class="btnZoek" value=""/>'; 
	 gTicketHTML +='		</div>'; 
	 gTicketHTML +='	</form>			'; 
	 gTicketHTML +='	<div class="babyWarning" style="display:none;" id="babyWarning">'; 
	 gTicketHTML +='		Ga voor deze tickets naar het uitgebreide menu'; 
	 gTicketHTML +='	</div>'; 
	 gTicketHTML +='</div>'; 
	 gTicketHTML +='<div class="smallFormShadow" id="smallFormShadow"></div>'; 

	var inlineTickets = Class.create({
	
		initialize : function(container){
			// ADD items to head:
			this.acZindex = '99999';
			container.insert(gTicketHTML);
			container.observe('click', (function(){
//				container.setStyle('z-index:99999;')
				this.originalZIndex = container.style.zIndex;
//				this.originalShadowZIndex = $("smallFormShadow").style.zIndex;
				if (gZindex){
					gZindex +=5;
				}else{
					gZindex = getHighestZIndex()
				}
				container.setStyle('z-index : ' + gZindex);
				this.acZindex = gZindex;
//				$("smallFormShadow").setStyle('z-index : ' + (gZindex -3) );
			}).bind(this))
//			container.observe('mouseout', function(){
//				container.setStyle('z-index:2;');
//			});

			// set Events:
			$('ticketDest').observe('focus', function(){
				if ($('ticketDest').getValue() == 'naar') {
					$('ticketDest').value = '';
				}				
			});

			$('ticketDest').observe('keydown', function(){
				var options = {
					script:'/include/ticket_autocomplete.php?json=true&limit=6&',
					varname:'input',
					json:true,
					shownoresults:true,
					maxresults:16,
					callback: function (obj) { 
						$('ticketDest').setStyle('background-image:none;');
						$('destt').value = obj.info;
					}
				};
				var json=new AutoComplete('ticketDest',options);
				return true;			
			});
			$('ticketDest').observe('blur', function(){
				if ($('ticketDest').getValue() == ''){
					$('ticketDest').value = "naar";
				}
//				if ($('ac_ul')) $('ac_ul').remove();
			});
			
			
			$('ticketFrom').observe('focus', function(){
				if ($('ticketFrom').getValue() == 'van') {
					$('ticketFrom').value = '';
				}
			});
			
			$('ticketFrom').observe('keydown', function(){
				var options = {
					script:'/include/ticket_autocomplete.php?json=true&limit=6&',
					varname:'input',
					json:true,
					shownoresults:true,
					maxresults:16,
					callback: function (obj) { 
						$('ticketFrom').setStyle('background-image:none;');$('fromt').value = obj.info 
					}
				};
				var json=new AutoComplete('ticketFrom',options);
				return true;				
			});	
			
			$('ticketFrom').observe('blur', function(){
				if ($('ticketFrom').getValue() == ''){
					$('ticketFrom').value = "van";
				}
//				if ($('ac_ul')) $('ac_ul').remove();
			});

			// fill options for date;
			var now = new Date();
			var tdat= new Date(now.valueOf() + (2*86400000));
			tdat = parseInt(tdat.getDate());
			// reset to beginning of this month;
			now = new Date(now.getFullYear(), now.getMonth(), 1);				
			var future = new Date(now.valueOf() + (365*86400000));

			for (var i=1;i<32;i++){
				var option = new Element('option', {value:i}).update(i);
				$('hdate1').insert(option);
				if (tdat == i) option.selected = true;
				var option = new Element('option', {value:i}).update(i);
				$('rdate1').insert(option);
			}
			// fill months until future:
			for (var y =now.valueOf();y<future.valueOf();y += (31*86400000)){
				var currMonth = new Date(y); 
				var month = (parseInt(currMonth.getMonth()) +1);
				month = month.toString();
				if (month.length < 2) month = "0" + month.toString();
				var mValue = (currMonth.getFullYear() + '' +  month);
				
                var option = new Element('option', {value:mValue}).update(month +'/'+currMonth.getYear().toString().substring(1));
                $('hdate2').insert(option);

                var option = new Element('option', {value:mValue}).update(month +'/'+currMonth.getYear().toString().substring(1));
                $('rdate2').insert(option);
			}
			
			$('agegroup').observe('change', function(e){
				var elem = e.element();
				if (elem.getValue() == 'infant'){
					$('babyWarning').show();
				}else{
					$('babyWarning').hide();
				}
			})			
						
			$('ticketbtnZoek').observe('click', this.submitTravelForm.bindAsEventListener(this));
			container.show();
		},
		
		submitTravelForm : function(){
			if ( ($('ticketDest').getValue() == 'naar' || $('ticketDest').getValue() == '') || ( $('ticketFrom').getValue() =='van' || $('ticketFrom').getValue() =='') ) {
				alert('Vertrek en/of aankomst-vliegveld is niet geldig');
				return;
			}
			
			// get amount of persons;
			var amount = $('amount').getValue();
			// get type;
			var type = $('agegroup').getValue();
			
			if ($('fromt').getValue() == ''){
				$('fromt').value="dus";
			}
			
			if ($('destt').getValue() == ''){
				// AJAX-search;
				searchDest();
			}else{
				//create hidden field;
				var elem = new Element('input', {type:'hidden', name:type, value:amount});
				$('onlinetravelForm').insert(elem);
				if (type != 'adult'){
					var elem = new Element('input', {type:'hidden', name:'adult', value:0});
					$('onlinetravelForm').insert(elem);
				}

				$('destt').value = $('destt').getValue().toString().replace(" ","");
				$('fromt').value = $('fromt').getValue().toString().replace(" ","");
				$('onlinetravelForm').submit();	
			}
		},
		
		
		injectScriptToHead : function(src){
	    	var theHead = document.getElementsByTagName("head");
			if (!theHead) {
				if (window.console) console.log("no head?");
				return false;
			}
			theHead = theHead.item(0);
	    	var oScriptElem = document.createElement('script');
			oScriptElem.setAttribute("src",src);
			oScriptElem.setAttribute("language","Javascript");
			oScriptElem.setAttribute("type","text/javascript");
			theHead.insertBefore(oScriptElem, theHead.childNodes.item(0));
		},
		
		injectCssToHead : function(src){
	    	var theHead = document.getElementsByTagName("head");
			if (!theHead) {
				if (window.console) console.log("no head?");
				return false;
			}
			theHead = theHead.item(0);
	    	var oScriptElem = document.createElement('link');
			oScriptElem.setAttribute("rel","stylesheet");
			oScriptElem.setAttribute("type","text/css");
			oScriptElem.setAttribute("media","screen");
			oScriptElem.setAttribute("href",src);
			theHead.insertBefore(oScriptElem, theHead.childNodes.item(0));
		}

		
	}) 

