 /*
 * jQuery history plugin
 * 
 * The MIT License
 * 
 * Copyright (c) 2006-2009 Taku Sano (Mikage Sawatari)
 * Copyright (c) 2010 Takayuki Miwa
 * 
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 * 
 * The above copyright notice and this permission notice shall be included in
 * all copies or substantial portions of the Software.
 * 
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
 * THE SOFTWARE.
 *
 * Modified by Matteo Cargasacchi up to disable when JQuery is not loaded
 */

if (typeof jQuery == 'function') {
	(function($) {
			var locationWrapper = {
					put: function(hash, win) {
							(win || window).location.hash = this.encoder(hash);
					},
					get: function(win) {
							var hash = ((win || window).location.hash).replace(/^#/, '');
							try {
									return $.browser.mozilla ? hash : decodeURIComponent(hash);
							}
							catch (error) {
									return hash;
							}
					},
					encoder: encodeURIComponent
			};
	
			var iframeWrapper = {
					id: "__jQuery_history",
					init: function() {
							var html = '<iframe id="'+ this.id +'" style="display:none" src="javascript:false;" />';
							$("body").prepend(html);
							return this;
					},
					_document: function() {
							return $("#"+ this.id)[0].contentWindow.document;
					},
					put: function(hash) {
							var doc = this._document();
							doc.open();
							doc.close();
							locationWrapper.put(hash, doc);
					},
					get: function() {
							return locationWrapper.get(this._document());
					}
			};
	
			function initObjects(options) {
					options = $.extend({
									unescape: false
							}, options || {});
	
					locationWrapper.encoder = encoder(options.unescape);
	
					function encoder(unescape_) {
							if(unescape_ === true) {
									return function(hash){ return hash; };
							}
							if(typeof unescape_ == "string" &&
								 (unescape_ = partialDecoder(unescape_.split("")))
								 || typeof unescape_ == "function") {
									return function(hash) { return unescape_(encodeURIComponent(hash)); };
							}
							return encodeURIComponent;
					}
	
					function partialDecoder(chars) {
							var re = new RegExp($.map(chars, encodeURIComponent).join("|"), "ig");
							return function(enc) { return enc.replace(re, decodeURIComponent); };
					}
			}
	
			var implementations = {};
	
			implementations.base = {
					callback: undefined,
					type: undefined,
	
					check: function() {},
					load:  function(hash) {},
					init:  function(callback, options) {
							initObjects(options);
							self.callback = callback;
							self._options = options;
							self._init();
					},
	
					_init: function() {},
					_options: {}
			};
	
			implementations.timer = {
					_appState: undefined,
					_init: function() {
							var current_hash = locationWrapper.get();
							self._appState = current_hash;
							self.callback(current_hash);
							setInterval(self.check, 100);
					},
					check: function() {
							var current_hash = locationWrapper.get();
							if(current_hash != self._appState) {
									self._appState = current_hash;
									self.callback(current_hash);
							}
					},
					load: function(hash) {
							if(hash != self._appState) {
									locationWrapper.put(hash);
									self._appState = hash;
									self.callback(hash);
							}
					}
			};
	
			implementations.iframeTimer = {
					_appState: undefined,
					_init: function() {
							var current_hash = locationWrapper.get();
							self._appState = current_hash;
							iframeWrapper.init().put(current_hash);
							self.callback(current_hash);
							setInterval(self.check, 100);
					},
					check: function() {
							var iframe_hash = iframeWrapper.get(),
									location_hash = locationWrapper.get();
	
							if (location_hash != iframe_hash) {
									if (location_hash == self._appState) {    // user used Back or Forward button
											self._appState = iframe_hash;
											locationWrapper.put(iframe_hash);
											self.callback(iframe_hash); 
									} else {                              // user loaded new bookmark
											self._appState = location_hash;  
											iframeWrapper.put(location_hash);
											self.callback(location_hash);
									}
							}
					},
					load: function(hash) {
							if(hash != self._appState) {
									locationWrapper.put(hash);
									iframeWrapper.put(hash);
									self._appState = hash;
									self.callback(hash);
							}
					}
			};
	
			implementations.hashchangeEvent = {
					_init: function() {
							self.callback(locationWrapper.get());
							$(window).bind('hashchange', self.check);
					},
					check: function() {
							self.callback(locationWrapper.get());
					},
					load: function(hash) {
							locationWrapper.put(hash);
					}
			};
	
			var self = $.extend({}, implementations.base);
	
			if($.browser.msie && ($.browser.version < 8 || document.documentMode < 8)) {
					self.type = 'iframeTimer';
			} else if("onhashchange" in window) {
					self.type = 'hashchangeEvent';
			} else {
					self.type = 'timer';
			}
	
			$.extend(self, implementations[self.type]);
			$.history = self;
	})(jQuery);
}

