/**
 * History.js HTML5 Support
 * @author Benjamin Arthur Lupton <contact@balupton.com>
 * @copyright 2010-2011 Benjamin Arthur Lupton <contact@balupton.com>
 * @license New BSD License <http://creativecommons.org/licenses/BSD/>
 */(function(a,b){a.History=a.History||{},a._History=a._History||{};var c=a.console||b,d=a.document,e=a._History,f=a.History,g=a.history;if(typeof f.initHtml5!=="undefined")throw new Error("History.js HTML5 Support has already been loaded...");f.initHtml5=function(){if(typeof f.Adapter==="undefined")return!1;f.options={hashChangeCheckerDelay:100,busyDelay:250},f.debug=function(){(f.debug.enable||!1)&&f.log.apply(f,arguments)},f.debug.enable=!1,f.log=function(){var a=typeof c!=="undefined",b=d.getElementById("log"),e="\n"+arguments[0]+"\n",f;if(a){var g=Array.prototype.slice.call(arguments),e=g.shift();typeof c.debug!=="undefined"?c.debug.apply(c,[e,g]):c.log.apply(c,[e,g])}for(f=1,n=arguments.length;f<n;++f){var h=arguments[f];if(typeof h==="object"&&typeof JSON!=="undefined")try{h=JSON.stringify(h)}catch(i){}e+="\n"+h+"\n"}b?(b.value+=e+"\n-----\n",b.scrollTop=b.scrollHeight-b.clientHeight):a||alert(e);return!0},e.getInternetExplorerMajorVersion=function(){var a=e.getInternetExplorerMajorVersion.cached=typeof e.getInternetExplorerMajorVersion.cached!=="undefined"?e.getInternetExplorerMajorVersion.cached:function(){var a,b=3,c=d.createElement("div"),e=c.getElementsByTagName("i");while(c.innerHTML="<!--[if gt IE "+ ++b+"]><i></i><![endif]-->",e[0]);return b>4?b:a}();return a},e.isInternetExplorer=function(){var a=e.isInternetExplorer.cached=typeof e.isInternetExplorer.cached!=="undefined"?e.isInternetExplorer.cached:e.getInternetExplorerMajorVersion()!==0;return a},f.emulated={pushState:!Boolean(a.history&&a.history.pushState&&a.history.replaceState)},e.isEmptyObject=function(a){for(var b in a){if(!this.hasOwnProperty(b))continue;return!1}return!0},e.cloneObject=function(a){var b,c;a?(b=JSON.stringify(a),c=JSON.parse(b)):c={};return c},f.contractUrl=function(a){a=f.expandUrl(a);var b=d.location.protocol+"//"+(d.location.hostname||d.location.host);if(d.location.port||!1)b+=":"+d.location.port;b+="/",a=a.replace(b,"/");return a},f.expandUrl=function(a){a=a||"";if(!/[a-z]+\:\/\//.test(a))if(a.length===0||a.substring(0,1)==="?"){var b=d.location.href.replace(/[#\?].*/,"");a=b+a}else{var c=d.getElementsByTagName("base"),e=null,f="";if(c.length===1)e=c[0],f=e.href,f[f.length-1]!=="/"&&(f+="/"),a=f+a.replace(/^\//,"");else if(a.substring(0,1)==="."){var g=d.location.href.replace(/[#\?].*/,"").replace(/[^\/]+$/,"");g[g.length-1]!=="/"&&(g+="/"),a=g+a}else{var h=d.location.protocol+"//"+(d.location.hostname||d.location.host);if(d.location.port||!1)h+=":"+d.location.port;h+="/",a=h+a.replace(/^\//,"")}}return a},f.expandState=function(a){a=a||{};var b={data:a.data||{},url:f.expandUrl(a.url||""),title:a.title||""};b.data.title=b.data.title||b.title,b.data.url=b.data.url||b.url;return b},f.createStateObject=function(a,b,c){var d={data:a,title:b,url:c};d=f.expandState(d);return d},f.expandHash=function(a){var b=null;try{b=JSON.parse(a)}catch(c){var d=/(.*)\/uid=([0-9]+)$/.exec(a),g=d?d[1]||a:a,h=d?String(d[2]||""):"";h&&(b=e.getStateByUid(h)||null);if(!b&&/\//.test(a)){var i=f.expandUrl(a);b=f.createStateObject(null,null,i)}}b=b?f.expandState(b):null;return b},f.contractState=function(a){if(!a)return null;var b=null,c=e.cloneObject(a);if(c){c.data=c.data||{},delete c.data.title,delete c.data.url;if(e.isEmptyObject(c)&&!c.title)b=f.contractUrl(c.url);else{b=JSON.stringify(c);var d;if(typeof e.hashesToUids[b]!=="undefined")d=e.hashesToUids[b];else while(!0){d=String(Math.floor(Math.random()*1e3));if(typeof e.uidsToStates[d]==="undefined")break}e.hashesToUids[b]=d,e.uidsToStates[d]=c,b=f.contractUrl(c.url)+"/uid="+d}}return b},e.uidsToStates={},e.hashesToUids={},e.getStateByUid=function(a){a=String(a);var c=e.uidsToStates[a]||b;return c},e.statesByUrl={},e.duplicateStateUrls={},e.statesByHash={},e.savedStates=[],f.getState=function(){return e.getStateByIndex()},f.getStateHash=function(){return f.contractState(f.getState())},e.getStateByUrl=function(a){var c=e.statesByUrl[a]||b;return c},e.getStateByHash=function(a){var c=e.statesByHash[a]||b;return c},e.storeState=function(a){var b=f.contractState(a),c=e.getStateByUrl(a.url);if(typeof c!=="undefined"){var d=f.contractState(c);d!==b&&(e.duplicateStateUrls[a.url]=!0)}e.statesByUrl[a.url]=e.statesByHash[b]=a;return!0},e.isLastState=function(a){var b=f.contractState(a),c=f.getStateHash(),d=e.savedStates.length&&b===c;return d},e.saveState=function(a){if(e.isLastState(a))return!1;e.savedStates.push(a);return!0},e.getStateByIndex=function(a){var b=null;typeof a==="undefined"?b=e.savedStates[e.savedStates.length-1]:a<0?b=e.savedStates[e.savedStates.length+a]:b=e.savedStates[a];return b},e.stateUrlExists=function(a){var b=typeof e.statesByUrl[a]!=="undefined";return b},e.urlDuplicateExists=function(a){var b=typeof e.duplicateStateUrls[a]!=="undefined";return b},f.getHash=function(){var a=e.unescapeHash(d.location.hash);return a},e.unescapeHash=function(a){var b=e.normalizeHash(a);/[\%]/.test(b)&&(b=unescape(b));return b},e.normalizeHash=function(a){var b=a.replace(/[^#]*#/,"").replace(/#.*/,"");return b},f.setHash=function(a,b){if(b!==!1&&f.busy()){f.debug("History.setHash: we must wait",arguments),f.pushQueue({scope:f,callback:f.setHash,args:arguments,queue:b});return!1}var c=e.escapeHash(a);f.debug("History.setHash",this,arguments,"hash:",a,"adjustedHash:",c,"oldHash:",d.location.hash),f.busy(!0),d.location.hash=c;return a},e.escapeHash=function(a){var b=e.normalizeHash(a);/[^a-zA-Z0-9\/\-\_\%\.]/.test(b)&&(b=escape(b));return b},f.extractHashFromUrl=function(a){var b=String(a).replace(/([^#]*)#?([^#]*)#?(.*)/,"$2");b=e.unescapeHash(b);return b},f.isTraditionalAnchor=function(a){var b=f.extractHashFromUrl(a),c=d.getElementById(b),e=typeof c!=="undefined";return e},f.queues=[],f.busy=function(a){f.debug("History.busy: called: changing ["+(f.busy.flag||!1)+"] to ["+(a||!1)+"]",f.queues),typeof a!=="undefined"?f.busy.flag=a:typeof f.busy.flag==="undefined"&&(f.busy.flag=!1);if(!f.busy.flag){clearTimeout(f.busy.timeout);var b=function(){if(!f.busy.flag)for(var a=f.queues.length-1;a>=0;--a){var c=f.queues[a];if(c.length===0)continue;var d=c.shift();f.debug("History.busy: firing",d),f.fireQueueItem(d),f.busy.timeout=setTimeout(b,f.options.busyDelay)}};f.busy.timeout=setTimeout(b,f.options.busyDelay)}return f.busy.flag},f.fireQueueItem=function(a){return a.callback.apply(a.scope||f,a.args||[])},f.pushQueue=function(a){f.debug("History.pushQueue: called",arguments),f.queues[a.queue||0]=f.queues[a.queue||0]||[],f.queues[a.queue||0].push(a);return!0},f.queue=function(a,b){typeof a==="function"&&(a={callback:a}),typeof b!=="undefined"&&(a.queue=b),f.busy()?f.pushQueue(a):f.fireQueueItem(a);return!0},f.back=function(a){f.debug("History.back: called",arguments);if(a!==!1&&f.busy()){f.debug("History.back: we must wait",arguments),f.pushQueue({scope:f,callback:f.back,args:arguments,queue:a});return!1}f.busy(!0);if(f.emulated.hashChange&&e.isInternetExplorer()){var b=f.getHash();setTimeout(function(){var a=f.getHash();if(a===b){f.debug("History.back: trying again");return f.back(!1)}return!0},f.options.hashChangeCheckerDelay*5)}g.go(-1);return!0},f.forward=function(a){f.debug("History.forward: called",arguments);if(a!==!1&&f.busy()){f.debug("History.forward: we must wait",arguments),f.pushQueue({scope:f,callback:f.forward,args:arguments,queue:a});return!1}f.busy(!0);if(f.emulated.hashChange&&e.isInternetExplorer()){var b=f.getHash();setTimeout(function(){var a=f.getHash();if(a===b){f.debug("History.forward: trying again");return f.forward(!1)}return!0},f.options.hashChangeCheckerDelay*5)}g.go(1);return!0},f.go=function(a,b){f.debug("History.go: called",arguments);if(a>0)for(var c=1;c<=a;++c)f.forward(b);else{if(!(a<0))throw new Error("History.go: History.go requires a positive or negative integer passed.");for(var c=-1;c>=a;--c)f.back(b)}return!0},f.emulated.pushState||(e.onPopState=function(b){f.debug("_History.onPopState",this,arguments);var c=unescape(f.getHash());if(c){var g=f.expandHash(c);g?(f.debug("_History.onPopState: state anchor",c,g),f.replaceState(g.data,g.tite,g.url,!1)):(f.debug("_History.onPopState: traditional anchor",c),f.Adapter.trigger(a,"anchorchange"),f.busy(!1));return!1}var h=null,i={},j=null,k=null,l=null;b=b||{},typeof b.state==="undefined"&&(typeof b.originalEvent!=="undefined"&&typeof b.originalEvent.state!=="undefined"?b.state=b.originalEvent.state:typeof b.event!=="undefined"&&typeof b.event.state!=="undefined"&&(b.state=b.event.state));if(b.state===null)i=b.state;else if(typeof b.state!=="undefined"){var m=f.expandUrl(d.location.href),n=e.getStateByUrl(m),o=e.urlDuplicateExists(m);typeof n!=="undefined"&&!o?i=n.data:i=b.state}else{var m=f.expandUrl(d.location.href),n=e.getStateByUrl(m);if(n&&m==n.url)i=n.data;else throw new Error("Unknown state")}i=typeof i!=="object"||i===null?{}:i,j=i.title||"",k=i.url||d.location.href,l=f.createStateObject(i,j,k);if(e.isLastState(l)){f.debug("_History.onPopState: no change",l,e.savedStates),f.busy(!1);return!1}f.debug("_History.onPopState","newState:",l,"oldState:",e.getStateByUrl(f.expandUrl(d.location.href)),"duplicateExists:",e.urlDuplicateExists(f.expandUrl(d.location.href))),e.storeState(l),e.saveState(l),l.title&&(d.title=l.title),f.Adapter.trigger(a,"statechange"),f.busy(!1);return!0},f.Adapter.bind(a,"popstate",e.onPopState),f.pushState=function(b,c,d,h){if(f.extractHashFromUrl(d))throw new Error("History.js does not support states with fragement-identifiers (hashes/anchors).");if(h!==!1&&f.busy()){f.debug("History.pushState: we must wait",arguments),f.pushQueue({scope:f,callback:f.pushState,args:arguments,queue:h});return!1}f.busy(!0);var i=f.createStateObject(b,c,d);e.storeState(i),g.pushState(i.data,i.title,i.url),f.Adapter.trigger(a,"popstate");return!0},f.replaceState=function(b,c,d,h){if(f.extractHashFromUrl(d))throw new Error("History.js does not support states with fragement-identifiers (hashes/anchors).");if(h!==!1&&f.busy()){f.debug("History.replaceState: we must wait",arguments),f.pushQueue({scope:f,callback:f.replaceState,args:arguments,queue:h});return!1}f.busy(!0);var i=f.createStateObject(b,c,d);e.storeState(i),g.replaceState(i.data,i.title,i.url),f.Adapter.trigger(a,"popstate");return!0},navigator.vendor==="Apple Computer, Inc."&&(f.Adapter.onDomLoad(function(){f.debug("Safari Initial State Change Fix");var a=f.createStateObject({},"",d.location.href);f.pushState(a.data,a.title,a.url)}),f.Adapter.bind(a,"hashchange",function(){f.Adapter.trigger(a,"popstate")})))},f.initHtml5()})(window)
