/*Fuel - Powering your web applicaitons. Copyright (c) 2010 - Arnout Kazemier ( hotels.nl ) *//*	
	Fuel - Powering your web applicaitons.
		
	Build:
		Date:
			Today, Now, Current year.
			
		Version: 
			0.0.0.0 - Working Draft
	
	Copyright:
	
		Copyright (c) 2009 - Arnout Kazemier ( hotels.nl ).
		All rights reserved.
		
		Redistribution and use in source and binary forms, with or without
		modification, are permitted provided that the following conditions are met:
		
		* 	Redistributions of source code must retain the above copyright notice,
			this list of conditions and the following disclaimer.
		* 	Redistributions in binary form must reproduce the above copyright notice,
			this list of conditions and the following disclaimer in the documentation
			and/or other materials provided with the distribution.
		
		THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
		AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
		IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
		ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
		LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
		CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
		SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
		INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
		CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
		ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
		POSSIBILITY OF SUCH DAMAGE.
		
		Phew.
 */
(function( top, tmp /* @PRIVATE: tmp storage obj */){
	// Create basic variables, the first bunch will help speed up references and will act as sortcuts to natives
	var document = top.document,
		documentElement = document.documentElement,
		fn = [ /* @NOTE caching these methods allows us to speed up references to these functions */
			Object.prototype.toString 
		],
		
		userAgent = navigator.userAgent.toLowerCase(),
		appVerson = navigator.appMinorVersion,
		
		/* @NOTE: this added so we can do typeof item === object */
		object = "object",
		string = "string",
		number = "number",
		
		undefined,
		v,
		
		fuel = top.fuel = top.fuel || {},
		vanilla;
		
		/* @NOTE: makes sure the top variable is really are top */
		try { while( top !== top.top ){ top = top.top; } if (top !== self) top.location.replace( self.location.href ); } catch( e ) { /* just fail silent */}
				
		vanilla = v = {
			/* 
				This is our vanilla object, it contains all utilitys that are not present in Spry it self, or can be done better.
				
				@NOTE: these are @PRIVATE functions. They will not be exposed to the public unless used by the fuel.vanillatize 
			
				vanilla.extend extends a object with another object
				
				@param toExtend {object}, object that gets extended with the new object
				@param extendWith {object}, this will be added to the toExtend object
				@param ignoreUndefined <boolean>, ignore undefined properties.
			*/
			extend: function( toExtend, extendWith, ignoreUndefined ){
				if( !extendWith ){
					return; // there is nothing to extend with
				}
				
				toExtend = toExtend || vanilla; // if no toExtend that they want to extend the vanilla object
				
				var fn = vanilla.is.fn( extendWith ),
					items; // create a variable where the items can be stored in.
					
				for( items in extendWith ){
					if( ignoreUndefined && ( extendWith[ items ] || toExtend.prototype[ items ] ) == undefined ){
						continue;	
					}
					
					// Extend the prototype of a function or just extend the object
					if( fn ){
						toExtend.prototype[ items ] = extendWidth[ items ];
					} else {
						toExtend[ items ] = extendWith[ items ];
					}
				}
				
				return v;
			},
			/*
				vanilla.addEvent is a small wrapper for eventListeners
				
				@param type "String", type of event
				@param fn Function(), function to be executed when event occures
				@param context &mixed&, item where the event should be attached on
			*/
			addEvent: function( type, fn, context){
				context = context || window;
				return context.attachEvent ? context.attachEvent( "on" + type, fn ) : context.addEventListener( type, fn, false );
			},
			
			/*
				vanilla.contains check arrays for the presents of item; 
				
				@param array [array], the array that needs to be searched
				@param item &mixed&, the item that needs to be found in the array
				
				@returns &mixed& number, if the item is found, the number represents the index, false if nothing is found 
			*/
			contains: function( array, string ){
				var i = array.length;
				while( i-- ){
					if( array[i] == string){
						return i;
					}
				}
				
				return false;
			},
			
			/*
				vanilla.is allows you to check if items are a array or object.
				
				@param o &mixed&, the item to be tested by the functions
				
				returns <boolean>, if case is true or not.
				
				examples:
					vanilla.is.fn(""); // returns false
					vanilla.is.fn(function(){}); // returns true
			*/
			is: {
				fn: function( o ){ return fn[ 0 ].call( o ) === "[object Function]"; },
				array: function( o ){ return fn[ 0 ].call( o ) === "[object Array]"; },
				object: function( o ){ return fn[ 0 ].call( o ) === "[object Object]"; },
				string: function( o ){ return fn[ 0 ].call( o ) === "[object String]"; },
				number: function( o ){ return fn[ 0 ].call( o ) === "[object Number]"; },
				node: function( o ){ return o.nodeType },
				bool: function( o ){ return fn[ 0 ].call( o ) === "[object Boolean]"; }
			},
			
			/*
				vanilla.browser contains all browser information, which userAgent it is, and what version.
				
				examples:
					vanilla.browser.ie; // false
					vanilla.browser.firefox; // true if you are 
			*/
			browser: {
				version: ( userAgent.match( /.+(?:rv|it|ra|ie)[\/: ]([\d.]+)/ ) || [ 0, "0" ] )[1],
				servicepack: appVerson ? appVerson.toLowerCase().replace( /;/g,"" ) : false,
				webkit: /webkit/.test( userAgent ),
				opera: /opera/.test( userAgent ),
				ie: /msie/.test( userAgent ) && !/opera/.test( userAgent ),
				firefox: /mozilla/.test( userAgent ) && !/(compatible|webkit)/.test( userAgent ),
				chrome: /google/.test( userAgent ) && /webkit/.test( userAgent ),
				mobile_safari: /Apple.*Mobile.*Safari/.test( userAgent ),
				iphone: /(iphone|ipod)/.test( userAgent )
			},
			
			/*
				vanilla.supports is a browser feature detection list so we know when native functionality is available
				
				examples:
					vanilla.supports.gears;
					vanilla.supports.workers;
			*/
			supports: {
				workers: !!( top.Worker && Worker.prototype.terminate ), // checks for web worker pool
				gears: !!( top.google && !!top.google.gears ),// checks for google gears support
				sessionStorage: !!top.sessionStorage, // support for session storage
				localStorage: !!top.localStorage, // support for local storage
				json: !!( top.JSON && top.JSON.parse ) // native JSON parsing or JSON2.js
			},
			
			/*
				vanilla.params is object representing the possible search string of the browsers.
				
				examples:
					searchstring: ?foo=bar&bar=1;
					
					vanilla.params.foo; // bar
					vanilla.params.bar; // 1
			*/
			params: (function(){
				var source = top.location.search.substr( 1 ).split( "&" ),
					result = {}, y = source.length, m, c, a, tmp;
					
				while(y--){
					m = source[y].split( "=" );
					c = unescape( m[0] ? m[0] : "" );
					a = unescape( m[1] ? m[1] : "" );
					
					if( a.match( /^0$|^[1-9]\d*$/ ) ){
						a = parseInt( a );
					} else {
						a = a.toLowerCase();
					}
					
					if( !result[ c ] ){
						result[ c ] = a;
					} else {
						if( typeof result[ c ] != object ){
							tmp = result[ c ];
							
							result[ c ] = [ tmp ];
						}
						
						result[ c ].push( a );
					}
				}
				
				return result;
			})(),
			
			/*
				vanilla.poll checks the DOM for presents of the a element based on the id attribute.
				polling would be faster than a DOM ready check as it wait for all elements
				
				@param element "string", the id attribute of the element that needes to be found in the DOM
				@param callback function(), the function that needs to execute when the element was found
				@param timeout Number, interval in miliseconds that is required used to check for elements
				
			*/
			poll: function( element, callback, timeout){
				var ele = document.getElementById( element );
				if( ele ){
					return callback( ele ); // the element has been found
				} else {
					(function( ele ){
						ele = document.getElementById( element );
						
						if( ele ){
							return callback( ele ); // found
						}
						
						return setTimeout( arguments.callee, timeout || 10 );
					})( ele );
				}
				
				return v;
			},
			
			/*
				vanila.chunk allows you to process a array with out freezing or interupting the UI.
				
				@NOTE: Copyright 2009 Nicholas C. Zakas. All rights reserved. MIT Licensed
				
				@param items [array], the items that needs to be chunked and processed
				@param process Function(), the process that handles each item.
				@param context &mixed&, the context for the process call
				@param callback Function(), the function that needs to be called when the chunking is completed
			*/
			chunk: function( items, process, context, callback ){
				var todo = items.concat();   //create a clone of the original
			
				setTimeout(function(){
					var start = + new Date();
			
					do {
						 process.call( context, todo.shift() );
					} while ( todo.length > 0 && ( + new Date() - start < 50 ) );
			
					if ( todo.length > 0 ){
						setTimeout( arguments.callee, 25 );
					} else {
						return callback ? callback( items ) : false;
					}
				}, 25);
				
				return v;
			},
			
			/*
				vanilla.notify is our notifier object it allows us to create custom "events" and "obeserve" them.
				
				@NOTE: Copyright 2009 Adobe Spry, but we needed to duplicate the functionality as we might use it as standalone
			*/
			notify: function(){
				this.observers = [];
				this.suppressNotifications = false;
				
				/* 
					.addObserver adds a new observer to the listing that can be fired on a event
					
					@param observer {Object}, example:  { test: function(){} }
				*/
				this.addObserver = function( observer ){
					if( !observer ){
						return;
					}
					
					var i =  this.observers.length,
						len = i;
					while( i-- ){
						if( this.observers[i] == observer ){
							return;
						}
					}
					
					this.observers[ len ] = observer
				};
				
				/*
					.removeObserver removes the observer that is listed
					
					@param observer {Object}, must equal the .addObserver
					returns {object} observers
				*/
				this.removeObserver = function( observer ){
					if( !observer ){
						return;
					}
					
					var i = this.observers.length;
					while( i-- ){
						if( this.observers[ i ] == observer ){
							return this.observers.splice( i , 1 );
						}
					}
				};
				
				/*
					.notifyObservers calls the added observer
					
					@param methodName {String}, name of the observer
					@param data &mixed& any kind of data that will be send to the observer
				*/
				this.notifyObservers = function( methodName, data ){
					if( !methodName || this.suppressNotifications ){
						return;
					}
					
					var i = this.observers.length, 
						obs;
					while( i-- ){
						obs = this.observers[i]
						if( obs ){
							if(typeof obs == "function"){
								obs( methodName, this, data );
							} else if (obs[ methodName ] && typeof obs[ methodName ] == "function"){
								obs[ methodName ]( this, data );
							}
						}
					}
				};
				
				/*
					.enableNotifications
					enables notifications, simple as that.
				*/
				this.enableNotifications = function(){
					this.suppressNotifications = false;
				};
				
				/*
					.disableNotifications
					stops the notifications form being send, all notifications
				*/
				this.disableNotifications = function(){
					this.suppressNotifications = true;
				}
			},
			
			/*
				vanilla.scrollto allows you to scroll to a element, doesn't matter what element. document.body or something else. 
				The location of the scrollbar gets calculated based on the elements position in the dom.
				
				@param element <HTMLElement>, element that we need to scroll to
			*/
			scrollto: function( element ){
				var stylize = function( element){ return !+"\v1" ? element.currentStyle : document.defaultView.getComputedStyle( element , null ) },
					getPosition = function( element ){
						var computedStyle, tryComputedStyle,
							position = { x: 0, y: 0 };
							
							if ( element.style.left  && /px/i.test(element.style.left) ){
								position.x = parseInt(element.style.left, 10); // without padding
							} else {
								computedStyle = stylize( element );
								var tryComputedStyle = computedStyle && computedStyle.left && /px/i.test( computedStyle.left );
						
								if (tryComputedStyle)
									position.x = parseInt( computedStyle.left, 10 ); // without padding, includes css
						
								if(!tryComputedStyle || position.x == 0) // otherwise we might run into problems on safari and opera (mac only)
									position.x = element.offsetLeft;   // includes padding
							}
						
							if ( element.style.top && /px/i.test(element.style.top) )
								position.y = parseInt( element.style.top, 10); // without padding
							else
							{
								if ( !computedStyle )
									computedStyle = stylize( element );
						
							var tryComputedStyle = computedStyle && computedStyle.top && /px/i.test( computedStyle.top );
						
								if ( tryComputedStyle )
									position.y = parseInt( computedStyle.top, 10 ); // without padding, includes css
						
								if( !tryComputedStyle || position.y == 0 ) // otherwise we might run into problems on safari and opera (mac only)
									position.y = element.offsetTop;   // includes padding
							}
						
						return position;
					}
					
					scroll( 0, getPosition( element ).y );
			},
			
			/*
				vanilla.forEach allows you to cicle over a object / array and execute a function based on that
				
				@param obj {Object}, the object that needs to be looped
				@param fn Function(), the function that needs to be executed for each item
			*/
			forEach:  function( obj , fn){
					if(! obj ){ return v }
					var key, i = 0, length, undefined, result = [];
					if( vanilla.is.array( obj ) ){
						length  = obj.length;
						for(; i < length; i++){
							result[ result.length ] = fn.apply( top, [ obj[ i ], i ]);
							if( result[ result.length - 1] === false ){
								break;
							}
						}
					} else {
						for(var key in obj){
							result[ result.length ] = fn.apply( top, [ obj[ key ], key ])
							if( result[ result.length - 1] === false ){
								break;
							}
						}
					}
				return result.length ? result : v;
			},
			
			/*
				vanilla.stringify is a compiled version of the JSON.stringify it only allows a object 
				to be string'd
				
				@param obj &mixed&, the item that needs to be converted to a string
			*/
			stringify: function( obj ){
				var t = typeof (obj);
				if (t != object || obj === null) {
			
					// simple data type
					if ( t == string ) {
						obj = '"'+obj+'"';
					}
					return String( obj );
			
				} else {
					// recurse array or object
					var n, v, json = [], arr = vanilla.is.array( obj );
			
					for (n in obj) {
						if( n !== "ds_JSONObject" ){
							v = obj[ n ]; 
							t = typeof( v );
				
							if ( t == string ) {
								v = '"' + v + '"';
							} else if (t == "object" && v !== null) {
								v = vanilla.stringify( v );
							}
				
							json.push((arr ? "" : '"' + n + '":') + String( v ));
						}
					}
			
					return ( arr ? "[" : "{" ) + String( json ) + ( arr ? "]" : "}" );
				}
			},
			
			cache: (function(){
				/*
					fuel.cache.internals stores the data temperaraily untill the a setItem has been called. This allows you to
					store the data in a later point of time. Eg. if onunload of if the user is idle. It does require a cache key.
				*/
				var internals = {},
					
					kb = 2000, // limit in kb
					
					/* @PRIVATE: checks if the user supports window.name storage */	
					notSupported = function(){ return ( vanilla.browser.ie && vanilla.browser.version <= 6 && vanilla.browser.servicepack != "sp3" )  },
					
					/* @PRIVATE: processes the returned value from the storage, it checks if its JSON and attempts to parse it */
					process = function( str ){
						var unsave = function(){ return (Function( "return " + str ))() }, res;
						
						if( vanilla.supports.json ){
							try{res = JSON.parse( str ) }catch(e){ res = unsave() }
						} else {
							res = unsave();
						}
						
						return res || false;
					},
					
					limit = function(){
						return Math.round( top.name.length /1024 ) < kb; 
					},
					
					/* @PRIVATE: sessionStorage doesn't allow strings to be set as data, so we need to parse it down */
					stringify = function( data ){
						if(!vanilla.is.string( data )){
							if(vanilla.is.array( data) || vanilla.is.object( data )){						
								/* @NOTE: Prevent ds_JSONObject parsing, as it causes recurrison errors */
								return vanilla.stringify( data ); // attempt to serialize data
							} else {
								try{ data = data.toString(); /* do a toString */ } catch( e ){}
							}
						}
						
						return data;
					},
					
					/* @NOTE: the data object wil be returned as methods for the fuel.cache function */
					api = {
						/*
							fuel.cache.getKey returns the key for cache, its based on the parameters of the page
							it will use the cookie if its found, else it will use the compiled cache key
						*/
						getKey: function(){
							var cookie = vanilla.cookie.getItem( "cacheToken" ),
								p = vanilla.params; // shortcut
								
							return cookie || [ p.destination, p.arrival, p.departure, p.lang, p.num_persons ].join( "/" );
						},
						
						/*
							fuel.cache.setItem allows you to set data as browser session. It attempts to use the HTML data storage, or will go with window.name as backup
							if that is supported.
							
							if no key is specified it will use the getKey method to generate one, also if no data is found it will check our "internals" object to search for data.
							and use that instead.
							
							@param key "String", identifyer for the cache
							@param data &mixed&, data that needs to be stored as session
						*/
						setItem: function( key, data ){
							key = key || api.getKey();

							// sessionStorrage only allows you to set strings as datatype
							data = ( data = data || ( internals && key ? internals[ key ] : false ) ) ? stringify( data ) : false;
							
							if( !data || notSupported() || !vanilla.is.string( data ) || !key || data == undefined){
								return v; // we have nothing to store so stop processing the function
							}
													
							if(!vanilla.supports.sessionStorage){
								if( !limit() ){
									top.name = "";
								}
								top.name += ( top.name.match( "::" ) ? "||" : "" ) + [ key, data ].join( "::" );
							} else {
								sessionStorage.setItem( key, data );
							}
							
							return v;
						},
						
						/*
							fuel.cache.getItem returns the set items for the speciefied key
							
							@param key "String", identifyer for the cache
							
							returns &mixed&, if the data matches JSON regexp, it will return a JS json Object else it will return a string. 
											 if no data has been found, it will return false.
						*/
						getItem: function( key, raw ){
							key = key || api.getKey();
							
							if( !key || notSupported() ){
								return; // nothing to see here
							}
							
							if( !vanilla.supports.sessionStorage ){
								var data = top.name.split( "||" ), // gets the data from the window.name
									i = data.length, // allows us to while loop it
									items, // stores cached items
									result; // result
									
								while( i-- ){
									items =  data[i].split( "::" ); // keys and data are seperated by ::
									if( items[0] === key ){ 
										return process( items[1] );
									}
								}
							} else {
								// get the sessionStorage data
								var data = sessionStorage.getItem( key );
								return raw ? data ? data : "[no-data]" : data ? process( data.value || data ) : false;
							}
							
							return false; // no data found 
						},
						/*
							fuel.cache.clear completly whips out the sessions storrage, removing all data in the storage
						*/
						clear: function(){
							if( !vanilla.supports.sessionStorage ){
								top.name = ""; // clear
							} else {
								// firefox 3.0 bug, doesn't support clear
								if( sessionStorage.clear ){
									sessionStorage.clear();
								} else if( sessionStorage.removeItem ){
									var storage;
									for( storage in sessionStorage ){
										sessionStorage.removeItem( storage );
									}
								}
							}
							return v;
						},
						
						/*
							fuel.cache.setInterals stores the data in our memory, so we can store it to our session storage on a later point.
							Because you don't want to set the data when a user is filtering or loading in a new page.
							
							@param key 'String', key for the cache
							@param data &mixed&, the data that needs to be stored
						*/
						setInternals: function( data, key ){
							key = key || api.getKey();
							
							if( !key || !data ){
								return v;
							}
							
							// set the internal data for the string
							internals[ key ] = data;
							return v;
						},
						
						/*
							fuel.cache.getInternals allows you to return the internal set data
							
							@param key "String", the key that gives access to the obj
						*/
						getInternals: function( key ){
							key = key || api.getKey();
							// returns a clone of the internals								
							return internals[ key ];
						}
					};
					
					return api;
			})(),
			
			/*
				vanilla.cookie, see methods for more information
			*/
			cookie: (function(){
					/* PRIVATE: maximum length of document.cookie, if its larger than that. It will cause apache to crash. Source:stevesouders.com */
				var limit = 8190,
					
					/* PRIVATE: checks if we will be able to set the cookie */
					exceeds =  function( str ){
						return ( document.cookie.length + str.length ) > limit;
					},
					
					/*
						vanilla.cookie.setItem sets cookies, by default it sets it for 1 day, on the current domain
						
						@param key "string", the "name" or "key" that identifys your cookie
						@param data "string", the data that needs to be stored
						
						@param options {object}, variouse of options to control your cookie:
							- days number, the amount days the cookie needs to exist
							- domain "string", on what domain the cookie needs to be set
							- path "string", if the cookie needs to set to specific path
							
						returns <boolean>, indicating if the cookie has been set or not
					*/
					set = function( key, data, options ){
						var defaults = {
							days: 1,
							domain: document.domain,
							path: "/"
						}, date = new Date(), dough;
						
						// check if the key contains 
						key = key + "=";
						vanilla.extend( defaults, options ); // set the new options
						
						date.setTime( date.getTime() + ( defaults.days * 86400000 )); // set the correct date accordion to the days
						
						defaults.days = date.toGMTString();
										
						// generate cookie str
						dough = [ key + escape( data ), "expires=" + defaults.days, "path=" + defaults.path, "domain=" + defaults.domain ].join( ";" );
						
						// only set cookie if it does not exceed the limit
						if( !exceeds( dough ) ){
							return document.cookie = dough; // ? true : false;
						} else {
							return false;
						}
					},
					
					/*
						vanilla.getItem reads the data from the cookie, for the specified key
						
						@param key "string", the "name" or "key" that identifys your cookie
						
						returns <boolean> || "string", if data is found, it returns the string, else it will return false
					*/
					
					get = function( key ){
						var cookieJar = document.cookie.split( ";" ),
							i = cookieJar.length, tmp;
						
						key = key + "=";
						
						while( i-- ){
							tmp = cookieJar[i];
							while( tmp.charAt(0) == " " ){ // remove redundant spaces
								tmp = tmp.substring( 1, tmp.length );
							}
							
							if( tmp.indexOf( key ) == 0 ){
								return unescape( tmp.substring( key.length, tmp.length ) );
							}
						}
						
						return false;
					},
					
					/*
						vanilla.cookie.clear deletes the cookie, specified for the key.
						
						@param key "string", the "name" or "key" that identifys your cookie
						
						returns <boolean>, indicating if the cookie has been deleted or not
					*/
					clear = function( key ){
						return set( key, "", { days: -1 } );
					},
					
					/*
						vanilla.cookie.once read the cookie and destroys it right after that
						
						@param key "string", the "name" or "key" that identifys your cookie
						
						returns <boolean> || "string", if data is found, it returns the string, else it will return false
					
					*/
					once = function( key ){
						var data = get( key );
						clear( key );
						return data;
					
					};
				return {
					getItem: get,
					setItem: set,
					clear: clear,
					once: once
				};
			})(),
			
			/*
				vanilla.eval does a local eval, so the variables will not mess with your global variables
				@param str "String", the content that needs to be evaluated during runtime
			*/
			eval: function( str ){ 
				return eval( str ); 
			},
			
			/*
				vanilla.delete removes items from a object so they are ready for garbage collection
				@param object {Object}, the object that contains the variouse of items that needed to be removed
				@param [Arguments], all items that need to be removed
			*/
			remove: function( object ){
				for( var i = 1, arg = arguments, length = arg.length; i < length; i++ ){
					delete object[ arg[i] ];
				}
				return v;
			},
			
			script: {
				/*
					vanilla.script.clean attempts to cleanup the filename so it will be prevent commen issues
					@param src "String", the filename that needs to cleaned
				*/
				clean: function( src ){
					return typeof src == string && src.length > 0 ? /^(.*\/)?([^?\/#]*)(\?.*)?(#.*)?$/i.exec( src )[ 2 ].toLowerCase() : "";
				},
				
				/*
					vanilla.script.exists
				*/
				exists: function( src ){
					var scripts = document.getElementsByTagName( "script" ),
						i = scripts.length;
					
					while( i-- ){
						if( typeof scripts[i].src === string && src === vanilla.script.clean( scripts[i].src ) ){
							return true;
						}
					}
					return false;
				}
			},
			
			ready: false,
			readyQue: [],
			
			/*
				vanilla.onDOMReady checks if the document is loaded. If this is the case it will execute the function
				
				@param fn Function(), the function that needs to be executed once the dom is ready
			*/
			onDOMReady: function( fn ){
				if( vanilla.ready ){
					return fn.call( document, vanilla, fuel );
				}	
				
				if( !vanilla.readyQue.length ){
					var ready = function(){
						if( vanilla.ready ){
							return;
						}
						
						vanilla.ready = true;
						
						var i = vanilla.readyQue.length;
						while( i-- ){
							vanilla.readyQue[ i ].call( document, vanilla, fuel );
						}
						
						vanilla.readyQue.length = 0;
					};
					
					if( document.readyState && !+"\v1" ){
						if( location.protocol !== "https" ){
							document.write( "<scr" + "ipt id='vanillaready' defer=true " + "src=//:><\/scr" + "ipt>" );
							document.getElementById( "vanillaready" ).onreadystatechange = function(){
								if( this.readyState && this.readyState !== "complete" && this.readyState !== "loaded" ){
									return;
								}
								
								ready();
							}
						} else {
							(function(){
								try {
									documentElement.doScroll( "left" );
								} catch(e) {
									return setTimeout( arguments.callee, 0 );
								}
								ready();
							})();
						}
					} else if( document.readySate && vanilla.is.webkit && vanilla.is.version < 525 ){
						(function(){
							return /loaded|complete/.test( document.readyState ) ? ready() : setTimeout( arguments.callee, 0 );
						})();
					} else if( document.addEventListener ){
						document.addEventListener("DOMContentLoaded", ready, false);
					}
					
					vanilla.addEvent("load", ready);
				}
				
				vanilla.readyQue[ vanilla.readyQue.length ] = fn;
			},
			
			/*
				vanilla.getLanguage() reads out the xml:lang attribute from html tag to get the correct langauge
				script by frequency-decoder.com
			*/
			getLanguage: function() {                                 
                var languageTag = document.getElementsByTagName("html")[0].getAttribute("lang") || document.getElementsByTagName("html")[0].getAttribute("xml:lang");
                
                if(!languageTag) {
                	languageTag = "en";
                } else {
                	languageTag = languageTag.toLowerCase();
				}
                                                            
                return languageTag;                       
        	},
			
			floatable: function(){
				var  context = document.body,
					nav_bar = Spry.$$( "div.nav-places", context ),
					search_bar = Spry.$$( "div.search-header", context ),
					limit = Spry.$$( "#frm-newsletter" ),
					btns = Spry.$$( "a.button", search_bar[0] ),
			
					blind = function(){
						if( !this.blinds ){
							this.blinds = new Spry.Effect.Blind(  Spry.$$( "img", search_bar[0] )[0], { duration:500, from:"0%", to:"100%", toggle:true });
						}
						blinded = !blinded;
						this.blinds.start(); // start the effect
					},
			
					get_offset = function( element ){
						var total = parseInt( element.offsetTop ), 
							parent = element.offsetParent; 
								
						while( parent ){
							total += parent.offsetTop; 
							parent = parent.offsetParent;
						} 
							
						return total;
					},
					
					reset_bar = function(){
						if( blinded && !incapablesonofabitch){ blind(); }
						if( button ){ button = false; btns[0].style.display = "none"; }
						
						// fixes sudden jumps to top, causing the menu to be hidden
						nav_bar.setStyle("margin-bottom:auto");
						search_bar.setStyle(
							!incapablesonofabitch ? 
								( "position:relative;top:auto;width:auto;" ) :
								( "position:relative;top:auto;width:auto;")
						).addClassName("clear");
					},
			
					blinded = false,
					button = false,
					last_position = 0,
					offset = 0,
					not_allowed_scroll = vanilla.cookie.getItem("floatable") || false,
					incapablesonofabitch = ( vanilla.browser.ie && vanilla.browser.version == 6 ),
					margin = Spry.Effect.getDimensionsRegardlessOfDisplayState( search_bar[0] ).height,
			
					start_position = get_offset( search_bar[0] ),
					end_position = get_offset( limit[0] ) - ( Spry.Effect ? Spry.Effect.getDimensionsRegardlessOfDisplayState( search_bar[0] ).height : 0  );
					
					if(!not_allowed_scroll){
						setTimeout(function(){
							Spry.$$("#arrival, #departure, a.date-picker-control", Spry.$("frm-search") ).addEventListener("click", function(){
								if(!not_allowed_scroll)
									if( last_position > 140 )
										setTimeout( function(){
											Spry.$$("div.datePicker.calendars-small").setStyle("top:" + ( last_position +( margin - ( incapablesonofabitch ? 70 : 50 ) )) + "px" );
										}, 100 );
							})
						}, 200 );
						
						btns.addEventListener("click", function(){
							vanilla.cookie.setItem( "floatable", "1" );
							not_allowed_scroll = true;
							reset_bar();
							current = 0;
							Spry.$$("div.datePicker.calendars-small").setStyle("top:208px" );
						});
						
						Spry.Utils.addEventListener( window, "scroll", function(){
							if( not_allowed_scroll ) return;
							var current = document.documentElement.scrollTop || document.body.scrollTop;
							
							if( current > start_position && !( current > end_position ) ){
								if(! blinded && !incapablesonofabitch  ){ blind(); }
								if(! button ){ button = true; btns[0].style.display = "inline";	}
								
								nav_bar.setStyle("margin-bottom:" + margin + "px");
								search_bar.setStyle( 
									!incapablesonofabitch ? 
										( "position:fixed;top:" + offset + "px;z-index:9999;width:100%;left:0" ) : 
										( "position:absolute;top:" + ( current - offset )  +"px;z-index:9999;left:0px;" ) 
								).removeClassName("clear");
							} else {
								reset_bar();
							}
							last_position = current;
						});
					}
			}
		};
	
	vanilla.extend( fuel, {
		/* 
			fuel.vanillatize returns a reference to the internal used vanilla object 
		*/
		vanillatize: function(){ return vanilla; },
		
		env: {
			lang: vanilla.getLanguage() // gets the [% lang %]
		},
		
		/* fuel.parseDate reads the arrdate cookie, and presents us with a datepicker usable object. */
		parseDate: function( arrdate, datePickerController, fancy ){
			if( !arrdate || !arrdate.match( /arrival/g ) ){ return {}; }
			
			// check if we got a reference to datePickerController
			datePickerController = datePickerController || window.datePickerController;
			
			var frags = arrdate.split( arrdate.match("&") ? "&" : ','),
				fix = function( num ){
					return num < 10 ? "0" + num : num;
				},
				result = {}, 
				length = frags.length, 
				i = 0, 
				pattern = "y-ds-m-ds-d",
				contents, arrival, departure, range = new Date(), ret = {};
			
			for(; i < length; i++ ){
				contents = frags[i].split("=");
				result[contents[0]] = contents[1].match( /^([0-9\-]*)$/g ) ? contents[1].split("-") : contents[1];
				if( arrdate.match(",") ){
					result[contents[0]].reverse();
				}
			}
			
			// date parser :D
			arrival = datePickerController.parseDateString(result.arrival.join(""),pattern);
			ret.arrival = datePickerController.printFormattedDate( arrival, fancy );
			range.setTime( arrival.getTime() + 86400000 /* 1 day */);
			departure = datePickerController.parseDateString(result.departure.join(""),pattern);
			ret.departure = datePickerController.printFormattedDate( departure, fancy );
			departure.setTime( arrival.getTime() + 2592000000 /* 30 days */ );
			
			ret.arrival_rangelow = result.arrival.join("");
			ret.departure_rangelow = [ range.getFullYear(), fix(range.getMonth() + 1), fix(range.getDate()) ].join("");
			ret.departure_rangehigh = [ departure.getFullYear(), fix(departure.getMonth() + 1), fix(departure.getDate()) ].join("");
				
			return ret;
		},
		
		/*
			fuel._autosuggest is the keydown listener for the searchfield, we do not want to create the autosuggest each time the page loads
			only when users intend to use it.
		*/
		_autosuggest: function(){
			if( !fuel.data ){ fuel.data = {}; }
			
			var ds = fuel.data,	suggestions, context = document.body;
			
			// only create ds.suggestions when its not found / created before
			if( !ds.suggestions ){
				this.setAttribute("AutoComplete", "off");
				suggestions = Spry.$( "suggestions" );
				
				// create datasets
				ds.suggestions = new Spry.Data.DataSet({ url:"/cgi-bin/autocomplete.pl?lang=" + vanilla.getLanguage(), name:"suggestions", useUnique:false, jsonpsuffix:"_suggest" });
				ds.suggestions.dataWasLoaded = true;
				ds.destination = new Spry.Data.NestedDataSet( ds.suggestions, "destinations", { name:"destinations" });
					
				// This creates the highlighted / bolded string when the dataset has been loaded
				ds.destination.addObserver({
					onPostLoad:function(){
						try{
						var data = ds.suggestions.data,
							i = data.length,
							regexp = new RegExp("(<[^>]*>)|("+ ( Spry.$("search").value.replace(/([-.*+?^${}()|[\]\/\\])/,"\\$1").replace(/([\.\/\]\[\{\}\(\)\\\$\^\?\*\|\!\=\+\-])/g, '\\$1') || "amsterdam" ) +")", "igm"),
							nested, j, rows;
						
						while( i-- ){
							nested = ds.destination.getNestedDataSetForParentRow( data[i] );
							if( nested ){
								rows = nested.getData();
								j = rows.length;
								while( j-- ){
									rows[j].result = rows[j].name.replace( regexp, function(a, b, c){
										return "<strong>" + c + "</strong>"; 
									});
								}
							}
						}
						} catch(e){}
					}
				});
				
				// create the autosuggest
				fuel.autosuggest = new Spry.Widget.AutoSuggest( "autosuggest", suggestions, ds.destination, "name", { 
						loadFromServer: true, 		// on each suggestion load data from the server, do not use the dataset
						urlParam: "q",  			// use url param ?q as feed
						containsString: true, 		// it should contain the string.
						callback: function( str ){ 	// when selected, do this function
							Spry.$( "type" ).value = str.length ? str[1] : "city"; 
						},
						hasFocus: true,
						stopFocus: false,
						moveNextKeyCode:40, 		// keyboard nav
						movePrevKeyCode: 38			// keyboard nav
					}
				);
				
				// init the region, as we prevent this region from beeing created
				Spry.Data.initRegions( suggestions );
				
				// remove the event listener
				Spry.$$( "#search", context ).removeEventListener( "keydown", arguments.callee );
			}
		},
		
		/*
			fuel._datePicker creates the arrival and departure datepickers, it reads out the arrdate cookie, or default computed values
			
			@param datePickerController {Object}, the reference to the dataPickerController object
			@param fancy "String", date format that is displayed in the inputs
			@param output "String", output for the printFormattedData function
			@param click "String", string with the word click
			@param arrival_min "String", minimum range / start date for the arrival in YYYYMMDD format
			@param arrival_max "String", maximum range / end date for the arrival in YYYYMMDD format
			@param departure_min "String", minimum range / start date for departure in YYYYMMDD format
			@param departure_max "String", maximum range / end date for departure in YYYYMMDD format
			@param close "String", language string, for the close button
		*/
		_datePicker: function( datePickerController, fancy, output, click, arrival_min, arrival_max, departure_min, departure_max, close ){
			var arrival = Spry.$$( 'input[name="arrival"]' ),
				departure = Spry.$$( 'input[name="departure"]' ),
				koekje = fuel.parseDate( vanilla.cookie.getItem("arrdate"), datePickerController, fancy ),
				nodepart = Spry.$("no-depart");

			/* create datepicker */
			arrival.forEach( function(node, i ){
				var a = {}, d = {}, self = this;
				a[ this.id ] = d[ departure[i].id ] = fancy;
				
				if( koekje && koekje.arrival && koekje.departure ){
					this.value = koekje.arrival;
					departure[i].value = koekje.departure;
				}
					
				datePickerController.createDatePicker({
					formElements:a,
					rangeLow: arrival_min,
					rangeHigh: arrival_max,
					showWeeks: true,
					noToday: true,
					noFadeEffect: true,
					close: close,
					statusFormat:"l-cc-sp-d-sp-F-sp-Y",
					
					/* callback functions, this controls limiting the departure date */
					callbackFunctions: {
						dateset: [function( options ){

							if( !options.date ){ return; }
							
							if( departure[i].id == "departure" && nodepart && this.firstRunRan ){
								nodepart.checked = false; /* uncheck no departure */
							}
							
							this.firstRunRan = true;
							var date = new Date( options.date );
							
							date.setTime( options.date.getTime() + 86400000 );
							datePickerController.setRangeLow(departure[ i ].id, datePickerController.printFormattedDate( date, output, true ) );
							
							if( document.getElementById("fd-" + self.id ) ){
								departure[ i ].value = datePickerController.printFormattedDate( date, fancy, true );
							}
							date.setTime( date.getTime() + 2505600000 /* 29 days + 1 from low range = 30 */ );
							datePickerController.setRangeHigh(departure[ i ].id, datePickerController.printFormattedDate( date, output, true ));
						}]
					}
				});
				datePickerController.createDatePicker({
					formElements:d,
					rangeLow: koekje.departure_rangelow || departure_min,
					rangeHigh: koekje.departure_rangehigh || departure_max,
					showWeeks:true,
					noToday:true,
					noFadeEffect:true,
					close: close,
					statusFormat:"l-cc-sp-d-sp-F-sp-Y",
					
					/* callback function */
					callbackFunctions: {
						dateset: [function(){
							if(!this.firstRunRan){ return this.firstRunRan = true }
							if( departure[i].id == "departure" && nodepart ){
								nodepart.checked = false; /* uncheck no departure */
							}
						}]
					}
				});
				this.readOnly = departure[i].readOnly = true;
			}).addEventListener( click, function(){ datePickerController.show( this.id ); });
			departure.addEventListener( click, function(){ datePickerController.show( this.id ); });
		},
		
		/*
			fuel._ready is called once the dom has been loaded successfully.
			
			@param dp_args [Array], the arguments for the datepicker
			@param context [HTMLNode], the HTML node that is used for context
			@param $$ {Object}, reference to the Spry CSS3 selector engine
		*/
		_ready: function( dp_args, context, $$ ){			
			fuel._datePicker.apply( top, dp_args );
			
			$$( "ul.service" ).forEach(function(){
				var active, timer, li = $$( "li.change", this ), a = $$( "li.change span + a", this );
					
				li.forEach(function( node, index ){
					/* now we know each index of ze nodes */
					Spry.Utils.addEventListener( this, "click", function(){
						if( active ){
							Spry.Utils.removeClassName( active, "active" );
						}
						
						active = li[ index ];
						Spry.Utils.addClassName( active, "active");
						return false;
					});
				});
				$$( "ul", this ).addEventListener( "mouseover", function(){ try{ clearTimeout( timer )}catch(e){}});
				$$( "ul", this ).addEventListener( "mouseout", function(){ timer = setTimeout(function(){Spry.Utils.removeClassName( active, "active" );}, 1000); } );
				$$( "ul a", this ).addEventListener( "click", function(){ if( this.href ){ top.location = this.href; }});
			});
		},
		
		/*
			fuel._init is activated once the SpryCore.js has been loaded. All Spry functionality and Datapicker tools is active
			
			@param version "String", the current JavaScript cachebuster version string. Its used for the inject @ google
			@param context [HTMLNode], the HTML node that is used for context
			@param $$ {Object}, reference to the Spry CSS3 selector engine
		*/
		_init: function( version, context, $$, value ){
			var set = Spry.Utils.setAttribute,
				form = Spry.$("frm-search"),
				field;
				
			/* attach the spry:attributes */
			$$( "#autosuggest", context ).forEach(function(){
				$$( "div", this ).setAttribute("spry:region", "fuel.data.suggestions fuel.data.destination");
				$$( "ul", this ).setAttribute("spry:repeat", "fuel.data.suggestions");
				
				var li = $$( "li", this );
				set( li[ 0 ], "spry:content", "{fuel.data.suggestions::name}");
				set( li[ 1 ], "spry:repeat", "fuel.data.destination");
				set( li[ 1 ], "spry:suggest", "{fuel.data.destination::name},{fuel.data.suggestions::type}");
				set( li[ 1 ], "spry:content", "{fuel.data.destination::result} <span>{fuel.data.destination::hotel_count}</span>");
			});
				
			field = $$( "#search", context ).addEventListener( "keydown", fuel._autosuggest );
			
			$$( "form.newsletter", context ).forEach( function(){
				var text = $$( "#email", context )
							.addEventListener( "focus", function(){ return this.value == text ? this.value = "" : false; })
							.addEventListener( "blur", function(){ return this.value == "" ? this.value = text : false; })[0].value;
			
			});
			$$( "#frm-search", context ).forEach( function(){
				var text = field
							.addEventListener( "focus", function(){ var type = Spry.$("type"); if( type ){ type.value = ""; } return this.value == text ? this.value = "" : false; })
							.addEventListener( "blur", function(){ return this.value == "" ? this.value = text : false; })[0].value;
			
			}).addEventListener("submit", function(){
				if( field[0].value == value || field[0].value == "" ){
					Spry.Effect.DoShake( field[0], { duration: 500 } );
					return false;
				}
			});
			$$( "ul.page-options li:last-child", context ).addEventListener( "click", function(){ top.print(); } );
			
			Spry.Utils.addEventListener( top, "unload", function(){
				$$( "ul.page-options li:last-child", context ).removeEventListener( "click", function(){ top.print(); });
				Spry.Utils.removeEventListener( top, "unload", arguments.callee );
			});
			
			/* Google */
			fuel.inject.script( "https:" == document.location.protocol ? "https://ssl.google-analytics.com/ga.js" : "http://scripts.hotels.nl/js/version:"+version+"/ga.js").wait(function(){
				( fuel.pageTracker = _gat._getTracker("UA-499674-5") )._setDomainName("www.hotels.nl");
				if( fuel.ga_pre ){
					var i = fuel.ga_pre.length;
					while( i-- ){
						try{ fuel.ga_pre[i]() }catch(e){}
					}
				}
				fuel.pageTracker._trackPageview();
			});
		},
		
		/*
			fuel.inject dynamically loads javascript files in a none blocking way. This allows the browser to
			load other resources parallel with other JavaScript files
			
			Its based on the vanilla.notify class so it inherits all its functionality. The diesel script calls the
			notifyObserver function when a script has been loaded
		*/
		inject: (function( allscripts ){
			var api = function(){
					vanilla.notify.call( this ); // activate the prototype inherentance
					var self = this;
					// few more methods
					this.script = function(){ var engine = new diesel( this ); return engine.script.apply( engine, arguments ); };
					this.wait = function(){ var engine = new diesel( this ); return engine.wait.apply( engine, arguments ); };
					this.diesel = function( where, queue ){ return (new diesel( this, queue, where ))};
					this.observe = function( observer){ self.addObserver( observer); return self; };
				},
				
				diesel = function( observer, queue, where ){
					this.scripts = {};
					this.queue = !( !queue );
					this.observer = observer;
					this.location = where || ( document.getElementsByTagName( "head" )[ 0 ] || documentElement );
					
					this.loading = false;
					this.ready = false;
					this.que = null;
					
					this.executeables = [];
				};
				
				diesel.prototype = {
					/* @PRIVATE creates javascript files */
					load: function( src, type, lang, duplicate ){
						var filename = vanilla.script.clean( src ),
							self = this,
							callback = function( script ){
								if( ( (this.readyState || fn[ 0 ].call( top.opera ) === "[object Opera]" ) && this.readyState !== "complete" && this.readyState !== "loaded" ) || script.loaded ){ 
									return; 
								}
								
								
								// garbage collection
								this.onload = this.onreadystatechange = null;
								script.loaded = true;
								setTimeout(function(){ self.observer.notifyObservers( filename, { vanilla: vanilla, fuel: fuel, ready: vanilla.ready, script: this }); },0)

								var i;
								for( i in self.scripts ){
									if( self.scripts[ i ] != Object.prototype[ i ] && !( self.scripts[ i ].loaded )){
										return;
									}
								}
								
								self.ready = true;
								
								if( self.que !== null ){
									return self.que();
								}
							}
						
						duplicate = !!duplicate;
						
						if( duplicate && (typeof allscripts[ filename ] !== undefined || vanilla.script.exists( filename) )){
							return this.que !== null ? this.que() : "";
						}
						
						if( this.scripts[ filename ] == undefined){
							this.scripts[ filename ] = { loaded: false };
						} else {
							this.scripts[ filename ].loaded = false;
						}
												
						allscripts[ filename ] = true;
						
						this.loading = true;
						
						setTimeout( function(){
							var scripty = document.createElement("script");
								scripty.setAttribute( "type", type || "text/javascript" );
								scripty.setAttribute( "language", lang || "javascript" );
								scripty.setAttribute( "src", src)
								scripty.onload = scripty.onreadystatechange = function(){
									callback.call( scripty, self.scripts[ filename ] );
								}
							
							self.location.appendChild( scripty ); // yay \o/
						} )
					},
					
					/*
						.script dynamically injects a script file in the dom to ensure proper the
						document doesn't need to wait on script to be loaded and potentially paralizing
						multiplie script connections
						
						@param argments: {
							"String", url of the script
							{Object}, object containing:
								lang: "String", language of the file, default: javascript
								type: "String", script type, default: text/javascript
								src: "String". the url of the script,
								duplicate: <boolean>, if we should allow duplicate files
						}
					*/
					script: function(){
						var arg = arguments,
							length = arg.length,
							i = 0,
							self = this,
							type;
						
						return this.executeOrQue( function(){
													
							for(; i < length; i++ ){
								type = typeof arg[i];
								if( vanilla.is.array( arg[i] ) ){
									arg.callee.apply( null, arg[i] ); // handle each item in the array
								} else if( type === object ){
									self.load( arg[i].src, arg[i].type, arg[i].lang, arg[i].duplicate );
								} else if( type === string ){
									self.load( arg[i] )
								}
							}
							
							return self }, self );
					},
					
					/*
						.wait ques all other chained calls untill the previouse script has been loaded.
						You can add a callback function if iyou with
						
						@param fn Function(), the function that needs to be called once the script has been loaded
					*/
					wait: function( fn ){
						var old = fn,
							engine = new diesel( this.observer, true, this.location ),
							self = this;
						
						fn = function(){
							try{ if( vanilla.is.fn( old ) ){ old(); } } catch( e ){ /* nothing */}
							return engine.processQues();
						}
						
						return this.executeOrQue( function(){
							
							if( self.loading && !self.ready ){
								self.que = fn;
							} else {
								setTimeout( fn, 0 );
							}
							return engine;
						}, engine );
					},
					
					/* @PRIVATE: decides if it should queue the call or not */
					executeOrQue: function( execute, ret ){
						if( this.queue ){
							this.executeables[ this.executeables.length ] = execute;
							return ret;
						}
						return execute( );
					},
					
					/* @PRIVATE: loops over the que and executes it all */
					processQues: function(){
						for(var i = 0, fns = this.executeables, length = fns.length; i < length; i++ ){
							fns[ i ]( vanilla, fuel, this );
						}
						
						this.observer.notifyObservers( "processedQue", { vanilla: vanilla, fuel: fuel, ready: vanilla.ready, que: this.executeables.concat() });
						
						this.executeables.length = 0; // clear array
					},
					
					/* 
						.diesel returns a fresh new diesel object
						
						@param where <HTMLElement>, node that represents the location of the scripts to be injected in 
						@param queue <boolean>, if the calls need to be queued or not so it can be executed later
					*/
					diesel: function( where, queue ){ return (new diesel( this.observer, queue, where ))}
				};
				
				api.prototype = new vanilla.notify();
				api.prototype.constructor = api;
			
			return new api(); // present us a inject ready api
		})( {} )
	});
	
	/* @NOTE these are browser specific hacks, they are intended to be executed and located with out usersniffing */
	if( fn[ 0 ].call( top.opera ) === "[object Opera]" ){
		/* tell opera to stop beeing a dickhead and stop disabling the onunload event, 
		   we need to check objects because some nutheads use fake userAgents, god knowns why.. */
		history.navigationMode = "compatible"; // force onunload events
	} else if( !+"\v1" && vanilla.browser.version == 6 ){
		/* the !+"\v1" is a hack to make sure we are on IE, no useragent spoofing here. If this is true 
		   we will check if the version is IE, so we are 100% we wont generate errors for others */
		try { document.execCommand( "BackgroundImageCache", false, true ); } catch( e ){ /* prevent back image flickr */ }
	}
	
	tmp.content = (tmp.scripts = document.getElementsByTagName("script"))[ tmp.scripts.length - 1].innerHTML;
	
	// start the DOMReady function
	vanilla.onDOMReady(function(){ tmp.end = (new Date()).valueOf(); var e = document.getElementById("parsetime"); if( e ){ e.innerHTML = tmp.end - fuel.start }} );
	vanilla.addEvent("load", function(){ tmp.enddate = (new Date()).valueOf(); var e = document.getElementById("loadtime"); if( e ){ e.innerHTML = tmp.enddate - fuel.start }});
	
	return setTimeout(Function(tmp.content.replace(/(\/\*([\s\S]*?)\*\/)|(?:^\s*<!--\s*|\s*(?:\/\/)?\s*-->\s*$)|(<!--([\s\S]*?)-->)/gm,"")),0);
	
})( window, {} );
