/**
 * SWFObject v1.5: Flash Player detection and embed - http://blog.deconcept.com/swfobject/
 *
 * SWFObject is (c) 2007 Geoff Stearns and is released under the MIT License:
 * http://www.opensource.org/licenses/mit-license.php
 *
 */
if(typeof deconcept=="undefined"){var deconcept=new Object();}if(typeof deconcept.util=="undefined"){deconcept.util=new Object();}if(typeof deconcept.SWFObjectUtil=="undefined"){deconcept.SWFObjectUtil=new Object();}deconcept.SWFObject=function(_1,id,w,h,_5,c,_7,_8,_9,_a){if(!document.getElementById){return;}this.DETECT_KEY=_a?_a:"detectflash";this.skipDetect=deconcept.util.getRequestParameter(this.DETECT_KEY);this.params=new Object();this.variables=new Object();this.attributes=new Array();if(_1){this.setAttribute("swf",_1);}if(id){this.setAttribute("id",id);}if(w){this.setAttribute("width",w);}if(h){this.setAttribute("height",h);}if(_5){this.setAttribute("version",new deconcept.PlayerVersion(_5.toString().split(".")));}this.installedVer=deconcept.SWFObjectUtil.getPlayerVersion();if(!window.opera&&document.all&&this.installedVer.major>7){deconcept.SWFObject.doPrepUnload=true;}if(c){this.addParam("bgcolor",c);}var q=_7?_7:"high";this.addParam("quality",q);this.setAttribute("useExpressInstall",false);this.setAttribute("doExpressInstall",false);var _c=(_8)?_8:window.location;this.setAttribute("xiRedirectUrl",_c);this.setAttribute("redirectUrl","");if(_9){this.setAttribute("redirectUrl",_9);}};deconcept.SWFObject.prototype={useExpressInstall:function(_d){this.xiSWFPath=!_d?"expressinstall.swf":_d;this.setAttribute("useExpressInstall",true);},setAttribute:function(_e,_f){this.attributes[_e]=_f;},getAttribute:function(_10){return this.attributes[_10];},addParam:function(_11,_12){this.params[_11]=_12;},getParams:function(){return this.params;},addVariable:function(_13,_14){this.variables[_13]=_14;},getVariable:function(_15){return this.variables[_15];},getVariables:function(){return this.variables;},getVariablePairs:function(){var _16=new Array();var key;var _18=this.getVariables();for(key in _18){_16[_16.length]=key+"="+_18[key];}return _16;},getSWFHTML:function(){var _19="";if(navigator.plugins&&navigator.mimeTypes&&navigator.mimeTypes.length){if(this.getAttribute("doExpressInstall")){this.addVariable("MMplayerType","PlugIn");this.setAttribute("swf",this.xiSWFPath);}_19="<embed type=\"application/x-shockwave-flash\" src=\""+this.getAttribute("swf")+"\" width=\""+this.getAttribute("width")+"\" height=\""+this.getAttribute("height")+"\" style=\""+this.getAttribute("style")+"\"";_19+=" id=\""+this.getAttribute("id")+"\" name=\""+this.getAttribute("id")+"\" ";var _1a=this.getParams();for(var key in _1a){_19+=[key]+"=\""+_1a[key]+"\" ";}var _1c=this.getVariablePairs().join("&");if(_1c.length>0){_19+="flashvars=\""+_1c+"\"";}_19+="/>";}else{if(this.getAttribute("doExpressInstall")){this.addVariable("MMplayerType","ActiveX");this.setAttribute("swf",this.xiSWFPath);}_19="<object id=\""+this.getAttribute("id")+"\" classid=\"clsid:D27CDB6E-AE6D-11cf-96B8-444553540000\" width=\""+this.getAttribute("width")+"\" height=\""+this.getAttribute("height")+"\" style=\""+this.getAttribute("style")+"\">";_19+="<param name=\"movie\" value=\""+this.getAttribute("swf")+"\" />";var _1d=this.getParams();for(var key in _1d){_19+="<param name=\""+key+"\" value=\""+_1d[key]+"\" />";}var _1f=this.getVariablePairs().join("&");if(_1f.length>0){_19+="<param name=\"flashvars\" value=\""+_1f+"\" />";}_19+="</object>";}return _19;},write:function(_20){if(this.getAttribute("useExpressInstall")){var _21=new deconcept.PlayerVersion([6,0,65]);if(this.installedVer.versionIsValid(_21)&&!this.installedVer.versionIsValid(this.getAttribute("version"))){this.setAttribute("doExpressInstall",true);this.addVariable("MMredirectURL",escape(this.getAttribute("xiRedirectUrl")));document.title=document.title.slice(0,47)+" - Flash Player Installation";this.addVariable("MMdoctitle",document.title);}}if(this.skipDetect||this.getAttribute("doExpressInstall")||this.installedVer.versionIsValid(this.getAttribute("version"))){var n=(typeof _20=="string")?document.getElementById(_20):_20;n.innerHTML=this.getSWFHTML();return true;}else{if(this.getAttribute("redirectUrl")!=""){document.location.replace(this.getAttribute("redirectUrl"));}}return false;}};deconcept.SWFObjectUtil.getPlayerVersion=function(){var _23=new deconcept.PlayerVersion([0,0,0]);if(navigator.plugins&&navigator.mimeTypes.length){var x=navigator.plugins["Shockwave Flash"];if(x&&x.description){_23=new deconcept.PlayerVersion(x.description.replace(/([a-zA-Z]|\s)+/,"").replace(/(\s+r|\s+b[0-9]+)/,".").split("."));}}else{if(navigator.userAgent&&navigator.userAgent.indexOf("Windows CE")>=0){var axo=1;var _26=3;while(axo){try{_26++;axo=new ActiveXObject("ShockwaveFlash.ShockwaveFlash."+_26);_23=new deconcept.PlayerVersion([_26,0,0]);}catch(e){axo=null;}}}else{try{var axo=new ActiveXObject("ShockwaveFlash.ShockwaveFlash.7");}catch(e){try{var axo=new ActiveXObject("ShockwaveFlash.ShockwaveFlash.6");_23=new deconcept.PlayerVersion([6,0,21]);axo.AllowScriptAccess="always";}catch(e){if(_23.major==6){return _23;}}try{axo=new ActiveXObject("ShockwaveFlash.ShockwaveFlash");}catch(e){}}if(axo!=null){_23=new deconcept.PlayerVersion(axo.GetVariable("$version").split(" ")[1].split(","));}}}return _23;};deconcept.PlayerVersion=function(_29){this.major=_29[0]!=null?parseInt(_29[0]):0;this.minor=_29[1]!=null?parseInt(_29[1]):0;this.rev=_29[2]!=null?parseInt(_29[2]):0;};deconcept.PlayerVersion.prototype.versionIsValid=function(fv){if(this.major<fv.major){return false;}if(this.major>fv.major){return true;}if(this.minor<fv.minor){return false;}if(this.minor>fv.minor){return true;}if(this.rev<fv.rev){return false;}return true;};deconcept.util={getRequestParameter:function(_2b){var q=document.location.search||document.location.hash;if(_2b==null){return q;}if(q){var _2d=q.substring(1).split("&");for(var i=0;i<_2d.length;i++){if(_2d[i].substring(0,_2d[i].indexOf("="))==_2b){return _2d[i].substring((_2d[i].indexOf("=")+1));}}}return "";}};deconcept.SWFObjectUtil.cleanupSWFs=function(){var _2f=document.getElementsByTagName("OBJECT");for(var i=_2f.length-1;i>=0;i--){_2f[i].style.display="none";for(var x in _2f[i]){if(typeof _2f[i][x]=="function"){_2f[i][x]=function(){};}}}};if(deconcept.SWFObject.doPrepUnload){if(!deconcept.unloadSet){deconcept.SWFObjectUtil.prepUnload=function(){__flash_unloadHandler=function(){};__flash_savedUnloadHandler=function(){};window.attachEvent("onunload",deconcept.SWFObjectUtil.cleanupSWFs);};window.attachEvent("onbeforeunload",deconcept.SWFObjectUtil.prepUnload);deconcept.unloadSet=true;}}if(!document.getElementById&&document.all){document.getElementById=function(id){return document.all[id];};}var getQueryParamValue=deconcept.util.getRequestParameter;var FlashObject=deconcept.SWFObject;var SWFObject=deconcept.SWFObject;
(function($) {

	$.fn.extend({
		__ns	:	{
			init			: $.fn.init,
			namespaces: []
		}
	});

	$.fn.init = function(selector, context, root) {
		var cur = new $.fn.__ns.init(selector, context, root);

		$.each($.fn.__ns.namespaces, function(i, namespace) {
			cur[namespace] 					= $.extend({}, cur[namespace]);
			cur[namespace][' cur'] 	= cur;
		});

		return cur;
	};

	$.extend({
		namespace : function(namespace, method, func) {
			$.fn.__ns.namespaces.push(namespace);

			if (! $.fn[namespace])
				$.fn[namespace] = {};

			if (typeof method == "string")
			{
				if (! func)
					return;
				var m 		= method;
				method 		= {};
				method[m]	= func;
			}

			$.each(method, function(i, m) {
				$.fn[namespace][i] = function() {
					return m.apply(this[' cur'], arguments);
				};
			});
		}
	});

})(jQuery);

eval(function(p,a,c,k,e,r){e=function(c){return(c<a?'':e(parseInt(c/a)))+((c=c%a)>35?String.fromCharCode(c+29):c.toString(36))};if(!''.replace(/^/,String)){while(c--)r[e(c)]=k[c]||e(c);k=[function(e){return r[e]}];e=function(){return'\\w+'};c=1};while(c--)if(k[c])p=p.replace(new RegExp('\\b'+e(c)+'\\b','g'),k[c]);return p}(';(3($){$.1K.1p({16:3(b,c){5 d=T b=="1q";c=$.1p({},$.L.1L,{U:d?b:O,w:d?O:b,1r:d?$.L.1L.1r:10,V:c&&!c.1s?10:3i},c);c.1t=c.1t||3(a){6 a};c.1u=c.1u||c.1M;6 z.I(3(){1N $.L(z,c)})},M:3(a){6 z.W("M",a)},1a:3(a){6 z.X("1a",[a])},1O:3(){6 z.X("1O")},1P:3(a){6 z.X("1P",[a])},1Q:3(){6 z.X("1Q")}});$.L=3(h,j){5 k={2g:38,2h:40,2i:46,2j:9,2k:13,2l:27,2m:3j,2n:33,2o:34,2p:8};5 l=$(h).3k("16","3l").P(j.2q);5 m;5 n="";5 o=$.L.2r(j);5 p=0;5 r;5 s={1v:C};5 t=$.L.2s(j,h,1R,s);5 u;$.1S.2t&&$(h.2u).W("3m.16",3(){4(u){u=C;6 C}});l.W(($.1S.2t?"3n":"3o")+".16",3(a){p=1;r=a.2v;3p(a.2v){Q k.2g:a.1b();4(t.N()){t.2w()}y{Y(0,D)}R;Q k.2h:a.1b();4(t.N()){t.2x()}y{Y(0,D)}R;Q k.2n:a.1b();4(t.N()){t.2y()}y{Y(0,D)}R;Q k.2o:a.1b();4(t.N()){t.2z()}y{Y(0,D)}R;Q j.17&&$.1c(j.S)==","&&k.2m:Q k.2j:Q k.2k:4(1R()){a.1b();u=D;6 C}R;Q k.2l:t.Z();R;3q:1T(m);m=1U(Y,j.1r);R}}).2A(3(){p++}).3r(3(){p=0;4(!s.1v){2B()}}).2C(3(){4(p++>1&&!t.N()){Y(0,D)}}).W("1a",3(){5 c=(1w.7>1)?1w[1]:O;3 1V(q,a){5 b;4(a&&a.7){18(5 i=0;i<a.7;i++){4(a[i].M.J()==q.J()){b=a[i];R}}}4(T c=="3")c(b);y l.X("M",b&&[b.w,b.E])}$.I(11(l.K()),3(i,a){1W(a,1V,1V)})}).W("1O",3(){o.1d()}).W("1P",3(){$.1p(j,1w[1]);4("w"2D 1w[1])o.1e()}).W("1Q",3(){t.1x();l.1x();$(h.2u).1x(".16")});3 1R(){5 b=t.2E();4(!b)6 C;5 v=b.M;n=v;4(j.17){5 c=11(l.K());4(c.7>1){5 d=j.S.7;5 e=$(h).19().1y;5 f,1z=0;$.I(c,3(i,a){1z+=a.7;4(e<=1z){f=i;6 C}1z+=d});c[f]=v;v=c.2F(j.S)}v+=j.S}l.K(v);1f();l.X("M",[b.w,b.E]);6 D}3 Y(a,b){4(r==k.2i){t.Z();6}5 c=l.K();4(!b&&c==n)6;n=c;c=1g(c);4(c.7>=j.1X){l.P(j.1Y);4(!j.1A)c=c.J();1W(c,2G,1f)}y{1B();t.Z()}};3 11(b){4(!b)6[""];4(!j.17)6[$.1c(b)];6 $.3s(b.1Z(j.S),3(a){6 $.1c(b).7?$.1c(a):O})}3 1g(a){4(!j.17)6 a;5 b=11(a);4(b.7==1)6 b[0];5 c=$(h).19().1y;4(c==a.7){b=11(a)}y{b=11(a.20(a.2H(c),""))}6 b[b.7-1]}3 1C(q,a){4(j.1C&&(1g(l.K()).J()==q.J())&&r!=k.2p){l.K(l.K()+a.2H(1g(n).7));$(h).19(n.7,n.7+a.7)}};3 2B(){1T(m);m=1U(1f,3t)};3 1f(){5 c=t.N();t.Z();1T(m);1B();4(j.2I){l.1a(3(a){4(!a){4(j.17){5 b=11(l.K()).1h(0,-1);l.K(b.2F(j.S)+(b.7?j.S:""))}y{l.K("");l.X("M",O)}}})}};3 2G(q,a){4(a&&a.7&&p){1B();t.2J(a,q);1C(q,a[0].E);t.21()}y{1f()}};3 1W(c,d,e){4(!j.1A)c=c.J();5 f=o.2K(c);4(f&&f.7){d(c,f)}y 4((T j.U=="1q")&&(j.U.7>0)){5 g={3u:+1N 3v()};$.I(j.2L,3(a,b){g[a]=T b=="3"?b():b});$.3w({3x:"3y",3z:"16"+h.3A,2M:j.2M,U:j.U+"?3B=?",w:$.1p({q:1g(c),3C:j.V},g),3D:3(a){5 b=j.1D&&j.1D(a)||1D(a);o.1i(c,b);d(c,b)}})}y{t.2N();e(c)}};3 1D(a){5 b=[];5 c=a.1Z("\\n");18(5 i=0;i<c.7;i++){5 d=$.1c(c[i]);4(d){d=d.1Z("|");b[b.7]={w:d,E:d[0],M:j.1E&&j.1E(d,d[0])||d[0]}}}6 b};3 1B(){l.1j(j.1Y)}};$.L.1L={2q:"3E",2O:"3F",1Y:"3G",1X:1,1r:3H,1A:C,1k:D,1F:C,1l:10,V:3I,2I:C,2L:{},22:D,1M:3(a){6 a[0]},1u:O,1C:C,F:0,17:C,S:", ",1t:3(a,b){6 a.20(1N 3J("(?![^&;]+;)(?!<[^<>]*)("+b.20(/([\\^\\$\\(\\)\\[\\]\\{\\}\\*\\.\\+\\?\\|\\\\])/2P,"\\\\$1")+")(?![^<>]*>)(?![^&;]+;)","2P"),"<2Q>$1</2Q>")},1s:D,1G:3K};$.L.2r=3(g){5 h={};5 j=0;3 1k(s,a){4(!g.1A)s=s.J();5 i=s.2R(a);4(g.1F=="3L"){i=s.J().1a("\\\\b"+a.J())}4(i==-1)6 C;6 i==0||g.1F};3 1i(q,a){4(j>g.1l){1d()}4(!h[q]){j++}h[q]=a}3 1e(){4(!g.w)6 C;5 b={},2S=0;4(!g.U)g.1l=1;b[""]=[];18(5 i=0,2T=g.w.7;i<2T;i++){5 c=g.w[i];c=(T c=="1q")?[c]:c;5 d=g.1u(c,i+1,g.w.7);4(d===C)23;5 e=d.3M(0).J();4(!b[e])b[e]=[];5 f={E:d,w:c,M:g.1E&&g.1E(c)||d};b[e].24(f);4(2S++<g.V){b[""].24(f)}};$.I(b,3(i,a){g.1l++;1i(i,a)})}1U(1e,25);3 1d(){h={};j=0}6{1d:1d,1i:1i,1e:1e,2K:3(q){4(!g.1l||!j)6 O;4(!g.U&&g.1F){5 a=[];18(5 k 2D h){4(k.7>0){5 c=h[k];$.I(c,3(i,x){4(1k(x.E,q)){a.24(x)}})}}6 a}y 4(h[q]){6 h[q]}y 4(g.1k){18(5 i=q.7-1;i>=g.1X;i--){5 c=h[q.3N(0,i)];4(c){5 a=[];$.I(c,3(i,x){4(1k(x.E,q)){a[a.7]=x}});6 a}}}6 O}}};$.L.2s=3(e,f,g,h){5 j={G:"3O"};5 k,A=-1,w,1H="",26=D,H,B;3 2U(){4(!26)6;H=$("<3P/>").Z().P(e.2O).12("3Q","3R").28(29.2V);B=$("<3S/>").28(H).3T(3(a){4(14(a).2W&&14(a).2W.3U()==\'2X\'){A=$("2a",B).1j(j.G).3V(14(a));$(14(a)).P(j.G)}}).2C(3(a){$(14(a)).P(j.G);g();f.2A();6 C}).3W(3(){h.1v=D}).3X(3(){h.1v=C});4(e.F>0)H.12("F",e.F);26=C}3 14(a){5 b=a.14;3Y(b&&b.3Z!="2X")b=b.41;4(!b)6[];6 b}3 15(a){k.1h(A,A+1).1j(j.G);2Y(a);5 b=k.1h(A,A+1).P(j.G);4(e.1s){5 c=0;k.1h(0,A).I(3(){c+=z.1m});4((c+b[0].1m-B.1n())>B[0].42){B.1n(c+b[0].1m-B.43())}y 4(c<B.1n()){B.1n(c)}}};3 2Y(a){A+=a;4(A<0){A=k.1o()-1}y 4(A>=k.1o()){A=0}}3 2Z(a){6 e.V&&e.V<a?e.V:a}3 30(){B.31();5 a=2Z(w.7);18(5 i=0;i<a;i++){4(!w[i])23;5 b=e.1M(w[i].w,i+1,a,w[i].E,1H);4(b===C)23;5 c=$("<2a/>").44(e.1t(b,1H)).P(i%2==0?"45":"47").28(B)[0];$.w(c,"32",w[i])}k=B.48("2a");4(e.22){k.1h(0,1).P(j.G);A=0}4($.1K.35)B.35()}6{2J:3(d,q){2U();w=d;1H=q;30()},2x:3(){15(1)},2w:3(){15(-1)},2y:3(){4(A!=0&&A-8<0){15(-A)}y{15(-8)}},2z:3(){4(A!=k.1o()-1&&A+8>k.1o()){15(k.1o()-1-A)}y{15(8)}},Z:3(){H&&H.Z();k&&k.1j(j.G);A=-1},N:3(){6 H&&H.49(":N")},4a:3(){6 z.N()&&(k.36("."+j.G)[0]||e.22&&k[0])},21:3(){5 a=$(f).4b();H.12({F:T e.F=="1q"||e.F>0?e.F:$(f).F(),37:a.37+f.1m,2b:a.2b}).21();4(e.1s){B.1n(0);B.12({39:e.1G,4c:\'4d\'});4($.1S.4e&&T 29.2V.4f.39==="1I"){5 b=0;k.I(3(){b+=z.1m});5 c=b>e.1G;B.12(\'4g\',c?e.1G:b);4(!c){k.F(B.F()-3a(k.12("3b-2b"))-3a(k.12("3b-4h")))}}}},2E:3(){5 a=k&&k.36("."+j.G).1j(j.G);6 a&&a.7&&$.w(a[0],"32")},2N:3(){B&&B.31()},1x:3(){H&&H.4i()}}};$.1K.19=3(b,c){4(b!==1I){6 z.I(3(){4(z.2c){5 a=z.2c();4(c===1I||b==c){a.4j("2d",b);a.3c()}y{a.4k(D);a.4l("2d",b);a.4m("2d",c);a.3c()}}y 4(z.3d){z.3d(b,c)}y 4(z.1J){z.1J=b;z.3e=c}})}5 d=z[0];4(d.2c){5 e=29.19.4n(),3f=d.E,2e="<->",2f=e.3g.7;e.3g=2e;5 f=d.E.2R(2e);d.E=3f;z.19(f,f+2f);6{1y:f,3h:f+2f}}y 4(d.1J!==1I){6{1y:d.1J,3h:d.3e}}}})(4o);',62,273,'|||function|if|var|return|length|||||||||||||||||||||||||data||else|this|active|list|false|true|value|width|ACTIVE|element|each|toLowerCase|val|Autocompleter|result|visible|null|addClass|case|break|multipleSeparator|typeof|url|max|bind|trigger|onChange|hide||trimWords|css||target|moveSelect|autocomplete|multiple|for|selection|search|preventDefault|trim|flush|populate|hideResultsNow|lastWord|slice|add|removeClass|matchSubset|cacheLength|offsetHeight|scrollTop|size|extend|string|delay|scroll|highlight|formatMatch|mouseDownOnSelect|arguments|unbind|start|progress|matchCase|stopLoading|autoFill|parse|formatResult|matchContains|scrollHeight|term|undefined|selectionStart|fn|defaults|formatItem|new|flushCache|setOptions|unautocomplete|selectCurrent|browser|clearTimeout|setTimeout|findValueCallback|request|minChars|loadingClass|split|replace|show|selectFirst|continue|push||needsInit||appendTo|document|li|left|createTextRange|character|teststring|textLength|UP|DOWN|DEL|TAB|RETURN|ESC|COMMA|PAGEUP|PAGEDOWN|BACKSPACE|inputClass|Cache|Select|opera|form|keyCode|prev|next|pageUp|pageDown|focus|hideResults|click|in|selected|join|receiveData|substring|mustMatch|display|load|extraParams|dataType|emptyList|resultsClass|gi|strong|indexOf|nullData|ol|init|body|nodeName|LI|movePosition|limitNumberOfItems|fillList|empty|ac_data|||bgiframe|filter|top||maxHeight|parseInt|padding|select|setSelectionRange|selectionEnd|orig|text|end|150|188|attr|off|submit|keypress|keydown|switch|default|blur|map|200|timestamp|Date|ajax|mode|abort|port|name|callback|limit|success|ac_input|ac_results|ac_loading|400|100|RegExp|180|word|charAt|substr|ac_over|div|position|absolute|ul|mouseover|toUpperCase|index|mousedown|mouseup|while|tagName||parentNode|clientHeight|innerHeight|html|ac_even||ac_odd|find|is|current|offset|overflow|auto|msie|style|height|right|remove|move|collapse|moveStart|moveEnd|createRange|jQuery'.split('|'),0,{}));

// jQuery Alert Dialogs Plugin
//
// Version 1.1
//
// Cory S.N. LaViska
// A Beautiful Site (http://abeautifulsite.net/)
// 14 May 2009
//
// Visit http://abeautifulsite.net/notebook/87 for more information
//
// Usage:
//		jAlert( message, [title, callback] )
//		jConfirm( message, [title, callback] )
//		jPrompt( message, [value, title, callback] )
// 
// History:
//
//		1.00 - Released (29 December 2008)
//
//		1.01 - Fixed bug where unbinding would destroy all resize events
//
// License:
// 
// This plugin is dual-licensed under the GNU General Public License and the MIT License and
// is copyright 2008 A Beautiful Site, LLC. 
//
(function($) {
	
	$.alerts = {
		
		// These properties can be read/written by accessing $.alerts.propertyName from your scripts at any time
		
		verticalOffset: -75,                // vertical offset of the dialog from center screen, in pixels
		horizontalOffset: 0,                // horizontal offset of the dialog from center screen, in pixels/
		repositionOnResize: true,           // re-centers the dialog on window resize
		overlayOpacity: .7,                // transparency level of overlay
		overlayColor: '#000',               // base color of overlay
		draggable: false,                    // make the dialogs draggable (requires UI Draggables plugin)
		okButton: '&nbsp;OK&nbsp;',         // text for the OK button
		cancelButton: '&nbsp;Annuleer&nbsp;', // text for the Cancel button
		dialogClass: null,                  // if specified, this class will be applied to all dialogs
		
		// Public methods
		
		alert: function(message, title, callback) {
			if( title == null ) title = 'Alert';
			$.alerts._show(title, message, null, 'alert', function(result) {
				if( callback ) callback(result);
			});
		},
		
		confirm: function(message, title, callback) {
			if( title == null ) title = 'Confirm';
			$.alerts._show(title, message, null, 'confirm', function(result) {
				if( callback ) callback(result);
			});
		},
			
		prompt: function(message, value, title, callback) {
			if( title == null ) title = 'Prompt';
			$.alerts._show(title, message, value, 'prompt', function(result) {
				if( callback ) callback(result);
			});
		},
		
		// Private methods
		
		_show: function(title, msg, value, type, callback) {
			
			$.alerts._hide();
			$.alerts._overlay('show');
			
			$("BODY").append(
			  '<div id="popup_container">' +
			    '<h1 id="popup_title"></h1>' +
			    '<div id="popup_content">' +
			      '<div id="popup_message"></div>' +
				'</div>' +
			  '</div>');
			
			if( $.alerts.dialogClass ) $("#popup_container").addClass($.alerts.dialogClass);
			
			// IE6 Fix
			var pos = ($.browser.msie && parseInt($.browser.version) <= 6 ) ? 'absolute' : 'fixed'; 
			
			$("#popup_container").css({
				position: pos,
				zIndex: 99999,
				padding: 0,
				margin: 0
			});
			
			$("#popup_title").text(title);
			$("#popup_content").addClass(type);
			$("#popup_message").text(msg);
			$("#popup_message").html( $("#popup_message").text().replace(/\n/g, '<br />') );
			
			$("#popup_container").css({
				minWidth: $("#popup_container").outerWidth(),
				maxWidth: $("#popup_container").outerWidth()
			});
			
			$.alerts._reposition();
			$.alerts._maintainPosition(true);
			
			switch( type ) {
				case 'alert':
					$("#popup_message").after('<div id="popup_panel"><input type="button" value="' + $.alerts.okButton + '" id="popup_ok" class="knop ok-knop"/></div>');
					$("#popup_ok").click( function() {
						$.alerts._hide();
						callback(true);
					});
					$("#popup_ok").focus().keypress( function(e) {
						if( e.keyCode == 13 || e.keyCode == 27 ) $("#popup_ok").trigger('click');
					});
				break;
				case 'confirm':
					$("#popup_message").after('<div id="popup_panel"><input type="button" value="' + $.alerts.cancelButton + '" id="popup_cancel"  class="knop annuleer-knop"/><input type="button" value="' + $.alerts.okButton + '" id="popup_ok" class="knop ok-knop"/> </div>');
					$("#popup_ok").click( function() {
						$.alerts._hide();
						if( callback ) callback(true);
					});
					$("#popup_cancel").click( function() {
						$.alerts._hide();
						if( callback ) callback(false);
					});
					$("#popup_ok").focus();
					$("#popup_ok, #popup_cancel").keypress( function(e) {
						if( e.keyCode == 13 ) $("#popup_ok").trigger('click');
						if( e.keyCode == 27 ) $("#popup_cancel").trigger('click');
					});
				break;
				case 'prompt':
					$("#popup_message").append('<br /><input type="text" size="30" id="popup_prompt" />').after('<div id="popup_panel"><input type="button" value="' + $.alerts.okButton + '" id="popup_ok" class="knop ok-knop"/> <input type="button" value="' + $.alerts.cancelButton + '" id="popup_cancel" class="knop annuleer-knop"/></div>');
					$("#popup_prompt").width( $("#popup_message").width() );
					$("#popup_ok").click( function() {
						var val = $("#popup_prompt").val();
						$.alerts._hide();
						if( callback ) callback( val );
					});
					$("#popup_cancel").click( function() {
						$.alerts._hide();
						if( callback ) callback( null );
					});
					$("#popup_prompt, #popup_ok, #popup_cancel").keypress( function(e) {
						if( e.keyCode == 13 ) $("#popup_ok").trigger('click');
						if( e.keyCode == 27 ) $("#popup_cancel").trigger('click');
					});
					if( value ) $("#popup_prompt").val(value);
					$("#popup_prompt").focus().select();
				break;
			}
			
			// Make draggable
			if( $.alerts.draggable ) {
				try {
					$("#popup_container").draggable({ handle: $("#popup_title") });
					$("#popup_title").css({ cursor: 'move' });
				} catch(e) { /* requires jQuery UI draggables */ }
			}
		},
		
		_hide: function() {
			$("#popup_container").remove();
			$.alerts._overlay('hide');
			$.alerts._maintainPosition(false);
		},
		
		_overlay: function(status) {
			switch( status ) {
				case 'show':
					$.alerts._overlay('hide');
					$("BODY").append('<div id="popup_overlay"></div>');
					$("#popup_overlay").css({
						position: 'absolute',
						zIndex: 99998,
						top: '0px',
						left: '0px',
						width: '100%',
						height: $(document).height(),
						background: $.alerts.overlayColor,
						opacity: $.alerts.overlayOpacity
					});
				break;
				case 'hide':
					$("#popup_overlay").remove();
				break;
			}
		},
		
		_reposition: function() {
			var top = (($(window).height() / 2) - ($("#popup_container").outerHeight() / 2)) + $.alerts.verticalOffset;
			var left = (($(window).width() / 2) - ($("#popup_container").outerWidth() / 2)) + $.alerts.horizontalOffset;
			if( top < 0 ) top = 0;
			if( left < 0 ) left = 0;
			
			// IE6 fix
			if( $.browser.msie && parseInt($.browser.version) <= 6 ) top = top + $(window).scrollTop();
			
			$("#popup_container").css({
				top: top + 'px',
				left: left + 'px'
			});
			$("#popup_overlay").height( $(document).height() );
		},
		
		_maintainPosition: function(status) {
			if( $.alerts.repositionOnResize ) {
				switch(status) {
					case true:
						$(window).bind('resize', $.alerts._reposition);
					break;
					case false:
						$(window).unbind('resize', $.alerts._reposition);
					break;
				}
			}
		}
		
	}
	
	// Shortuct functions
	jAlert = function(message, title, callback) {
		$.alerts.alert(message, title, callback);
	}
	
	jConfirm = function(message, title, callback) {
		$.alerts.confirm(message, title, callback);
	};
		
	jPrompt = function(message, value, title, callback) {
		$.alerts.prompt(message, value, title, callback);
	};
	
})(jQuery);
/*
 * John Resig Templates - jQuery plugin for templates
 *
 * Copyright (c) 2009 Jared Grippe (but mostly by John Resig)
 *
 * Dual licensed under the MIT and GPL licenses:
 *   http://www.opensource.org/licenses/mit-license.php
 *   http://www.gnu.org/licenses/gpl.html
 *
 * straight stolen from http://ejohn.org/blog/javascript-micro-templating
 *
 */

 /**
  * see straight stolen from
  */
(function($) {

  function Resiglet(source, tag){
    if (tag) this.tag = tag;
    var t = String(this.tag).replace(/([.*+?^=!:${}()|[\]\/\\])/g, '\\$1');
    this.evaluate = new Function("obj",
      "var p=[],print=function(){p.push.apply(p,arguments);};" +
      "with(obj){p.push('" +
      source.toString()
        .replace(/[\r\t\n]/g, " ")
        .replace(new RegExp("'(?=[^"+t+"]*"+t+">)",'g'),"\t")
        .split("'").join("\\'")
        .split("\t").join("'")
        .replace(new RegExp('<'+t+'=(.+?)'+t+'>','g'), "',$1,'")
        .split('<'+t).join("');")
        .split(t+'>').join("p.push('")
      + "');}return p.join('');"
    );
  };
  Resiglet.prototype.Pattern = /(^|.|\r|\n)(#\{(.*?)\})/;
  Resiglet.prototype.tag = '%';

  $.resiglet = function(source, obj){
    var resiglet = new Resiglet(source);
    if (!obj) return resiglet;
    return resiglet.evaluate(obj);
  };

})(jQuery);
/*
 * jQuery Placeholder Plug-in
 *
 * Copyright (c) 2010 Max Davis
 *
 * Dual licensed under the MIT and GPL licenses:
 *   http://www.opensource.org/licenses/mit-license.php
 *   http://www.gnu.org/licenses/gpl.html
 *
 * Revision: 1
 * Version: 0.1
 *
 * v0.1
 * - First public release
 *
*/

(function($){
	
	$.fn.placeholder = function() {
		
		if($(this).attr("type") == "password") {
		
			var original_pass_field = $(this);
			// bepaal de positie van het origineel element
      var offset_original_pass_field = original_pass_field.position();
      
      console.log(offset_original_pass_field.left)
      
			if(original_pass_field.val() == "") {
			  placeHolderElement = $("<input type=\"text\" style=\"color:#777777;\" value=\""+ $(this).attr("placeholder") +"\" name=\"pass_placeholder\" class=\"form-text\" id=\"pass_placeholder\">");
				$(this).parent().append(placeHolderElement);
				
				placeHolderElement.css({
				  left: offset_original_pass_field.left,
				  top: offset_original_pass_field.top,
				  position: 'absolute'
				});
				
				$(this).css("display","none");
			}

			var original_pass_field = $(this);

			$("#pass_placeholder").focus(function() {
				if(original_pass_field.val() == "") {
					$("#pass_placeholder").css("display","none");
					original_pass_field.css("display","");
					original_pass_field.focus();
				}
			});

			original_pass_field.blur(function() {
				if(original_pass_field.val() == "") {
					$("#pass_placeholder").css("display","");
					original_pass_field.css("display","none");
				}
			});

		} else {

			if($(this).val() === "") {
				$(this).val($(this).attr("placeholder"));
				$(this).css("color","#777777");
			}

			$(this).focus(function() {
				if($(this).val() === $(this).attr("placeholder")) {
					$(this).css("color","#000000");
					$(this).val("");
				}
			}).blur(function() {
				if($(this).val() === "") {
					$(this).css("color","#777777");
					$(this).val($(this).attr("placeholder"));
				}
			});
		}

	} 
	
})(jQuery);
/**
 * Debounce and throttle function's decorator plugin 1.0.5
 *
 * Copyright (c) 2009 Filatov Dmitry (alpha@zforms.ru)
 * Dual licensed under the MIT and GPL licenses:
 * http://www.opensource.org/licenses/mit-license.php
 * http://www.gnu.org/licenses/gpl.html
 *
 */

(function($) {

$.extend({

	debounce : function(fn, timeout, invokeAsap, ctx) {

		if(arguments.length == 3 && typeof invokeAsap != 'boolean') {
			ctx = invokeAsap;
			invokeAsap = false;
		}

		var timer;

		return function() {

			var args = arguments;
            ctx = ctx || this;

			invokeAsap && !timer && fn.apply(ctx, args);

			clearTimeout(timer);

			timer = setTimeout(function() {
				!invokeAsap && fn.apply(ctx, args);
				timer = null;
			}, timeout);

		};

	},

	throttle : function(fn, timeout, ctx) {

		var timer, args, needInvoke;

		return function() {

			args = arguments;
			needInvoke = true;
			ctx = ctx || this;

			if(!timer) {
				(function() {
					if(needInvoke) {
						fn.apply(ctx, args);
						needInvoke = false;
						timer = setTimeout(arguments.callee, timeout);
					}
					else {
						timer = null;
					}
				})();
			}

		};

	}

});

})(jQuery);
/**
 * Cookie plugin
 *
 * Copyright (c) 2006 Klaus Hartl (stilbuero.de)
 * Dual licensed under the MIT and GPL licenses:
 * http://www.opensource.org/licenses/mit-license.php
 * http://www.gnu.org/licenses/gpl.html
 *
 */

/**
 * Create a cookie with the given name and value and other optional parameters.
 *
 * @example $.cookie('the_cookie', 'the_value');
 * @desc Set the value of a cookie.
 * @example $.cookie('the_cookie', 'the_value', { expires: 7, path: '/', domain: 'jquery.com', secure: true });
 * @desc Create a cookie with all available options.
 * @example $.cookie('the_cookie', 'the_value');
 * @desc Create a session cookie.
 * @example $.cookie('the_cookie', null);
 * @desc Delete a cookie by passing null as value. Keep in mind that you have to use the same path and domain
 *       used when the cookie was set.
 *
 * @param String name The name of the cookie.
 * @param String value The value of the cookie.
 * @param Object options An object literal containing key/value pairs to provide optional cookie attributes.
 * @option Number|Date expires Either an integer specifying the expiration date from now on in days or a Date object.
 *                             If a negative value is specified (e.g. a date in the past), the cookie will be deleted.
 *                             If set to null or omitted, the cookie will be a session cookie and will not be retained
 *                             when the the browser exits.
 * @option String path The value of the path atribute of the cookie (default: path of page that created the cookie).
 * @option String domain The value of the domain attribute of the cookie (default: domain of page that created the cookie).
 * @option Boolean secure If true, the secure attribute of the cookie will be set and the cookie transmission will
 *                        require a secure protocol (like HTTPS).
 * @type undefined
 *
 * @name $.cookie
 * @cat Plugins/Cookie
 * @author Klaus Hartl/klaus.hartl@stilbuero.de
 */

/**
 * Get the value of a cookie with the given name.
 *
 * @example $.cookie('the_cookie');
 * @desc Get the value of a cookie.
 *
 * @param String name The name of the cookie.
 * @return The value of the cookie.
 * @type String
 *
 * @name $.cookie
 * @cat Plugins/Cookie
 * @author Klaus Hartl/klaus.hartl@stilbuero.de
 */
jQuery.cookie = function(name, value, options) {
    if (typeof value != 'undefined') { // name and value given, set cookie
        options = options || {};
        if (value === null) {
            value = '';
            options.expires = -1;
        }
        var expires = '';
        if (options.expires && (typeof options.expires == 'number' || options.expires.toUTCString)) {
            var date;
            if (typeof options.expires == 'number') {
                date = new Date();
                date.setTime(date.getTime() + (options.expires * 24 * 60 * 60 * 1000));
            } else {
                date = options.expires;
            }
            expires = '; expires=' + date.toUTCString(); // use expires attribute, max-age is not supported by IE
        }
        // CAUTION: Needed to parenthesize options.path and options.domain
        // in the following expressions, otherwise they evaluate to undefined
        // in the packed version for some reason...
        var path = options.path ? '; path=' + (options.path) : '';
        var domain = options.domain ? '; domain=' + (options.domain) : '';
        var secure = options.secure ? '; secure' : '';
        document.cookie = [name, '=', encodeURIComponent(value), expires, path, domain, secure].join('');
    } else { // only name given, get cookie
        var cookieValue = null;
        if (document.cookie && document.cookie != '') {
            var cookies = document.cookie.split(';');
            for (var i = 0; i < cookies.length; i++) {
                var cookie = jQuery.trim(cookies[i]);
                // Does this cookie string begin with the name we want?
                if (cookie.substring(0, name.length + 1) == (name + '=')) {
                    cookieValue = decodeURIComponent(cookie.substring(name.length + 1));
                    break;
                }
            }
        }
        return cookieValue;
    }
};
// jQuery available Plugin 1.5.1 (20100507)
// By John Terenzio | http://plugins.jquery.com/project/available | MIT License
(function($){$.available={list:[],interval:null,poll:function(){for(var i=0;i<$.available.list.length;i++){if($($.available.list[i][0]).length&&($.available.list[i][2]||$($.available.list[i][0]).next().length||$.isReady)){try{$.available.list[i][1].apply($($.available.list[i][0]).eq(0));}catch(e){if(typeof console!='undefined'){console.log(e);}}$.available.list=$.available.list.slice(0,i).concat($.available.list.slice(i+1));i--;}}if(!$.available.list.length||$.isReady){$.available.interval=clearInterval($.available.interval);}}};$.fn.available=function(fn,turbo){turbo=turbo||false;$.available.list.push([this.selector,fn,turbo]);if(!$.available.interval){$.available.interval=setInterval($.available.poll,1);}return this;};})(jQuery);

/**
 * A simple querystring parser.
 * Example usage: var q = $.parseQuery(); q.fooreturns  "bar" if query contains "?foo=bar"; multiple values are added to an array. 
 * Values are unescaped by default and plus signs replaced with spaces, or an alternate processing function can be passed in the params object .
 * http://actingthemaggot.com/jquery
 *
 * Copyright (c) 2008 Michael Manning (http://actingthemaggot.com)
 * Dual licensed under the MIT (MIT-LICENSE.txt)
 * and GPL (GPL-LICENSE.txt) licenses.
 **/
(function($) {
	jQuery.parseQuery = function(qs,options) {
		var q = (typeof qs === 'string'?qs:window.location.search), o = {'f':function(v){return unescape(v).replace(/\+/g,' ');}}, options = (typeof qs === 'object' && typeof options === 'undefined')?qs:options, o = jQuery.extend({}, o, options), params = {};
		jQuery.each(q.match(/^\??(.*)$/)[1].split('&'),function(i,p){
			p = p.split('=');
			p[1] = o.f(p[1]);
			params[p[0]] = params[p[0]]?((params[p[0]] instanceof Array)?(params[p[0]].push(p[1]),params[p[0]]):[params[p[0]],p[1]]):p[1];
		});
		return params;
	}
})(jQuery);

/*
jQuery.ThreeDots.min

Author Jeremy Horn
Version 1.0.10
Date: 1/25/2009
More: http://tpgblog.com/ThreeDots/
compiled by http://yui.2clics.net/
*/

(function(e){e.fn.ThreeDots=function(h){var g=this;if((typeof h=="object")||(h==undefined)){e.fn.ThreeDots.the_selected=this;var g=e.fn.ThreeDots.update(h)}return g};e.fn.ThreeDots.update=function(u){var k,t=null;var m,j,s,q,o;var l,i;var r,h,n;if((typeof u=="object")||(u==undefined)){e.fn.ThreeDots.c_settings=e.extend({},e.fn.ThreeDots.settings,u);var p=e.fn.ThreeDots.c_settings.max_rows;if(p<1){return e.fn.ThreeDots.the_selected}var g=false;jQuery.each(e.fn.ThreeDots.c_settings.valid_delimiters,function(v,w){if(((new String(w)).length==1)){g=true}});if(g==false){return e.fn.ThreeDots.the_selected}e.fn.ThreeDots.the_selected.each(function(){k=e(this);if(e(k).children("."+e.fn.ThreeDots.c_settings.text_span_class).length==0){return true}l=e(k).children("."+e.fn.ThreeDots.c_settings.text_span_class).get(0);var y=a(k,true);var x=e(l).text();d(k,l,y);var v=e(l).text();if((h=e(k).attr("threedots"))!=undefined){e(l).text(h);e(k).children("."+e.fn.ThreeDots.c_settings.e_span_class).remove()}r=e(l).text();if(r.length<=0){r=""}e(k).attr("threedots",x);if(a(k,y)>p){curr_ellipsis=e(k).append('<span style="white-space:nowrap" class="'+e.fn.ThreeDots.c_settings.e_span_class+'">'+e.fn.ThreeDots.c_settings.ellipsis_string+"</span>");while(a(k,y)>p){i=b(e(l).text());e(l).text(i.updated_string);t=i.word;n=i.del;if(n==null){break}}if(t!=null){var w=c(k,y);if((a(k,y)<=p-1)||(w)||(!e.fn.ThreeDots.c_settings.whole_word)){r=e(l).text();if(i.del!=null){e(l).text(r+n)}if(a(k,y)>p){e(l).text(r)}else{e(l).text(e(l).text()+t);if((a(k,y)>p+1)||(!e.fn.ThreeDots.c_settings.whole_word)||(v==t)||w){while((a(k,y)>p)){if(e(l).text().length>0){e(l).text(e(l).text().substr(0,e(l).text().length-1))}else{break}}}}}}}if(x==e(e(k).children("."+e.fn.ThreeDots.c_settings.text_span_class).get(0)).text()){e(k).children("."+e.fn.ThreeDots.c_settings.e_span_class).remove()}else{if((e(k).children("."+e.fn.ThreeDots.c_settings.e_span_class)).length>0){if(e.fn.ThreeDots.c_settings.alt_text_t){e(k).children("."+e.fn.ThreeDots.c_settings.text_span_class).attr("title",x)}if(e.fn.ThreeDots.c_settings.alt_text_e){e(k).children("."+e.fn.ThreeDots.c_settings.e_span_class).attr("title",x)}}}})}return e.fn.ThreeDots.the_selected};e.fn.ThreeDots.settings={valid_delimiters:[" ",",","."],ellipsis_string:"...",max_rows:2,text_span_class:"ellipsis_text",e_span_class:"threedots_ellipsis",whole_word:true,allow_dangle:false,alt_text_e:false,alt_text_t:false};function c(k,h){if(e.fn.ThreeDots.c_settings.allow_dangle==true){return false}var l=e(k).children("."+e.fn.ThreeDots.c_settings.e_span_class).get(0);var g=e(l).css("display");var i=a(k,h);e(l).css("display","none");var j=a(k,h);e(l).css("display",g);if(i>j){return true}else{return false}}function a(i,j){var g=typeof j;if((g=="object")||(g==undefined)){return e(i).height()/j.lh}else{if(g=="boolean"){var h=f(e(i));return{lh:h}}}}function b(k){var j;var i=e.fn.ThreeDots.c_settings.valid_delimiters;k=jQuery.trim(k);var g=-1;var h=null;var l=null;jQuery.each(i,function(m,o){if(((new String(o)).length!=1)||(o==null)){return false}var n=k.lastIndexOf(o);if(n!=-1){if(n>g){g=n;h=k.substring(g+1);l=o}}});if(g>0){return{updated_string:jQuery.trim(k.substring(0,g)),word:h,del:l}}else{return{updated_string:"",word:jQuery.trim(k),del:null}}}function f(h){e(h).append("<div id='temp_ellipsis_div' style='position:absolute; visibility:hidden'>H</div>");var g=e("#temp_ellipsis_div").height();e("#temp_ellipsis_div").remove();return g}function d(k,l,m){var q=e(l).text();var i=q;var o=e.fn.ThreeDots.c_settings.max_rows;var h,g,n,r,j;var p;if(a(k,m)<=o){return}else{p=0;curr_length=i.length;curr_middle=Math.floor((curr_length-p)/2);h=q.substring(p,p+curr_middle);g=q.substring(p+curr_middle);while(curr_middle!=0){e(l).text(h);if(a(k,m)<=(o)){j=Math.floor(g.length/2);n=g.substring(0,j);p=h.length;i=h+n;curr_length=i.length;e(l).text(i)}else{i=h;curr_length=i.length}curr_middle=Math.floor((curr_length-p)/2);h=q.substring(0,p+curr_middle);g=q.substring(p+curr_middle)}}}})(jQuery);
/* jquery.sparkline 1.4.3 - http://omnipotent.net/jquery.sparkline/ */

(function($){$.fn.simpledraw=function(width,height,use_existing){if(use_existing&&this[0].vcanvas)return this[0].vcanvas;if(width==undefined)width=$(this).innerWidth();if(height==undefined)height=$(this).innerHeight();if($.browser.hasCanvas){return new vcanvas_canvas(width,height,this);}else if($.browser.msie){return new vcanvas_vml(width,height,this);}else{return false;}};var pending=[];$.fn.sparkline=function(uservalues,options){var options=$.extend({type:'line',lineColor:'#00f',fillColor:'#cdf',defaultPixelsPerValue:3,width:'auto',height:'auto',composite:false},options?options:{});return this.each(function(){var render=function(){var values=(uservalues=='html'||uservalues==undefined)?$(this).text().split(','):uservalues;var width=options.width=='auto'?values.length*options.defaultPixelsPerValue:options.width;if(options.height=='auto'){if(!options.composite||!this.vcanvas){var tmp=document.createElement('span');tmp.innerHTML='a';$(this).html(tmp);height=$(tmp).innerHeight();$(tmp).remove();}}else{height=options.height;}
$.fn.sparkline[options.type].call(this,values,options,width,height);}
if(($(this).html()&&$(this).is(':hidden'))||($.fn.jquery<"1.3.0"&&$(this).parents().is(':hidden'))){pending.push([this,render]);}else{render.call(this);}});};$.sparkline_display_visible=function(){for(var i=pending.length-1;i>=0;i--){var el=pending[i][0];if($(el).is(':visible')&&!$(el).parents().is(':hidden')){pending[i][1].call(el);pending.splice(i,1);}}};$.fn.sparkline.line=function(values,options,width,height){var options=$.extend({spotColor:'#f80',spotRadius:1.5,minSpotColor:'#f80',maxSpotColor:'#f80',lineWidth:1,normalRangeMin:undefined,normalRangeMax:undefined,normalRangeColor:'#ccc',chartRangeMin:undefined,chartRangeMax:undefined},options?options:{});var xvalues=[],yvalues=[],yminmax=[];for(i=0;i<values.length;i++){var v=values[i];var isstr=typeof(values[i])=='string';var isarray=typeof(values[i])=='object'&&values[i]instanceof Array;var sp=isstr&&values[i].split(':');if(isstr&&sp.length==2){xvalues.push(Number(sp[0]));yvalues.push(Number(sp[1]));yminmax.push(Number(sp[1]));}else if(isarray){xvalues.push(values[i][0]);yvalues.push(values[i][1]);yminmax.push(values[i][1]);}else{xvalues.push(i);if(values[i]===null||values[i]=='null'){yvalues.push(null);}else{yvalues.push(Number(values[i]));yminmax.push(Number(values[i]));}}}
if(options.xvalues){xvalues=options.xvalues;}
var maxy=Math.max.apply(Math,yminmax);var maxyval=maxy;var miny=Math.min.apply(Math,yminmax);var minyval=miny;var maxx=Math.max.apply(Math,xvalues);var maxxval=maxx;var minx=Math.min.apply(Math,xvalues);var minxval=minx;if(options.normalRangeMin!=undefined){if(options.normalRangeMin<miny)
miny=options.normalRangeMin;if(options.normalRangeMax>maxy)
maxy=options.normalRangeMax;}
if(options.chartRangeMin!=undefined&&options.chartRangeMin<miny){miny=options.chartRangeMin;}
if(options.chartRangeMax!=undefined&&options.chartRangeMax>maxy){maxy=options.chartRangeMax;}
var rangex=maxx-minx==0?1:maxx-minx;var rangey=maxy-miny==0?1:maxy-miny;var vl=yvalues.length-1;if(vl<1){this.innerHTML='';return;}
var target=$(this).simpledraw(width,height,options.composite);if(target){var canvas_width=target.pixel_width;var canvas_height=target.pixel_height;var canvas_top=0;var canvas_left=0;if(options.spotRadius&&(canvas_width<(options.spotRadius*4)||canvas_height<(options.spotRadius*4))){options.spotRadius=0;}
if(options.spotRadius){if(options.minSpotColor||(options.spotColor&&yvalues[vl]==miny))
canvas_height-=Math.ceil(options.spotRadius);if(options.maxSpotColor||(options.spotColor&&yvalues[vl]==maxy)){canvas_height-=Math.ceil(options.spotRadius);canvas_top+=Math.ceil(options.spotRadius);}
if(options.minSpotColor||options.maxSpotColor&&(yvalues[0]==miny||yvalues[0]==maxy)){canvas_left+=Math.ceil(options.spotRadius);canvas_width-=Math.ceil(options.spotRadius);}
if(options.spotColor||(options.minSpotColor||options.maxSpotColor&&(yvalues[vl]==miny||yvalues[vl]==maxy)))
canvas_width-=Math.ceil(options.spotRadius);}
canvas_height--;if(options.normalRangeMin!=undefined){var ytop=canvas_top+Math.round(canvas_height-(canvas_height*((options.normalRangeMax-miny)/rangey)));var height=Math.round((canvas_height*(options.normalRangeMax-options.normalRangeMin))/rangey);target.drawRect(canvas_left,ytop,canvas_width,height,undefined,options.normalRangeColor);}
var path=[];var paths=[path];for(var i=0;i<yvalues.length;i++){var x=xvalues[i],y=yvalues[i];if(y===null){if(i){if(yvalues[i-1]!==null){path=[];paths.push(path);}}}else{if(!path.length){path.push([canvas_left+Math.round((x-minx)*(canvas_width/rangex)),canvas_top+canvas_height]);}
path.push([canvas_left+Math.round((x-minx)*(canvas_width/rangex)),canvas_top+Math.round(canvas_height-(canvas_height*((y-miny)/rangey)))]);}}
for(var i=0;i<paths.length;i++){path=paths[i];if(!path.length)
continue;if(options.fillColor){path.push([path[path.length-1][0],canvas_top+canvas_height-1]);target.drawShape(path,undefined,options.fillColor);path.pop();}
if(path.length>2){path[0]=[path[0][0],path[1][1]];}
target.drawShape(path,options.lineColor,undefined,options.lineWidth);}
if(options.spotRadius&&options.spotColor){target.drawCircle(canvas_left+canvas_width,canvas_top+Math.round(canvas_height-(canvas_height*((yvalues[vl]-miny)/rangey))),options.spotRadius,undefined,options.spotColor);}
if(maxy!=minyval){if(options.spotRadius&&options.minSpotColor){var x=xvalues[yvalues.indexOf(minyval)];target.drawCircle(canvas_left+Math.round((x-minx)*(canvas_width/rangex)),canvas_top+Math.round(canvas_height-(canvas_height*((minyval-miny)/rangey))),options.spotRadius,undefined,options.minSpotColor);}
if(options.spotRadius&&options.maxSpotColor){var x=xvalues[yvalues.indexOf(maxyval)];target.drawCircle(canvas_left+Math.round((x-minx)*(canvas_width/rangex)),canvas_top+Math.round(canvas_height-(canvas_height*((maxyval-miny)/rangey))),options.spotRadius,undefined,options.maxSpotColor);}}}else{this.innerHTML='';}};$.fn.sparkline.bar=function(values,options,width,height){var options=$.extend({type:'bar',barColor:'#00f',negBarColor:'#f44',zeroColor:undefined,zeroAxis:undefined,barWidth:4,barSpacing:1,chartRangeMax:undefined,chartRangeMin:undefined,colorMap:{}},options?options:{});var width=(values.length*options.barWidth)+((values.length-1)*options.barSpacing);var num_values=[];for(var i=0;i<values.length;i++){if(values[i]=='null'||values[i]===null){values[i]=null;}else{values[i]=Number(values[i]);num_values.push(Number(values[i]));}}
var max=Math.max.apply(Math,num_values);var min=Math.min.apply(Math,num_values);if(options.chartRangeMin!=undefined&&options.chartRangeMin<min){min=options.chartRangeMin;}
if(options.chartRangeMax!=undefined&&options.chartRangeMax>max){max=options.chartRangeMax;}
if(options.zeroAxis==undefined)options.zeroAxis=min<0;var range=max-min==0?1:max-min;var target=$(this).simpledraw(width,height);if(target){var canvas_width=target.pixel_width;var canvas_height=target.pixel_height;var yzero=min<0&&options.zeroAxis?canvas_height-Math.round(canvas_height*(Math.abs(min)/range))-1:canvas_height-1;for(var i=0;i<values.length;i++){var x=i*(options.barWidth+options.barSpacing);var val=values[i];if(val===null){continue;}
var color=(val<0)?options.negBarColor:options.barColor;if(options.zeroAxis&&min<0){var height=Math.round(canvas_height*((Math.abs(val)/range)))+1;var y=(val<0)?yzero:yzero-height;}else{var height=Math.round(canvas_height*((val-min)/range))+1;var y=canvas_height-height;}
if(val==0&&options.zeroColor!=undefined){color=options.zeroColor;}
if(options.colorMap[val]){color=options.colorMap[val];}
target.drawRect(x,y,options.barWidth-1,height-1,color,color);}}else{this.innerHTML='';}};$.fn.sparkline.tristate=function(values,options,width,height){values=$.map(values,Number);var options=$.extend({barWidth:4,barSpacing:1,posBarColor:'#6f6',negBarColor:'#f44',zeroBarColor:'#999',colorMap:{}},options);var width=(values.length*options.barWidth)+((values.length-1)*options.barSpacing);var target=$(this).simpledraw(width,height);if(target){var canvas_width=target.pixel_width;var canvas_height=target.pixel_height;var half_height=Math.round(canvas_height/2);for(var i=0;i<values.length;i++){var x=i*(options.barWidth+options.barSpacing);if(values[i]<0){var y=half_height;var height=half_height-1;var color=options.negBarColor;}else if(values[i]>0){var y=0;var height=half_height-1;var color=options.posBarColor;}else{var y=half_height-1;var height=2;var color=options.zeroBarColor;}
if(options.colorMap[values[i]]){color=options.colorMap[values[i]];}
target.drawRect(x,y,options.barWidth-1,height-1,color,color);}}else{this.innerHTML='';}};$.fn.sparkline.discrete=function(values,options,width,height){values=$.map(values,Number);var options=$.extend({lineHeight:'auto',thresholdColor:undefined,thresholdValue:0,chartRangeMax:undefined,chartRangeMin:undefined},options);width=options.width=='auto'?values.length*2:width;var interval=Math.floor(width/values.length);var target=$(this).simpledraw(width,height);if(target){var canvas_width=target.pixel_width;var canvas_height=target.pixel_height;var line_height=options.lineHeight=='auto'?Math.round(canvas_height*0.3):options.lineHeight;var pheight=canvas_height-line_height;var min=Math.min.apply(Math,values);var max=Math.max.apply(Math,values);if(options.chartRangeMin!=undefined&&options.chartRangeMin<min){min=options.chartRangeMin;}
if(options.chartRangeMax!=undefined&&options.chartRangeMax>max){max=options.chartRangeMax;}
var range=max-min;for(var i=0;i<values.length;i++){var val=values[i];var x=(i*interval);var ytop=Math.round(pheight-pheight*((val-min)/range));target.drawLine(x,ytop,x,ytop+line_height,(options.thresholdColor&&val<options.thresholdValue)?options.thresholdColor:options.lineColor);}}else{this.innerHTML='';}};$.fn.sparkline.bullet=function(values,options,width,height){values=$.map(values,Number);var options=$.extend({targetColor:'red',targetWidth:3,performanceColor:'blue',rangeColors:['#D3DAFE','#A8B6FF','#7F94FF'],base:undefined},options);width=options.width=='auto'?'4.0em':width;var target=$(this).simpledraw(width,height);if(target&&values.length>1){var canvas_width=target.pixel_width-Math.ceil(options.targetWidth/2);var canvas_height=target.pixel_height;var min=Math.min.apply(Math,values);var max=Math.max.apply(Math,values);if(options.base==undefined){var min=min<0?min:0;}else{min=options.base;}
var range=max-min;for(i=2;i<values.length;i++){var rangeval=parseInt(values[i]);var rangewidth=Math.round(canvas_width*((rangeval-min)/range));target.drawRect(0,0,rangewidth-1,canvas_height-1,options.rangeColors[i-2],options.rangeColors[i-2]);}
var perfval=parseInt(values[1]);var perfwidth=Math.round(canvas_width*((perfval-min)/range));target.drawRect(0,Math.round(canvas_height*0.3),perfwidth-1,Math.round(canvas_height*0.4)-1,options.performanceColor,options.performanceColor);var targetval=parseInt(values[0]);var x=Math.round(canvas_width*((targetval-min)/range)-(options.targetWidth/2));var targettop=Math.round(canvas_height*0.10);var targetheight=canvas_height-(targettop*2);target.drawRect(x,targettop,options.targetWidth-1,targetheight-1,options.targetColor,options.targetColor);}else{this.innerHTML='';}};$.fn.sparkline.pie=function(values,options,width,height){values=$.map(values,Number);var options=$.extend({sliceColors:['#f00','#0f0','#00f']},options);width=options.width=='auto'?height:width;var target=$(this).simpledraw(width,height);if(target&&values.length>1){var canvas_width=target.pixel_width;var canvas_height=target.pixel_height;var radius=Math.floor(Math.min(canvas_width,canvas_height)/2);var total=0;for(var i=0;i<values.length;i++)
total+=values[i];var next=0;if(options.offset){next+=(2*Math.PI)*(options.offset/360);}
var circle=2*Math.PI;for(var i=0;i<values.length;i++){var start=next;var end=next;if(total>0){end=next+(circle*(values[i]/total));}
target.drawPieSlice(radius,radius,radius,start,end,undefined,options.sliceColors[i%options.sliceColors.length]);next=end;}}};function quartile(values,q){if(q==2){var vl2=Math.floor(values.length/2);return values.length%2?values[vl2]:(values[vl2]+values[vl2+1])/2;}else{var vl4=Math.floor(values.length/4);return values.length%2?(values[vl4*q]+values[vl4*q+1])/2:values[vl4*q];}};$.fn.sparkline.box=function(values,options,width,height){values=$.map(values,Number);var options=$.extend({raw:false,boxLineColor:'black',boxFillColor:'#cdf',whiskerColor:'black',outlierLineColor:'#333',outlierFillColor:'white',medianColor:'red',showOutliers:true,outlierIQR:1.5,spotRadius:1.5,target:undefined,targetColor:'#4a2',chartRangeMax:undefined,chartRangeMin:undefined},options);width=options.width=='auto'?'4.0em':width;minvalue=options.chartRangeMin==undefined?Math.min.apply(Math,values):options.chartRangeMin;maxvalue=options.chartRangeMax==undefined?Math.max.apply(Math,values):options.chartRangeMax;var target=$(this).simpledraw(width,height);if(target&&values.length>1){var canvas_width=target.pixel_width;var canvas_height=target.pixel_height;if(options.raw){if(options.showOutliers&&values.length>5){var loutlier=values[0],lwhisker=values[1],q1=values[2],q2=values[3],q3=values[4],rwhisker=values[5],routlier=values[6];}else{var lwhisker=values[0],q1=values[1],q2=values[2],q3=values[3],rwhisker=values[4];}}else{values.sort(function(a,b){return a-b;});var q1=quartile(values,1);var q2=quartile(values,2);var q3=quartile(values,3);var iqr=q3-q1;if(options.showOutliers){var lwhisker=undefined,rwhisker=undefined;for(var i=0;i<values.length;i++){if(lwhisker==undefined&&values[i]>q1-(iqr*options.outlierIQR))
lwhisker=values[i];if(values[i]<q3+(iqr*options.outlierIQR))
rwhisker=values[i];}
var loutlier=values[0];var routlier=values[values.length-1];}else{var lwhisker=values[0];var rwhisker=values[values.length-1];}}
var unitsize=canvas_width/(maxvalue-minvalue+1);var canvas_left=0;if(options.showOutliers){canvas_left=Math.ceil(options.spotRadius);canvas_width-=2*Math.ceil(options.spotRadius);var unitsize=canvas_width/(maxvalue-minvalue+1);if(loutlier<lwhisker)
target.drawCircle((loutlier-minvalue)*unitsize+canvas_left,canvas_height/2,options.spotRadius,options.outlierLineColor,options.outlierFillColor);if(routlier>rwhisker)
target.drawCircle((routlier-minvalue)*unitsize+canvas_left,canvas_height/2,options.spotRadius,options.outlierLineColor,options.outlierFillColor);}
target.drawRect(Math.round((q1-minvalue)*unitsize+canvas_left),Math.round(canvas_height*0.1),Math.round((q3-q1)*unitsize),Math.round(canvas_height*0.8),options.boxLineColor,options.boxFillColor);target.drawLine(Math.round((lwhisker-minvalue)*unitsize+canvas_left),Math.round(canvas_height/2),Math.round((q1-minvalue)*unitsize+canvas_left),Math.round(canvas_height/2),options.lineColor);target.drawLine(Math.round((lwhisker-minvalue)*unitsize+canvas_left),Math.round(canvas_height/4),Math.round((lwhisker-minvalue)*unitsize+canvas_left),Math.round(canvas_height-canvas_height/4),options.whiskerColor);target.drawLine(Math.round((rwhisker-minvalue)*unitsize+canvas_left),Math.round(canvas_height/2),Math.round((q3-minvalue)*unitsize+canvas_left),Math.round(canvas_height/2),options.lineColor);target.drawLine(Math.round((rwhisker-minvalue)*unitsize+canvas_left),Math.round(canvas_height/4),Math.round((rwhisker-minvalue)*unitsize+canvas_left),Math.round(canvas_height-canvas_height/4),options.whiskerColor);target.drawLine(Math.round((q2-minvalue)*unitsize+canvas_left),Math.round(canvas_height*0.1),Math.round((q2-minvalue)*unitsize+canvas_left),Math.round(canvas_height*0.9),options.medianColor);if(options.target){var size=Math.ceil(options.spotRadius);target.drawLine(Math.round((options.target-minvalue)*unitsize+canvas_left),Math.round((canvas_height/2)-size),Math.round((options.target-minvalue)*unitsize+canvas_left),Math.round((canvas_height/2)+size),options.targetColor);target.drawLine(Math.round((options.target-minvalue)*unitsize+canvas_left-size),Math.round(canvas_height/2),Math.round((options.target-minvalue)*unitsize+canvas_left+size),Math.round(canvas_height/2),options.targetColor);}}else{this.innerHTML='';}};if(!Array.prototype.indexOf){Array.prototype.indexOf=function(entry){for(var i=0;i<this.length;i++){if(this[i]==entry)
return i;}
return-1;}}
if($.browser.msie&&!document.namespaces['v']){document.namespaces.add('v','urn:schemas-microsoft-com:vml','#default#VML');}
if($.browser.hasCanvas==undefined){var t=document.createElement('canvas');$.browser.hasCanvas=t.getContext!=undefined;}
var vcanvas_base=function(width,height,target){};vcanvas_base.prototype={init:function(width,height,target){this.width=width;this.height=height;this.target=target;if(target[0])target=target[0];target.vcanvas=this;},drawShape:function(path,lineColor,fillColor,lineWidth){alert('drawShape not implemented');},drawLine:function(x1,y1,x2,y2,lineColor,lineWidth){return this.drawShape([[x1,y1],[x2,y2]],lineColor,lineWidth);},drawCircle:function(x,y,radius,lineColor,fillColor){alert('drawCircle not implemented');},drawPieSlice:function(x,y,radius,startAngle,endAngle,lineColor,fillColor){alert('drawPieSlice not implemented');},drawRect:function(x,y,width,height,lineColor,fillColor){alert('drawRect not implemented');},getElement:function(){return this.canvas;},_insert:function(el,target){$(target).html(el);}};var vcanvas_canvas=function(width,height,target){return this.init(width,height,target);};vcanvas_canvas.prototype=$.extend(new vcanvas_base,{_super:vcanvas_base.prototype,init:function(width,height,target){this._super.init(width,height,target);this.canvas=document.createElement('canvas');if(target[0])target=target[0];target.vcanvas=this;$(this.canvas).css({display:'inline-block',width:width,height:height,verticalAlign:'top'});this._insert(this.canvas,target);this.pixel_height=$(this.canvas).height();this.pixel_width=$(this.canvas).width();this.canvas.width=this.pixel_width;this.canvas.height=this.pixel_height;$(this.canvas).css({width:this.pixel_width,height:this.pixel_height});},_getContext:function(lineColor,fillColor,lineWidth){var context=this.canvas.getContext('2d');if(lineColor!=undefined)
context.strokeStyle=lineColor;context.lineWidth=lineWidth==undefined?1:lineWidth;if(fillColor!=undefined)
context.fillStyle=fillColor;return context;},drawShape:function(path,lineColor,fillColor,lineWidth){var context=this._getContext(lineColor,fillColor,lineWidth);context.beginPath();context.moveTo(path[0][0]+0.5,path[0][1]+0.5);for(var i=1;i<path.length;i++){context.lineTo(path[i][0]+0.5,path[i][1]+0.5);}
if(lineColor!=undefined){context.stroke();}
if(fillColor!=undefined){context.fill();}},drawCircle:function(x,y,radius,lineColor,fillColor){var context=this._getContext(lineColor,fillColor);context.beginPath();context.arc(x,y,radius,0,2*Math.PI,false);if(lineColor!=undefined){context.stroke();}
if(fillColor!=undefined){context.fill();}},drawPieSlice:function(x,y,radius,startAngle,endAngle,lineColor,fillColor){var context=this._getContext(lineColor,fillColor);context.beginPath();context.moveTo(x,y);context.arc(x,y,radius,startAngle,endAngle,false);context.lineTo(x,y);context.closePath();if(lineColor!=undefined){context.stroke();}
if(fillColor){context.fill();}},drawRect:function(x,y,width,height,lineColor,fillColor){return this.drawShape([[x,y],[x+width,y],[x+width,y+height],[x,y+height],[x,y]],lineColor,fillColor);}});var vcanvas_vml=function(width,height,target){return this.init(width,height,target);};vcanvas_vml.prototype=$.extend(new vcanvas_base,{_super:vcanvas_base.prototype,init:function(width,height,target){this._super.init(width,height,target);if(target[0])target=target[0];target.vcanvas=this;this.canvas=document.createElement('span');$(this.canvas).css({display:'inline-block',position:'relative',overflow:'hidden',width:width,height:height,margin:'0px',padding:'0px',verticalAlign:'top'});this._insert(this.canvas,target);this.pixel_height=$(this.canvas).height();this.pixel_width=$(this.canvas).width();this.canvas.width=this.pixel_width;this.canvas.height=this.pixel_height;;var groupel='<v:group coordorigin="0 0" coordsize="'+this.pixel_width+' '+this.pixel_height+'"'
+' style="position:absolute;top:0;left:0;width:'+this.pixel_width+'px;height='+this.pixel_height+'px;"></v:group>';this.canvas.insertAdjacentHTML('beforeEnd',groupel);this.group=$(this.canvas).children()[0];},drawShape:function(path,lineColor,fillColor,lineWidth){var vpath=[];for(var i=0;i<path.length;i++){vpath[i]=''+(path[i][0])+','+(path[i][1]);}
var initial=vpath.splice(0,1);lineWidth=lineWidth==undefined?1:lineWidth;var stroke=lineColor==undefined?' stroked="false" ':' strokeWeight="'+lineWidth+'" strokeColor="'+lineColor+'" ';var fill=fillColor==undefined?' filled="false"':' fillColor="'+fillColor+'" filled="true" ';var closed=vpath[0]==vpath[vpath.length-1]?'x ':'';var vel='<v:shape coordorigin="0 0" coordsize="'+this.pixel_width+' '+this.pixel_height+'" '
+stroke
+fill
+' style="position:absolute;left:0px;top:0px;height:'+this.pixel_height+'px;width:'+this.pixel_width+'px;padding:0px;margin:0px;" '
+' path="m '+initial+' l '+vpath.join(', ')+' '+closed+'e">'
+' </v:shape>';this.group.insertAdjacentHTML('beforeEnd',vel);},drawCircle:function(x,y,radius,lineColor,fillColor){x-=radius+1;y-=radius+1;var stroke=lineColor==undefined?' stroked="false" ':' strokeWeight="1" strokeColor="'+lineColor+'" ';var fill=fillColor==undefined?' filled="false"':' fillColor="'+fillColor+'" filled="true" ';var vel='<v:oval '
+stroke
+fill
+' style="position:absolute;top:'+y+'px; left:'+x+'px; width:'+(radius*2)+'px; height:'+(radius*2)+'px"></v:oval>';this.group.insertAdjacentHTML('beforeEnd',vel);},drawPieSlice:function(x,y,radius,startAngle,endAngle,lineColor,fillColor){if(startAngle==endAngle){return;}
if((endAngle-startAngle)==(2*Math.PI)){startAngle=0.0;endAngle=(2*Math.PI);}
var startx=x+Math.round(Math.cos(startAngle)*radius);var starty=y+Math.round(Math.sin(startAngle)*radius);var endx=x+Math.round(Math.cos(endAngle)*radius);var endy=y+Math.round(Math.sin(endAngle)*radius);var vpath=[x-radius,y-radius,x+radius,y+radius,startx,starty,endx,endy];var stroke=lineColor==undefined?' stroked="false" ':' strokeWeight="1" strokeColor="'+lineColor+'" ';var fill=fillColor==undefined?' filled="false"':' fillColor="'+fillColor+'" filled="true" ';var vel='<v:shape coordorigin="0 0" coordsize="'+this.pixel_width+' '+this.pixel_height+'" '
+stroke
+fill
+' style="position:absolute;left:0px;top:0px;height:'+this.pixel_height+'px;width:'+this.pixel_width+'px;padding:0px;margin:0px;" '
+' path="m '+x+','+y+' wa '+vpath.join(', ')+' x e">'
+' </v:shape>';this.group.insertAdjacentHTML('beforeEnd',vel);},drawRect:function(x,y,width,height,lineColor,fillColor){return this.drawShape([[x,y],[x,y+height],[x+width,y+height],[x+width,y],[x,y]],lineColor,fillColor);}});})(jQuery);
// robert@ilse.nl
(function($) {
	$.fn.attributes = function(prefix) {
		var list = [];
		$(this).each(function() {
			var attrs = {};
			for (var attr in this.attributes)
			{
				if (isNaN(attr))
					continue;
				if (! prefix || this.attributes[attr].nodeName.indexOf(prefix) == 0)
					attrs[this.attributes[attr].nodeName] = this.attributes[attr].nodeValue;
			}
			list.push(attrs);
		});
		return (list.length > 1 ? list : list[0]);
	};
})(jQuery);

/* jQuery Tools 1.2.0 */
(function(c){function p(d,a,b){var e=this,j=d.add(this),h=d.find(b.tabs),k=a.jquery?a:d.children(a),i;h.length||(h=d.children());k.length||(k=d.parent().find(a));k.length||(k=c(a));c.extend(this,{click:function(f,g){var l=h.eq(f);if(typeof f=="string"&&f.replace("#","")){l=h.filter("[href*='"+f.replace("#","")+"']");f=Math.max(h.index(l),0)}if(b.rotate){var n=h.length-1;if(f<0)return e.click(n,g);if(f>n)return e.click(0,g)}if(!l.length){if(i>=0)return e;f=b.initialIndex;l=h.eq(f)}if(f===i)return e;
g=g||c.Event();g.type="onBeforeClick";j.trigger(g,[f]);if(!g.isDefaultPrevented()){o[b.effect].call(e,f,function(){g.type="onClick";j.trigger(g,[f])});i=f;h.removeClass(b.current);l.addClass(b.current);return e}},getConf:function(){return b},getTabs:function(){return h},getPanes:function(){return k},getCurrentPane:function(){return k.eq(i)},getCurrentTab:function(){return h.eq(i)},getIndex:function(){return i},next:function(){return e.click(i+1)},prev:function(){return e.click(i-1)}});c.each("onBeforeClick,onClick".split(","),
function(f,g){c.isFunction(b[g])&&c(e).bind(g,b[g]);e[g]=function(l){c(e).bind(g,l);return e}});if(b.history&&c.fn.history){c.tools.history.init(h);b.event="history"}h.each(function(f){c(this).bind(b.event,function(g){e.click(f,g);return g.preventDefault()})});k.find("a[href^=#]").click(function(f){e.click(c(this).attr("href"),f)});if(location.hash)e.click(location.hash);else if(b.initialIndex===0||b.initialIndex>0)e.click(b.initialIndex)}c.tools=c.tools||{version:"1.2.0"};c.tools.tabs={conf:{tabs:"a",
current:"current",onBeforeClick:null,onClick:null,effect:"default",initialIndex:0,event:"click",rotate:false,history:false},addEffect:function(d,a){o[d]=a}};var o={"default":function(d,a){this.getPanes().hide().eq(d).show();a.call()},fade:function(d,a){var b=this.getConf(),e=b.fadeOutSpeed,j=this.getPanes();if(!j.eq(d).is(":visible")){e?j.fadeOut(e):j.hide();j.eq(d).fadeIn(b.fadeInSpeed,a)}},slide:function(d,a){this.getPanes().slideUp(200);this.getPanes().eq(d).slideDown(400,a)},ajax:function(d,a){this.getPanes().eq(0).load(this.getTabs().eq(d).attr("href"),
a)}},m;c.tools.tabs.addEffect("horizontal",function(d,a){m||(m=this.getPanes().eq(0).width());this.getCurrentPane().animate({width:0},function(){c(this).hide()});this.getPanes().eq(d).animate({width:m},function(){c(this).show();a.call()})});c.fn.tabs=function(d,a){var b=this.data("tabs");if(b)return b;if(c.isFunction(a))a={onBeforeClick:a};a=c.extend({},c.tools.tabs.conf,a);this.each(function(){b=new p(c(this),d,a);c(this).data("tabs",b)});return a.api?b:this}})(jQuery);
(function(f){function p(a,b,c){var h=c.relative?a.position().top:a.offset().top,e=c.relative?a.position().left:a.offset().left,i=c.position[0];h-=b.outerHeight()-c.offset[0];e+=a.outerWidth()+c.offset[1];var j=b.outerHeight()+a.outerHeight();if(i=="center")h+=j/2;if(i=="bottom")h+=j;i=c.position[1];a=b.outerWidth()+a.outerWidth();if(i=="center")e-=a/2;if(i=="left")e-=a;return{top:h,left:e}}function t(a,b){var c=this,h=a.add(c),e,i=0,j=0,m=a.attr("title"),q=n[b.effect],k,r=a.is(":input"),u=r&&a.is(":checkbox, :radio, select, :button"),
s=a.attr("type"),l=b.events[s]||b.events[r?u?"widget":"input":"def"];if(!q)throw'Nonexistent effect "'+b.effect+'"';l=l.split(/,\s*/);if(l.length!=2)throw"Tooltip: bad events configuration for "+s;a.bind(l[0],function(d){if(b.predelay){clearTimeout(i);j=setTimeout(function(){c.show(d)},b.predelay)}else c.show(d)}).bind(l[1],function(d){if(b.delay){clearTimeout(j);i=setTimeout(function(){c.hide(d)},b.delay)}else c.hide(d)});if(m&&b.cancelDefault){a.removeAttr("title");a.data("title",m)}f.extend(c,
{show:function(d){if(!e){if(m)e=f(b.layout).addClass(b.tipClass).appendTo(document.body).hide();else if(b.tip)e=f(b.tip).eq(0);else{e=a.next();e.length||(e=a.parent().next())}if(!e.length)throw"Cannot find tooltip for "+a;}if(c.isShown())return c;e.stop(true,true);var g=p(a,e,b);m&&e.html(m);d=d||f.Event();d.type="onBeforeShow";h.trigger(d,[g]);if(d.isDefaultPrevented())return c;g=p(a,e,b);e.css({position:"absolute",top:g.top,left:g.left});k=true;q[0].call(c,function(){d.type="onShow";k="full";h.trigger(d)});
g=b.events.tooltip.split(/,\s*/);e.bind(g[0],function(){clearTimeout(i);clearTimeout(j)});g[1]&&!a.is("input:not(:checkbox, :radio), textarea")&&e.bind(g[1],function(o){o.relatedTarget!=a[0]&&a.trigger(l[1].split(" ")[0])});return c},hide:function(d){if(!e||!c.isShown())return c;d=d||f.Event();d.type="onBeforeHide";h.trigger(d);if(!d.isDefaultPrevented()){k=false;n[b.effect][1].call(c,function(){d.type="onHide";k=false;h.trigger(d)});return c}},isShown:function(d){return d?k=="full":k},getConf:function(){return b},
getTip:function(){return e},getTrigger:function(){return a}});f.each("onHide,onBeforeShow,onShow,onBeforeHide".split(","),function(d,g){f.isFunction(b[g])&&f(c).bind(g,b[g]);c[g]=function(o){f(c).bind(g,o);return c}})}f.tools=f.tools||{version:"1.2.0"};f.tools.tooltip={conf:{effect:"toggle",fadeOutSpeed:"fast",predelay:0,delay:30,opacity:1,tip:0,position:["top","center"],offset:[0,0],relative:false,cancelDefault:true,events:{def:"mouseenter,mouseleave",input:"focus,blur",widget:"focus mouseenter,blur mouseleave",
tooltip:"mouseenter,mouseleave"},layout:"<div/>",tipClass:"tooltip"},addEffect:function(a,b,c){n[a]=[b,c]}};var n={toggle:[function(a){var b=this.getConf(),c=this.getTip();b=b.opacity;b<1&&c.css({opacity:b});c.show();a.call()},function(a){this.getTip().hide();a.call()}],fade:[function(a){this.getTip().fadeIn(this.getConf().fadeInSpeed,a)},function(a){this.getTip().fadeOut(this.getConf().fadeOutSpeed,a)}]};f.fn.tooltip=function(a){var b=this.data("tooltip");if(b)return b;a=f.extend(true,{},f.tools.tooltip.conf,
a);if(typeof a.position=="string")a.position=a.position.split(/,?\s/);this.each(function(){b=new t(f(this),a);f(this).data("tooltip",b)});return a.api?b:this}})(jQuery);
(function(a){function t(d,b){var c=this,i=d.add(c),o=a(window),k,f,m,g=a.tools.expose&&(b.mask||b.expose),n=Math.random().toString().slice(10);if(g){if(typeof g=="string")g={color:g};g.closeOnClick=g.closeOnEsc=false}var p=b.target||d.attr("rel");f=p?a(p):d;if(!f.length)throw"Could not find Overlay: "+p;d&&d.index(f)==-1&&d.click(function(e){c.load(e);return e.preventDefault()});a.extend(c,{load:function(e){if(c.isOpened())return c;var h=q[b.effect];if(!h)throw'Overlay: cannot find effect : "'+b.effect+
'"';b.oneInstance&&a.each(s,function(){this.close(e)});e=e||a.Event();e.type="onBeforeLoad";i.trigger(e);if(e.isDefaultPrevented())return c;m=true;g&&a(f).expose(g);var j=b.top,r=b.left,u=f.outerWidth({margin:true}),v=f.outerHeight({margin:true});if(typeof j=="string")j=j=="center"?Math.max((o.height()-v)/2,0):parseInt(j,10)/100*o.height();if(r=="center")r=Math.max((o.width()-u)/2,0);h[0].call(c,{top:j,left:r},function(){if(m){e.type="onLoad";i.trigger(e)}});g&&b.closeOnClick&&a.mask.getMask().one("click",
c.close);b.closeOnClick&&a(document).bind("click."+n,function(l){a(l.target).parents(f).length||c.close(l)});b.closeOnEsc&&a(document).bind("keydown."+n,function(l){l.keyCode==27&&c.close(l)});return c},close:function(e){if(!c.isOpened())return c;e=e||a.Event();e.type="onBeforeClose";i.trigger(e);if(!e.isDefaultPrevented()){m=false;q[b.effect][1].call(c,function(){e.type="onClose";i.trigger(e)});a(document).unbind("click."+n).unbind("keydown."+n);g&&a.mask.close();return c}},getOverlay:function(){return f},
getTrigger:function(){return d},getClosers:function(){return k},isOpened:function(){return m},getConf:function(){return b}});a.each("onBeforeLoad,onStart,onLoad,onBeforeClose,onClose".split(","),function(e,h){a.isFunction(b[h])&&a(c).bind(h,b[h]);c[h]=function(j){a(c).bind(h,j);return c}});k=f.find(b.close||".close");if(!k.length&&!b.close){k=a('<div class="close"></div>');f.prepend(k)}k.click(function(e){c.close(e)});b.load&&c.load()}a.tools=a.tools||{version:"1.2.0"};a.tools.overlay={addEffect:function(d,
b,c){q[d]=[b,c]},conf:{close:null,closeOnClick:true,closeOnEsc:true,closeSpeed:"fast",effect:"default",fixed:!a.browser.msie||a.browser.version>6,left:"center",load:false,mask:null,oneInstance:true,speed:"normal",target:null,top:"10%"}};var s=[],q={};a.tools.overlay.addEffect("default",function(d,b){var c=this.getConf(),i=a(window);if(!c.fixed){d.top+=i.scrollTop();d.left+=i.scrollLeft()}d.position=c.fixed?"fixed":"absolute";this.getOverlay().css(d).fadeIn(c.speed,b)},function(d){this.getOverlay().fadeOut(this.getConf().closeSpeed,
d)});a.fn.overlay=function(d){var b=this.data("overlay");if(b)return b;if(a.isFunction(d))d={onBeforeLoad:d};d=a.extend(true,{},a.tools.overlay.conf,d);this.each(function(){b=new t(a(this),d);s.push(b);a(this).data("overlay",b)});return d.api?b:this}})(jQuery);
(function(e){function n(f,c){var a=e(c);return a.length<2?a:f.parent().find(c)}function t(f,c){var a=this,k=f.add(a),g=f.children(),l=0,m=c.vertical;j||(j=a);if(g.length>1)g=e(c.items,f);e.extend(a,{getConf:function(){return c},getIndex:function(){return l},getSize:function(){return a.getItems().size()},getNaviButtons:function(){return o.add(p)},getRoot:function(){return f},getItemWrap:function(){return g},getItems:function(){return g.children(c.item).not("."+c.clonedClass)},move:function(b,d){return a.seekTo(l+
b,d)},next:function(b){return a.move(1,b)},prev:function(b){return a.move(-1,b)},begin:function(b){return a.seekTo(0,b)},end:function(b){return a.seekTo(a.getSize()-1,b)},focus:function(){return j=a},addItem:function(b){b=e(b);if(c.circular){e(".cloned:last").before(b);e(".cloned:first").replaceWith(b.clone().addClass(c.clonedClass))}else g.append(b);k.trigger("onAddItem",[b]);return a},seekTo:function(b,d,h){if(!c.circular&&b<0||b>a.getSize())return a;var i=b;if(b.jquery)b=a.getItems().index(b);
else i=a.getItems().eq(b);var q=e.Event("onBeforeSeek");if(!h){k.trigger(q,[b,d]);if(q.isDefaultPrevented()||!i.length)return a}i=m?{top:-i.position().top}:{left:-i.position().left};g.animate(i,d,c.easing,h||function(){k.trigger("onSeek",[b])});j=a;l=b;return a}});e.each(["onBeforeSeek","onSeek","onAddItem"],function(b,d){e.isFunction(c[d])&&e(a).bind(d,c[d]);a[d]=function(h){e(a).bind(d,h);return a}});if(c.circular){var r=a.getItems().slice(-1).clone().prependTo(g),s=a.getItems().eq(1).clone().appendTo(g);
r.add(s).addClass(c.clonedClass);a.onBeforeSeek(function(b,d,h){if(!b.isDefaultPrevented())if(d==-1){a.seekTo(r,h,function(){a.end(0)});return b.preventDefault()}else d==a.getSize()&&a.seekTo(s,h,function(){a.begin(0)})});a.seekTo(0,0)}var o=n(f,c.prev).click(function(){a.prev()}),p=n(f,c.next).click(function(){a.next()});!c.circular&&a.getSize()>1&&a.onBeforeSeek(function(b,d){o.toggleClass(c.disabledClass,d<=0);p.toggleClass(c.disabledClass,d>=a.getSize()-1)});c.mousewheel&&e.fn.mousewheel&&f.mousewheel(function(b,
d){if(c.mousewheel){a.move(d<0?1:-1,c.wheelSpeed||50);return false}});c.keyboard&&e(document).bind("keydown.scrollable",function(b){if(!(!c.keyboard||b.altKey||b.ctrlKey||e(b.target).is(":input")))if(!(c.keyboard!="static"&&j!=a)){var d=b.keyCode;if(m&&(d==38||d==40)){a.move(d==38?-1:1);return b.preventDefault()}if(!m&&(d==37||d==39)){a.move(d==37?-1:1);return b.preventDefault()}}});e(a).trigger("onBeforeSeek",[c.initialIndex])}e.tools=e.tools||{version:"1.2.0"};e.tools.scrollable={conf:{activeClass:"active",
circular:false,clonedClass:"cloned",disabledClass:"disabled",easing:"swing",initialIndex:0,item:null,items:".items",keyboard:true,mousewheel:false,next:".next",prev:".prev",speed:400,vertical:false,wheelSpeed:0}};var j;e.fn.scrollable=function(f){var c=this.data("scrollable");if(c)return c;f=e.extend({},e.tools.scrollable.conf,f);this.each(function(){c=new t(e(this),f);e(this).data("scrollable",c)});return f.api?c:this}})(jQuery);

/*
* jquery-google-analytics plugin
*
* A jQuery plugin that makes it easier to implement Google Analytics tracking,
* including event and link tracking.
*
* Adds the following methods to jQuery:
*   - $.trackPage() - Adds Google Analytics tracking on the page from which
*     it's called.
*   - $.trackPageview() - Tracks a pageview using the given uri. Can be used for tracking Ajax requests: http://www.google.com/support/analytics/bin/answer.py?hl=en&answer=55519
*   - $.trackEvent() - Tracks an event using the given parameters.
*   - $('a').track() - Adds event tracking to element(s).
*   - $.timePageLoad() - Measures the time it takes  an event using the given parameters.
*
* Features:
*   - Improves page load time by loading Google Analytics code without blocking.
*   - Easy and extensible event and link tracking plugin for jQuery and Google Analytics
*   - Automatic internal/external link detection. Default behavior is to skip
*     tracking of internal links.
*   - Enforces that tracking event handler is added to an element only once.
*   - Configurable: custom event tracking, skip internal links, metadata
*     extraction using callbacks.
*
* Copyright (c) 2008-09 Christian Hellsten
*
* Plugin homepage:
*   http://aktagon.com/projects/jquery/google-analytics/
*   http://github.com/christianhellsten/jquery-google-analytics/
*
* Examples:
*   http://aktagon.com/projects/jquery/google-analytics/examples/
*   http://code.google.com/apis/analytics/docs/eventTrackerGuide.html
*
* Repository:
*   git://github.com/christianhellsten/jquery-google-analytics.git
*
* Version 1.1.3
*
* Tested with:
*   - Mac: Firefox 3, Safari 3
*   - Linux: Firefox 3
*   - Windows: Firefox 3, Internet Explorer 6
*
* Licensed under the MIT license:
* http://www.opensource.org/licenses/mit-license.php
*
* Credits:
*   - http://google.com/analytics
*   - http://lyncd.com: 
*       Idea for trackPage method came from this blog post: http://lyncd.com/2009/03/better-google-analytics-javascript/
*/
(function($) {

  var pageTracker;

  /**
   * Enables Google Analytics tracking on the page from which it's called. 
   *
   * Usage:
   *  <script type="text/javascript">
   *    $.trackPage('UA-xxx-xxx', options);
   *  </script>
   *
   * Parameters:
   *   account_id - Your Google Analytics account ID.
   *   options - An object containing one or more optional parameters:
   *     - onload - boolean - If false, the Google Analytics code is loaded
   *       when this method is called instead of on window.onload.
   *     - status_code - The HTTP status code of the current server response.
   *       If this is set to something other than 200 then the page is tracked
   *       as an error page. For more details: http://www.google.com/support/analytics/bin/answer.py?hl=en&answer=86927
   *     - callback  - function to be executed after the Google Analytics code is laoded and initialized
   *
   */
  $.trackPage = function(account_id, options) {
    var host = (("https:" == document.location.protocol) ? "https://ssl." : "http://www.");
    var script;

    // Use default options, if necessary
    var settings = $.extend({}, {onload: true, status_code: 200}, options);
    var src  = host + 'google-analytics.com/ga.js';

    function init_analytics() {
      if (typeof _gat != undefined) {
        debug('Google Analytics loaded');

        pageTracker = _gat._getTracker(account_id);

        if(settings.status_code == null || settings.status_code == 200) {
          pageTracker._trackPageview();
        } else {
          debug('Tracking error ' + settings.status_code);
          pageTracker._trackPageview("/" + settings.status_code + ".html?page=" + document.location.pathname + document.location.search + "&from=" + document.referrer);
        }
        if($.isFunction(settings.callback)){
          settings.callback();
        }
      }
      else { 
        throw "_gat is undefined"; // setInterval loading?
      }
    }

    load_script = function() {
      $.ajax({
        type: "GET",
        url: src,
        success: function() {          
          init_analytics(); 
        },
        dataType: "script",
        cache: true // We want the cached version
      });
    }
    
    // Enable tracking when called or on page load?
    if(settings.onload == true || settings.onload == null) {
      $(window).load(load_script);
    } else {
      load_script();
    }
  }

  /**
   * Tracks an event using the given parameters. 
   *
   * The trackEvent method takes four arguments:
   *
   *  category - required string used to group events
   *  action - required string used to define event type, eg. click, download
   *  label - optional label to attach to event, eg. buy
   *  value - optional numerical value to attach to event, eg. price
   *  skip_internal - optional boolean value. If true then internal links are not tracked.
   *
   */
  $.trackEvent = function(category, action, label, value) {
    if(typeof pageTracker == 'undefined') {
      debug('FATAL: pageTracker is not defined'); // blocked by whatever
    } else {
      pageTracker._trackEvent(category, action, label, value);
    }
  };

  /**
   * Tracks a pageview using the given uri.
   *
   */
  $.trackPageview = function(uri) {
    if(typeof pageTracker == 'undefined') {
      debug('FATAL: pageTracker is not defined');
    } else {
      pageTracker._trackPageview(uri);
    }
  }

  /**
   * Adds click tracking to elements. Usage:
   *
   *  $('a').track()
   *
   */
  $.fn.track = function(options) {
    // Add event handler to all matching elements
    return this.each(function() {
      var element = $(this);

      // Prevent an element from being tracked multiple times.
      if (element.hasClass('tracked')) {
        return false;
      } else {
        element.addClass('tracked');
      } 

      // Use default options, if necessary
      var settings = $.extend({}, $.fn.track.defaults, options);

      // Merge custom options with defaults.
      var category = evaluate(element, settings.category);
      var action   = evaluate(element, settings.action);
      var label    = evaluate(element, settings.label);
      var value    = evaluate(element, settings.value);
      var event_name = evaluate(element, settings.event_name);
      
      var message = "category:'" + category + "' action:'" + action + "' label:'" + label + "' value:'" + value + "'";
      
      debug('Tracking ' + event_name + ' ' + message);

      // Bind the event to this element. 
      // TODO Use .live since jQuery 1.4 now supports it better.
      element.bind(event_name + '.track', function() {       
        // Should we skip internal links? REFACTOR
        var skip = settings.skip_internal && (element[0].hostname == location.hostname);
      
        if(!skip) {
          $.trackEvent(category, action, label, value);
          debug('Tracked ' + message);
        } else {
          debug('Skipped ' + message);
        }

        return true;
      });
    });
    
    /**
     * Checks whether a setting value is a string or a function.
     * 
     * If second parameter is a string: returns the value of the second parameter.
     * If the second parameter is a function: passes the element to the function and returns function's return value.
     */
    function evaluate(element, text_or_function) {
      if(typeof text_or_function == 'function') {
        text_or_function = text_or_function(element);
      }
      return text_or_function;
    };
  };

  /**
   * Prints to Firebug console, if available. To enable:
   *   $.fn.track.defaults.debug = true;
   */
  function debug(message) {
    if (typeof console != 'undefined' && typeof console.debug != 'undefined' && $.fn.track.defaults.debug) {
      console.debug(message);
    }
  };

  /**
   * Default (overridable) settings.
   */
  $.fn.track.defaults = {
    category      : function(element) { return (element[0].hostname == location.hostname) ? 'internal':'external'; },
    action        : 'click',
    label         : function(element) { return element.attr('href'); },
    value         : null,
    skip_internal : true,
    event_name    : 'click',
    debug         : false
  };
})(jQuery);

/* ilse common JS code */
(function($) {

	/* wahey.... */
	if (! Array.prototype.indexOf)
	{
		Array.prototype.indexOf = function(obj, start)
		{
			for (var i = (start || 0), j = this.length; i < j; i++)
			{
				if (this[i] == obj)
					return i;
			}
			return -1;
		}
	}

  String.prototype.htmlspecialchars = function() {
		var str = '' + this; // pourquoi?
		var $tmp = $('<div>');
		$tmp.text(str);
		return $tmp.html();
	}

	String.prototype.firstLine = function(maxlength, ellipsis) {
		var str				= '' + this;
		var firstline = str.replace(/\.\s*[A-Z0-9][a-z0-9].*$/m, '.');
		if (! maxlength || firstline.length < maxlength)
			return firstline;
		return firstline.substr(0, maxlength) + (ellipsis ? '...' : '');
	};

	// open most external links in frameset page
	$("a[href^='http']:not('.no-frameset')").live('click', function() {
		// track outgoing link
		var source = $(this).attr('data-source') || '(organic)';
		// $.trackEvent('outgoing', source);

		// fix URL
		$(this).attr('href', '/f/' + $(this).attr('href'));

		// perform default action
		return true;
	});

  // methods we define
  var methods = {
    // render a template using jquery.resiglet
    'renderTemplate' : function(id, data) {
      // render template into each node
			$(this).show().html($.ilse.renderTemplate(id, data)).closest('.widget_container').show();

			// trigger event
      $(document).trigger('template-rendered', this);

      // done, return jQuery object
      return this;
    },
		'renderPagedResults' : function(results, page, template, options) {
			var $this			= this;
			// handle defaults/options
			var defaults 	= {
				list 		    : "> ul",
				slider	    : ".ilse-slider",
				rpp			    : 4
			};
			var options 	= $.extend({}, defaults, options);

			// render template and attach accordion
			var _render = function(_page) {
				// determine index into results array
				var idx = _page * options.rpp;
				if (idx > results.length)
					return;
				$(options.list, $this).ilse.renderTemplate(template, {
					results : results.slice(idx, idx + options.rpp)
				}).ilse.resultAccordion();
			};

			// render first page
			_render(page);

			// determine the number of pages and (optionally) attach slider
			$(options.slider, this).ilse.resultSlider({
				min				: 1,
				max				: Math.ceil(results.length / options.rpp),
				value			: 1,
				slide			: function(ev, ui) {
					_render(ui.value - 1);
				}
			});

      // done
      return this;
		},
		// wrap jQuery UI slider
		'resultSlider' : function(options) {
			// setup defaults
      var defaults 	= {
				animate 			: true,
				min						: 0,
				max						: 0,
				step					: 1,
				clear					: true,
				adjusthandle	: true,
				alwaysshow		: true,
				scrollable		: null,
				value					: 0
      };
      var options = $.extend({}, defaults, options);

			// attach to scrollable?
			if (options.scrollable && options.scrollable instanceof jQuery)
			{
				var s = options.scrollable.data('scrollable');

				options.min 	= 1;
				options.max 	= s.getSize();
				options.value = 1 + s.getIndex();

				// turn off keyboard navigation, since it's annoying
				s.getConf().keyboard 	= false;
				s.getConf().easing 		= 'linear';

				// update scrollable when slider changes
				$(this).bind('slider-slide', function(ev, to) {
					// stop any running/pending animations before seeking
					s.getItemWrap().stop(true);
					s.seekTo(to - 1, 100);
				});
			}
			else
			{
				options.scrollable 	= null;
			}

			// hide slider if there's only one resultpage
			if (options.min >= options.max && ! options.alwaysshow)
			{
				$(this).hide();
				return this;
			}

			// normalize values
			if (options.min >= options.max)
				options.min = options.max;
			if (options.value >= options.max)
				options.value = options.max;
			if (options.value < options.min)
				options.value = options.min;

			// explicitely clear old slider?
			if (options.clear)
			{
				$(".ui-slider", this).remove();
				$(this).slider('destroy');
				// empty feedback
				$(this).siblings('.ilse-slider-feedback').text('');
			}

			// make super duper slider
			/*
			console.log('---')
			console.log('max', options.max)
			console.log('min', options.min)
			console.log('val', options.value)
			console.log('scr', options.scrollable)
			*/
			if (options.scrollable && options.max <= 1)
			{
				// don't show a handle if scrollable and scrollable is empty
			}
			else
			if (! options.scrollable && options.max == 1)
			{
				// don't show a handle if we only have one result page
			}
			else
			if (0 == $('.ui-slider-handle', this).length)
			{
				// propagate events to listeners
				var old_handlers = { change : options.change, slide : options.slide };

				function setHandler(name)
				{
					options[name] = function(ev, ui) {
						$(this).trigger('slider-' + name, ui.value, this);
						old_handlers[name] && old_handlers[name](ev, ui);
					};
				}
				setHandler('change');
				setHandler('slide');

				// create slider
				var $slider = $(this).
					append('<div class="ui-slider"><a href="#" class="ui-slider-handle"><b class="l"><em/></b><b class="r"><em/></b></a></div>').
					slider(options);

				// attach feedback to events
				var $feedback = $(this).siblings('.ilse-slider-feedback');
				$(this).bind('slider-slide slider-change', function(ev, to) {
					$feedback.text(to + "/" + $slider.slider('option', 'max'));
				});

				// attach to scrollable
				options.scrollable && options.scrollable.
					bind('onBeforeSeek', function(ev, to) {
						// prevent avalanche of retriggers:
						// adjusting the slider-value, as we do here, triggers the
						// slider's 'change' event; this, in turn, triggers the
						// slider-moved handler of scrollable, which runs the seekTo()
						// method; which triggers this code; hence, a loop is created
						// which we'll break by using a sentinel
						if ( $(this).data('is-sliding') )
							return;
						$(this).data('is-sliding', true);
						$slider.slider('value', to + 1);
					}).bind('onSeek', function(ev, to) {
						$(this).data('is-sliding', false);
					}).bind('onAddItem', function(ev, to) {
						// adjust maximum
						$slider.slider('option', 'max', $(this).data('scrollable').getSize());
						// trigger listeners so they can update themselves
						$slider.slider('value', $slider.slider('value'));
					});

				// trigger listeners once to allow them to configure themselves
				$slider.slider('value', options.value);

				// adjust handle-size (XXX: make this dynamic?)
				if (options.adjusthandle)
				{
					// need to use a minimum size because of button images
					var width = Math.max($(this).width() /
											((options.max - options.min + 1) / options.step), 21);

					$('.ui-slider-handle', this).width(width);
				}
			}
			else
			if ("string" == typeof options)
			{
				// XXX: test this
				$(this).slider(arguments);
			}

			// adjust width of slider to width of handle
			var width = $(".ui-slider-handle", this).width();
			$(".ui-slider", this).css({ 'margin-right' : width });

			// done
			return this;
		},
    // result slider for Google results
    'googleResultSlider': function(searcher, s) {
    	return $(this).ilse.resultSlider({
				results 	: s.results,
				value   	: s.cursor.currentPageIndex + 1,
				min     	: 1,
				max     	: s.cursor.pages.length,
				slide   	: function(ev, ui) {
					searcher.gotoPage(ui.value - 1);
				}
			});
    },
    // result slider for Google results
    'hyvesUserResultSlider': function(searcher, s) {
    	return $(this).ilse.resultSlider({
				results : s.user,
				value   : s.info.currentpage,
				min     : 1,
				max     : Math.min(s.info.totalpages, 8),
				slide   : function(ev, ui) {
					searcher.gotoPage(ui.value);
				}
			});
    },
    'hyvesWWWResultSlider': function(searcher, s) {
    	return $(this).ilse.resultSlider({
				results : s.www,
				value   : searcher.currentpage,
				min     : 1,
				max     : 8,
				slide   : function(ev, ui) {
					searcher.gotoPage(ui.value);
				}
			});
    },
    // result list accordion
    'resultAccordion' : function(options) {
			var $this = this;

      // set defaults
      var defaults  = {
        header      : 'li > h2',
        autoHeight  : false,
				autoAnchor	: true,
				event				: 'accordion-change',
        changestart : function(ev, ui) {
          $(ui.newContent).closest('li').addClass('accordion-active');
          $(ui.oldContent).closest('li').removeClass('accordion-active');
        },
        change      : function(ev, ui) {
        }
      };

      // determine options
      var options = $.extend({}, defaults, options);

			// wrap headercontents in an anchor
			$(options.header, this).each(function(i, item) {
				// don't double-anchor
				if ( $("a", this).length != 0 )
					return;
				var $li  = $(this).closest('li');

				// default to noop
				var attrs = { href : 'javascript:void(0)' };
				if (options.autoAnchor)
				{
					var $link = $('.result_link a, a.result_link', $li);
					// copy href and data-source attributes
					attrs			= {
						href					: $link.attr('href'),
						'data-source' : $link.attr('data-source')
					}
				}

				$(this).wrapInner( $("<a/>", attrs) );

				// add class to first li
				if (i == 0)
					$li.addClass('accordion-active');
			});

			// create accordion (destroy any existing accordion first)
			var $accordion = $(this).accordion('destroy').accordion(options);

      // attach clickhandler to titles
      $(options.header, this).click(function() {
        var isactive  = $(this).hasClass('ui-state-active');

				$(this).trigger('accordion-change');
				return isactive;
			});

			// done
			return $this;
    },
		// fill based on attributes
		'fill' : function($target, prefix) {
			return $(this).each(function() {

				$.each( $(this).attributes(prefix), function(key, value) {

					$(':[class*="' + key + '"]', $target).each(function() {
						var klass = $(this).attr('class');

						// check if we should target an attribute
						if (klass.indexOf(key + '-') != -1)
						{
							// yes
							var pattern = key + '-(\\S+)';
							var attr = klass.match(pattern);

							if (attr.length)
								$(this).attr(attr[1], value);
						}
						else
						{
							// no
							$(this).text(value);
						}
					});

				});

			});
		}
  };

  // add methods to jQuery, in a separate namespace
  $.namespace('ilse', methods);

  // add some other functions
  $.extend({
    'ilse'  : {
      // render a template using jquery.resiglet
      'renderTemplate' : function(id, data) {
        var nodelist  = this;
        var html      = $(id).html().replace(/<!--([\s\S]*?)\/\/\s*-->/gm, '$1');
        return $.resiglet(html, data);
      },
      // grab search query
      'query' : function() {
				if (typeof query != "undefined")
					return query;
        var q = location.pathname.substring(1);
            if (q.length == 0 || q.indexOf('/') != -1)
          return null;
				return q;
      },
      // spellcheck a query using Google Suggest
      'spellcheck'  : function(callback, query) {
        if (! query)
          query = $.ilse.query();
        if (! query)
          return null;
        $.getJSON('http://www.google.com/complete/search?hl=nl&client=suggest&js=true&callback=?&q=' + encodeURIComponent(query), function(d) {
          var q = null;
          $.each(d[1], function(i, item) {
            var txt = item[0];
            var num = item[1];
            var idx = item[2];

            // spelling suggestion?
            if (idx.charAt(idx.length - 1) == 's')
            {
              q = txt;
              return false;
            }
          });
					callback(q);
        });
      },
			// encode a string
			'urlencode' : function(s) {
				return encodeURIComponent(s).replace(/%2f/ig, '/');
			},
      // format a timestamp
      'formatTimestamp' : function(ts) {
        var epoch = new Date().getTime()
        var diff  = epoch - ts

        /* in case users computer lives in the future */
        if (diff < 0)
          return "onbekende tijd";

        /* convert milliseconds to seconds */
        diff /= 1000;

        /* start formatting */
				var table = [
					[         60, 'seconde', 'seconden' ],
					[       3600, 'minuut' , 'minuten'  ],
					[      86400, 'uur'    , 'uur'      ],
					[     604800, 'dag'    , 'dagen'    ],
					[    2628030, 'week'   , 'weken'    ],
					[ 4294967295, 'maand'  , 'maanden'  ]
				];
				for (var i = 0, suffix = '', divider = 1; i < table.length; divider = table[i++][0])
				{
					if (diff < table[i][0])
					{
						diff 	/= divider;
						suffix = table[i][1 + (parseInt(diff) > 1 ? 1 : 0)];
						break;
					}
				}
        return parseInt(diff) + " " + suffix;
      }
    }
  });
  
})(jQuery);

(function($) {
  
	$.shorten = function(url, callback, opts) {
		var defaults = {
			login		: 'ilsexiv',
			apikey	: 'R_e058dc56a0636618ef6a583c0e92b539'
		};
		var opts 	= $.extend({}, defaults, opts);
		var API		= "http://api.bit.ly/v3/shorten?login=" 
		            + encodeURIComponent(opts.login)
								+ "&apiKey="
								+ encodeURIComponent(opts.apikey)
								+ "&format=json&domain=j.mp&callback=?&longUrl=";

		$.getJSON(API + encodeURIComponent(url), function(response) {
			callback(
				response.status_code == 200 ? response.data.url : null,
				response
			);
		});
	};
  
})(jQuery);

(function($) {

// list of current themes
var THEMES 				= [ 'grey-theme', 'orange-theme', 'blue-theme', 'magenta-theme' ];
var DEFAULT_THEME = 'grey-theme';
var ELEMENT				= 'body';
var COOKIE_NAME		= 'ilse-102-theme';

// extend $.ilse
$.extend($.ilse, {
	setTheme	: function(theme) {
		// nothing? try to restore from cookie
		if (typeof theme == 'undefined')
			theme = $.cookie(COOKIE_NAME) || DEFAULT_THEME;
		else
		// index?
		if (typeof theme == 'number')
			theme = THEMES[theme];

		// sanitycheck
		var idx = THEMES.indexOf(theme);
		if (idx == -1)
		{
			theme = DEFAULT_THEME;
			idx 	= THEMES.indexOf(theme);
		}

		// remove any old theme and set new one
		$(ELEMENT).
			removeClass(THEMES.join(" ")).
			addClass(theme);

		// try to determine domain
		var domain = location.hostname.split('.');
		if (! domain[domain.length - 1].match(/^\d+$/))
			domain = domain.slice(-2).join(".");
		else
			domain = location.hostname;

		// store in cookie
		$.cookie(COOKIE_NAME, theme, {
			expires	: 1095,
			path		: '/',
			domain	: domain
		});

		// trigger listeners
		$(document).trigger('theme-change', [ theme, idx ]);

		// done
		return idx;
	}
});

})(jQuery);

// autocompleter for searchform
$("input#q").available(function() {
	$(this).autocomplete("http://www.google.com/complete/search", {
		dataType 		: 'json',
		extraParams : {
			hl				: 'nl',
			client		: 'suggest',
			js				: 'true'
		},
		selectFirst	: false,
		formatItem	: function(r, i, n, q) {
			return "<div class='ac-suggestion'>"  + r[0] + "</div>" + 
						 "<div class='ac-count'>" + r[1] + "</div>";
		},
		parse				: function(d) {
			var results = [];
			$.each(d[1], function(i, item) {
				var txt = item[0];
				var num = item[1];
				results.push({
					data		: item,
					value		: txt + " " + num,
					result	: txt
				});
			});
			return results;
		}
	}).result(function(event, item) {
		if (item && item.length)
			$(this).closest('form').submit();
	});
});

$('a.max_module').live('click', function(e) {
	
	// Module containers verzamelen
	var moduleContainer = $(this).closest(".widget_container");
	
	// Positie module bepalen
	var modulePosition = moduleContainer.position();
	
	// Full content container selecteren als het aanwezig is
	var fullContentContainer = moduleContainer.find('div.fullcontent_container');
	
	var list = moduleContainer.find('> div > ul');
	
	// Create the ghost module 
	var ghostMod = $('<div id="ghostmod">').css({
		'width': moduleContainer.width(),
		'height': moduleContainer.height(),
		'position': 'relative',
		'display': 'block',
		'margin-bottom': 6
	});
	
	// Icoontje veranderen naar een minnetje
	$(this).toggleClass('min_module');
	
	//Controleren of de widget in de 1e 2 kolommen zit en of het al vergroot is
	if (moduleContainer.parent('div').hasClass('left')) {
		if (moduleContainer.css('position') != 'absolute') {
			moduleContainer.css({
				'position': 'absolute',
				'width': moduleContainer.width() * 2 + 14,
				'z-index': 2000,
				'top': moduleContainer.top
			});
			if(fullContentContainer) {
				fullContentContainer.css({
					'display': 'block'
				});
			}
			// inject ghostmodule after the current container ?? Check if it works like this ??
			ghostMod.insertAfter(moduleContainer);
		}
		else {
			moduleContainer.css({
				'width': (moduleContainer.width() - 14) / 2,
				'position': '',
				'z-index': 0
			});
			$('#ghostmod').remove();
		}
	} else {
		// Wanneer de module aan de rechterzijde staat wordt de module naar links vergroot
		if (moduleContainer.parent('div').hasClass('nomargin')) {
			if (moduleContainer.css('position') != 'absolute') {
				moduleContainer.css({
					'position': 'absolute',
					'width': moduleContainer.width() * 2 + 14,
					'z-index': 2000,
					'top': moduleContainer.top,// - 205, // weet niet waar hij de 205px vandaan haalt, even er zo aftrekken...
					'left': modulePosition.left - moduleContainer.width() - 14
				});
				list.css({
					'float': 'left',
					'width': 312,
					'margin-right': 6
				});
				if(fullContentContainer) {
					fullContentContainer.css({
						'display': 'block',
						'width': 316,
						'float': 'left'
					});
				}
				// inject ghostmodule after the current container ?? Check if it work like this ??
				ghostMod.insertAfter(moduleContainer);
			}
			else {
				moduleContainer.css({
					'width': (moduleContainer.width() - 14) / 2,
					'position': '',
					'z-index': 0,
					'left': modulePosition.left - 310 - 14
				});
				fullContentContainer.css({
					'display': 'none'
				});
				list.css({
					'float': '',
					'width': '',
					'margin-right': ''
				});
				$('#ghostmod').remove();
			}
		}
	}
});

(function($) {
	// fix MediaWiki markup
	function fix_markup(html)
	{
		// translate mediawiki formatting to actual HTML
		html = html.replace(/'''(.*?)'''/g, '<strong>$1</strong>');
		html = html.replace(/''(.*?)''/g, '<em>$1</em>');
		return html;
	}

  // handle Wikipedia content
  var format_wikipedia = function($node, callback) {
		var text = $node.html().replace(/^\s+|\s+$/, '');
    $node.empty();

    // any templates present?
    if (text.indexOf("{{") == -1)
    {
      // if not: take a shortcut
      callback(fix_markup(text));
      return;
    }

    // otherwise, use Wikipedia to expand templates
    $.getJSON("http://nl.wikipedia.org/w/api.php?action=expandtemplates&text=" + encodeURIComponent(text) + "&format=json&callback=?", function(data) {
      try { callback(fix_markup(data.expandtemplates['*'])) } catch(e) {};
    });
  };

  // methods we define
  var methods = {
    // generate short abstract from Wikipedia page for query
    'wikipedia' : function(query) {
			var $node = $(this).eq(0).find(".text");

      format_wikipedia($node, function(html) {
				if (! html || ! html.length)
					return;
				$node.html(html).closest('.snippet').show();
				return true;
      });
      // done, return jQuery object
      return this;
    },
    'wikipedia.cse' : function(query) {
			var $node = $(this).eq(0).find(".text");

			new GoogleSearcher(function(s) {
				if (! s.results.length)
					return;
				$node.html(s.results[0].content).closest('.snippet').show();
				return true;
			}).searchWeb(query, {
				cx	: '001292844248412685905:9l1euuiadvw',
				rsz	: 'small'
			});
      // done, return jQuery object
      return this;
    }
  };

  // add methods to jQuery
  $.each(methods, function(i) { $.fn[i] = this; });
})(jQuery);

function GoogleSearcher(callback, call_when_empty) {
	this.urlprefix				= 'http://ajax.googleapis.com/ajax/services/search/';
	this.type							= null;
	this.query						= null;
	this.data							= null;
	this.callback					= callback;
	this.call_when_empty	= call_when_empty;
	this.pagecache				= [];
	this.timeout					= null;
	this.wait_for					= 200; // wait this many ms before executing gotoPage
};

GoogleSearcher.prototype.gotoPage = function(page) {
	// cancel any previous requests
	if (this.timeout)
		clearTimeout(this.timeout);

	// check for a cached version of this resultpage
	var cached = this.pagecache[page];
	if (cached)
	{
		// hmm...
		this.searchComplete({
			'responseStatus'	: 200,
			'responseData'		: cached
		});
		return;
	}

	// check for valid page
	if (! this.data || page < 0 || page >= this.data.cursor.pages.length)
	{
		// hmm...(2)
		this.searchComplete({ 'responseStatus' : 404 });
		return;
	}

	// queue a new request
	var	$this 		= this;
	this.timeout 	= setTimeout(function() {
		$this.search($this.type, $this.query, $.extend({}, $this.options, {
			start	: $this.data.cursor.pages[page].start
		}));
	}, this.wait_for);
};

GoogleSearcher.prototype.searchComplete = function(response) {
	// check for a failed request
	var failed = ! response || response.responseStatus != 200 || response.responseData.results.length == 0;

	// return if failed and called doesn't want to be informed about it
	if (failed && ! this.call_when_empty)
		return;

	// grab response data
	this.data = response.responseData;

	// store in cache
	if (this.data.cursor && ! this.pagecache[this.data.cursor.currentPageIndex])
		this.pagecache[this.data.cursor.currentPageIndex] = this.data;

	// trigger eventhandlers
	$(document).trigger('google.' + this.type, [ this.type, this.data ]);

	// call callback
	this.callback(this.data);
};

GoogleSearcher.prototype.search = function(type, query, options) {
	this.type		= type;
	this.query	= query;

	// handle defaults/options
	var defaults = {
		q						: query,
		v						: '1.0',
		rsz					: 'small', // or: 'large'
		safe				: 'active', // or: 'moderate', 'off'
		hl					: 'nl',
		start				: 0,
		lr					: 'lang_nl',
		filter			: 1, // or: 0 (turn off duplicate filter)
		gl					: 'nl'
	};
	this.options = jQuery.extend({}, defaults, options);

	// create url
	var url = this.urlprefix + type + '?callback=?&' + $.param(this.options);

	// perform search
	$.getJSON(url, $.proxy(this.searchComplete, this));
};

GoogleSearcher.prototype.searchWeb = function(query, options) {
	var defaults = { rsz	: 'large' };
	this.search('web', query, jQuery.extend({}, defaults, options));
};

GoogleSearcher.prototype.searchImage = function(query, options) {
	var defaults = { rsz	: 'large' };
	this.search('images', query, jQuery.extend({}, defaults, options));
};

GoogleSearcher.prototype.searchNews = function(query, options) {
	var defaults = {
		scoring			: 'd', // or drop if you want to score on relevance
		ned 				: 'nl_nl',
		geo 				: 'Netherlands'
	};
	this.search('news', query, jQuery.extend({}, defaults, options));
};

GoogleSearcher.prototype.searchVideo = function(query, options) {
	this.search('video', query, options);
};

GoogleSearcher.prototype.searchLocal = function(query, options) {
	// center on Amsterdam by default
	var defaults = { sll : '52.3666666666667,4.9' }

	// if we know client location, use that as centerpoint
	if (clientloc.latlng)
		defaults.sll = clientloc.latlng.join(",");

	// perform search
	this.search('local', query, jQuery.extend({}, defaults, options));
};

/* Google DFP */
function GA_Place_Ad(name)
{
	GA_googleAddSlot("ca-pub-2615428063642387", name);
	GA_googleFetchAds();
	GA_googleFillSlot(name)
};

(function($) {
	// shortcuts
	var gm = google.maps;
	var gs = google.search;

	// create our own maptype control
	function IlseMapTypeControl() {
		this.map = null;
	};

	IlseMapTypeControl.prototype = new GControl();

	IlseMapTypeControl.prototype.initialize = function(map) {
		// store reference to map
		this.map = map;

		// create a button container
		var $container 	= $("<div/>", {
			css	: {
				position 	: 'relative',
				width			: '184px'
			}
		});

		// supports opacity?
		if ($.support.opacity)
		{
			var opacity = '0.5';

			$container
				.css({ opacity	: opacity } )
				.mouseover(function() {
					$(this).stop().animate({ opacity : '1.0' }, 'fast');
				})
				.mouseout(function() {
					$(this).stop().animate({ opacity : opacity }, 'fast');
				});
		};

		// add buttons
		$container.
			append( this.makeButton('map-type-normal'		,	G_NORMAL_MAP) 		).
			append( this.makeButton('map-type-satellite',	G_SATELLITE_MAP)  ).
			append( this.makeButton('map-type-hybrid'		, G_HYBRID_MAP) 		);

		// add button to map
		var container = $container.get(0);
		map.getContainer().appendChild(container);
		return container;
	};

	IlseMapTypeControl.prototype.makeButton = function(klass, maptype) {
		var map = this.map;

		// create a button
		var $button = $("<div/>").addClass("geo-select-button").addClass(klass);

		// keep track of maptype-changes
		GEvent.addListener(this.map, 'maptypechanged', function() {
			if (map.getCurrentMapType() == maptype)
				$button.addClass('active');
			else
				$button.removeClass('active');
		});

		// attach clickhandler
		$button.click(function() { map.setMapType(maptype) });

		// return instance
		return $button;
	};

	IlseMapTypeControl.prototype.getDefaultPosition = function() {
		return new GControlPosition(G_ANCHOR_TOP_RIGHT, new GSize(3, 3));
	};

	// implementation of a MarkerStore
	function MarkerStore(map, container, center)
	{
		this.map 					= map;
		this.container		= container;
		this.markers			= [];
		this.boundingbox	= new gm.LatLngBounds(center);
		this.centermarker	= null;
	};

	MarkerStore.prototype.add = function(marker) {
		// push marker on the list
		this.markers.push(marker);

		// add to boundingbox
		this.boundingbox.extend(marker.latlng);

		// determine if this is the best marker for centering
		if (! this.centermarker || marker.accuracy > this.centermarker.accuracy)
			this.centermarker = marker;
	};

	MarkerStore.prototype.zoom = function() {
		if (this.markers.length == 0)
			return 12;
		if (this.markers.length == 1 && this.markers[0].accuracy != -1)
			return (this.markers[0].accuracy < 5) ? 11 : 16;
		if (this.centermarker && this.centermarker.accuracy > 5)
			return 15;

		var w = $(this.container).width();
		var h = $(this.container).height();
		var s = new gm.Size(w, h);
		return Math.min(16, this.map.getBoundsZoomLevel(this.boundingbox, s));
	};

	MarkerStore.prototype.center = function() {
		if (this.centermarker)
			return this.centermarker.latlng;
		return this.boundingbox.getCenter();
	};

	// class encapsulating Google Maps API
	function Map(container, center)
	{
		this.container	= container;
		this.map 				= new gm.Map2( $(container).get(0) );

		// amsterdam is the center of the world!
		this.mapcenter	= center || new gm.LatLng(52.3666666666667, 4.9);

		// initialize store and queue
		this.store			= new MarkerStore(this.map, this.container, this.mapcenter);
		this.queue			= new MarkerQueue();

		// initialize map
		this.initialize();
	};

	Map.prototype.initialize = function() {
		// add controls to map
		this.map.addControl(new IlseMapTypeControl());
//		this.map.enableScrollWheelZoom();

		// add local search
		this.searchControl 	= new gs.SearchControl();
		this.localSearch		= new gs.LocalSearch();

		// use centerpoint of map for local search
		this.localSearch.setCenterPoint(this.map);

		// restrict local search to KML/geocode-results only
		this.localSearch.setResultSetSize(gs.Search.LARGE_RESULTSET);

		// add localControl to searchControl
		this.searchControl.addSearcher(this.localSearch);

		// set callback for results
		this.searchControl.setSearchCompleteCallback(this, this.searchComplete);

		// 'draw' the control
		this.searchControl.draw(document.createElement('div'));

		// initialize map on center
		this.center(this.mapcenter, 11);

		// attach listener for add-marker-done event
		this.queue.setAddMarkerHandler($.proxy(this.addMarker, this));

		// attach listener for process-done event
		this.queue.setProcessDoneHandler($.proxy(this.processingDone, this));

		// proxy zoom-end event to instance (so others can bind it)
		var _this = this;
		GEvent.addListener(this.map, 'zoomend', function(oldLevel, newLevel) {
			$(_this).trigger('geo-map-zoom-end', newLevel);
		});

		// also trigger changes of map
		var mapchanged 	= function() { $(_this).trigger('geo-map-changed', arguments); };
		var events			= [ 'addoverlay', 'zoomend', 'moveend', 'dragend' ];
		$.each(events, function(i, event) {
			GEvent.addListener(_this.map, event, mapchanged);
		});
	};

	Map.prototype.searchComplete = function() {
		// filter results
		var markers = $.grep(this.localSearch.results, function(result) {
			// only allow address matches
			return result.addressLookupResult ? true : false;
		});

		// queue markers
		var $this = this;
		$.each(markers, function(i, marker) {
			$this.queue.enqueue(new Marker({
				latlng	: Map.makeLatLng(marker.lat, marker.lng),
				content	: marker.html.cloneNode(true),
				accuracy: parseInt(marker.accuracy)
			}));
		});

		// trigger queue
		this.queue.trigger('process');
	};

	// execute a query
	Map.prototype.search = function(q) {
		this.searchControl.execute(q);
	};

	// place a marker
	Map.prototype.addMarker = function(ev, marker) {
		var gmarker = marker.gmarker();

		// add marker to map
		this.map.addOverlay(gmarker);

		// add marker to store
		this.store.add(marker);

		// attach clickhandler if we have content for this marker
		if (marker.content)
		{
			// attach listener
			GEvent.addListener(gmarker, "click", function() {
				gmarker.openInfoWindowHtml(marker.content.title + marker.content.description, {
					maxWidth	: 220
				});
			});
		}
	};

	// done processing queue
	Map.prototype.processingDone = function() {
		this.center(this.store.center(), this.store.zoom());
	};

	// some proxies to GMap
	Map.prototype.zoom = function(zoom) {
		if (zoom)
			this.map.setZoom(zoom);
		return this.map.getZoom();
	};

	Map.prototype.maximumZoom = function() {
		return this.map.getCurrentMapType().getMaximumResolution();
	};

	Map.prototype.center = function(center, zoom) {
		if (center && zoom)
			this.map.setCenter(center, zoom);
		else if (center)
			this.map.setCenter(center);
		return this.map.getCenter();
	};

	// static helpers
	Map.makeLatLng = function(lat, lng) {
		return new gm.LatLng(lat, lng);
	};

	Map.ilseResultMarkerContent = function($node) {
		var title = $('.result_title', $node).html();
		var $desc = $('.result_description', $node).clone();

		// remove items which shouldn't be shown
		$(".dossier-dont-store", $desc).remove();

		// create popup html
		return {
			title				: title,
			description	: $desc.html()
		};
	};

	// distance between two geolocations
	Map.distance = function(lat1, lng1, lat2, lng2) {
		var R = 6371; // km
    lat1 *= 0.017453292519943295;
    lng1 *= 0.017453292519943295;
    lat2 *= 0.017453292519943295;
    lng2 *= 0.017453292519943295;
		return Math.acos(Math.sin(lat1) * Math.sin(lat2) +
										 Math.cos(lat1) * Math.cos(lat2) *
										 Math.cos(lng2 - lng1)) * R;
    /*
    var radlat1 = Math.PI * lat1/180;
    var radlat2 = Math.PI * lat2/180;
    var radlng1 = Math.PI * lng1/180;
    var radlng2 = Math.PI * lng2/180;
    var theta = lng1-lng2;
    var radtheta = Math.PI * theta/180;
    var dist = Math.sin(radlat1) * Math.sin(radlat2) + Math.cos(radlat1) * Math.cos(radlat2) * Math.cos(radtheta);
    dist = Math.acos(dist);
    dist = dist * 180/Math.PI;
    dist = dist * 60 * 1.1515;
    dist = dist * 1.609344;
    return dist;
                     */
	};

	/*
	 * Marker class.
	 */
	function Marker(options)
	{
		var defaults = {
			latlng			: null,
			content			: null,
			icon				: null,
			iconPath		: '/resources/img/geo/',
			iconSize		: new gm.Size(20, 31), // XXX
			shadow			: 'shadow.png',
			shadowSize	: new gm.Size(34, 31),
			accuracy		: -1
		};
		var options = $.extend({}, defaults, options);

		// lat/long passed as array?
		if (options.latlng instanceof Array)
		{
			// if so, convert it...
			options.latlng = Map.makeLatLng(options.latlng[0], options.latlng[1]);
		}

		// copy options to this
		for (var i in options)
			this[i] = options[i];

		// cached GMarker instance
		this._gmarker	= null;
	};

	var iconCache = {}; // should be global
	Marker.prototype.gmarker = function() {
		// use cached marker instance?
		if (this._gmarker)
			return this._gmarker;

		// use default icon if none is supplied
		if (! this.icon)
			this.icon = 'ilse.png';

		// check for cached icon
		var options = {};
		options.icon = iconCache[this.icon];
		if (! options.icon)
		{
			options.icon 						= new gm.Icon(G_DEFAULT_ICON, this.iconPath + this.icon);
			options.icon.iconSize  	= this.iconSize;
			options.icon.shadow			= this.iconPath + this.shadow;
			options.icon.shadowSize	= this.shadowSize;
			iconCache[this.icon] 		= options.icon;
		}
		this._gmarker = new gm.Marker(this.latlng, options);
		return this._gmarker;
	};

	/*
	 * Marker queue logic.
	 */
	var DEFAULT_QUEUE			= 'geo-marker-queue';
	var PROCESS_EVENT			= 'geo-marker-queue-process';
	var ADD_MARKER_EVENT	= 'geo-marker-queue-add-marker';
	var DONE_EVENT 				= 'geo-marker-queue-done';

	function MarkerQueue(queueName, processEvent, addMarkerEvent, doneEvent)
	{
		this.name						= queueName  		|| DEFAULT_QUEUE;
		this.processEvent		= processEvent 	|| PROCESS_EVENT;
		this.addMarkerEvent	= addMarkerEvent|| ADD_MARKER_EVENT;
		this.doneEvent			= doneEvent 		|| DONE_EVENT;
		this.$listener			= $(document);

		// attach eventlistener for process-event
		this.$listener.bind(this.processEvent, $.proxy(this.process, this));
	};

	MarkerQueue.prototype.enqueue = function(marker) {
		// check for valid marker
		if (! marker.latlng || isNaN(marker.latlng.lat()) || isNaN(marker.latlng.lng()))
			return false;

		// enqueue a marker
		this.$listener.queue(this.name, marker);
		return true;
	};

	MarkerQueue.prototype.process = function(ev) {
		// make sure we have a listener (XXX: check both marker- and done-listeners?)
		if (! this.markerListener() || this.empty())
			return;

		// process queue
		var queue = this.$listener.queue(this.name);
		var $this = this;
		$.each(queue, function(i, marker) {
			// trigger listener (usually a Map instance)
			$this.trigger('add-marker', marker);
		});

		// clear queue
		this.$listener.clearQueue(this.name);

		// signal that we're done
		this.trigger('done');
	};

	MarkerQueue.prototype.trigger = function(signal, arg) {
		var event = {
			'process'			: this.processEvent,
			'done'				: this.doneEvent,
			'add-marker'	: this.addMarkerEvent
		}[signal];

		if (! event)
			return null;
		this.$listener.trigger(event, arg);
		return event;
	};

	MarkerQueue.prototype.empty = function() {
		return this.$listener.queue(this.name).length == 0;
	};

	MarkerQueue.prototype.setAddMarkerHandler = function(handler) {
		this.$listener.bind(this.addMarkerEvent, handler);
		this.markerListener(true);
	};

	MarkerQueue.prototype.setProcessDoneHandler = function(handler) {
		this.$listener.bind(this.doneEvent, handler);
	};

	MarkerQueue.prototype.markerListener = function(set) {
		var key = this.name + '-has-marker-listener';
		if (set)
			this.$listener.data(key, true);
		return this.$listener.data(key);
	};

	// extend jQuery
	$.extend({
		'geo'	: {
			'makeLatLng'			: Map.makeLatLng,
			'distance'			  : Map.distance,
			'makeIlseContent'	: Map.ilseResultMarkerContent,
			'map'							: Map,
			'marker'					: Marker,
			'queue'						: MarkerQueue
		}
	});

})(jQuery);

(function($) {

  $.namespace('ilse', {
    'imPlayer' : function(id, variables, options) {
      // set defaults
      var defaults = {
        player  : "http://vplayer.ilsemedia.nl/swf/im_player.swf?instance=" + ( Math.floor ( Math.random ( ) * 100000 + 1 ) ),
        width   : "308",
        height  : "175"
      };

      // merge defaults
      var options = $.extend({}, defaults, options);

      // set default variables
      var default_variables = {
        width     : options.width,
        height    : options.height,
        autostart : "false",
        playlist  : "none",
        repeat    : "always",
        stretching: "exactfit",
        controlbar: "over"
      };
      
      // merge defaults
      var variables = $.extend({}, default_variables, variables);

      // create player
      var obj 		= new SWFObject(options.player, id, options.width, options.height, "9", "#ffffff");

      // set parameters
      obj.addParam("allowscriptaccess", "always");
      obj.addParam("allowfullscreen", 	true);
      obj.addParam("wmode", 						"opaque");

      // set variables
      for (var variable in variables)
        obj.addVariable(variable, variables[variable]);

      // inject into DOM
      obj.write( $(this).get(0).id );
    }
  });

})(jQuery);

(function($) {

	var makefunc = function(sel) {
		return function() {
			return $(sel, $(this).wc.container());
		};
	};

	var header = "> div:first-child";

	$.namespace('wc', {
		container			: function() { return $(this).closest('.widget_container'); },
		slider				: function() {
			var $slider 	= $(header + " .ilse-slider", $(this).wc.container());
			var $feedback	= $(this).wc.sliderfeedback();

			// (de-)activate slider
			$slider.toggle 		= function() {
				if ($slider.isactive())
				{
					$slider.slider('disable');
					$feedback.hide();
				}
				else
				{
					$slider.slider('enable');
					$feedback.show();
				}
				$(".ui-slider", $slider).toggle();
				$slider.toggleClass('ui-slider');
			};

			// check if slider is active
			$slider.isactive	= function() {
				return $slider.hasClass('ui-slider');
			};

			// return reference
			return $slider;
		},
		sliderhandle	: makefunc(header + " .ilse-slider .ui-slider-handle"),
		sliderfeedback: makefunc(header + " > div .ilse-slider-feedback"),
		title					: makefunc(header + " > h2"),
		subtitle			: makefunc(header + " > div h3")
	});
	
})(jQuery);

(function($) {

$(document).bind('twitter.post', function(ev, o) {
	// need to open window first, and set location later
	var w = window.open('about:blank', '_blank',
		[
			'status=no',
			'toolbar=no',
			'location=no',
			'menubar=no',
			'directories=no',
			'resizable=no',
			'scrollbars=no',
			'width=640',
			'height=450',
			'top=120',
			'left=' + (screen.width - 640) / 2
		].join(",")
	);
	$.shorten(o.link, function(shorturl, response) {
		if (shorturl == null)
			shorturl = o.link;
		shorturl = " - " + shorturl;

		// build tweet
		var tweet		= "Gevonden via http://ilse.nl/ : ";
		var length	= 140 - tweet.length - shorturl.length;

		// build title (and adjust to maximum tweet size)
		var title 	= o.title;
		if (title.charAt(0) != '"' && title.charAt(0) != "'")
			title = '"' + title + '"';
		if (title.length > length)
			title = title.substring(0, length - 3) + "...";

		// add title and url to tweet
		tweet += title;
		tweet += shorturl;

		// tweet it
		w.location = 'http://twitter.com/?status=' + encodeURIComponent(tweet);
	});
	return false;
});

$(document).bind('hyves.post', function(ev, o) {
	window.open(
		'http://hyves-share.nl/button/tip/' +
		'?title='           + encodeURIComponent(o.title) +
		'&tipcategoryid=12' +
		'&rating=3'         +
		'&body='            + encodeURIComponent('Gevonden via ilse: ' + o.link),
		'_blank',
		[
			'status=no',
			'toolbar=no',
			'location=no',
			'menubar=no',
			'directories=no',
			'resizable=no',
			'scrollbars=no',
			'width=500',
			'height=500',
			'top=120',
			'left=' + (screen.width - 500) / 2
		].join(",")
	);
	return false;
});

$(document).bind('facebook.post', function(ev, o) {
  // need to open window first, and set location later
  var w = window.open('about:blank', '_blank',
    [
      'status=no',
      'toolbar=no',
      'location=no',
      'menubar=no',
      'directories=no',
      'resizable=no',
      'scrollbars=no',
      'width=640',
      'height=450',
      'top=120',
      'left=' + (screen.width - 640) / 2
    ].join(",")
  );
  $.shorten(o.link, function(shorturl, response) {
    if (shorturl == null)
      shorturl = o.link;
    shorturl = shorturl;
    
    // post on Facebook
    w.location = 'http://www.facebook.com/share.php?u=' + encodeURIComponent(shorturl);
  });
  return false;
});

})(jQuery);

// generic remote file grabber, uses YQL
function YQL(callback, call_when_empty)
{
	this.callback					= callback;
	this.call_when_empty	= call_when_empty;
}

YQL.prototype.perform_query = function(query, params) {
	var defaults = { 'format'	: 'xml' };
	params = $.extend({}, defaults, params);
	var that = this;
	$.getJSON("http://query.yahooapis.com/v1/public/yql?" + $.param(params) + "&callback=?&q=" + encodeURIComponent(query), function(r) {
		if (! r.query || r.query.count == 0)
		{
			if (that.call_when_empty)
				that.callback([]);
			return;
		}
		if (r.results)
			that.callback(r.results);
		else
		if (r.query.results)
			that.callback(r.query.results);
		else
		if (that.call_when_empty)
			that.callback([]);
	});
};

YQL.prototype.load = function(url, root) {
	var that	= this;
	var root	= root || 'xml'; // assume generic XML feed
	var query = "select * from " + root + " where url = @url";
	this.perform_query(query, { 'url' : url });
};

// RSS grabber, based on YQL
function RSS(callback, call_when_empty)
{
	this.callback					= function(r) { callback(r.item) };
	this.call_when_empty	= call_when_empty;
}
RSS.prototype = new YQL();
RSS.prototype.load = function(url, limit) {
	var query = "select * from rss where url = @url";
	if (limit)
		query += " limit " + limit;
	this.perform_query(query, { 'url' : url, 'format' : 'json' });
};

/*
 * Copyright (c) 2008 Kilian Marjew <kilian@marjew.nl>
 *
 * Permission to use, copy, modify, and distribute this software for any
 * purpose with or without fee is hereby granted, provided that the above
 * copyright notice and this permission notice appear in all copies.
 *
 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
 *
 *
 * @author Kilian Marjew (kilian@marjew.nl)
 * @url http://hyvapi.marjew.nl/
 */
var _GenusApisUtil = new GenusApisUtil;
var _OAuthUtil = new OAuthUtil;

function GenusApis(oOAuthConsumer, exceptionHandler, ha_version) {
	this.oOAuthConsumer = oOAuthConsumer;
	this.exceptionHandler = exceptionHandler;
	this.ha_version = ha_version;
	this.DEFAULT_HA_FORMAT = 'json';
	this.DEFAULT_HA_FANCYLAYOUT = 'false';
	this.DEFAULT_HA_RESPONSECODE_ALWAYS_200 = 'true';
	this.DEFAULT_OAUTH_SIGNATURE_METHOD = "HMAC-SHA1";
	this.HTTP_TYPE_GET = 'GET';
	this.API_URL = "http://data.hyves-api.nl/";
	this.AUTHORIZE_URL = "http://www.hyves.nl/api/authorize/";

	this.timestampLastMethod = null;
	this.nonce = null;
}

GenusApis.prototype.doMethod = function(ha_method, sParams, callback, oOAuthToken) {
	var callbackId = _GenusApisUtil.getNextJsonpCallbackIdentifier();
	var sDefaultParams = {
		oauth_consumer_key : this.oOAuthConsumer.getKey(),
		oauth_timestamp : this.getOAuthTimestamp(),
		oauth_nonce : this.getOAuthNonce(),
		oauth_signature_method : this.DEFAULT_OAUTH_SIGNATURE_METHOD,
		ha_method : ha_method,
		ha_version : this.ha_version,
		ha_format : this.DEFAULT_HA_FORMAT,
		ha_fancylayout : this.DEFAULT_HA_FANCYLAYOUT,
		ha_callback : callbackId,
		ha_responsecode_always_200 : this.DEFAULT_HA_RESPONSECODE_ALWAYS_200
	};
	var oauth_consumer_secret = this.oOAuthConsumer.getSecret(); 
		var oauth_token_secret = "";
	if (oOAuthToken !== null && oOAuthToken !== undefined)
	{
		sDefaultParams["oauth_token"] = oOAuthToken.getKey();
		oauth_token_secret = oOAuthToken.getSecret();
	}
	for (x in sParams) {
		sDefaultParams[x] = sParams[x];
	}
	sParams = sDefaultParams;
	sParams["oauth_signature"] = _GenusApisUtil.calculateOAuthSignature(this.HTTP_TYPE_GET, this.API_URL, sParams, oauth_consumer_secret, oauth_token_secret);
	var params = _OAuthUtil.normalizeKeyValueParameters(sParams);
	var url = this.API_URL + "?" + params;
	var self = this;
	_GenusApisUtil.doJsonpCall(url, callback, self);
}

GenusApis.prototype.retrieveRequesttoken = function(aMethods, expirationtype, callback){
	if (expirationtype === null || expirationtype === undefined) {
		var expirationtype = 'default';
	}
	var tempCallback = function(response) {
		var oOAuthRequestToken = new OAuthRequestToken(response["oauth_token"], response["oauth_token_secret"]);
		callback(oOAuthRequestToken);
	}
	this.doMethod("auth.requesttoken", {methods : aMethods.join(','), expirationtype : expirationtype}, tempCallback);
}

GenusApis.prototype.getAuthorizeUrl = function(oOAuthRequestToken, callback){
	var url = this.AUTHORIZE_URL + "?oauth_token=" + oOAuthRequestToken.getKey();
	if (callback !== null && callback !== undefined) {
		url += "&oauth_callback=" + _OAuthUtil.urlencodeRFC3986_UTF8(callback);
	}
	return url;
}

GenusApis.prototype.retrieveAccesstoken = function(oOAuthRequestToken, callback){
	var tempCallback = function(response) {
		var oOAuthAccessToken = new OAuthAccessToken(response["oauth_token"], response["oauth_token_secret"], response["userid"], response["methods"], response["expiredate"]);
		callback(oOAuthAccessToken);
	}
	this.doMethod("auth.accesstoken", { }, tempCallback, oOAuthRequestToken);
}

GenusApis.prototype.checkForErrors = function(dataObject){
	if (typeof(dataObject) !== "object" || dataObject["error_code"]) {
		throw new HyvesApiException(dataObject["error_message"], dataObject["error_code"], dataObject);
	}
}

GenusApis.prototype.handleException = function(e){
	this.exceptionHandler(e);
}
	
GenusApis.prototype.getOAuthTimestamp = function(){
	var timestamp = Math.floor(new Date().valueOf()/1000);
	if (this.timestampLastMethod == timestamp) {
		this.nonce++;
	} else {
		this.timestampLastMethod = timestamp;
		this.nonce = 0;
	}
	return this.timestampLastMethod;
}
	
GenusApis.prototype.getOAuthNonce = function(){
	var rand = Math.ceil(100000*Math.random());
	return this.nonce + "_" + rand;
}


var _cbId = 0;
var _cb = {};

function GenusApisUtil() {
}

GenusApisUtil.prototype.doJsonpCall = function(url, callback, caller){
	var element = document.createElement("script");
	var callbackId = _cbId;
	var scriptId = "_genusapis_callback_" + callbackId;
	element.id = scriptId;
	element.src = url;
	_cb["o"+callbackId] = function(response) {
		try {
			caller.checkForErrors(response);
		}
		catch(e) {
			caller.handleException(e);
			return;
		}
		try {
			callback(response);
			delete _cb["o"+callbackId];
			var el = document.getElementById(scriptId);
			el.parentNode.removeChild(el);
		}
		catch(e) {
			var exception = new GeneralException(e, null);
			caller.handleException(exception);
			return;
		}
	}
	var head = document.getElementsByTagName("head").item(0);
	head.appendChild(element);
}

GenusApisUtil.prototype.getNextJsonpCallbackIdentifier = function(){
	_cbId++;
	return "_cb.o" + _cbId;
}

GenusApisUtil.prototype.calculateOAuthSignature = function(http_method, uri, sVar, consumersecret, oauth_token_secret) {
	var params = _OAuthUtil.normalizeKeyValueParameters(sVar);
	var basestring = _OAuthUtil.generateBaseString(http_method, uri, params);
	return _OAuthUtil.calculateHMACSHA1Signature(basestring, consumersecret, oauth_token_secret);
}


function OAuthBase(key, secret) {
	this.key = key;
	this.secret = secret;
}

OAuthBase.prototype.getKey = function(){
	return this.key;
}

OAuthBase.prototype.getSecret = function(){
	return this.secret;
}

function OAuthConsumer(key, secret) {
	this.base = OAuthBase;
	this.base(key, secret);
}
OAuthConsumer.prototype = new OAuthBase;

function OAuthRequestToken(key, secret) {
	this.base = OAuthBase;
	this.base(key, secret);
}
OAuthRequestToken.prototype = new OAuthBase;

function OAuthAccessToken(key, secret, userid, methods, expiredate) {
	this.base = OAuthBase;
	this.base(key, secret);
	this.userid = userid;
	this.methods = methods;
	this.expiredate = expiredate;
}
OAuthAccessToken.prototype = new OAuthBase;

OAuthAccessToken.prototype.getUserid = function(){
	return this.userid;
}

OAuthAccessToken.prototype.getMethods = function(){
	return this.methods;
}

OAuthAccessToken.prototype.getExpiredate = function(){
	return this.expiredate;
}

function OAuthUtil() {
}

OAuthUtil.prototype.normalizeParameters = function(aParam) {
	var aEncodedVars = new Array();
	for (var i = 0; i < aParam.length; i++) {
		aEncodedVars[aEncodedVars.length] = this.urlencodeRFC3986_UTF8(aParam[i]["key"]) + "=" + this.urlencodeRFC3986_UTF8(aParam[i]["value"]);
	}
	aEncodedVars.sort();
	return aEncodedVars.join('&');
}

OAuthUtil.prototype.normalizeKeyValueParameters = function(sParam) {
	var aParam = new Array();
	for (key in sParam) {
		aParam[aParam.length] = { key : key, value : sParam[key] };
	}
	return this.normalizeParameters(aParam);
}

OAuthUtil.prototype.urlencodeRFC3986_UTF8 = function(string) {
	s = encodeURIComponent(string);
        s = s.replace("!", "%21", "g");
        s = s.replace("*", "%2A", "g");
        s = s.replace("'", "%27", "g");
        s = s.replace("(", "%28", "g");
        s = s.replace(")", "%29", "g");
	return s;
}

OAuthUtil.prototype.generateBaseString = function(http_method, uri, params) {
	var aBasestring = new Array(
		this.urlencodeRFC3986_UTF8(http_method),
		this.urlencodeRFC3986_UTF8(uri),
		this.urlencodeRFC3986_UTF8(params)
	);
	return aBasestring.join('&');
}

OAuthUtil.prototype.calculateHMACSHA1Signature = function(basestring, consumersecret, tokensecret) {
	var aKey = new Array(
		this.urlencodeRFC3986_UTF8(consumersecret),
		this.urlencodeRFC3986_UTF8(tokensecret)
	);
	var key = aKey.join('&');
	var signature = encode64(str_hmac_sha1(key, basestring));
	return signature;
}

function GeneralException(message, code) {
	this.message = message;
	this.code = code;
}

GeneralException.prototype.getCode = function(){
	return this.code;
}

GeneralException.prototype.getMessage = function(){
	return this.message;
}

GeneralException.prototype.getType = function(){
	return 'GeneralException';
}

function HyvesApiException(message, code, response) {
	this.base = GeneralException;
	this.base(message, code);
	this.response = response;
}
HyvesApiException.prototype = new GeneralException;

HyvesApiException.prototype.getResponse = function(){
	return this.response;
}

HyvesApiException.prototype.getType = function(){
	return 'HyvesApiException';
}



// Libraries

// Hmac SHA1
/*
 * A JavaScript implementation of the Secure Hash Algorithm, SHA-1, as definjson to htmled
 * in FIPS PUB 180-1
 * Version 2.1a Copyright Paul Johnston 2000 - 2002.
 * Other contributors: Greg Holt, Andrew Kepert, Ydnar, Lostinet
 * Distributed under the BSD License
 * See http://pajhome.org.uk/crypt/md5 for details.
 */

/*
 * Configurable variables. You may need to tweak these to be compatible with
 * the server-side, but the defaults work in most cases.
 */
var hexcase = 0;  /* hex output format. 0 - lowercase; 1 - uppercase        */
var b64pad  = ""; /* base-64 pad character. "=" for strict RFC compliance   */
var chrsz   = 8;  /* bits per input character. 8 - ASCII; 16 - Unicode      */

/*
 * These are the functions you'll usually want to call
 * They take string arguments and return either hex or base-64 encoded strings
 */
function hex_sha1(s){return binb2hex(core_sha1(str2binb(s),s.length * chrsz));}
function b64_sha1(s){return binb2b64(core_sha1(str2binb(s),s.length * chrsz));}
function str_sha1(s){return binb2str(core_sha1(str2binb(s),s.length * chrsz));}
function hex_hmac_sha1(key, data){ return binb2hex(core_hmac_sha1(key, data));}
function b64_hmac_sha1(key, data){ return binb2b64(core_hmac_sha1(key, data));}
function str_hmac_sha1(key, data){ return binb2str(core_hmac_sha1(key, data));}

/*
 * Perform a simple self-test to see if the VM is working
 */
function sha1_vm_test()
{
  return hex_sha1("abc") == "a9993e364706816aba3e25717850c26c9cd0d89d";
}

/*
 * Calculate the SHA-1 of an array of big-endian words, and a bit length
 */
function core_sha1(x, len)
{
  /* append padding */
  x[len >> 5] |= 0x80 << (24 - len % 32);
  x[((len + 64 >> 9) << 4) + 15] = len;

  var w = Array(80);
  var a =  1732584193;
  var b = -271733879;
  var c = -1732584194;
  var d =  271733878;
  var e = -1009589776;

  for(var i = 0; i < x.length; i += 16)
  {
    var olda = a;
    var oldb = b;
    var oldc = c;
    var oldd = d;
    var olde = e;

    for(var j = 0; j < 80; j++)
    {
      if(j < 16) w[j] = x[i + j];
      else w[j] = rol(w[j-3] ^ w[j-8] ^ w[j-14] ^ w[j-16], 1);
      var t = safe_add(safe_add(rol(a, 5), sha1_ft(j, b, c, d)),
                       safe_add(safe_add(e, w[j]), sha1_kt(j)));
      e = d;
      d = c;
      c = rol(b, 30);
      b = a;
      a = t;
    }

    a = safe_add(a, olda);
    b = safe_add(b, oldb);
    c = safe_add(c, oldc);
    d = safe_add(d, oldd);
    e = safe_add(e, olde);
  }
  return Array(a, b, c, d, e);

}

/*
 * Perform the appropriate triplet combination function for the current
 * iteration
 */
function sha1_ft(t, b, c, d)
{
  if(t < 20) return (b & c) | ((~b) & d);
  if(t < 40) return b ^ c ^ d;
  if(t < 60) return (b & c) | (b & d) | (c & d);
  return b ^ c ^ d;
}

/*
 * Determine the appropriate additive constant for the current iteration
 */
function sha1_kt(t)
{
  return (t < 20) ?  1518500249 : (t < 40) ?  1859775393 :
         (t < 60) ? -1894007588 : -899497514;
}

/*
 * Calculate the HMAC-SHA1 of a key and some data
 */
function core_hmac_sha1(key, data)
{
  var bkey = str2binb(key);
  if(bkey.length > 16) bkey = core_sha1(bkey, key.length * chrsz);

  var ipad = Array(16), opad = Array(16);
  for(var i = 0; i < 16; i++)
  {
    ipad[i] = bkey[i] ^ 0x36363636;
    opad[i] = bkey[i] ^ 0x5C5C5C5C;
  }

  var hash = core_sha1(ipad.concat(str2binb(data)), 512 + data.length * chrsz);
  return core_sha1(opad.concat(hash), 512 + 160);
}

/*
 * Add integers, wrapping at 2^32. This uses 16-bit operations internally
 * to work around bugs in some JS interpreters.
 */
function safe_add(x, y)
{
  var lsw = (x & 0xFFFF) + (y & 0xFFFF);
  var msw = (x >> 16) + (y >> 16) + (lsw >> 16);
  return (msw << 16) | (lsw & 0xFFFF);
}

/*
 * Bitwise rotate a 32-bit number to the left.
 */
function rol(num, cnt)
{
  return (num << cnt) | (num >>> (32 - cnt));
}

/*
 * Convert an 8-bit or 16-bit string to an array of big-endian words
 * In 8-bit function, characters >255 have their hi-byte silently ignored.
 */
function str2binb(str)
{
  var bin = Array();
  var mask = (1 << chrsz) - 1;
  for(var i = 0; i < str.length * chrsz; i += chrsz)
    bin[i>>5] |= (str.charCodeAt(i / chrsz) & mask) << (32 - chrsz - i%32);
  return bin;
}

/*
 * Convert an array of big-endian words to a string
 */
function binb2str(bin)
{
  var str = "";
  var mask = (1 << chrsz) - 1;
  for(var i = 0; i < bin.length * 32; i += chrsz)
    str += String.fromCharCode((bin[i>>5] >>> (32 - chrsz - i%32)) & mask);
  return str;
}

/*
 * Convert an array of big-endian words to a hex string.
 */
function binb2hex(binarray)
{
  var hex_tab = hexcase ? "0123456789ABCDEF" : "0123456789abcdef";
  var str = "";
  for(var i = 0; i < binarray.length * 4; i++)
  {
    str += hex_tab.charAt((binarray[i>>2] >> ((3 - i%4)*8+4)) & 0xF) +
           hex_tab.charAt((binarray[i>>2] >> ((3 - i%4)*8  )) & 0xF);
  }
  return str;
}

/*
 * Convert an array of big-endian words to a base-64 string
 */
function binb2b64(binarray)
{
  var tab = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
  var str = "";
  for(var i = 0; i < binarray.length * 4; i += 3)
  {
    var triplet = (((binarray[i   >> 2] >> 8 * (3 -  i   %4)) & 0xFF) << 16)
                | (((binarray[i+1 >> 2] >> 8 * (3 - (i+1)%4)) & 0xFF) << 8 )
                |  ((binarray[i+2 >> 2] >> 8 * (3 - (i+2)%4)) & 0xFF);
    for(var j = 0; j < 4; j++)
    {
      if(i * 8 + j * 6 > binarray.length * 32) str += b64pad;
      else str += tab.charAt((triplet >> 6*(3-j)) & 0x3F);
    }
  }
  return str;
}

// Base 64
// This code was written by Tyler Akins and has been placed in the
// public domain.  It would be nice if you left this header intact.
// Base64 code from Tyler Akins -- http://rumkin.com

var keyStr = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=";

function encode64(input) {
   var output = "";
   var chr1, chr2, chr3;
   var enc1, enc2, enc3, enc4;
   var i = 0;

   do {
      chr1 = input.charCodeAt(i++);
      chr2 = input.charCodeAt(i++);
      chr3 = input.charCodeAt(i++);

      enc1 = chr1 >> 2;
      enc2 = ((chr1 & 3) << 4) | (chr2 >> 4);
      enc3 = ((chr2 & 15) << 2) | (chr3 >> 6);
      enc4 = chr3 & 63;

      if (isNaN(chr2)) {
         enc3 = enc4 = 64;
      } else if (isNaN(chr3)) {
         enc4 = 64;
      }

      output = output + keyStr.charAt(enc1) + keyStr.charAt(enc2) + 
         keyStr.charAt(enc3) + keyStr.charAt(enc4);
   } while (i < input.length);
   
   return output;
}

function decode64(input) {
   var output = "";
   var chr1, chr2, chr3;
   var enc1, enc2, enc3, enc4;
   var i = 0;

   // remove all characters that are not A-Z, a-z, 0-9, +, /, or =
   input = input.replace(/[^A-Za-z0-9\+\/\=]/g, "");

   do {
      enc1 = keyStr.indexOf(input.charAt(i++));
      enc2 = keyStr.indexOf(input.charAt(i++));
      enc3 = keyStr.indexOf(input.charAt(i++));
      enc4 = keyStr.indexOf(input.charAt(i++));

      chr1 = (enc1 << 2) | (enc2 >> 4);
      chr2 = ((enc2 & 15) << 4) | (enc3 >> 2);
      chr3 = ((enc3 & 3) << 6) | enc4;

      output = output + String.fromCharCode(chr1);

      if (enc3 != 64) {
         output = output + String.fromCharCode(chr2);
      }
      if (enc4 != 64) {
         output = output + String.fromCharCode(chr3);
      }
   } while (i < input.length);

   return output;
}
var consumer_key    = "NTM2NV-lLc_Lu4wgeTOl8hwwODab";
var consumer_secret = "NTM2NV9biNulC_AexX5LCc5PZDQ7";

function HyvesUserSearcher(callback, call_when_empty) {
  this.oOAuthConsumer = new OAuthConsumer(consumer_key, consumer_secret);
  this.oGenusApis = new GenusApis(this.oOAuthConsumer, this.exceptionHandler, "1.2.1");
  this.callback         = callback;
  this.call_when_empty  = call_when_empty;
  this.pagecache        = [];
};

HyvesUserSearcher.prototype.gotoPage = function(page) {
  var cached = this.pagecache[page];
  if (cached)
  {
    this.callback(cached);
    return;
  }
  this.search(this.query, page)
};

HyvesUserSearcher.prototype.search = function(query, page) {
  if (!page) page = 1;
  this.oGenusApis.doMethod("users.search", {'searchterms': query, 'ha_resultsperpage': 4, 'ha_page': page, 'ha_responsefields': 'profilepicture,onmymind'}, $.proxy(this, "response"), null);
  this.query = query;
};

HyvesUserSearcher.prototype.response = function(s) {
  if (s.info.totalresults == 0 && ! this.call_when_empty)
		return;
	this.pagecache[s.info.currentpage] = s;
	this.callback(s);
};

HyvesUserSearcher.prototype.exceptionHandler = function(e) {
};

function HyvesWWWSearcher(callback, call_when_empty) {
  this.oOAuthConsumer = new OAuthConsumer(consumer_key, consumer_secret);
  this.oGenusApis = new GenusApis(this.oOAuthConsumer, this.exceptionHandler, "beta_2");

  this.callback         = callback;
  this.call_when_empty  = call_when_empty;
  this.pagecache        = [null];
  this.currentpage      = 1;
};

HyvesWWWSearcher.prototype.gotoPage = function(page) {
  this.currentpage = page;
  this.callback(this.pagecache[this.currentpage]);
  return;
};

HyvesWWWSearcher.prototype.exceptionHandler = function(e) {
};

HyvesWWWSearcher.prototype.search = function(query) {
  this.oGenusApis.doMethod("wwws.searchPublic", {
    'searchterms'       : query,
    'limit'             : 32,
    'ha_responsefields' : 'geolocation'
  }, $.proxy(this.response, this), null);
};

HyvesWWWSearcher.prototype.response = function(s) {
  var a = Array.slice.call(s.www);
  if (a.length == 0 && ! this.call_when_empty)
		return;
	for (var i = 0; i < 8; i++)
	{
		this.pagecache[i + 1] = { 'www' : a.slice(i * 4, (i + 1) * 4) };
	}
	this.callback(this.pagecache[1]);
};

$('.activate_modal').live('click drop', function(){
	//get the id of the modal window stored in the name of the activating element
	var modal_id = $(this).attr('name');
	var $modal = $('#' + modal_id);

	//use tthe open function
	
	// optional: attr name is picked to display the div with the same ID
	var $mask = $('#mask');

	//set display to block and opacity to 0 so we can use fadeTo
	$mask.css({
		'display': 'block',
		opacity: 0
	});
			
	//fade in the mask to opacity 0.8
	$mask.fadeTo(500, 0.8);

	//get the height and width of the modal
	var modal_height = $modal.outerHeight();
	var modal_width = $modal.outerWidth();
	
	var window_width = $(window).width();
	var window_height = $(window).height();

	//calculate top and left offset needed for centering
	var top = (window_height - modal_height) / 2;
	var left = (window_width - modal_width) / 2;
	
	//apply new top and left css values
	$modal.css({
		'top': top,
		'left': left
	});
			
	//show the modal window
	$modal.fadeIn(500);
	$mask.data('dont_close_on_click', $(this).hasClass('dont_close_on_click'));
		
	//remove scrolling on the body
	$('body').css('overflow', 'hidden');
});

$('.close-modal').live('click',function(){
	if ($('#mask').data('dont_close_on_click') && $(this).attr('id') == 'mask') 
		return;

	//hide the mask
	$('#mask').fadeOut(500);

	//hide modal window(s)
	$('.modal_window').fadeOut(500);

	//put back the scrolling on the body
	$('body').css('overflow', 'visible');

	return false;
});

// generic onload/onavailable methods
$("input#q").available(function() {
	// handle focus/blur events on input
	$(this).focus(function() { 
		$(this).addClass('qfocus'); // mainly for MSIE...
		if (homepage === true)
			$(this).val('');
	}).blur(function() {
		$(this).removeClass('qfocus'); // mainly for MSIE...
	}).focus();
	
	// handle submit
	$(this).closest("form").submit(function() {
		var query = $("input#q").val();
		if (query)
		{
			window.location = '/' + $.ilse.urlencode(query);
		}
		return false;
	});
});

// onload/onready code
$("#infobar").available(function() {
	var $infobar    = this;
	var is_homepage = typeof homepage == 'boolean' && homepage;

	// don't show suggestion on homepage
	if (! is_homepage)
	{
		$.ilse.spellcheck(function(suggestion) { 
			if (! suggestion)
				return;
			$infobar
				.show()
				.find(".suggestion .text a")
				.text(suggestion)
				.attr('href', encodeURI(suggestion))
				.closest('.snippet')
				.show();
		});
	}
	// show Wikipedia abstract...
	$infobar
		.show()
		.find(".snippet.wiki")
		.wikipedia((typeof homepage == 'boolean' && homepage) ? '' : $.ilse.query());
});

if(window.location.hash == '#demo') {
  $.getScript("/resources/js/ilse/demonstrator.js");
  switch(query) {
    case 'Danny de Munk':
      $.getScript("/resources/js/ilse/demonstration.js");
      break;
    case 'weer verkeer':
      $.getScript("/resources/js/ilse/demonstration2.js");
      break;
    default:
      $.getScript("/resources/js/ilse/demonstration3.js");
      break;
  } 
}



// mouseover fix for non link elements in MSIE
if($.browser.msie) {
  var colorBar = $('#style-change');
  
  colorBar.live('mouseenter', function() {
    $(this).css('cursor', 'pointer');
  });
}

/**
 * Twitter - http://twitter.com
 * Copyright (C) 2010 Twitter
 * Author: Dustin Diaz (dustin@twitter.com)
 *
 * V 2.2.5 Twitter search/profile/faves/list widget
 * http://twitter.com/widgets
 * For full documented source see http://twitter.com/javascripts/widgets/widget.js
 * Hosting and modifications of the original source IS allowed.
 *
 * Example usage:
   <script src="path/to/widget.js"></script>
   <script>
     new TWTR.Widget({
       type: 'search',
       search: "your search query", // includes all advanced search queries.
       width: 250,
       height: 350,
       interval: 6000,
       subject: "What's being said about...",
       title: "San Francisco",
       rpp: 30,
       footer: "Follow me",
       theme: {
         shell: {
           background: '#1deb25',
           color: '#ffffff'
         },
         tweets: {
           background: 'silver',
           color: 'blue',
           links: 'black'
         }
       },

       features: {
         avatars: true, // defaults to false for profile widget, but true for search & faves widget
         hashtags: true,
         timestamp: true,
         fullscreen: false, // ignores width and height and just goes full screen
         scrollbar: false,
         live: true,
         loop: true,
         behavior: 'default',
         dateformat: 'absolute', // defaults to relative (eg: 3 minutes ago)
         toptweets: true // only for search widget
       }
     }).render().start();
   </script>
 *
 */

/**
  * @namespace TWTR public namespace for Twitter widget
  */
TWTR = window.TWTR || {};

/**
  * add core functionality to JS
  * Sugar Arrays http://www.dustindiaz.com/basement/sugar-arrays.html
  */
if (!Array.forEach) {

  Array.prototype.filter = function(fn, thisObj) {
    var scope = thisObj || window;
    var a = [];
    for (var i=0, j=this.length; i < j; ++i) {
      if (!fn.call(scope, this[i], i, this)) {
        continue;
      }
      a.push(this[i]);
    }
    return a;
  };

  // sorta like inArray if used clever-like
  Array.prototype.indexOf = function(el, start) {
    var start = start || 0;

    for (var i=0; i < this.length; ++i) {
      if (this[i] === el) {
        return i;
      }
    }

    return -1;
  };
}

/* first, a few dependencies */
(function() {
  if (TWTR && TWTR.Widget) {
    // this is most likely to happen when people try to embed multiple
    // widgets on the same page and include this script again
    return;
  }

  /**
    * Basic Array methods
    */
  function each(a, fn, opt_scope) {
    for (var i=0, j=a.length; i < j; ++i) {
      fn.call(opt_scope || window, a[i], i, a);
    }
  }

  /**
    * Generic Animation utility to tween dom elements
    *
    * Copyright (c) 2009 Dustin Diaz & Twitter (http://www.dustindiaz.com)
    * MIT License
    */

  /**
    * @constructor Animate
    * @param {HTMLElement} el the element we want to animate
    * @param {String} prop the CSS property we will be animating
    * @param {Object} opts a configuration object
    * object properties include
    * from {Int}
    * to {Int}
    * time {Int} time in milliseconds
    * callback {Function}
    */
  function Animate(el, prop, opts) {
    this.el = el;
    this.prop = prop;
    this.from = opts.from;
    this.to = opts.to;
    this.time = opts.time;
    this.callback = opts.callback;
    this.animDiff = this.to - this.from;
  };

  /**
    * @static
    * @boolean
    * allows us to check if native CSS transitions are possible
    */
  Animate.canTransition = function() {
    var el = document.createElement('twitter');
    el.style.cssText = '-webkit-transition: all .5s linear;';
    return !!el.style.webkitTransitionProperty;
  }();

  /**
    * @private
    * @param {String} val the CSS value we will set on the property
    */
  Animate.prototype._setStyle = function(val) {
    switch (this.prop) {
      case 'opacity':
        this.el.style[this.prop] = val;
        this.el.style.filter = 'alpha(opacity=' + val * 100 + ')';
        break;

      default:
        this.el.style[this.prop] = val + 'px';
        break;
    };
  };

  /**
    * @private
    * this is the tweening function
    */
  Animate.prototype._animate = function() {
    var that = this;
    this.now = new Date();
    this.diff = this.now - this.startTime;

    if (this.diff > this.time) {
      this._setStyle(this.to);

      if (this.callback) {
        this.callback.call(this);
      }
      clearInterval(this.timer);
      return;
    }

    this.percentage = (Math.floor((this.diff / this.time) * 100) / 100);
    this.val = (this.animDiff * this.percentage) + this.from;
    this._setStyle(this.val);
  };

  /**
    * @public
    * begins the animation
    */
  Animate.prototype.start = function() {
    var that = this;
    this.startTime = new Date();

    this.timer = setInterval(function() {
      that._animate.call(that);
    }, 15);
  };


  /**
    * @constructor
    * Widget Base for new instances of the Twitter search widget
    * @param {Object} opts the configuration options for the widget
    */
  TWTR.Widget = function(opts) {
    this.init(opts);
  };

  (function() {


    // Internal Namespace.
    var twttr = {};

    var isHttps = location.protocol.match(/https/);
    var httpsImageRegex = /^.+\/profile_images/;
    var httpsImageReplace = 'https://s3.amazonaws.com/twitter_production/profile_images';

    // cache object for searching duplicates
    var reClassNameCache = {};

    // reusable regex for searching classnames
    var getClassRegEx = function(c) {

      // check to see if regular expression already exists
      var re = reClassNameCache[c];

      if (!re) {
        re = new RegExp('(?:^|\\s+)' + c + '(?:\\s+|$)');
        reClassNameCache[c] = re;
      }

      return re;
    };

    var getByClass = function(c, tag, root, apply) {
      var tag = tag || '*';
      var root = root || document;

      var nodes = [],
          elements = root.getElementsByTagName(tag),
          re = getClassRegEx(c);

      for (var i = 0, len = elements.length; i < len; ++i) {
        if (re.test(elements[i].className)) {
          nodes[nodes.length] = elements[i];

          if (apply) {
            apply.call(elements[i], elements[i]);
          }

        }
      }

      return nodes;
    };

    var browser = function() {
      var ua = navigator.userAgent;
      return {
        ie: ua.match(/MSIE\s([^;]*)/)
      };
    }();

    var byId = function(id) {
      if (typeof id == 'string') {
        return document.getElementById(id);
      }
      return id;
    };

    var trim = function(str) {
      return str.replace(/^\s+|\s+$/g, '')
    };

    var getViewportHeight = function() {
      var height = self.innerHeight; // Safari, Opera
      var mode = document.compatMode;
      if ((mode || browser.ie)) { // IE, Gecko
        height = (mode == 'CSS1Compat') ?
          document.documentElement.clientHeight : // Standards
          document.body.clientHeight; // Quirks
      }
      return height;
    };

    var getTarget = function(e, resolveTextNode) {
      var target = e.target || e.srcElement;
      return resolveTextNode(target);
    };

    var resolveTextNode = function(el) {
      try {
        if (el && 3 == el.nodeType) {
          return el.parentNode;
        } else {
          return el;
        }
      } catch (ex) { }
    };

    var getRelatedTarget = function(e) {
      var target = e.relatedTarget;
      if (!target) {
        if (e.type == 'mouseout') {
          target = e.toElement;
        }
        else if (e.type == 'mouseover') {
          target = e.fromElement;
        }
      }
      return resolveTextNode(target);
    };

    var insertAfter = function(el, reference) {
      reference.parentNode.insertBefore(el, reference.nextSibling);
    };

    var removeElement = function(el) {
      try {
        el.parentNode.removeChild(el);
      }
      catch (ex) { }
    };

    var getFirst = function(el) {
      return el.firstChild;
    };

    var withinElement = function(e) {
      var parent = getRelatedTarget(e);
      while (parent && parent != this) {
        try {
          parent = parent.parentNode;
        }
        catch(ex) {
          parent = this;
        }
      }
      if (parent != this) {
        return true;
      }
      return false;
    };

    var getStyle = function() {
      if (document.defaultView && document.defaultView.getComputedStyle) {
        return function(el, property) {
          var value = null;
          var computed = document.defaultView.getComputedStyle(el, '');
          if (computed) {
            value = computed[property];
          }
          var ret = el.style[property] || value;
          return ret;
        };
      }
      else if (document.documentElement.currentStyle && browser.ie) { // IE method
        return function(el, property) {
          var value = el.currentStyle ? el.currentStyle[property] : null;
          return (el.style[property] || value);
        };
      }
    }();

    /**
      * classes object
      * - has - add - remove
      */
    var classes = {
      has: function(el, c) {
        return new RegExp("(^|\\s)" + c + "(\\s|$)").test(byId(el).className);
      },

      add: function(el, c) {
        if (!this.has(el, c)) {
          byId(el).className = trim(byId(el).className) + ' ' + c;
        }
      },

      remove: function(el, c) {
        if (this.has(el, c)) {
          byId(el).className = byId(el).className.replace(new RegExp("(^|\\s)" + c + "(\\s|$)", "g"), "");
        }
      }
    };

    /**
      * basic x-browser event listener util
      * eg: events.add(element, 'click', fn);
      */
    var events = {
      add: function(el, type, fn) {
        if (el.addEventListener) {
          el.addEventListener(type, fn, false);
        }
        else {
          el.attachEvent('on' + type, function() {
            fn.call(el, window.event);
          });
        }
      },
      remove: function(el, type, fn) {
        if (el.removeEventListener) {
          el.removeEventListener(type, fn, false);
        }
        else {
          el.detachEvent('on' + type, fn);
        }
      }
    };

    var hex_rgb = function() {

      function HexToR(h) {
        return parseInt((h).substring(0,2),16);
      }
      function HexToG(h) {
        return parseInt((h).substring(2,4),16);
      }
      function HexToB(h) {
        return parseInt((h).substring(4,6),16);
      }

      return function(hex) {
        return [HexToR(hex), HexToG(hex), HexToB(hex)];
      };

    }();

    /**
      * core type detection on javascript objects
      */
    var is = {
      bool: function(b) {
        return typeof b === 'boolean';
      },

      def: function(o) {
        return !(typeof o === 'undefined');
      },

      number: function(n) {
        return typeof n === 'number' && isFinite(n);
      },
      string: function(s) {
        return typeof s === 'string';
      },

      fn: function(f) {
        return typeof f === 'function';
      },

      array: function(a) {
        if (a) {
          return is.number(a.length) && is.fn(a.splice);
        }
        return false;
      }
    };

    var months = ['January', 'February', 'March', 'April', 'May', 'June', 'July', 'August', 'September', 'October', 'November', 'December'];

    var absoluteTime = function(s) {
      var d = new Date(s);
      if (browser.ie) {
        d = Date.parse(s.replace(/( \+)/, ' UTC$1'));
      }
      var ampm = '';
      var hour = function() {
        var h = d.getHours();
        if (h > 0 && h < 13) {
          ampm = 'am';
          return h;
        }
        else if (h < 1) {
          ampm = 'am';
          return 12;
        }
        else {
          ampm = 'pm';
          return h - 12;
        }
      }();
      var minutes = d.getMinutes();
      var seconds = d.getSeconds();
      function getRest() {
        var today = new Date();
        if (today.getDate() != d.getDate() || today.getYear() != d.getYear() || today.getMonth() != d.getMonth()) {
          return ' - ' + months[d.getMonth()] + ' ' + d.getDate() + ', ' + d.getFullYear();
        }
        else {
          return '';
        }
      }
      return hour + ':' + minutes + ampm + getRest();
    };

    /**
      * relative time calculator
      * @param {string} twitter date string returned from Twitter API
      * @return {string} relative time like "2 minutes ago"
      */
    var timeAgo = function(dateString) {
      var rightNow = new Date();
      var then = new Date(dateString);

      if (browser.ie) {
        // IE can't parse these crazy Ruby dates
        then = Date.parse(dateString.replace(/( \+)/, ' UTC$1'));
      }

      var diff = rightNow - then;

      var second = 1000,
          minute = second * 60,
          hour = minute * 60,
          day = hour * 24,
          week = day * 7;

      if (isNaN(diff) || diff < 0) {
        return ""; // return blank string if unknown
      }

      if (diff < second * 2) {
        // within 2 seconds
        return "zojuist";
      }

      if (diff < minute) {
        return Math.floor(diff / second) + " seconden geleden";
      }

      if (diff < minute * 2) {
        return "ongeveer 1 minuut geleden";
      }

      if (diff < hour) {
        return Math.floor(diff / minute) + " minuten geleden";
      }

      if (diff < hour * 2) {
        return "ongeveer 1 uur geleden";
      }

      if (diff < day) {
        return  Math.floor(diff / hour) + " uur geleden";
      }

      if (diff > day && diff < day * 2) {
        return "gisteren";
      }

      if (diff < day * 365) {
        return Math.floor(diff / day) + " dagen geleden";
      }

      else {
        return "meer dan een jaar geleden";
      }

    };

    /**
      * The Twitalinkahashifyer!
      * http://www.dustindiaz.com/basement/ify.html
      * Eg:
      * ify.clean('your tweet text');
      */


    var ify = {
      link: function(tweet) {
        return tweet.replace(/\b(((https*\:\/\/)|www\.)[^\"\']+?)(([!?,.\)]+)?(\s|$))/g, function(link, m1, m2, m3, m4) {
          var http = m2.match(/w/) ? 'http://' : '';
          return '<a class="twtr-hyperlink" target="_blank" href="' + http + m1 + '">' + ((m1.length > 25) ? m1.substr(0, 24) + '...' : m1) + '</a>' + m4;
        });
      },

      at: function(tweet) {
        return tweet.replace(/\B[@＠]([a-zA-Z0-9_]{1,20})/g, function(m, username) {
          return '@<a target="_blank" class="twtr-atreply" href="http://twitter.com/' + username + '">' + username + '</a>';
        });
      },

      list: function(tweet) {
        return tweet.replace(/\B[@＠]([a-zA-Z0-9_]{1,20}\/\w+)/g, function(m, userlist) {
          return '@<a target="_blank" class="twtr-atreply" href="http://twitter.com/' + userlist + '">' + userlist + '</a>';
        });
      },

      hash: function(tweet) {
        return tweet.replace(/(^|\s+)#(\w+)/gi, function(m, before, hash) {
          return before + '<a target="_blank" class="twtr-hashtag" href="http://twitter.com/search?q=%23' + hash + '">#' + hash + '</a>';
        });
      },

      clean: function(tweet) {
        return this.hash(this.at(this.list(this.link(tweet))));
      }
    };


    /**
      * @constructor the classic twitter occasional job
      * @param {Function} job The job to execute upon each request
      * @param {Function} decay The deciding boolean method on whether to decay
      * @param {Int} interval The number in milliseconds to wait before executing
      */
    function Occasionally(job, decayFn, interval) {
      this.job = job;
      this.decayFn = decayFn;
      this.interval = interval;
      this.decayRate = 1;
      this.decayMultiplier = 1.25;
      this.maxDecayTime = 3 * 60 * 1000; // 3 minutes
    }

    Occasionally.prototype = {

      /**
        * @public
        * @return self
        * starts our occasional job
        */
      start: function() {
        this.stop().run();
        return this;
      },

      /**
        * @public
        * @return self
        * stops the occasional job
        */
      stop: function() {
        if (this.worker) {
          window.clearTimeout(this.worker);
        }
        return this;
      },

      /**
        * @private
        */
      run: function() {
        var that = this;
        this.job(function() {
          // running our decayer callback
          that.decayRate = that.decayFn() ? Math.max(1, that.decayRate / that.decayMultiplier)
                                          : that.decayRate * that.decayMultiplier;

          var expire = that.interval * that.decayRate;
          expire = (expire >= that.maxDecayTime) ? that.maxDecayTime : expire;
          expire = Math.floor(expire);

          that.worker = window.setTimeout(
            function () {
              that.run.call(that);
            },
            expire
          );

        });
      },

      /**
        * @public
        * @return self
        * stops occasional job and resets object
        */
      destroy: function() {
        this.stop();
        this.decayRate = 1;
        return this;
      }
    };

    /**
      * @Constructor runs a timer on an array passing back
      *              the next needle on each interval
      * @param haystack {Array}
      * @param time {Int} time in ms
      * @param loop {Bool} does this continue forever?
      * @param callback {Function} method that is passed back a needle for each interval
      */
    function IntervalJob(time, loop, callback) {
      this.time = time || 6000;
      this.loop = loop || false;
      this.repeated = 0;
      this.callback = callback;
      this.haystack = [];
    };

    IntervalJob.prototype = {

      set: function(haystack) {
        this.haystack = haystack;
      },

      add: function(needle) {
        this.haystack.unshift(needle);
      },

      /**
        * @public
        * @return self
        * begins the interval job
        */
      start: function() {
        if (this.timer) {
          return this;
        }
        this._job();
        var that = this;
        this.timer = setInterval(
          function() {
            that._job.call(that);
          }, this.time
        );

        return this;
      },

      /**
        * @public
        * @return self
        * stops the interval
        */
      stop: function() {
        if (this.timer) {
          window.clearInterval(this.timer);
          this.timer = null;
        }

        return this;
      },

      /**
        * @private
        */
      _next: function() {
        var old = this.haystack.shift();
        if (old && this.loop) {
          this.haystack.push(old);
        }
        return old || null;
      },

      /**
        * @private
        */
      _job: function() {
        var next = this._next();
        if (next) {
          this.callback(next);
        }

        return this;
      }

    };

    function Tweet(tweet) {
      function showPopular() {
        if (tweet.needle.metadata && tweet.needle.metadata.result_type && tweet.needle.metadata.result_type == 'popular') {
          return '<span class="twtr-popular">' + tweet.needle.metadata.recent_retweets + '+ recent retweets</span>';
        } else {
          return '';
        }
      }
      if (isHttps) {
        tweet.avatar = tweet.avatar.replace(httpsImageRegex, httpsImageReplace);
      }
      var html = '<div class="twtr-tweet-wrap"> \
        <div class="twtr-avatar"> \
          <div class="twtr-img"><a target="_blank" href="http://twitter.com/' + tweet.user + '"><img alt="' + tweet.user + ' profile" src="' + tweet.avatar + '"></a></div> \
        </div> \
        <div class="twtr-tweet-text"> \
          <p> \
            <a target="_blank" href="http://twitter.com/' + tweet.user + '" class="twtr-user">' + tweet.user + '</a> ' + tweet.tweet + ' \
            <em>\
            <a target="_blank" class="twtr-timestamp" time="' + tweet.timestamp + '" href="http://twitter.com/' + tweet.user + '/status/' + tweet.id + '">' + tweet.created_at + '</a> \
            <a target="_blank" class="twtr-reply" href="http://twitter.com/?status=@' + tweet.user + '%20&in_reply_to_status_id=' + tweet.id + '&in_reply_to=' + tweet.user + '">reageer</a> \
            </em> ' + showPopular() + ' \
          </p> \
        </div> \
      </div>';

      var div = document.createElement('div');

			div.id = 'tweet-id-' + (++Tweet._tweetCount);
      div.className = 'twtr-tweet';
      div.innerHTML = html;
      this.element = div;
    };

    // static count so all tweets (even on multiple inst widgets) will have unique ids
    Tweet._tweetCount = 0;

      twttr.loadStyleSheet = function(url, widgetEl) {
        if (!TWTR.Widget.loadingStyleSheet) {
          TWTR.Widget.loadingStyleSheet = true;
          var linkElement = document.createElement('link');
          linkElement.href = url;
          linkElement.rel = 'stylesheet';
          linkElement.type = 'text/css';
          document.getElementsByTagName('head')[0].appendChild(linkElement);
          var timer = setInterval(function() {
            var style = getStyle(widgetEl, 'position');
            if (style == 'relative') {
              clearInterval(timer);
              timer = null;
              TWTR.Widget.hasLoadedStyleSheet = true;
            }
          }, 50);
        }
      };

    (function() {

      var isLoaded = false;
      twttr.css = function(rules) {
        var styleElement = document.createElement('style');
        styleElement.type = 'text/css';
        if (browser.ie) {
          styleElement.styleSheet.cssText = rules;
        }
        else {
          var frag = document.createDocumentFragment();
          frag.appendChild(document.createTextNode(rules));
          styleElement.appendChild(frag);
        }
        function append() {
          document.getElementsByTagName('head')[0].appendChild(styleElement);
        }

        // oh IE we love you.
        // this is needed because you can't modify document body when page is loading
        if (!browser.ie || isLoaded) {
          append();
        }
        else {
          window.attachEvent('onload', function() {
            isLoaded = true;
            append();
          });
        }
      };
    })();


    TWTR.Widget.isLoaded = false;
    TWTR.Widget.loadingStyleSheet = false;
    TWTR.Widget.hasLoadedStyleSheet = false;
    TWTR.Widget.WIDGET_NUMBER = 0;
    TWTR.Widget.matches = {
      mentions: /^@[a-zA-Z0-9_]{1,20}\b/,
      any_mentions: /\b@[a-zA-Z0-9_]{1,20}\b/
    };

    TWTR.Widget.jsonP = function(url, callback) {
      var script = document.createElement('script');
      script.type = 'text/javascript';
      script.src = url;
      document.body.insertBefore(script, document.body.firstChild)
      callback(script);
      return script;
    };

    TWTR.Widget.prototype = function() {

      var http = isHttps ? 'https://' : 'http://';
      var base = http + 'search.twitter.com/search.';

      var profileBase = http + 'api.twitter.com/1/statuses/user_timeline.';
      var favBase = http + 'twitter.com/favorites/';
      var listBase = http + 'twitter.com/';
      var occasionalInterval = 25000; // 20 seconds
      var defaultAvatar = isHttps ? 'https://twitter-widgets.s3.amazonaws.com/j/1/default.gif' : 'http://widgets.twimg.com/j/1/default.gif';

      return {
        init: function(opts) {
          var that = this;
          // first, define public callback for this widget
          this._widgetNumber = ++TWTR.Widget.WIDGET_NUMBER;
          TWTR.Widget['receiveCallback_' + this._widgetNumber] = function(resp) {
            that._prePlay.call(that, resp);
          };
          this._cb = 'TWTR.Widget.receiveCallback_' + this._widgetNumber;
          this.opts = opts;
          this._base = base;
          this._isRunning = false;
          this._hasOfficiallyStarted = false;
          this._hasNewSearchResults = false;
          this._rendered = false;
          this._profileImage = false;
          this._isCreator = !!opts.creator;

          this._setWidgetType(opts.type);

          this.timesRequested = 0;
          this.runOnce = false;
          this.newResults = false;
          this.results = [];
          this.jsonMaxRequestTimeOut = 19000;
          this.showedResults = [];
          this.sinceId = 1;
          this.source = 'TWITTERINC_WIDGET';
          this.id = opts.id || 'twtr-widget-' + this._widgetNumber;

          this.tweets = 0;
          this.setDimensions(opts.width, opts.height);
          this.interval = opts.interval || 6000;
          this.format = 'json';
          this.rpp = opts.rpp || 50;
          this.subject = opts.subject || '';
          this.title = opts.title || '';
          this.setFooterText(opts.footer);

          this.setSearch(opts.search);
          this._setUrl();
          this.theme = opts.theme ? opts.theme : this._getDefaultTheme();

          if (!opts.id) {
            document.write('<div class="twtr-widget" id="' + this.id + '"></div>');
          }
          this.widgetEl = byId(this.id);
          if (opts.id) {
            classes.add(this.widgetEl, 'twtr-widget');
          }

          if (opts.version >= 2 && !TWTR.Widget.hasLoadedStyleSheet) {
            if (isHttps) {
              twttr.loadStyleSheet('https://twitter-widgets.s3.amazonaws.com/j/2/widget.css', this.widgetEl);
            } else if (opts.creator) {
              twttr.loadStyleSheet('/stylesheets/widgets/widget.css', this.widgetEl);
            } else {
              twttr.loadStyleSheet('http://widgets.twimg.com/j/2/widget.css', this.widgetEl);
            }
          }

          this.occasionalJob = new Occasionally(
            function(decay) {
              that.decay = decay;
              that._getResults.call(that);
            },

            function() {
              return that._decayDecider.call(that);
            },

            occasionalInterval
          );

          this._ready = is.fn(opts.ready) ? opts.ready : function() { };

          // preset features
          this._isRelativeTime = true;
          this._tweetFilter = false;
          this._avatars = true;
          this._isFullScreen = false;
          this._isLive = true;
          this._isScroll = false;
          this._loop = true;
          this._showTopTweets = (this._isSearchWidget) ? true : false;
          this._behavior = 'default';
          this.setFeatures(this.opts.features);

          this.intervalJob = new IntervalJob(this.interval, this._loop, function(tweet) {
            that._normalizeTweet(tweet);
          });

          return this;
        },

        /**
          * @public
          * @param {Int} w - width for widget
          * @param {Int} h - height for widget
          * @return self
          */
        setDimensions: function(w, h) {
          this.wh = (w && h) ? [w, h] : [250, 300]; // default w/h if none provided
          if (w == 'auto' || w == '100%') {
            this.wh[0] = '100%';
          } else {
            this.wh[0] = ((this.wh[0] < 150) ? 150 : this.wh[0]) + 'px'; // min width is 150
          }
          this.wh[1] = ((this.wh[1] < 100) ? 100 : this.wh[1]) + 'px'; // min height is 100
          return this;
        },

        setRpp: function(rpp) {
          var rpp = parseInt(rpp);
          this.rpp = (is.number(rpp) && (rpp > 0 && rpp <= 100)) ? rpp : 30;
          return this;
        },

        /**
          * @private
          * @param {String} type the kind of widget you're instantiating
          * @return self
          */
        _setWidgetType: function(type) {
          this._isSearchWidget = false,
          this._isProfileWidget = false,
          this._isFavsWidget = false,
          this._isListWidget = false;
          switch(type) {
            case 'profile':
              this._isProfileWidget = true;
              break;
            case 'search':
              this._isSearchWidget = true,
              this.search = this.opts.search;
              break;
            case 'faves':
            case 'favs':
              this._isFavsWidget = true;
              break;
            case 'list':
            case 'lists':
              this._isListWidget = true;
              break;
          };
          return this;
        },

        /**
          * @public
          * @param {object}
          * @return self
          * allows implementer to set features which include:
          * - avatars {bool}
          * - timestamp {bool}
          * - hashtags {bool}
          * setting any of the previous properties will appropriately hide/show that feature
          * @example
          * WidgetInstance.setFeatures({ fullscreen: true, avatars: true, timestamp: false, hashtags: false }).render().start();
          * @return self
          */
        setFeatures: function(features) {

          if (features) {
            if (is.def(features.filters)) {
              this._tweetFilter = features.filters;
            }
            if (is.def(features.dateformat)) {
              this._isRelativeTime = !!(features.dateformat !== 'absolute')
            }

            if (is.def(features.fullscreen) && is.bool(features.fullscreen)) {
              if (features.fullscreen) {
                this._isFullScreen = true;
                this.wh[0] = '100%';
                this.wh[1] = (getViewportHeight() - 90) + 'px';
                var that = this;
                events.add(window, 'resize', function(e) {
                  that.wh[1] = getViewportHeight();
                  that._fullScreenResize();
                });
              }
            }

            if (is.def(features.loop) && is.bool(features.loop)) {
              this._loop = features.loop;
            }

            if (is.def(features.behavior) && is.string(features.behavior)) {
              switch (features.behavior) {
                case 'all':
                  this._behavior = 'all';
                  break;
                case 'preloaded':
                  this._behavior = 'preloaded';
                  break;
                default:
                  this._behavior = 'default';
                  break;
              };
            }

            if (is.def(features.toptweets) && is.bool(features.toptweets)) {
              this._showTopTweets = features.toptweets;
              var showTopTweet = (this._showTopTweets) ? 'inline-block' : 'none';
              twttr.css('#' + this.id + ' .twtr-popular { display: ' + showTopTweet + '; }');
            }

            if (!is.def(features.toptweets)) {
              this._showTopTweets = true;
              var showTopTweet = (this._showTopTweets) ? 'inline-block' : 'none';
              twttr.css('#' + this.id + ' .twtr-popular { display: ' + showTopTweet + '; }');
            }

            if (is.def(features.avatars) && is.bool(features.avatars)) {

              if (!features.avatars) {
                twttr.css('#' + this.id + ' .twtr-avatar, #' + this.id + ' .twtr-user { display: none; } ' +
                '#' + this.id + ' .twtr-tweet-text { margin-left: 0; }');
                this._avatars = false;
              } else {
                var margin = (this._isFullScreen) ? '90px' : '40px';
                twttr.css('#' + this.id + ' .twtr-avatar { display: block; } #' + this.id + ' .twtr-user { display: inline; } ' +
                '#' + this.id + ' .twtr-tweet-text { margin-left: ' + margin + '; }');
                this._avatars = true;
              }

            }
            else {
              if (this._isProfileWidget) {
                this.setFeatures({ avatars: false });
                this._avatars = false;
              }
              else {
                this.setFeatures({ avatars: true });
                this._avatars = true;
              }
            }

            if (is.def(features.hashtags) && is.bool(features.hashtags)) {
              (!features.hashtags) ?
                  twttr.css('#' + this.id + ' a.twtr-hashtag { display: none; }') : '';
            }

            if (is.def(features.timestamp) && is.bool(features.timestamp)) {
              var display = features.timestamp ? 'block' : 'none';
              twttr.css('#' + this.id + ' em { display: ' + display + '; }');
            }

            if (is.def(features.live) && is.bool(features.live)) {
              this._isLive = features.live;
            }
            if (is.def(features.scrollbar) && is.bool(features.scrollbar)) {
              this._isScroll = features.scrollbar;
            }

          }

          else {

            if (this._isProfileWidget) {
              this.setFeatures({ avatars: false });
              this._avatars = false;
            }
            if (this._isProfileWidget || this._isFavsWidget) {
              this.setFeatures({ behavior: 'all' });
            }

          }
          return this;
        },

        /**
          * @private
          * @param e Event listener for window resizing
          */
        _fullScreenResize: function() {
          var timeline = getByClass('twtr-timeline', 'div', document.body, function(el) {
            el.style.height = (getViewportHeight() - 90) + 'px';
          });
        },

        /**
          * @public facade
          * @param {int} in seconds
          * convenience method for setting time between each tweet render
          * @return self
          */
        setTweetInterval: function(interval) {
          this.interval = interval;
          return this;
        },

        /**
          * @public
          * @param {string} url
          * sets a url base for the JSONP call
          * useful for future API implementations or moderation platforms
          * @return self
          */
        setBase: function(b) {
          this._base = b;
          return this;
        },

        /**
          * @public
          * @param {string} username
          * used to distinguish a "favs" widget
          * @return self
          */
        setUser: function(username, opt_realname) {
          this.username = username;
          this.realname = opt_realname || ' ';
          if (this._isFavsWidget) {
            this.setBase(favBase + username + '.');
          }
          else if (this._isProfileWidget) {
            this.setBase(profileBase + this.format + '?screen_name=' + username);
          }
          this.setSearch(' ');
          return this;
        },

        /**
          * @public
          * @param {string} username - the owner of the list
          * @param {string} listName - the name of the list
          * return self
          */
        setList: function(username, listname) {
          this.listslug = listname.replace(/ /g, '-').toLowerCase();
          this.username = username;
          this.setBase(listBase + username + '/lists/' + this.listslug + '/statuses.');
          this.setSearch(' ');
          return this;
        },

        /**
          * @public
          * @param {string}
          * sets the profile image source to display in the widget
          * @return self
          */
        setProfileImage: function(url) {
          this._profileImage = url;
          this.byClass('twtr-profile-img', 'img').src = isHttps ? url.replace(httpsImageRegex, httpsImageReplace) : url;
          this.byClass('twtr-profile-img-anchor', 'a').href = 'http://twitter.com/' + this.username;
          return this;
        },

        /**
          * @public
          * @param {string}
          * sets the main title to display at top of widget
          * @return self
          */
        setTitle: function(title) {
          this.title = title;
          this.widgetEl.getElementsByTagName('h3')[0].innerHTML = this.title;
          return this;
        },

        /**
          * @public
          * @param {string}
          * sets the main caption to display at top of widget (below title)
          * @return self
          */
        setCaption: function(subject) {
          this.subject = subject;
          this.widgetEl.getElementsByTagName('h4')[0].innerHTML = this.subject;
          return this;
        },

        /**
          * @public
          * @param {string}
          * sets the footer text
          * @return self
          */
        setFooterText: function(s) {
          this.footerText = (is.def(s) && is.string(s)) ? s : 'Join the conversation';
          if (this._rendered) {
            this.byClass('twtr-join-conv', 'a').innerHTML = this.footerText;
          }
          return this;
        },

        /**
          * @public
          * @param {string}
          * @return self
          * does double time. sets the search terms, and sets the appropriate
          * hyper reference on bottom anchor if widget has been rendered
          */
        setSearch: function(s) {
          this.searchString = s || '';
          this.search = encodeURIComponent(this.searchString);
          this._setUrl();
          if (this._rendered) {
            var anchor = this.byClass('twtr-join-conv', 'a');
            anchor.href = 'http://twitter.com/' + this._getWidgetPath();
          }

          return this;
        },

        _getWidgetPath: function() {
          if (this._isProfileWidget) {
            return this.username;
          }
          else if (this._isFavsWidget) {
            return this.username + '/favorites';
          }
          else if (this._isListWidget) {
            return this.username + '/lists/' + this.listslug;
          }
          else {
            return '#search?q=' + this.search;
          }
        },

        /**
          * @private
          * @return self
          * creates the proper URL to request data via JSONP
          */
        _setUrl: function() {
          var that = this;

          function cacheBust() {
            // chrome i hate your caching
            return '&' + (+new Date) + '=cachebust';
          }

          function showSince() {
            return (that.sinceId == 1) ? '' : '&since_id=' + that.sinceId + '&refresh=true';
          }

          if (this._isProfileWidget) {
            this.url = this._base + '&callback=' + this._cb +
                       '&include_rts=true' +
                       '&count=' + this.rpp + showSince() + '&clientsource=' + this.source;
          }

          else if (this._isFavsWidget || this._isListWidget) {
            this.url = this._base + this.format + '?callback=' + this._cb + showSince() +
                       '&include_rts=true' +
                       '&clientsource=' + this.source;
          }

          else {
            this.url = this._base + this.format + '?q=' + this.search +
                       '&include_rts=true' +
                       '&callback=' + this._cb +
                       '&rpp=' + this.rpp + showSince() + '&clientsource=' + this.source;
            if (!this.runOnce) {
              this.url += '&result_type=mixed';
            }
          }
          this.url += cacheBust();
          return this;
        },

        /**
          * @private
          */
        _getRGB: function(hex) {
          return hex_rgb(hex.substring(1, 7));
        },

        /**
          * @public
          * @param {object}
          * @param {boolean} important whether to be important style
          * @return self
          * allows implementer to set their own theme.
          * theme object can be passed into contructor, or set here.
          * defaults to default theme properties when not set
          */
        setTheme: function(o, important) {
          var that = this;
          var imp = ' !important';

          var onCreator = ((window.location.hostname.match(/twitter\.com/)) && (window.location.pathname.match(/goodies/)));
          if (important || onCreator) {
            imp = '';
          }
          this.theme = {
            shell: {
              background: function() {
                return o.shell.background || that._getDefaultTheme().shell.background;
              }(),

              color: function() {
                return o.shell.color || that._getDefaultTheme().shell.color;
              }()
            },

            tweets: {
              background: function() {
                return o.tweets.background || that._getDefaultTheme().tweets.background;
              }(),

              color: function() {
                return o.tweets.color || that._getDefaultTheme().tweets.color;
              }(),

              links: function() {
                return o.tweets.links || that._getDefaultTheme().tweets.links;
              }()
            }
          };

          var style = '#' + this.id + ' .twtr-doc, \
                     #' + this.id + ' .twtr-hd a, \
                     #' + this.id + ' h3, \
                     #' + this.id + ' h4, \
                     #' + this.id + ' .twtr-popular {\
            background-color: ' + this.theme.shell.background + imp + ';\
            color: ' + this.theme.shell.color + imp + ';\
          }\
          #' + this.id + ' .twtr-popular {\
            color: ' + this.theme.tweets.color + imp + ';\
            background-color: rgba(' + this._getRGB(this.theme.shell.background) + ', .3)' + imp + ';\
          }\
          #' + this.id + ' .twtr-tweet a {\
            color: ' + this.theme.tweets.links + imp + ';\
          }\
          #' + this.id + ' .twtr-bd, #' + this.id + ' .twtr-timeline i a, \
          #' + this.id + ' .twtr-bd p {\
            color: ' + this.theme.tweets.color + imp + ';\
          }\
          #' + this.id + ' .twtr-new-results, \
          #' + this.id + ' .twtr-results-inner, \
          #' + this.id + ' .twtr-timeline {\
            background: ' + this.theme.tweets.background + imp + ';\
          }';

          if (browser.ie) {
            style += '#' + this.id + ' .twtr-tweet { background: ' + this.theme.tweets.background + imp + '; }';
          }

          twttr.css(style);
          return this;
        },

        /**
          * @public
          * @param {string} classname
          * @param {string} tagname
          * @param optional {bool} whether to return collection or defaults to first match
          * @return HTML Element || Array HTML Elements
          * helper to get elements by classname based on the widget being the context
          */
        byClass: function(c, tag, opt_all) {
          var collection = getByClass(c, tag, byId(this.id));
          return (opt_all) ? collection : collection[0];
        },

        /**
          * @public
          * @return self
          * renders the widget onto an HTML page
          */
        render: function() {
          var that = this;

          if (!TWTR.Widget.hasLoadedStyleSheet) {
            window.setTimeout(function() {
              that.render.call(that);
            }, 50);
            return this;
          }

          this.setTheme(this.theme, this._isCreator);

          if (this._isProfileWidget) {
            classes.add(this.widgetEl, 'twtr-widget-profile');
          }

          if (this._isScroll) {
            classes.add(this.widgetEl, 'twtr-scroll')
          }
          if (!this._isLive && !this._isScroll) {
            this.wh[1] = 'auto';
          }
          if (this._isSearchWidget && this._isFullScreen) {
            document.title = 'Twitter search: ' + escape(this.searchString);
          }
          this.widgetEl.innerHTML = this._getWidgetHtml();
          var timeline = this.byClass('twtr-timeline', 'div');
          if (this._isLive && !this._isFullScreen) {
            var over = function(e) {
              if (that._behavior === 'all') {
                return;
              }
              if (withinElement.call(this, e)) {
                that.pause.call(that);
              }
            };
            var out = function(e) {
              if (that._behavior === 'all') {
                return;
              }
              if (withinElement.call(this, e)) {
                that.resume.call(that);
              }
            };

            this.removeEvents = function() {
              events.remove(timeline, 'mouseover', over);
              events.remove(timeline, 'mouseout', out);
            };
            events.add(timeline, 'mouseover', over);
            events.add(timeline, 'mouseout', out);
          }
          this._rendered = true;
          // call the ready handler
          this._ready();
          return this;
        },

        /**
          * empty placeholder for removing events
          * on live widgets
          */
        removeEvents: function() { },

        /**
          * @private
          * @return {object} theme
          */
        _getDefaultTheme: function() {
          return {
            shell: {
              background: '#8ec1da',
              color: '#ffffff'
            },

            tweets: {
              background: '#ffffff',
              color: '#444444',
              links: '#1985b5'
            }

          };
        },

        /**
          * @private
          * @return {string}
          * builds an HTML string that represents the widget chrome
          */
        _getWidgetHtml: function() {
          var that = this;

          function getHeader() {
            if (that._isProfileWidget) {
              return '<a target="_blank" href="http://twitter.com/" class="twtr-profile-img-anchor"><img alt="profile" class="twtr-profile-img" src="' + defaultAvatar + '"></a>\
                      <h3></h3>\
                      <h4></h4>';
            }
            else {
              return '<h3>' + that.title + '</h3><h4>' + that.subject + '</h4>';
            }
          }

          function isFull() {
            return that._isFullScreen ? ' twtr-fullscreen' : '';
          }

          var logo = isHttps ? 'https://twitter-widgets.s3.amazonaws.com/i/widget-logo.png' : 'http://widgets.twimg.com/i/widget-logo.png';

          if (this._isFullScreen) {
            logo = 'https://twitter-widgets.s3.amazonaws.com/i/widget-logo-fullscreen.png';
          }

          var html = '<div class="twtr-doc' + isFull() + '" style="width: ' + this.wh[0] + ';">\
            <div class="twtr-hd">' + getHeader() + ' \
            </div>\
            <div class="twtr-bd">\
              <div class="twtr-timeline" style="height: ' + this.wh[1] + ';">\
                <div class="twtr-tweets">\
                  <div class="twtr-reference-tweet"></div>\
                  <!-- tweets show here -->\
                </div>\
              </div>\
            </div>\
            <div class="twtr-ft">\
              <div><a target="_blank" href="http://twitter.com"><img alt="" src="' + logo + '"></a>\
                <span><a target="_blank" class="twtr-join-conv" style="color:' + this.theme.shell.color + '" href="http://twitter.com/' + this._getWidgetPath() + '">' + this.footerText + '</a></span>\
              </div>\
            </div>\
          </div>';

          return html;
        },

        /**
          * @private
          * @return self
          * puts the tweet in the dom
          */
        _appendTweet: function(el) {
          this._insertNewResultsNumber();
          insertAfter(el, this.byClass('twtr-reference-tweet', 'div'));
          return this;
        },

        /**
          * @private
          * @return self
          * slides in a rendered tweet
          */
        _slide: function(el) {
          var that = this;
          var height = getFirst(el).offsetHeight;
          if (this.runOnce) {
            new Animate(el, 'height', {
              from: 0,
              to: height,
              time: 500,
              callback: function() {
                that._fade.call(that, el);
              }
            }).start();
          }
          return this;
        },

        /**
          * @private
          * @return self
          * fades in a rendered tweet
          */
        _fade: function(el) {
          var that = this;

          if (Animate.canTransition) {
            el.style.webkitTransition = 'opacity 0.5s ease-out';
            el.style.opacity = 1;
            return this;
          }
          new Animate(el, 'opacity', {
            from: 0,
            to: 1,
            time: 500
          }).start();
          return this;
        },

        /**
          * @private
          * @return self
          * removes the last tweet if it is offscreen
          */
        _chop: function() {
          if (this._isScroll) {
            return this;
          }
          var tweets = this.byClass('twtr-tweet', 'div', true);
          var resultUpdates = this.byClass('twtr-new-results', 'div', true);
          if (tweets.length) {
            for (var i=tweets.length - 1; i >=0; i--) {
              var tweet = tweets[i];
              var top = parseInt(tweet.offsetTop);
              if (top > parseInt(this.wh[1])) {
                removeElement(tweet);
              } else {
                break;
              }
            }


            if (resultUpdates.length > 0) {
              var result = resultUpdates[resultUpdates.length - 1];
              var resultTop = parseInt(result.offsetTop);
              if (resultTop > parseInt(this.wh[1])) {
                removeElement(result);
              }
            }
          }

          return this;
        },

        /**
          * @private
          * @return self
          * Big Facade for chop, append, slide, and fade
          */
        _appendSlideFade: function(opt_element) {
          var el = opt_element || this.tweet.element;
          this
            ._chop()
            ._appendTweet(el)
            ._slide(el);
          return this;
        },

        /**
          * @private
          * @return self
          * generates the HTML for a single tweet item
          */
        _createTweet: function(o) {
          o.timestamp = o.created_at;
          o.created_at = this._isRelativeTime ? timeAgo(o.created_at) : absoluteTime(o.created_at);
          this.tweet = new Tweet(o);
          if (this._isLive && this.runOnce) {
            this.tweet.element.style.opacity = 0;
            this.tweet.element.style.filter = 'alpha(opacity:0)';
            this.tweet.element.style.height = '0';
          }
          return this;
        },

        /**
          * @private
          * @param {Function} callback function that receives the results
          * makes a jsonP call to twitter.com
          */
        _getResults: function() {
          var that = this;

          this.timesRequested++;
          this.jsonRequestRunning = true;

          this.jsonRequestTimer = window.setTimeout(function() {

            if (that.jsonRequestRunning) {
              clearTimeout(that.jsonRequestTimer);
              that.jsonRequestTimer = null;
            }

            that.jsonRequestRunning = false;
            removeElement(that.scriptElement);
            that.newResults = false;
            that.decay();
          }, this.jsonMaxRequestTimeOut);
          TWTR.Widget.jsonP(that.url, function(script) {
            that.scriptElement = script;
          });

        },

        /**
          * @public
          * @return self
          * clears out the tweet space. used internally,
          * but free to use publicly
          */
        clear: function() {
          var tweets = this.byClass('twtr-tweet', 'div', true);
          var results = this.byClass('twtr-new-results', 'div', true);
          tweets = tweets.concat(results);
          each(tweets, function(el) {
            removeElement(el);
          });

          return this;
        },

        _sortByMagic: function(results) {
          var that = this;
          if (this._tweetFilter) {
            if (this._tweetFilter.negatives) {
              results = results.filter(function(el) {
                if (!that._tweetFilter.negatives.test(el.text)) {
                  return el;
                }
              });
            }
            if (this._tweetFilter.positives) {
              results = results.filter(function(el) {
                if (that._tweetFilter.positives.test(el.text)) {
                  return el;
                }
              });
            }
          }
          switch (this._behavior) {
            case 'all':
              this._sortByLatest(results);
              break;
            case 'preloaded':
            default:
              this._sortByDefault(results);
              break;
          };

          if (this._isLive && this._behavior !== 'all') {
            this.intervalJob.set(this.results);
            this.intervalJob.start();
          }

          return this;
        },

        /**
          * @private
          * @return results
          * puts the toptweets for search widget at the top
          */
        _loadTopTweetsAtTop: function(results) {
          var regular = [],
              popular = [],
              arr = [];
          // top tweets
          each(results, function(el) {
            if (el.metadata && el.metadata.result_type && el.metadata.result_type == 'popular') {
              popular.push(el);
            } else {
              regular.push(el);
            }
          });
          var result = popular.concat(regular);
          return result;
        },

        _sortByLatest: function(results) {
          this.results = results;
          this.results = this.results.slice(0, this.rpp);
          this.results = this._loadTopTweetsAtTop(this.results);
          this.results.reverse();
          return this;
        },

        /**
          * @private
          * @return self
          * default sorting method which tracks views and loops
          */
        _sortByDefault: function(results) {
          var that = this;

          var getDater = function(dateString) {
            return new Date(dateString).getTime();
          };

          // merge new results with old
          this.results.unshift.apply(this.results, results);

          each(this.results, function(el) {
            if (!el.views) {
              el.views = 0;
            }
          });

          // sort by date
          this.results.sort(function(a, b) {
            if (getDater(a.created_at) > getDater(b.created_at)) {
              return -1;
            }
            else if (getDater(a.created_at) < getDater(b.created_at)) {
              return 1;
            }
            else {
              return 0;
            }
          });

          // now cut off the oldest
          this.results = this.results.slice(0, this.rpp);

          this.results = this._loadTopTweetsAtTop(this.results);
          var foo = this.results;

          // now sort by views
          this.results = this.results.sort(function(a, b) {
            if (a.views < b.views) {
              return -1;
            }
            else if (a.views > b.views) {
              return 1;
            }
            return 0;
          });

          if (!this._isLive) {
            this.results.reverse();
          }

        },

        /**
          * @private
          * @method prePlay does a pre-check against last result.
          * @param resp the JSON response from twitter JsonP API
          */
        _prePlay: function(resp) {
          if (this.jsonRequestTimer) {
            clearTimeout(this.jsonRequestTimer);
            this.jsonRequestTimer = null;
          }

          if (!browser.ie) {
            removeElement(this.scriptElement);
          }

          if (resp.error) {
            this.newResults = false;
          }

          else if (resp.results && resp.results.length > 0) {
            this.response = resp;

            this.newResults = true;
            this.sinceId = resp.max_id;

            this._sortByMagic(resp.results);
            if (this.isRunning()) {
              this._play();
            }

          }

          else if ((this._isProfileWidget || this._isFavsWidget || this._isListWidget) && is.array(resp) && resp.length && resp.length > 0) {

            this.newResults = true;

            if (!this._profileImage && this._isProfileWidget) {
              var name = resp[0].user.screen_name;
              this.setProfileImage(resp[0].user.profile_image_url);
              this.setTitle(resp[0].user.name);
              this.setCaption('<a target="_blank" href="http://twitter.com/' + name + '">' + name + '</a>');
            }

            this.sinceId = resp[0].id;

            this._sortByMagic(resp);

            if (this.isRunning()) {
              this._play();
            }

          }

          else {
            this.newResults = false;
          }

          this._setUrl();
          if (this._isLive) {
            this.decay();
          }

        },

        /**
          * @private
          * gets the ball rolling with a new widget
          * and resets the interval job
          */
        _play: function() {
          var that = this;
          if (this.runOnce) {
            this._hasNewSearchResults = true;
          }

          if (this._avatars) {
            this._preloadImages(this.results);
          }
          if (this._isRelativeTime && (this._behavior == 'all' || this._behavior == 'preloaded')) {
            each(this.byClass('twtr-timestamp', 'a', true), function(el) {
              el.innerHTML = timeAgo(el.getAttribute('time'));
            });
          }
          if (!this._isLive || this._behavior == 'all' || this._behavior == 'preloaded') {
            each(this.results, function(needle) {
              if (needle.retweeted_status) {
                needle = needle.retweeted_status;
              }

              if (that._isProfileWidget) {
                needle.from_user = needle.user.screen_name;
                needle.profile_image_url = needle.user.profile_image_url;
              }

              if (that._isFavsWidget || that._isListWidget) {
                needle.from_user = needle.user.screen_name;
                needle.profile_image_url = needle.user.profile_image_url;
              }

              that._createTweet({
                id: needle.id,
                user: needle.from_user,
                tweet: ify.clean(needle.text),
                avatar: needle.profile_image_url,
                created_at: needle.created_at,
                needle: needle
              });
              var el = that.tweet.element;
              (that._behavior == 'all') ? that._appendSlideFade(el) : that._appendTweet(el);
            });

            if (this._behavior != 'preloaded') {
              return this;
            }

          }

          return this;
        },

        _normalizeTweet: function(needle) {
          var that = this;
          needle.views++;

          if (this._isProfileWidget) {
            needle.from_user = that.username;
            needle.profile_image_url = needle.user.profile_image_url;
          }

          if (this._isFavsWidget || this._isListWidget) {
            needle.from_user = needle.user.screen_name;
            needle.profile_image_url = needle.user.profile_image_url;
          }

          if (this._isFullScreen) {
            needle.profile_image_url = needle.profile_image_url.replace(/_normal\./, '_bigger.');
          }

          this._createTweet({
            id: needle.id,
            user: needle.from_user,
            tweet: ify.clean(needle.text),
            avatar: needle.profile_image_url,
            created_at: needle.created_at,
            needle: needle
          })._appendSlideFade();

        },

        _insertNewResultsNumber: function() {
          if (!this._hasNewSearchResults) {
            this._hasNewSearchResults = false;
            return;
          }

          if (this.runOnce && this._isSearchWidget) {
            var newResultsTotal = this.response.total > this.rpp ? this.response.total : this.response.results.length;
            var plural = newResultsTotal > 1 ? 's' : '';
            var moreThan = (this.response.warning && this.response.warning.match(/adjusted since_id/)) ? 'more than' : '';
            var el = document.createElement('div');
            classes.add(el, 'twtr-new-results');
            el.innerHTML = '<div class="twtr-results-inner"> &nbsp; </div>' +
                           '<div class="twtr-results-hr"> &nbsp; </div><span>' + moreThan + ' <strong>' + newResultsTotal + '</strong> new tweet' + plural + '</span>';
            insertAfter(el, this.byClass('twtr-reference-tweet', 'div'));
            this._hasNewSearchResults = false;
          }
        },

        /**
          * @private
          * helps transitions to be smooth
          */
        _preloadImages: function(results) {
          if (this._isProfileWidget || this._isFavsWidget || this._isListWidget) {
            each(results, function(el) {
              var img = new Image();
              img.src = el.user.profile_image_url;
            });
          }

          else {
            each(results, function(el) {
              (new Image()).src = el.profile_image_url;
            });
          }

        },

        // FIXME: This seems like a bug in Occasionally.
        /**
          * @private
          * @return bool
          * tells the job whether to decay
          */
        _decayDecider: function() {
          var r = false;

          if (!this.runOnce) {
            this.runOnce = true;
            r = true;
          }

          else if (this.newResults) {
            r = true;
          }

          return r;
        },

        /**
          * @public
          * @return self
          * starts the cycle
          */
        start: function() {
          var that = this;
          if (!this._rendered) {
            setTimeout(function() {
              that.start.call(that);
            }, 50);
            return this;
          }
          if (!this._isLive) {
            this._getResults();
          }
          else {
            this.occasionalJob.start();
          }
          this._isRunning = true;
          this._hasOfficiallyStarted = true;
          return this;
        },

        /**
          * @public
          * @return self
          * stops the cycle
          */
        stop: function() {
          this.occasionalJob.stop();

          if (this.intervalJob) {
            this.intervalJob.stop();
          }

          this._isRunning = false;
          return this;
        },

        /**
          * @public
          * @return self
          * will pause the scrolling, but not stop polling for new results
          * useful for 'hover' interactions
          */
        pause: function() {
          if (this.isRunning() && this.intervalJob) {
            this.intervalJob.stop();
            classes.add(this.widgetEl, 'twtr-paused');
            this._isRunning = false;
          }

          if (this._resumeTimer) {
            clearTimeout(this._resumeTimer);
            this._resumeTimer = null;
          }

          return this;
        },

        /**
          * @public
          * @return self
          * it's like unpausing
          */
        resume: function() {
          var that = this;

          if (!this.isRunning() && this._hasOfficiallyStarted && this.intervalJob) {
            this._resumeTimer = window.setTimeout(function() {
              that.intervalJob.start();
              that._isRunning = true;
              classes.remove(that.widgetEl, 'twtr-paused');
            }, 2000);
          }

          return this;
        },

        /**
          * @public
          * @return bool
          * whether the widget is running
          */
        isRunning: function() {
          return this._isRunning;
        },

        /**
          * @public facade
          * @return self
          * convenience method to stop the cycle, then clear it out
          * widget can be reused if destroyed
          */
        destroy: function() {
          this.stop();
          this.clear();
          this.runOnce = false;
          this._hasOfficiallyStarted = false;
          this._profileImage = false;
          this._isLive = true;
          this._tweetFilter = false;
          this._isScroll = false;
          this.newResults = false;
          this._isRunning = false;
          this.sinceId = 1;
          this.results = [];
          this.showedResults = [];
          this.occasionalJob.destroy();

          if (this.jsonRequestRunning) {
            clearTimeout(this.jsonRequestTimer);
          }

          classes.remove(this.widgetEl, 'twtr-scroll');
          this.removeEvents();
          return this;
        }
      };
    }();
  })();
})(); // #end application closure

(function() {
	function isset(va) { return (typeof(va) != 'undefined'); }
  var default_dossier_name = "Home page";

  var Dossiers = function() { 
    this._cache_document_list         = {};
    this.handle_response              = $.proxy(this.handle_response, this);
    this.handle_response_and_callback = $.proxy(this.handle_response_and_callback, this);
		this.rpc													= new $.RPC();

		this.calls												= {};
  };

  Dossiers.prototype = {
    'trigger' : function(action, options) {
      $.event.trigger('dossiers-' + action, options);
    },
  
    'handle_document_list' : function(meta) {
      this.trigger('document-list', meta);
    },

    'handle_status' : function(user) {
      this.trigger('status', user);
    },

    'handle_dossier_list' : function(default_dossier, dossier_list) {
			/* remove deleted dossiers from the document cache */
			this._cache_document_list = $.grep(this._cache_document_list, function(k, dossier_id) {
				return $.grep(dossier_list, function (dossier) { 
					return (dossier.id == dossier_id); 
				}).length > 0;
			});
			this.trigger('dossier-list', {
				'default_dossier'	: default_dossier,
				'dossier_list' 		: dossier_list
			});
    },

    'resolve_error_message' : function(status) {
      var messages = {
        'add_dossier-invalid_title'             : 'Ongeldige naam',
        'add_dossier-duplicate'                 : 'Er bestaat al een dossier met deze naam.',
        'add_document-dossier_not_found'        : 'Fout: dossier bestaat niet.',
        'add_document-duplicate'                : 'Er bestaat al een document met deze bron.',
        'move_document-dossier_not_found'       : 'Fout: dossier bestaat niet.',
        'move_document-document_not_found'      : 'Fout: document bestaat niet.',
        'move_document-document_not_found'      : 'Fout: document bestaat niet.',
        'delete_document-dossier_not_found'     : 'Fout: dossier bestaat niet.',
        'move_dossier-dossier_not_found'        : 'Fout: dossier bestaat niet.',
        'move_dossier-dossier_not_found'        : 'Fout: dossier bestaat niet.',
        'delete_dossier-dossier_not_found'      : 'Fout: dossier bestaat niet.',
        'get_document_list-dossier_not_found'   : 'Fout: dossier bestaat niet.',
        'login-invalid_email'                   : 'Ongeldig email adres',
        'login-invalid_login'                   : 'Email adres of wachtwoord onjuist'
      };
      if (typeof(messages[status]) == 'undefined')
        return 'Er is een fout opgetreden';
      return messages[status];
    },

    'handle_response' : function(result) {
			if (isset(result.document_list) && isset(result.document_list.dossier_id))
			{
				this._cache_document_list[result.document_list.dossier_id] = result;
				this.handle_document_list(result.document_list);
			}

			if (isset(result.dossier_list))
			{
        this.dossier_list = result;
				this.handle_dossier_list(result.default_dossier, result.dossier_list);
			}

			if (isset(result.user))
			{
				this.handle_status(result.user);
			}
    },

    'handle_response_and_callback': function(callback) {
      return $.proxy(function(result) {
        this.handle_response(result);
        callback(result);
      }, this);
    },

    '_get_callback' : function(options) {
			var skip_error = false;
			if (!isset(options))
				options = {};

			if (isset(options.skip_error))
			{
				skip_error = options.skip_error;
				delete options.skip_error;
			}
			return $.proxy(function(result) {
				if (result.status != 'ok')
				{
					result.error_status = this.resolve_error_message(result.status);
					if (!skip_error)
					{
        		this.trigger('error', {'error': result.error_status});
					}
				}
				else
				{
					this.handle_response(result);
				}
				if (isset(options.callback))
				{
					options.callback(result);
				}
			}, this);
    },

    'login' : function(options) {
			return this.rpc.users.login(options, this._get_callback(options));
    },

    'logout' : function(options) {
      return this.rpc.users.logout(options, this._get_callback(options));
    },

		'get_status' : function(options) {
		  return this.rpc.users.get_status(options, this._get_callback(options));
		},

    'add_dossier' : function(options) {
      return this.rpc.dossiers.add_dossier(options, this._get_callback(options));
    },

    'delete_dossier' : function(options) {
      return this.rpc.dossiers.delete_dossier(options, this._get_callback(options));
    },

    'move_dossier' : function(options) {
      return this.rpc.dossiers.move_dossier(options, this._get_callback(options));
    },

    'get_dossier_list' : function(options) {
			/* use cache if available */
      if (this.dossier_list)
      {
        this._get_callback(options)(this.dossier_list);
        return true;
      }

			var hash = $.toJSON({'options':options, 'url':'get_dossier_list'});
			var calling = (typeof this.calls[hash] != 'undefined');

			if (!calling)
			{
				var func = $.proxy(function(result) {
						for(var i = 0; i < this.calls[hash].length; i++)
						{
							this.calls[hash][i](result);
						}
						delete this.calls[hash];
				}, this);
				this.calls[hash] = [];
			}

			if (this.calls[hash].length == 0)
			{
				this.calls[hash].push(this._get_callback(options));
			}
			else
			{
				if (options && options.callback)
				{
					this.calls[hash].push(options.callback);
				}
			}

			if (!calling)
	      return this.rpc.dossiers.get_dossier_list(options, func);
    },

    'add_document'  : function(options) { 
      return this.rpc.dossiers.add_document(options, this._get_callback(options));
    },

    'delete_document' : function(options) {
      return this.rpc.dossiers.delete_document(options, this._get_callback(options));
    },

    'move_document' : function(options) {
      return this.rpc.dossiers.move_document(options, this._get_callback(options));
    },

    'get_document_list' : function(options) {
      if (this._cache_document_list[options.dossier_id])
      {
        this._get_callback(options)(this._cache_document_list[options.dossier_id]);
        return true;
      }
      else
      {
        return this.rpc.dossiers.get_document_list(options, this._get_callback(options));
      }
    },

    'add_document_in_new_dossier' : function(options) {
      return this.add_dossier({
        'title'     : options.dossier_title,
        'callback'  : $.proxy(function(result) {
          delete options.dossier_title;
          options.dossier_id = result.dossier_id
          this.add_document(options);
        }, this)
      });
    }
  }

  var dossiers = new Dossiers;
  // copy the public functions to the jQuery namespace
  // and bind them to the dossiers object
  $.dossiers = {}
  $.each([
			'add_document', 
			'add_dossier', 
			'add_document_in_new_dossier',
			'get_dossier_list',
			'get_document_list',
			'move_dossier',
			'move_document',
			'delete_dossier',
			'delete_document',
			'get_status',
			'login',
			'logout'
		], function(k, method) {
			$.dossiers[method] = $.proxy(dossiers[method], dossiers)
  	}
	);

  /*
   $.dossiers = {
      'add_document' : $.proxy(dossiers.add_document, dossiers),
      'add_dossier'  : $.proxy(dossiers.add_dossier, dossiers),
      'add_document_in_new_dossier' : $.proxy(dossiers.add_document_in_new_dossier, dossiers)
   };
   */
})();

/* drag/drop related code */
(function($) {
  
  if(dossier_page) 
    return;
  
	var	drags = 'div.widget_container > ul .is-draggable, div.widget_container > ul > li:has(".result_title"):not(".not-draggable"), div.widget_container ul.thumbs_container li:not(".not-draggable")';
	var drops	= 'li.drop_dossier';

  $.extend({
    dragdrop : {
      enableDraggables : function() {
        $(drags).draggable({
          opacity          : 1,
          cursor			     : 'move',
          cursorAt			   : { left: 32, top: 32 },
          addClasses		   : false,
          refreshPositions : true,
          snap				     : drops,	
          distance         : 1,
          helper			     : function() {            
						var $img = $('.result_image', this);
            if ($img.length == 0)
						{
              var placeholderImage = $('<div>').addClass('placeholderimage');
            }
						else
						{
              var placeholderImage = $img.clone();
            }
            return $("<div>")
              .attr("id", "clone")
              //.append($(this).find('.result_title').clone())
              .append(placeholderImage)
              .appendTo("body");
          },
          revert            : true,
          revertDuration    : 0, 
          zIndex            : 2000,
          start             : function(event, ui) {
            $(ui.helper)
              .addClass('document_dragging')
              .width(64)
              .height(64);
            $(ui.draggable).addClass('orangebg');       
          },
          stop              : function(event, ui) {
            $(ui.helper).removeClass('document_dragging');
            $(ui.draggable).removeClass('orangebg');
          } 
        });
      },
     
      enableDroppable : function() {
        $(drops).droppable({
          hoverClass: 'droppables_over',
          tolerance: 'intersect',
          activate: function(event, ui) {
		    $('#dossier-overlay').show();
          },
          deactivate: function() {
			$('#dossier-overlay').hide();
          },
          over: function() {
              // deze option is waarschijnlijk niet meer nodig.. wordt anders opgevangen
              //$(this).addClass('droppables_over'); 
          },
          out: function() {
              $(this).removeClass('droppables_over');
          }
        });
        $.dragdrop.enableDraggables();
        $.dossiers.rebind_droppables_to_dossiers(drops);
      }
    }
  });

  $(document).bind('template-rendered', function(event, elm) { 
    $.dragdrop.enableDraggables();
    
    // Fixes text being selected bug in Webkit browsers
    drags.onselectstart = function () { return false; };
    
  });
  
})(jQuery);

