
try{document.execCommand('BackgroundImageCache',false,true);}catch(err){}

//-------------------------------------------------------------------
//  lang. from prototype.js
//-------------------------------------------------------------------
Kore_DEVELOPMENT = false;

/**
 * Defines a generic abstract 'Class' object; its "initialize" method will 
 * automatically  be called upon instantiation, with the parameters sent to
 * the constructor.
 * @constructor
 */
Class = {
	create: function() {
	  return function() {
	    this.initialize.apply(this, arguments);
	  }
	}
};

/**
 * Binds a deferred function call ( closure) to a certain object, to preserve 
 * the "this" instance inside the call
 * - the first parameter is used as this. 
 * - the rest of the parameters are passed as well
 * @param {Function} destination 	This is the object to copy properties to.
 * @param {Object} the object t be used as this inside the deferred call
 * @return a new function using the passed parameter as "this" inside the new 
 * 	function
 * @type Function
 */

Function.prototype.bind = function() {
  var __method = this;
  var args = $A(arguments);
  var object = args.shift();
  return function() {
    return __method.apply(object, args.concat($A(arguments)));
  }
}

/**
 * Binds a deferred function call ( closure) as an event listener to a certain 
 * object, to preserve the "this" instance inside the call
 * @param {Function} destination 	This is the object to copy properties to.
 * @param {Object} the object t be used as this inside the deferred call
 * @return a new function using the passed parameter as "this" inside the new 
 * 	function
 * @type Function
 */
Function.prototype.bindAsEventListener = function(object) {
  var __method = this;
  return function(event) {
    return __method.call(object, event || window.event);
  }
}

/**
 * Copies an object properties to another.
 * @param {Object} destination 	This is the object to copy properties to.
 * @param {Object} source		This is the object to copy properties from.
 * @return void
 */
Object.extend = function(destination, source) {
  for (var property in source) {
    destination[property] = source[property];
  }
  return destination;
};


/**
 * Copies all properties of an object to a new Object instance
 * @param {Object} source		This is the object to copy.
 * @return {Object} a copy of the source object
 */
Object.copy = function(source) {
	return Object.extend(new Object(), source);
}

$A = Array.from = function(iterable) {
  if (!iterable) return [];
  if (iterable.toArray) {
    return iterable.toArray();
  } else {
    var results = [];
    for (var i = 0; i < iterable.length; i++)
      results.push(iterable[i]);
    return results;
  }
}

/**
 * Abstract class to be extended by all interfaces that provide indexable
 * content (such as Arrays);
 * @private
 */
Enumerable = {
  _break: {},
  /**
   * @private
   * @see each
   */   
  _each: function(iterator) {
    for (var key in this) {
      var value = this[key];
      if (typeof value == 'function') continue;
      var pair = [key, value];
      pair.key = key;
      pair.value = value;
      iterator(pair);
    }
  },
  /**
   * Executes an iterator function with each element of the given Enumerator
   * object as parameter
   * @param {Function} iterator		A function to receive each element of 
   * 								the collection, in turn.
   * @return: void
   */
  each: function(iterator) {
    var index = 0;
    try {
      this._each(function(value) {
        try {
          iterator(value, index++);
        } catch (e) {
          throw e;
        }
      });
    } catch (e) {
      if (e != Enumerable._break) throw e;
    }
  },
  /**
   * Checks if a particular object is to be found in a given Enumerator object
   * @param {Any}			The object to be searched for
   * @return {Boolean}	True if the object is found
   */
  include: function(object) {
    var found = false;
    this.each(function(value) {
      if (value == object) {
        found = true;
        throw Enumerable._break;
      }
    });
    return found;
  },
/**
 * Combines all the elements of the collection using the iterator function. 
 * The iterator is called passing the result of the previous iteration in the 
 * 'accumulator' argument. 
 * The first iteration gets 'initialValue' in the 'accumulator' argument. The 
 * last result is the final return value.
 * @param {Any} initialValue		any object to be used as the initial value
 * @param {Function} iterator	a function object conforming to func(accumulator, value, index)
 */
  inject: function(memo, iterator) {
    this.each(function(value, index) {
      memo = iterator(memo, value, index);
    });
    return memo;
  },
  /**
   * Calls the iterator function for each element in the collection and returns each result 
   * in an Array, one result element for each element in the collection, in the same sequence.
   * @param {Function}		iterator: a function object conforming to func(value, index)
   */
  collect: function(iterator) {
    var results = [];
    this.each(function(value, index) {
      results.push(iterator(value, index));
    });
    return results;
  },
  /**
   * Calls the iterator function for each element in the collection and returns all elements
   * that caused the iterator to return a result that could evaluate to true.
   * @param {Function}		iterator: a function object conforming to func(value, index)
   */
  findAll: function(iterator) {
    var results = [];
    this.each(function(value, index) {
      if (iterator(value, index))
        results.push(value);
    });
    return results;
  }
}
Object.extend(Enumerable, {
  /**
   * @see Enumerable#collect
   */
  map: Enumerable.collect
})
Object.extend(Array.prototype, Enumerable);
/**
 * @private
 */
Object.extend(Array.prototype, {
  /**
   * @private
   */
  _each: function(iterator) {
    for (var i = 0; i < this.length; i++)
      iterator(this[i]);
  },
  /**
   * Returns de last item in the array
   * @return {Any}
   */
  last: function() {
    return this[this.length - 1];
  }
});



Object.extend(String.prototype, {
  /**
  * Splits a querystring into an associative Array indexed by parameter
  * name (more like a hash).
  * @return {Object} -- Hash
  */
  toQueryParams: function() {
  	if(this.length != 0){
	    var pairs = this.match(/^\??(.*)$/)[1].split('&');
	    return pairs.inject({}, function(params, pairString) {
	      var pair = pairString.split('=');
	      params[pair[0]] = pair[1];
	      return params;
	    });
  	} else {
  		return {};
  	};
  },
  /**
  * Removes white spaces from beginning and end of the String object called on.
  * @return {String} -- The new string
  */
  trim: function() {
    return this.replace(/^\s*/, "").replace(/\s*$/, "");
  }, 

  escape_entities: function() {
  	return this.replace(/\&/g, "&amp;").replace(/"/g, "&quot;").replace(/</g, "&lt;").replace(/>/g, "&gt;");
  }, 
 
  unescape_entities: function() {
  	return this.replace(/\&amp;/, "&").replace(/\&quot;/, "\"").replace(/\&lt;/, "<").replace(/\&gt;/g, ">");
  }


});
/**
* @see String#toQueryParams
*/
String.prototype.parseQuery = String.prototype.toQueryParams;


/**
 * Defines a generic abstract 'Hash' object -- language extension.
 * @constructor
 */
Hash = {
  /**
   * Returns all the items of the hash in a string formatted like a query string, e.g. 
   * 'key1=value1&key2=value2&key3=value3'
   * @return {String}
   */
  toQueryString: function() {
	var pairs = this.map(function(pair) {
		var validPair = ((typeof pair[0] == 'string') ||
                        (typeof pair[0] == 'number'))  && 
                        ((typeof pair[1] == 'string') ||
                        (typeof pair[1] == 'number'))
		return validPair? pair.map(encodeURIComponent).join('='): null;
    });
    var toret = pairs.findAll(function(pair){return pair!== null});
    return toret.join('&');
  }
}
/**
 * Public interface to convert a generic Javascript Object into a Hash object (i.e., add all
 * members of Hash).
 * @param {Object}			The Object to be 'converted'
 * @return {Object}--Hash 	A Hash object holding the content of the old Object
 */
function $H(object) {
  var hash = Object.extend({}, object || {});
  Object.extend(hash, Enumerable);
  Object.extend(hash, Hash);
  return hash;
}

Form = {};
Form.serialize = function(frm) {
	var queryComponents = new Array();
	var element = null;
	var elementType = '';
	var parameter = null;
	var queryComponent = null;
	for(var i=0; i<frm.elements.length; i++) {
		element = frm.elements[i];
		if (element.disabled) {
			//ignore disabled elements; should not be submited
			continue;
		}
		try {
			//ignore form elements without name
			if(!element.name) {
				continue;
			}
		} catch(err) {
			continue;
		}
		//some form elements do not have type set (FIELDSET)
		elementType = element.type ? element.type.toLowerCase()	: '';
		if (!elementType) {
			continue;
		}
		parameter = null;
		switch (elementType) {
		case 'submit':
		case 'hidden':
		case 'password':
		case 'text':
		case 'textarea':
			parameter = [element.name, element.value];
			break;
		case 'checkbox':
		case 'radio':
			if (element.checked) {
			  parameter = [element.name, element.value];
			}
			break;
		case 'select-one':
			var value = '';
			var opt;
			var index = element.selectedIndex;
			if (index >= 0) {
				opt = element.options[index];
				value = opt.value || '';
			}
			parameter = [element.name, value];
    	break;
		case 'select-multiple':
			var value = [];
			for (var j = 0; j < element.length; j++) {
				var opt = element.options[j];
				if (opt.selected) {
					value.push(opt.value || '');
				}
			}
			parameter = [element.name, value];
    	break;
		}
		if (parameter != null) {
			var charset = Kore.getDocumentCharset();
			var escapeFunction = charset.toLowerCase()=='iso-8859-1'?escape:encodeURIComponent;
			queryComponent = escapeFunction(parameter[0]) + '=' + escapeFunction(parameter[1]);
			queryComponents.push(queryComponent);
		}
	}
	return queryComponents.join('&');
}


//-------------------------------------------------------------------
//  Kore.Loader
//-------------------------------------------------------------------


/**
 * The loading module will use the server side web service to load modules 
 * or will load directly specific js/css files.
 * 
 * If there is no server side (HTML only sites) the loading mode will 
 * request the JSON configuration file (see server side) and will start 
 * loading all the js files one by one. 
 * 
 * The loader will have a cache to store the loaded modules 
 * and if a module is requested again if will be loaded from cache and 
 * evaluated again.
 */

if (!Kore) {
	var Kore = {}
}
Kore._empty = function(){};

/** 
 * all the containers will be registered here by the html processor 
 * so the addLoadListener() function to know at which container to register
 * the listener.
 */
Kore.container = null;

/**
 * Adds a load listener to a container.
 * @param {Function} callback The callback function to be called when the event 
 * 		is fired.
 * @param {Object} scope The callback's scope object.
 */
Kore.addLoadListener = function(callback, scope) {
	if(typeof scope == 'undefined' || scope == null) {
		throw 'Calling addLoadListener without a scope is not allowed.\n' +
				'Remove information must be stored.';
	}
	if(Kore.container != null) {
		Kore.container.loadEvent.subscribe(callback, scope, true);
	} else {
		YAHOO.util.Event.addListener(window, "load", callback, scope, true);
	}
}

/**
 * Removes a load listener from a container.
 * @param {Function} callback The callback function to be called when the event 
 * 		is fired.
 * @param {Object} scope The callback's scope object.
 */
Kore.removeLoadListener = function(callback, scope) {
	if (scope.loadContainer) {
		scope.loadContainer.loadEvent.unsubscribe(callback, scope);
	} else {
		YAHOO.util.Event.removeListener(window, "load", callback, scope);
	}
}


/**
 * Adds an unload listener to a container.
 * @param {Function} callback The callback function to be called when the event 
 * 		is fired.
 * @param {Object} scope The callback's scope object.
 */
Kore.addUnloadListener = function(callback, scope) {
	if(typeof scope == 'undefined' || scope == null) {
		throw 'Calling addUnloadListener without a scope is not allowed.\n' +
				'Remove information must be stored.';
	}
	if(Kore.container != null) {
		Kore.container.unloadEvent.subscribe(callback, scope, true);
		scope.unloadContainer = Kore.container;
	} else {
		YAHOO.util.Event.addListener(window, "unload", callback, scope, true);
	}
}

/**
 * Removes an unload listener from a container.
 * @param {Function} callback The callback function to be called when the event 
 * 		is fired.
 * @param {Object} scope The callback's scope object.
 */
Kore.removeUnloadListener = function(callback, scope) {
	if (scope.unloadContainer) {
		scope.unloadContainer.unloadEvent.unsubscribe(callback, scope);
	} else {
		YAHOO.util.Event.removeListener(window, "unload", callback, scope);
	}
}

Kore.getIncludesBase = function(callback, scope ) {
    var s = null;
    var scripts = document.getElementsByTagName("script");
    for (var i=0; i< scripts.length; i++) {
        var url = scripts[i].src;
        if (typeof url !== "undefined") {
            if (url.indexOf("includes/kore/kore.js") != -1) {
                s = scripts[i];
                break;
            }
        }
    }
    if (s == null) {
		// TODO remove the hack
		window.setTimeout(function(){ Kore.getIncludesBase(callback) }, 10);
		return null;
    }
	var url = s.src;
	url = url.replace(/includes\/kore\/kore\.js/, '');
	if(typeof callback == 'function'){
		if(!scope ){ scope = window };
		callback.call(scope, url);
	};
	return url;
}


Kore._dependencies = null;
Kore._pathToDependenciesFile = 'includes/kore/dependencies.js';
Kore._loaderService = 'includes/kore/ldr/resProviderService';
Kore._pathToLogging = 'includes/kore/log/loggingService';

//the list of js files not to be loaded by the loader
//Kore.excludeJSFileList = ['kore.js', 'load.js'];

/*
 * Kore.Cache - manage cacheable items
 * used by JsLoader, CssLoader to store js files, css files and modules
 */
Kore.Cache = function () {
	this._cache = {};
	this._callbacks = {};
}

Kore.Cache = Object.extend(new Kore.Cache(), {
	
	/**
	 * Adds a new pair (key, value) to the cache. 
	 * Each (key, value) pair may have different
	 * stares. This sets the state to 0, the default value. 
	 * @param {String} key The pair's key
	 * @param {String} value The pair's value
	 */
	add: function(key, value) {	
		// hard ignore the same file
		if(key.indexOf("includes/kore/kore.js") != -1) {
			this._cache[key] = {
				'value': '',
				'state': Kore.Cache.States.executed
			}
			return;
		}
		this._cache[key] = {
			'value': value,
			'state': 0
		}
	},
	
	/**
	 * Sets the value for an item in the cache.
	 * @param {String} key The item identifier.
	 * @param {String} value The new value.
	 */
	setValue: function(key, value) {
		var item = this._get(key);
		if(item != null) {
			item.value = value;
		}
	},

	/** 
	 * Gets the value for the identified item.
	 * @param {String} key The item identifier.
	 * @return the item's value.
	 */
	getValue: function(key) {
		var item = this._get(key);
		if(item != null) {
			return item.value;
		}
	}, 
	
	/**
	 * Gets the item for the specified key. 
	 * @param {String} key The item identifier.
	 * @return The item if it is found or null.
	 */
	_get: function(key) {
		var item = this._cache[key];
		if(!item) {
			return null;
		}
		
		return item;
	},

	/**
	 * Sets the state for an item in the cache.
	 * It fires a state change event
	 * for the key.
	 * @param {String} key The item identifier.
	 * @param {int} state The new state.
	 */
	setState: function(key, state) {
		var item = this._get(key);
		if(item != null && item.state != state) {
			item.state = state;
			this._fireStateChange(key, state);
		}
	},

	/** 
	 * Gets the state for the identified item.
	 * @param {String} key The item identifier.
	 * @return the item's state.
	 */
	getState: function(key) {
		var item = this._get(key);
		if(item != null) {
			return item.state;
		}
	}, 
	
	/** 
	 * Checks the existance of the specified key inside the cache.
	 * @param {String} key The item identifier.
	 * @return true if the key is in the cache
	 * @type Boolean
	 */
	has: function(key) {
		return (this._get(key) != null);
	},

	
	/** 
	 * Fires the state change event. This will call all registered callbacks 
	 * for the key.
	 * @param {String} key The item identifier.
	 * @param {Object} item The item that changed it's state.
	 * @private
	 */
	_fireStateChange: function(key, state) {
		var /** Array */ listeners = this._callbacks[key];
		if (!listeners) {
			return;
		}
		
		for(var i=0; i<listeners.length; i++) {
			var li = listeners[i];
			if(li.state == state) {
				(li.fn || Kore._empty)(key);
			}
		}
		
	},

	/**
	 * Adds a callback function as a listener for the state change event 
	 * of the item identified by key.
	 * @param {String} key The item identifier. 
	 * @param {int} state The state function is interested in
	 * @param {Function} fn The function to be called when the item identified
	 * 		by key is changing state to the specified state.
	 */
	_addStateChangeListener: function(key, state, fn) {
		if (!this._callbacks[key]) {
			this._callbacks[key] = [];
		}
		
		this._callbacks[key].push({
			'fn': fn,
			'state': state
		});
		
		// call the listener it item already at the interested state.
		if(this.getState(key) == state) {
			fn(key);
		}
	}
	
});


Kore.Cache.States = {
	'loading': 0, 
	'loaded': 1,
	'executed': 4
};

Kore.getDependencies = function (relPath) {
	if (Kore._dependencies == null) {
		var script = '';
	    var sock = new Kore.Request(relPath + Kore._pathToDependenciesFile, {
			method: 'get', 
			asynchronous: false
	    });

		if (sock.transport.responseText) {
			script = sock.transport.responseText;
		}

		try {
			Kore._dependencies = eval('(' + script + ')');
		} catch(err) {
			Kore._dependencies = {};
		}
	}
	return Kore._dependencies;
}

Kore.Loader = Class.create();
Kore.Loader.prototype = {
	relPath: null,
	initialize: function () {
	},

	/**
	 * Set the path to site root 
	 * @param {String} path path to site root
	 */
	setRelPath : function(path) {
		this.relPath = path;
	}, 

	/**
	 * Set the setServerExtension
	 * @param {String} server extension
	 */
	setServerExtension : function(serverExtension) {
		this.serverExtension = serverExtension;
	}, 
	/**
	 * Adds a module to the module list to be loaded.
	 * @param {String} moduleName The modules name that will be loaded.
	 */
	addModule : function(moduleName) {
		if(!this.modulesToLoad.include(file)) {
			this.modulesToLoad.push(file);
		}
	}, 
	/**
	 * Loads all modules set to be loaded in the 
	 * <code>modulesToLoad</code> array. 
	 * asynch call
	 * @param {Ref} callback optional callback function to be executed 
	 * 		when all modules are loaded
	 */
	loadModulesClientSide : function (callback) {
		if (this.modulesToLoad.length == 0) {
			return;
		}
		var toLoad = this.buildModulesFilesList(this.modulesToLoad);
		for (var i=0; i < toLoad.files.length; i++) {
			this.addFile(toLoad.files[i][0]);
		}

		var self = this;

		this.loadFiles(function() {
			self.modulesToLoad = new Array();
			(callback || Kore._empty)();
		});
	}, 

	/**
	 * Builds the list of files to be loaded for a list of modules, 
	 * starting from the dependencies file
	 * @param {Array} modulesToLoad an Array of module names
	 * @return struct containing modules available in the dependencies 
	 *  	file and all their included files
	 */
	buildModulesFilesList : function (modulesToLoad) {
		var dependencies = Kore.getDependencies(this.relPath);
		var modules = [];
		var file_urls = ',';
		var files = [];
		var module = '';
		for(var i=0; i<modulesToLoad.length; i++) {
			module = modulesToLoad[i];
//			Kore.Cache.add(module, module);
			if (dependencies[module]) {
				for (var j=0; j<dependencies[module].includes.length; j++) {
					var file = dependencies[module].includes[j];
					//add and execute only ONCE
					if ((file_urls+',').indexOf(',' + file + ',') != -1) {
						continue;
					}
					file_urls += ',' + file;
					//these are the files that will be aggregated by the ProviderService
					files.push([file, '']);
				}
				module += '_' + dependencies[module].version;
				modules.push(module);
			}
		}
		return {modules:modules, files:files};
	}, 

	setServerSide: function(val) {
		this.serverSide = val;
	}, 


	/**
	 * Loads all modules set to be loaded in the <code>modulesToLoad</code> array. 
	 * If a modules already exists in cache it will be loaded from cache. 
	 * Asynchronous call to includes/kore/ldr/resProviderService.php?cssmodule=kore_v1
	 * or asynchronous call to includes/kore/ldr/resProviderService.php?jsmodule=kore_v1
	 * asynch call
	 * @param {Ref} callback optional callback function to be executed 
	 * 		when all modules are loaded
	 * @return undefined
	 */
	load: function(callback) {
		if (this.modulesToLoad.length == 0) {
			(callback || Kore._empty)();
			return;
		}
		if (!this.serverSide) {
			this.loadModulesClientSide(callback);
			return;
		}
		var self = this;
		var toLoad = this.buildModulesFilesList(this.modulesToLoad);
		//check if at least one requested module is defined in the dependencies file
		if (toLoad.modules.length) {
			var ajxUrl = Kore._loaderService + '.' + this.serverExtension 
					+ '?' + this.type + 'module=' + toLoad.modules.join("|");
			
			//add the file to the cache, only if it does not exist
			if (!Kore.Cache.has(ajxUrl)) {
				Kore.Cache.add(ajxUrl, '');

				Kore.Cache._addStateChangeListener(ajxUrl, 
						Kore.Cache.States.loaded, 
						function(ajxUrl) {
							this.modulesToLoad = [];
							this.interpretFile(ajxUrl);
							(callback || Kore._empty)();
						}.bind(this));

				this.loadFile(ajxUrl, true);
			} else {
				if (!this.isLoaded(ajxUrl)) {
					Kore.Cache._addStateChangeListener(ajxUrl,
						Kore.Cache.States.loaded,
						function(ajxUrl) {
							this.modulesToLoad = [];
							(callback || Kore._empty)();
						}.bind(this));
				}
			}

		} else {
			(callback || Kore._empty)();
		}
	}, 
	
	isAbsolutePath: function(src) {
		var is_absolute = false;
		if (src.toString().match(/^(https?\:\/\/|\/)/)) {
			is_absolute = true;
		}
		return is_absolute;
	}, 
	
	/**
	 * Load the file content using XmlHttpRequest
	 *  it checks for 404 - not found - response and invalid content-type header
	 * @param {String} file the file to be loaded
	 * @param {Boolean} async indicate if the request should be non-blocking
	 * @param {Ref} callback the function to be called when done with success
	 */
	loadFile: function (file, async) {
		if (this.notFoundFiles[file]) {
			return;
		}

		var self = this;
		var source = file;
		if (!this.isAbsolutePath(source)) {
			source = this.relPath + file;
		}
		var request = new Kore.Request(source, {
			method: 'get',
			asynchronous: async,
			onComplete: function(sock) {
				if (sock.status ==  404) {
					self.notFoundFiles[file] = true;
					Kore.Cache.setValue(file, '');
					Kore.Cache.setState(file, Kore.Cache.States.loaded);
					if (file.indexOf(Kore._loaderService) != -1) {
						return;
					}
				} else {
					Kore.Cache.setValue(file, sock.responseText);
					Kore.Cache.setState(file, Kore.Cache.States.loaded);
				}
			},
			on404: function(sock) {
				self.notFoundFiles[file] = true;
				if (file.indexOf(Kore._loaderService) != -1) {
					// if file is "Kore._loaderService" then no server side, degrade.
					self.setServerSide(false);
					self.loadModulesClientSide();
				}
			}
		});
		
		if (!async) {
			if (request.transport.status == 404) {
				this.notFoundFiles[file] = true;
				Kore.Cache.setValue(file, '');
			} else {
				Kore.Cache.setValue(file, request.transport.responseText);
			}
			Kore.Cache.setState(file, Kore.Cache.States.loaded);
		}
	}, 
	
	/**
	 * Loads all files set to be loaded in the <code>filesToLoad</code> array. 
	 * If a file already exists in cache it will be loaded from cache. 
	 * This function prepares the list of files to be loaded, grouped by
	 * The actual load process will take place in _loadFiles
	 * asynch load
	 * @param {Ref} callback optional callback function to be executed 
	 * 		when all files are loaded
	 */
	loadFiles: function (callback) {
		if(this.relPath == null) {
			Kore.getIncludesBase(function(url) {
				this.relPath = url;
				this._loadFiles(callback);
			}, this);
		} else {
			this._loadFiles(callback);
		}
	}, 
	
	isLoaded: function(file) {
		return (Kore.Cache.getState(file) == Kore.Cache.States.loaded ||
				Kore.Cache.getState(file) == Kore.Cache.States.executed );
	},

	/**
	 * Loads and evaluates several files corresponding to one batch
	 * If a file already exists in cache it will be loaded from cache. 
	 * asynch load
	 * @param {Ref} callback optional callback function to be executed 
	 * 		when all files are loaded
	 * @private
	 */
	 _loadFiles : function (callback) {
		if (this.filesToLoad.length == 0) {
			(callback || Kore._empty)();
			return;
		}

		var loaded_count = 0;

		for (var i=0; i < this.filesToLoad.length; i++) {
			var fileToLoad = this.filesToLoad[i];
            
            // ignore kore
            if(fileToLoad.indexOf('includes/kore/kore.js') != -1) {
                Kore.Cache.add(fileToLoad, null);
                this.finalizeLoad( callback);
                continue;
            }
			
			//add the file to the cache, only if it does not exist
			if (!Kore.Cache.has(fileToLoad)) {
				Kore.Cache.add(fileToLoad, null);

				Kore.Cache._addStateChangeListener(fileToLoad, 
						Kore.Cache.States.loaded, 
						function(fileToLoad) {
							this.loadedFiles[fileToLoad] = Kore.Cache.getValue(fileToLoad);
							this.finalizeLoad(callback);
						}.bind(this));

				this.loadFile(fileToLoad, true);
			} else {
				if (this.isLoaded(fileToLoad)) {
						this.finalizeLoad(callback);
				} else {
					// the file was already in the cache, not loaded!!!!!!
					// the loaded case is caught in the function call before this
					// if the file is already in the cache, only register me
					// to listen when the file is ready
					Kore.Cache._addStateChangeListener(fileToLoad,
						Kore.Cache.States.loaded,
						function(fileToLoad) {
							this.loadedFiles[fileToLoad] = Kore.Cache.getValue(fileToLoad);
							this.finalizeLoad(callback);
						}.bind(this));
				}
			}
		}
	}, 

	/**
	 * Ends the file loading.
	 * @param {Integer} batch_id 
	 */
	finalizeLoad : function (callback) {
		this.loadedCount++;
		if (this.filesToLoad.length == this.loadedCount) {
			for (var j=0; j < this.filesToExecute.length; j++) {
				this.interpretFile(this.filesToExecute[j]);
			}

			(callback || Kore._empty)();
		}
		
	}, 

	/**
	 * Interprets the source. To be implemented by derived classes to 
	 * performe specific interpretation of js or css sources. 
	 * @param {String} source The source string. 
	 */
	interpretSource: function(source) {
		
	}
}

Kore.JSLoader = Class.create();
Kore.JSLoader.prototype = Object.extend(new Kore.Loader(), {

	type: 'js', 

	/**
	 * Safely executes JavaScript
	 * @param {String} the script to be evaluated
	 * @return nothing
	 */
	initialize: function(doEvaluation) {
		/**
		 * The list of the modules to be loaded on the next load() call.
		 */
		this.modulesToLoad = new Array();
		/**
		 * The list of the files to be loaded on the next loadFiles() call.
		 * load each file once, no matter how many addFile() calls
		 */
		this.filesToLoad = new Array();
		/**
		 * The list of the files to be executed on the next loadFiles() call.
		 * load each file once, execute for each addFile() call
		 */
		this.filesToExecute = new Array();
	
	
		this.loadedFiles = {};
		/**
		 * Flag that indicates that the loading module will use the server side
		 * service to retrieve concatenated js files.
		 */
		this.serverSide = true;
		/**
		 * Path to site root
		 * file paths inside the dependencies file are relative to site root
		 */
		this.relPath = Kore.getIncludesBase();
	
		this.serverExtension = "";
		
		this.loadedCount = 0;
		
		/**
		 * The list of the files not found (404) by Request
		 */
		this.notFoundFiles = {};

		if (typeof doEvaluation == 'undefined') {
			doEvaluation = true;
		}
		this.doEvaluation = doEvaluation;
	}, 
	
	interpretSource : function(script) {
		if (script.trim() == "") {
			return;
		}


		try {
			if (window.execScript) {
				/**
				 * IE fails if script is surrounded by comments: <!-- //-->
				 * Could not complete the operation due to error 80020101.
				 **/
				script = script.replace(/^[\r\n\s]*<!--/i, '').replace(/\/\/-->[\r\n\s]*$/i, '');
				window.execScript(script, "JavaScript");
			} else {
				if (navigator.userAgent.indexOf('Safari')>0) {
					script = script.replace(/\r\nvar\s+([a-z0-9_\-\$]+)\s*\=/ig, "\r\nwindow['$1'] =");
					script = script.replace(/\r\nfunction\s+([a-z0-9_\-]+)\s*\(/ig, "\r\nwindow['my$1'] = my$1; function $1(){return my$1.apply(this, arguments);}; window['$1']=$1; function my$1(");
				}
				window.eval(script);
			}
		} catch(err) {
			alert("Error in Kore.JSLoader.interpretSource:\r\n[" + err.message + "]");
		}
	},
	
	interpretFile: function(fileName) {
		if(!this.doEvaluation) {
			return;
		}
		if (Kore.Cache.getState(fileName) != Kore.Cache.States.executed) {
			var src = Kore.Cache.getValue(fileName);
			//console.info("interpretFile", fileName);
			this.interpretSource(src);
			Kore.Cache.setState(fileName, Kore.Cache.States.executed);
		}
	},
		
	/**
	 * Loads a js file from the server. After the file is loaded
	 * it must be evaluated.
	 * @param {String} file The path of the file to be loaded.
	 * synch call
	 */
	loadJsFile : function(file) {
		if (this.isLoaded(file)) {
			this.interpretFile(file);
			return;
		}

		Kore.Cache._addStateChangeListener(file, 
				Kore.Cache.States.loaded, 
				this.interpretFile.bind(this));		

		this.loadFile(file, false);
	}, 

	/**
	 * Adds a file to the file list to be loaded async.
	 * @param {String} file The file path that will be loaded.
	 */
	addFile: function(file) {
		if (this.isLoaded(file)) {
			this.interpretFile(file);
			return false;
		}
		
		if(!this.filesToLoad.include(file)) {
			this.filesToLoad.push(file);
		}
		
		this.filesToExecute.push(file);
	}

});

Kore.CSSLoader = Class.create();
Kore.CSSLoader.prototype = Object.extend(new Kore.Loader(), {
	type: 'css', 
	/**
	 * Safely add css to document
	 * @param {String} css string containg CSS style rules
	 * @return nothing
	 */
	initialize: function(doEvaluation) {
		/**
		 * The list of the modules to be loaded on the next load() call.
		 */
		this.modulesToLoad = new Array();
		/**
		 * The list of the files to be loaded on the next loadFiles() call.
		 * load each file once, no matter how many addFile() calls
		 */
		this.filesToLoad = new Array();
		/**
		 * The list of the files to be executed on the next loadFiles() call.
		 * load each file once, execute for each addFile() call
		 */
		this.filesToExecute = new Array();
	
		this.loadedCount = 0;
		
		this.loadedFiles = {};
		/**
		 * Flag that indicates that the loading module will use the server side
		 * service to retrieve concatenated js files.
		 */
		this.serverSide = true;
		/**
		 * Path to site root
		 * file paths inside the dependencies file are relative to site root
		 */
		this.relPath = Kore.getIncludesBase();
	
		this.serverExtension = "";
		if (typeof doEvaluation == 'undefined') {
			doEvaluation = true;
		}
		this.doEvaluation = doEvaluation;
		/**
		 * The list of the files not found (404) by Request
		 */
		this.notFoundFiles = {};
	}, 
	
	/**
	 * Adds the specified css file into the document
	 * @param {String} fileName the file to be imported
	 */
	interpretFile: function(fileName) {
		if(!this.doEvaluation) {
			return;
		}
		var src = Kore.Cache.getValue(fileName);
		if (Kore.Cache.getState(fileName) != Kore.Cache.States.executed) {
			if (document.createStyleSheet) {
				var head = document.getElementsByTagName("HEAD")[0];
				var link = document.createElement('link');
				link.rel = 'stylesheet';
				link.type = 'text/css';
				link = (head || document.body).appendChild(link);
				link.href = fileName;
			} else {
				this.interpretSource('@import "' + fileName + '";');
			}

			Kore.Cache.setState(fileName, Kore.Cache.States.executed);
		}
	},

	/**
	 * Adds the specified css style string into the document
	 * @param {String} css the style rules to be inserted
	 */
	interpretSource : function(css) {
		var head = document.getElementsByTagName('head')[0];
		if (document.createStyleSheet) {
			//IE only
			var style = document.createElement('style');
			style = (head || document.body).appendChild(style);
			if (style) {
				style.styleSheet.cssText = css;
			}
		} else {
			var tmp = document.createElement("SPAN");
			tmp.innerHTML = '<style>' + css + '</style>';
			try {
				(head || document.body).appendChild(tmp.firstChild);
			}catch(err) {
				alert("CssLoader interpret source error:" + err.message+"\r\n" + css);
			}
		}
	}, 
	/**
	 * Loads a css file from the server. After the file is loaded
	 * the css must be added to the document.
	 * @param {String} file The path of the file to be loaded.
	 * synch call
	 */
	loadCssFile: function(file) {
		if (this.isLoaded(file)) {
			return;
		}

		Kore.Cache._addStateChangeListener(file, 
				Kore.Cache.States.loaded, 
				function(file) {
					this.interpretFile(file);
				}.bind(this));		

		this.loadFile(file, false);
	}, 

	/**
	 * Adds a file to the file list to be loaded async.
	 * @param {String} file The file path that will be loaded.
	 */
	addFile : function(file) {
		if (this.isLoaded(file)) {
			return false;
		}
		if(!this.filesToLoad.include(file)) {
			this.filesToLoad.push(file);
		}
		this.filesToExecute.push(file);
	}	
});

/**
 * Logs a messege to the server.
 */
Kore.Log = function() {}
Kore.Log.prototype = {
	serverExtension: 'php',
	send: function(msg) {
		var relPath = Kore.getIncludesBase();
		
		var ajxUrl = relPath + Kore._pathToLogging + '.' + this.serverExtension 
				+ '?' + 'message=' + msg;
	
		var request = new Kore.Request(ajxUrl, {
			method: 'get',
			asynchronous: true
		});
	}
}

Kore.Request = function(url, options) {
	this.transport = this.getTransport();
	this.setOptions(options);
	this.request(url);
}
Kore.Request.Events = ['Uninitialized', 'Loading', 'Loaded', 'Interactive', 'Complete'];
Kore.Request.prototype = {
	getTransport: function() {
		var ret = false;
		var options = ['new XMLHttpRequest()', 
			'new ActiveXObject("Msxml2.XMLHTTP")', 
			'new ActiveXObject("Microsoft.XMLHTTP")'];
			
		for (var i=0; i<options.length; i++) {
			try {
				ret = eval(options[i]);
				break;
			} catch(err) {
				ret = false;
			}
		}
		return ret;
	} 
	, setOptions: function(options) {
		this.options = {
			method:       'post',
			asynchronous: true,
			contentType:  'application/x-www-form-urlencoded',
			parameters:   ''
		}
		Object.extend(this.options, options || {});
	}
	, responseIsSuccess: function() {
		return this.transport.status == undefined
			|| this.transport.status == 0
			|| (this.transport.status >= 200 && this.transport.status < 300);
	}
	, responseIsFailure: function() {
		return !this.responseIsSuccess();
	}
	, request: function(url) {
		var parameters = this.options.parameters || '';
		if (parameters.length > 0) parameters += '&_=';
		try {
			this.url = url;
			if (this.options.method == 'get' && parameters.length > 0) {
				this.url += (this.url.match(/\?/) ? '&' : '?') + parameters;
			}
			this.transport.open(this.options.method, this.url, this.options.asynchronous);
			if (this.options.asynchronous) {
				var self = this;
				this.transport.onreadystatechange = function () {
					self.onStateChange();
				}
				setTimeout((function() {self.respondToReadyState(1)}), 10);
			}
			this.setRequestHeaders();
			var body = this.options.postBody ? this.options.postBody : parameters;
			this.transport.send(this.options.method == 'post' ? body : null);
		} catch (e) { }
	}
	, setRequestHeaders: function() {
		var requestHeaders = ['X-Requested-With', 'XMLHttpRequest', 'Accept', 
			'text/javascript, text/html, application/xml, text/xml, */*'];
		if (this.options.method == 'post') {
			requestHeaders.push('Content-type', this.options.contentType);
			if (this.transport.overrideMimeType) {
				requestHeaders.push('Connection', 'close');
			}
		}
		if (this.options.requestHeaders) {
			for (var i=0; i<this.options.requestHeaders.length; i++) {
				requestHeaders.push(this.options.requestHeaders[i]);
			}
		}
		for (var i=0; i < requestHeaders.length; i += 2) {
			this.transport.setRequestHeader(requestHeaders[i], requestHeaders[i+1]);
		}
	}
	, onStateChange: function() {
		var readyState = this.transport.readyState;
		if (readyState != 1) {
			this.respondToReadyState(this.transport.readyState);
		}
	}
	, respondToReadyState: function(readyState) {
		if(typeof Kore == "undefined") {
			// request has arrived after the browser switched the page
			// bug on firefox
			return;
		}
		var event = Kore.Request.Events[readyState];
		var transport = this.transport;
		if (event == 'Complete') {
			try {
				(this.options['on' + this.transport.status]
					|| this.options['on' + (this.responseIsSuccess() ? 'Success' : 'Failure')]
					|| Kore._empty)(transport);
			} catch (e) { }
		}
		try {
			(this.options['on' + event] || Kore._empty)(transport);
		} catch (e) { }

		if (event == 'Complete') {
			this.transport.onreadystatechange = Kore._empty;
		}
	}
}

/**
 * Detect and returns the current user defined document charset
 * @return the document defined charset
 */
Kore.getDocumentCharset = function() {
	if (typeof(Kore.charset) != 'undefined') {
		return Kore.charset;
	}

	var charset = "";
	if (/Opera[\/\s]\d|AppleWebKit/i.test(navigator.userAgent)) {
		var metas = document.getElementsByTagName("META");
		var m = null;
		for( var i=0; i<metas.length; i++) {
			if (metas[i].httpEquiv.toString().toLowerCase() == 'content-type') {
				m = metas[i].content.match(/text\/html\s*;\s*charset\s*=\s*([^\s]*)/i);
				if (m) {
					charset = m[1];
				}
			}
		}
	} else {
		charset = document.charset?document.charset:document.characterSet;
	}
	if (typeof charset == 'undefined') {
		charset = 'iso-8859-1';
	}
	Kore.charset = charset;
	return Kore.charset;
}

Kore.Url = {};
/**
 * Extracts the parameters of the current URL, and returns 
 * it in two fashions:
 * 
 *	-> 	BACKWARD COMPATIBLE WAY:
 *      all that follows the question mark sign, 
 *      this actually returning the concatenated 
 * 		string of "location.search" and "location.hash".
 * 
 * 	->  NEW WAY:
 *      what follows the question mark sign, and 
 * 		what follows the hash sign, separately, as an
 * 		array.
 * 
 * @param {Boolean} rough When present, puts the function 
 * 					in background compatible mode.
 * @return {String} what follows the "?" -- <verbose == true>
 * @return {Object -- Array} [location.search, location.hash]
 */
Kore.Url.getParamsFromCurrentUrl = function(verbose) {
	var toret;
	if(verbose){
		toret = [ $H(window.location.search.replace(/^\?/, '').parseQuery()).toQueryString(),
		$H(window.location.hash.replace(/^\#/, '').parseQuery()).toQueryString()]
		return toret;
	} else {
		var _location = window.location.href.toString(); 
		toret = (/\?/.test(_location))? _location.replace(/^.*\?/, '') : '';
		return $H(toret.parseQuery()).toQueryString();
	};
};


Kore.isOkForAjax = function() {
	var toret = false;
	//test for ie
	if (Kore.is.ie && Kore.is.version >= 6) {
		toret = true;
	}
	//test for opera
	if (Kore.is.opera && Kore.is.version >= 9) {
		toret = true;
	}
	//test for firefox
	if (Kore.is.mozilla && Kore.is.version >= 1.6) {
		toret = true;
	}
	//test for safari
	if (Kore.is.safari && Kore.is.version >= 1.4) {
		toret = true;
	}
	return toret;
}
