Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse files

MINOR Added history.js dependency

  • Loading branch information...
commit a5f841764de94d768990f4776c905ecfe8daf201 1 parent 8378a9d
@chillu chillu authored
Showing with 27,308 additions and 0 deletions.
  1. +8 −0 admin/thirdparty/history-js/.piston.yml
  2. +311 −0 admin/thirdparty/history-js/README.md
  3. +351 −0 admin/thirdparty/history-js/cli
  4. +58 −0 admin/thirdparty/history-js/demo/bcherry-orig.html
  5. +62 −0 admin/thirdparty/history-js/demo/bcherry.html
  6. +37 −0 admin/thirdparty/history-js/demo/chrome.html
  7. +101 −0 admin/thirdparty/history-js/demo/index.html
  8. +43 −0 admin/thirdparty/history-js/demo/native-auto.html
  9. +62 −0 admin/thirdparty/history-js/demo/native.html
  10. +23 −0 admin/thirdparty/history-js/demo/navigator.html
  11. +61 −0 admin/thirdparty/history-js/demo/safari.html
  12. +10 −0 admin/thirdparty/history-js/license.txt
  13. +74 −0 admin/thirdparty/history-js/package.json
  14. +1 −0  admin/thirdparty/history-js/scripts/compressed/amplify.store.js
  15. 0  admin/thirdparty/history-js/scripts/compressed/history.adapter.dojo.js
  16. +1 −0  admin/thirdparty/history-js/scripts/compressed/history.adapter.jquery.js
  17. +1 −0  admin/thirdparty/history-js/scripts/compressed/history.adapter.mootools.js
  18. +1 −0  admin/thirdparty/history-js/scripts/compressed/history.adapter.prototype.js
  19. +1 −0  admin/thirdparty/history-js/scripts/compressed/history.adapter.yui.js
  20. +1 −0  admin/thirdparty/history-js/scripts/compressed/history.adapter.zepto.js
  21. +1 −0  admin/thirdparty/history-js/scripts/compressed/history.html4.js
  22. +1 −0  admin/thirdparty/history-js/scripts/compressed/history.js
  23. +1 −0  admin/thirdparty/history-js/scripts/compressed/json2.js
  24. +247 −0 admin/thirdparty/history-js/scripts/uncompressed/amplify.store.js
  25. +1 −0  admin/thirdparty/history-js/scripts/uncompressed/history.adapter.dojo.js
  26. +58 −0 admin/thirdparty/history-js/scripts/uncompressed/history.adapter.jquery.js
  27. +66 −0 admin/thirdparty/history-js/scripts/uncompressed/history.adapter.mootools.js
  28. +197 −0 admin/thirdparty/history-js/scripts/uncompressed/history.adapter.prototype.js
  29. +64 −0 admin/thirdparty/history-js/scripts/uncompressed/history.adapter.yui.js
  30. +58 −0 admin/thirdparty/history-js/scripts/uncompressed/history.adapter.zepto.js
  31. +606 −0 admin/thirdparty/history-js/scripts/uncompressed/history.html4.js
  32. +1,867 −0 admin/thirdparty/history-js/scripts/uncompressed/history.js
  33. +480 −0 admin/thirdparty/history-js/scripts/uncompressed/json2.js
  34. +28 −0 admin/thirdparty/history-js/tests.src/_header.php
  35. +59 −0 admin/thirdparty/history-js/tests.src/all.php
  36. +62 −0 admin/thirdparty/history-js/tests.src/each.php
  37. +25 −0 admin/thirdparty/history-js/tests.src/index.php
  38. +13 −0 admin/thirdparty/history-js/tests/.htaccess
  39. +47 −0 admin/thirdparty/history-js/tests/compressed-html4-nonpersistant-jquery.html
  40. +47 −0 admin/thirdparty/history-js/tests/compressed-html4-nonpersistant-mootools.html
  41. +47 −0 admin/thirdparty/history-js/tests/compressed-html4-nonpersistant-prototype.html
  42. +47 −0 admin/thirdparty/history-js/tests/compressed-html4-nonpersistant-zepto.html
  43. +48 −0 admin/thirdparty/history-js/tests/compressed-html4-persistant-jquery.html
  44. +48 −0 admin/thirdparty/history-js/tests/compressed-html4-persistant-mootools.html
  45. +48 −0 admin/thirdparty/history-js/tests/compressed-html4-persistant-prototype.html
  46. +48 −0 admin/thirdparty/history-js/tests/compressed-html4-persistant-zepto.html
  47. +46 −0 admin/thirdparty/history-js/tests/compressed-html5-nonpersistant-jquery.html
  48. +46 −0 admin/thirdparty/history-js/tests/compressed-html5-nonpersistant-mootools.html
  49. +46 −0 admin/thirdparty/history-js/tests/compressed-html5-nonpersistant-prototype.html
  50. +46 −0 admin/thirdparty/history-js/tests/compressed-html5-nonpersistant-zepto.html
  51. +47 −0 admin/thirdparty/history-js/tests/compressed-html5-persistant-jquery.html
  52. +47 −0 admin/thirdparty/history-js/tests/compressed-html5-persistant-mootools.html
  53. +47 −0 admin/thirdparty/history-js/tests/compressed-html5-persistant-prototype.html
  54. +47 −0 admin/thirdparty/history-js/tests/compressed-html5-persistant-zepto.html
  55. +3 −0  admin/thirdparty/history-js/tests/image.php
  56. +28 −0 admin/thirdparty/history-js/tests/index.html
  57. +254 −0 admin/thirdparty/history-js/tests/tests.js
  58. +47 −0 admin/thirdparty/history-js/tests/uncompressed-html4-nonpersistant-jquery.html
  59. +47 −0 admin/thirdparty/history-js/tests/uncompressed-html4-nonpersistant-mootools.html
  60. +47 −0 admin/thirdparty/history-js/tests/uncompressed-html4-nonpersistant-prototype.html
  61. +47 −0 admin/thirdparty/history-js/tests/uncompressed-html4-nonpersistant-zepto.html
  62. +48 −0 admin/thirdparty/history-js/tests/uncompressed-html4-persistant-jquery.html
  63. +48 −0 admin/thirdparty/history-js/tests/uncompressed-html4-persistant-mootools.html
  64. +48 −0 admin/thirdparty/history-js/tests/uncompressed-html4-persistant-prototype.html
  65. +48 −0 admin/thirdparty/history-js/tests/uncompressed-html4-persistant-zepto.html
  66. +46 −0 admin/thirdparty/history-js/tests/uncompressed-html5-nonpersistant-jquery.html
  67. +46 −0 admin/thirdparty/history-js/tests/uncompressed-html5-nonpersistant-mootools.html
  68. +46 −0 admin/thirdparty/history-js/tests/uncompressed-html5-nonpersistant-prototype.html
  69. +46 −0 admin/thirdparty/history-js/tests/uncompressed-html5-nonpersistant-zepto.html
  70. +47 −0 admin/thirdparty/history-js/tests/uncompressed-html5-persistant-jquery.html
  71. +47 −0 admin/thirdparty/history-js/tests/uncompressed-html5-persistant-mootools.html
  72. +47 −0 admin/thirdparty/history-js/tests/uncompressed-html5-persistant-prototype.html
  73. +47 −0 admin/thirdparty/history-js/tests/uncompressed-html5-persistant-zepto.html
  74. +8,316 −0 admin/thirdparty/history-js/vendor/jquery.js
  75. +5,491 −0 admin/thirdparty/history-js/vendor/mootools.js
  76. +6,082 −0 admin/thirdparty/history-js/vendor/prototype.js
  77. +13 −0 admin/thirdparty/history-js/vendor/yui.js
  78. +576 −0 admin/thirdparty/history-js/vendor/zepto.js
View
8 admin/thirdparty/history-js/.piston.yml
@@ -0,0 +1,8 @@
+---
+format: 1
+handler:
+ commit: 861b4b1f7240b9d5e50d560ba5b94de78aa439e5
+ branch: master
+lock: false
+repository_class: Piston::Git::Repository
+repository_url: https://github.com/balupton/history.js.git
View
311 admin/thirdparty/history-js/README.md
@@ -0,0 +1,311 @@
+Welcome to History.js (v1.7.0 - April 01 2011)
+==================
+
+
+This project is the successor of [jQuery History](http://balupton.com/projects/jquery-history), it aims to:
+
+- Follow the [HTML5 History API](https://developer.mozilla.org/en/DOM/Manipulating_the_browser_history) as much as possible
+- Provide a cross-compatible experience for all HTML5 Browsers (they all implement the HTML5 History API a little bit differently causing different behaviours and sometimes bugs - History.js fixes this ensuring the experience is as expected / the same / great throughout the HTML5 browsers)
+- Provide a backwards-compatible experience for all HTML4 Browsers using a hash-fallback (including continued support for the HTML5 History API's `data`, `title`, `pushState` and `replaceState`) with the option to [remove HTML4 support if it is not right for your application](https://github.com/balupton/History.js/wiki/Intelligent-State-Handling)
+- Provide a forwards-compatible experience for HTML4 States to HTML5 States (so if a hash-fallbacked url is accessed by a HTML5 browser it is naturally transformed into its non-hashed url equivalent)
+- Provide support for as many javascript frameworks as possible via adapters; especially [jQuery](http://jquery.com/), [MooTools](http://mootools.net/), [Prototype](http://www.prototypejs.org/) and [Zepto](http://zeptojs.com/)
+
+Licensed under the [New BSD License](http://creativecommons.org/licenses/BSD/)
+Copyright 2011 [Benjamin Arthur Lupton](http://balupton.com)
+
+
+## Usage
+
+### Working with History.js:
+
+ (function(window,undefined){
+
+ // Prepare
+ var History = window.History; // Note: We are using a capital H instead of a lower h
+ if ( !History.enabled ) {
+ // History.js is disabled for this browser.
+ // This is because we can optionally choose to support HTML4 browsers or not.
+ return false;
+ }
+
+ // Bind to StateChange Event
+ History.Adapter.bind(window,'statechange',function(){ // Note: We are using statechange instead of popstate
+ var State = History.getState(); // Note: We are using History.getState() instead of event.state
+ History.log(State.data, State.title, State.url);
+ });
+
+ // Change our States
+ History.pushState({state:1}, "State 1", "?state=1"); // logs {state:1}, "State 1", "?state=1"
+ History.pushState({state:2}, "State 2", "?state=2"); // logs {state:2}, "State 2", "?state=2"
+ History.replaceState({state:3}, "State 3", "?state=3"); // logs {state:3}, "State 3", "?state=3"
+ History.pushState(null, null, "?state=4"); // logs {}, '', "?state=4"
+ History.back(); // logs {state:3}, "State 3", "?state=3"
+ History.back(); // logs {state:1}, "State 1", "?state=1"
+ History.back(); // logs {}, "Home Page", "?"
+ History.go(2); // logs {state:3}, "State 3", "?state=3"
+
+ })(window);
+
+To ajaxify your entire website with the HTML5 History API, History.js and jQuery [this snippet of code](https://gist.github.com/854622) is all you need. It's that easy.
+
+### How would the above operations look in a HTML5 Browser?
+
+1. www.mysite.com
+1. www.mysite.com/?state=1
+1. www.mysite.com/?state=2
+1. www.mysite.com/?state=3
+1. www.mysite.com/?state=4
+1. www.mysite.com/?state=3
+1. www.mysite.com/?state=1
+1. www.mysite.com
+1. www.mysite.com/?state=3
+
+> Note: These urls also work in HTML4 browsers and Search Engines. So no need for the hashbang (`#!`) fragment-identifier that google ["recommends"](https://github.com/balupton/History.js/wiki/Intelligent-State-Handling).
+
+### How would they look in a HTML4 Browser?
+
+1. www.mysite.com
+1. www.mysite.com/#?state=1&_suid=1
+1. www.mysite.com/#?state=2&_suid=2
+1. www.mysite.com/#?state=3&_suid=3
+1. www.mysite.com/#?state=4
+1. www.mysite.com/#?state=3&_suid=3
+1. www.mysite.com/#?state=1&_suid=1
+1. www.mysite.com
+1. www.mysite.com/#?state=3&_suid=3
+
+> Note 1: These urls also work in HTML5 browsers - we use `replaceState` to transform these HTML4 states into their HTML5 equivalents so the user won't even notice :-)
+>
+> Note 2: These urls will be automatically url-encoded in IE6 to prevent certain browser-specific bugs.
+>
+> Note 3: Support for HTML4 browsers (this hash fallback) is optional [- why supporting HTML4 browsers could be either good or bad based on my app's use cases](https://github.com/balupton/History.js/wiki/Intelligent-State-Handling)
+
+### What's the deal with the SUIDs used in the HTML4 States?
+
+- SUIDs (State Unique Identifiers) are used when we utilise a `title` and/or `data` in our state. Adding a SUID allows us to associate particular states with data and titles while keeping the urls as simple as possible (don't worry it's all tested, working and a lot smarter than I'm making it out to be).
+- If you aren't utilising `title` or `data` then we don't even include a SUID (as there is no need for it) - as seen by State 4 above :-)
+- We also shrink the urls to make sure that the smallest url will be used. For instance we will adjust `http://www.mysite.com/#http://www.mysite.com/projects/History.js` to become `http://www.mysite.com/#/projects/History.js` automatically. (again tested, working, and smarter).
+- It works with domains, subdomains, subdirectories, whatever - doesn't matter where you put it. It's smart.
+- Safari 5 will also have a SUID appended to the URL, it is entirely transparent but just a visible side-effect. It is required to fix a bug with Safari 5.
+
+### Is there a working demo?
+
+- Sure is, give it a download and navigate to the demo directory in your browser :-)
+- If you are after something a bit more adventurous than a end-user demo, open up the tests directory in your browser and editor - it'll rock your world and show all the vast use cases that History.js supports.
+
+
+## Download & Installation
+
+1. Download History.js and upload it to your webserver. Download links: [tar.gz](https://github.com/balupton/History.js/tarball/master) or [zip](https://github.com/balupton/History.js/zipball/master)
+
+2. Include [JSON2](http://www.json.org/js.html) for HTML4 Browsers Only *(replace www.yourwebsite.com)*
+
+ <script>if ( typeof window.JSON === 'undefined' ) { document.write('<script src="http://www.yourwebsite.com/history.js/scripts/compressed/json2.js"><\/script>'); }</script>
+
+3. Include [Amplify.js Store](http://amplifyjs.com/) for Data Persistance and Synchronisation Support (optional but recommended)
+
+ <script src="http://www.yourwebsite.com/history.js/scripts/compressed/amplify.store.js"></script>
+
+4. Include the Adapter for your Framework:
+
+ - [jQuery](http://jquery.com/) v1.3+
+
+ <script src="http://www.yourwebsite.com/history.js/scripts/compressed/history.adapter.jquery.js"></script>
+
+ - [Mootools](http://mootools.net/) v1.3+
+
+ <script src="http://www.yourwebsite.com/history.js/scripts/compressed/history.adapter.mootools.js"></script>
+
+ - [Prototype](http://www.prototypejs.org/) v1.7+ (does not support versions of IE prior to 9 due to a bug in the prototype library)
+
+ <script src="http://www.yourwebsite.com/history.js/scripts/compressed/history.adapter.prototype.js"></script>
+
+ - [Zepto](http://zeptojs.com/) v0.5+
+
+ <script src="http://www.yourwebsite.com/history.js/scripts/compressed/history.adapter.zepto.js"></script>
+
+ - _Would you like to support another framework? No problem! It's very easy to create adapters, and I'll be happy to include them or help out if you [let me know](https://github.com/balupton/history.js/issues) :-)_
+
+5. Include History.js
+
+ <script src="http://www.yourwebsite.com/history.js/scripts/compressed/history.js"></script>
+ <script src="http://www.yourwebsite.com/history.js/scripts/compressed/history.html4.js"></script>
+
+> Note: If you want to only support HTML5 Browsers and not HTML4 Browsers (so no hash fallback support) then just remove the `history.html4.js` file include in step #5 and the JSON2 (`json2.js`) file include in step #2 [- why supporting HTML4 browsers could be either good or bad based on my app's use cases](https://github.com/balupton/History.js/wiki/Intelligent-State-Handling)
+
+
+## Subscribe to Updates
+
+- For Email Updates:
+ - You can subscribe via the subscription form included in the demo page
+- For Commit RSS/Atom Updates:
+ - You can subscribe via the [GitHub Commit Atom Feed](https://github.com/balupton/History.js/commits/master.atom)
+- For GitHub News Feed Updates:
+ - You can click the "watch" button up the top right of History.js's [GitHub Project Page](https://github.com/balupton/History.js)
+
+
+## Getting Support
+
+History.js is an actively developed, supported and maintained project. You can grab support via its [GitHub Issue Tracker](https://github.com/balupton/History.js/issues). Alternatively you can reach [Benjamin Lupton](http://balupton.com) (the core developer) via [twitter](http://twitter.com/balupton), skype (balupton) or email (contact@balupton.com).
+
+
+## Giving Support
+
+If you'd love to give some support back and make a difference; here are a few great ways you can give back!
+
+- Give it your honest rating on its [jQuery Plugin's Page](http://plugins.jquery.com/project/history-js) and its [Ohloh Page](https://www.ohloh.net/p/history-js)
+- If you have any feedback or suggestions let me know via its [Issue Tracker](https://github.com/balupton/History.js/issues) - so that I can ensure you get the best experience!
+- Spread the word via tweets, blogs, tumblr, whatever - the more people talking about it the better!
+- Donate via the donation form at the bottom right of [balupton.com](http://balupton.com) - every cent truly does help!
+- Make it easier for me to let you know about future releases and updates by subscribing via the signup form inside the demo page
+- Watch it via clicking the "watch" button up the top of its [Project Page](https://github.com/balupton/History.js)
+
+Thanks! every bit of help really does make a difference. Again thank you.
+
+
+## Browsers: Tested and Working In
+
+### HTML5 Browsers
+
+- Chrome 8,9,10
+- Firefox 4
+- Safari 5
+- Safari iOS 4.3
+
+### HTML4 Browsers
+
+- IE 6,7,8,9
+- Firefox 3
+- Opera 10,11
+- Safari 4
+- Safari iOS prior to version 4.3
+
+
+## Exposed API
+
+### Functions
+
+- `History.pushState(data,title,url)` <br/> Pushes a new state to the browser; `data` can be null or an object, `title` can be null or a string, `url` must be a string
+- `History.replaceState(data,title,url)` <br/> Replaces the existing state with a new state to the browser; `data` can be null or an object, `title` can be null or a string, `url` must be a string
+- `History.getState()` <br/> Gets the current state of the browser, returns an object with `data`, `title` and `url`
+- `History.getHash()` <br/> Gets the current hash of the browser
+- `History.Adapter.bind(element,event,callback)` <br/> A framework independent event binder, you may either use this or your framework's native event binder.
+- `History.Adapter.trigger(element,event)` <br/> A framework independent event trigger, you may either use this or your framework's native event trigger.
+- `History.Adapter.onDomLoad(callback)` <br/> A framework independent onDomLoad binder, you may either use this or your framework's native onDomLoad binder.
+- `History.back()` <br/> Go back once through the history (same as hitting the browser's back button)
+- `History.forward()` <br/> Go forward once through the history (same as hitting the browser's forward button)
+- `History.go(X)` <br/> If X is negative go back through history X times, if X is positive go forwards through history X times
+- `History.log(...)` <br/> Logs messages to the console, the log element, and fallbacks to alert if neither of those two exist
+- `History.debug(...)` <br/> Same as `History.log` but only runs if `History.debug.enable === true`
+
+### Events
+
+- `window.onstatechange` <br/> Fired when the state of the page changes (does not include hash changes)
+- `window.onanchorchange` <br/> Fired when the anchor of the page changes (does not include state hashes)
+
+
+## Notes on Compatibility
+
+- History.js **solves** the following browser bugs:
+ - HTML5 Browsers
+ - Chrome 8 sometimes does not contain the correct state data when traversing back to the initial state
+ - Safari 5, Safari iOS 4 and Firefox 3 and 4 do not fire the `onhashchange` event when the page is loaded with a hash
+ - Safari 5 and Safari iOS 4 do not fire the `onpopstate` event when the hash has changed unlike the other browsers
+ - Safari 5 and Safari iOS 4 fail to return to the correct state once a hash is replaced by a `replaceState` call / [bug report](https://bugs.webkit.org/show_bug.cgi?id=56249)
+ - Safari 5 and Safari iOS 4 sometimes fail to apply the state change under busy conditions / [bug report](https://bugs.webkit.org/show_bug.cgi?id=42940)
+ - Google Chrome 8,9,10 and Firefox 4 prior to the RC will always fire `onpopstate` once the page has loaded / [change recommendation](http://hacks.mozilla.org/2011/03/history-api-changes-in-firefox-4/)
+ - Safari iOS 4.0, 4.1, 4.2 have a working HTML5 History API - although the actual back buttons of the browsers do not work, therefore we treat them as HTML4 browsers
+ - None of the HTML5 browsers actually utilise the `title` argument to the `pushState` and `replaceState` calls
+ - HTML4 Browsers
+ - Old browsers like MSIE 6,7 and Firefox 2 do not have a `onhashchange` event
+ - MSIE 6 and 7 sometimes do not apply a hash even it was told to (requiring a second call to the apply function)
+ - Non-Opera HTML4 browsers sometimes do not apply the hash when the hash is not `urlencoded`
+ - All Browsers
+ - State data and titles do not persist once the site is left and then returned (includes page refreshes)
+ - State titles are never applied to the `document.title`
+- ReplaceState functionality is emulated in HTML4 browsers by discarding the replaced state, so when the discarded state is accessed it is skipped using the appropriate `History.back()` / `History.forward()` call
+- Data persistance and synchronisation works like so: Every second or so, the SUIDs and URLs of the states will synchronise between the store and the local session. When a new session opens a familiar state (via the SUID or the URL) and it is not found locally then it will attempt to load the last known stored state with that information.
+- URLs will be unescaped to the maximum, so for instance the URL `?key=a%20b%252c` will become `?key=a b c`. This is to ensure consistency between browser url encodings.
+- Changing the hash of the page causes `onpopstate` to fire (this is expected/standard functionality). To ensure correct compatibility between HTML5 and HTML4 browsers the following events have been created:
+ - `window.onstatechange`: this is the same as the `onpopstate` event except it does not fire for traditional anchors
+ - `window.onanchorchange`: this is the same as the `onhashchange` event except it does not fire for states
+- Known Issues
+ - Opera 11 fails to create history entries when under stressful loads (events fire perfectly, just the history events fail) - there is nothing we can do about this
+ - Mercury iOS fails to apply url changes (hashes and HTML5 History API states) - there is nothing we can do about this
+
+
+## Changelog
+
+- v1.7.0 - April 01 2011
+ - Added `History.enabled` property (refer to usage section). This reflects whether or not History.js is enabled for our particular browser. For instance, if we have not included support for a HTML4 browser and we are accessing through a HTML4 browser then `History.enabled` will be `false`.
+ - Added (optional but recommended) Data Persistance and Synchronisation Support thanks to [AppendTo's](http://appendto.com/) [Amplify.js](http://amplifyjs.com/) (refer to installation and compatibility sections for details)
+ - Made HTML5 SUIDs more transparent - [Reported](https://github.com/balupton/History.js/issues#issue/34) by [azago](https://github.com/azago) and [Mark Jaquith](http://markjaquith.com/)
+ - Fixed Session Storage Issue - Reported by a whole bunch of different people; [one](https://github.com/balupton/History.js/issues#issue/36), [two](https://github.com/balupton/History.js/issues#issue/37), [three](http://getsatisfaction.com/balupton/topics/history_js_1_6_losing_state_after_manual_page_reload)
+ - Fixed URL Encoding Issue - [Reported](https://github.com/balupton/history.js/issues/#issue/33) by [Rob Madole](http://robmadole.com/)
+ - Disabled support for IE6,7,8 when using the Prototype Adapter (there is nothing we can do about this, it is due to a bug in the prototype library) - [Reported](https://github.com/balupton/history.js/issues#issue/39) by [Sindre Wimberger](http://sindre.at/)
+ - URLs in the State Hashes for HTML4 Browsers are now even shorter - [Discussion](https://github.com/balupton/history.js/issues#issue/28)
+ - Fixed a issue with the MooTools Adapter and JSON with IE7 and IE8
+
+- v1.6.0 - March 22 2011
+ - Added Zepto adapter thanks to [Matt Garrett](http://twitter.com/#!/matthewgarrett)
+ - The readme now references the supported versions of the libraries we use
+ - Updated vendors to the most recent versions. jQuery 1.5.1 and Mootools 1.3.1
+ - Reverted versions of Safari iOS prior to version 4.3 to be HTML4 browsers, Safari iOS 4.3 is a HTML5 browser
+ - Refined code in History.js and its adapters
+ - Fixed issue with extra state being inserted on Safari 5 requiring an extra click on the back button to go home - [Reported](https://github.com/balupton/history.js/issues#issue/17) by [Rob Madole](http://robmadole.com/)
+ - Fixed issue with Safari 5 and Safari iOS 4 sometimes failing to apply the state change under busy conditions - Solution conceived with [Matt Garrett](http://twitter.com/matthewgarrett)
+ - Fixed issue with HTML4 browsers requiring a query-string in the urls of states - [Reported](https://github.com/balupton/history.js/issues#issue/26) by [azago](https://github.com/azago)
+ - Fixed issue with HTML4 browsers requiring title in the states in order to use state data - [Reported](https://github.com/balupton/history.js/issues#issue/25) by [Jonathan McLaughlin](http://system-werks.com/)
+ - Fixed issue with HTML4 browsers failing is a state is pushed/replaced twice in a row - [Reported](https://github.com/balupton/history.js/issues#issue/17) by [Joey Baker](http://byjoeybaker.com/)
+ - **B/C BREAK:** The `statechange` event now only fires if the state has changed; it no longer fires on page initialisation. This is following the [Firefox 4 History API Changes](http://hacks.mozilla.org/2011/03/history-api-changes-in-firefox-4/) which we agree with - this breaks standard, but makes more sense.
+
+- v1.5.0 - February 12 2011
+ - Moved to UglifyJS instead of Google Closure
+ - Split HTML4 functionality from HTML5 functionality
+ - Installation details have changed (the filenames are different)
+
+- v1.4.1 - February 10 2011
+ - Added HTML History API Support for Safari 5 and Safari iOS 4.2.1
+ - Cleaned code a bit (mostly with unit tests)
+
+- v1.4.0 - February 10 2011
+ - Unit Testing now uses [QUnit](http://docs.jquery.com/Qunit)
+ - Corrected Safari 5 Support
+ - Now uses queues instead of timeouts
+ - This means the API works exactly as expected, no more need to wrap calls in timeouts
+ - Included a Subscribe Form in the Demo for Version Updates via Email
+ - Small updates to Documentation
+
+- v1.3.1 - February 04 2011
+ - Improved Documentation
+
+- v1.3.0 - January 31 2011
+ - Support for cleaner HTML4 States
+
+- v1.2.1 - January 30 2011
+ - Fixed History.log always being called - [reported by dlee](https://github.com/balupton/History.js/issues/#issue/2)
+ - Re-Added `History.go(index)` support
+
+- v1.2.0 - January 25 2011
+ - Support for HTML4 States in HTML5 Browsers (added test)
+ - Updates of Documentation
+
+- v1.1.0 - January 24 2011
+ - Developed a series of automated test cases
+ - Fixed issue with traditional anchors
+ - Fixed issue with differing replaceState functionality in HTML4 Browsers
+ - Fixed issue with Google Chrome artefacts being carried over to the initial state
+ - Provided `onstatechange` and `onanchorchange` events
+
+- v1.0.0 - January 22 2011
+ - Supported `History.pushState` and `History.replaceState` degradation
+ - Supported jQuery, MooTools and Prototype Frameworks
+
+
+## Todo for Upcoming Releases
+
+- Allow for url to be optional in `pushState` and `replaceState` calls
+- Add an Ajax extension to succeed the [jQuery Ajaxy](http://balupton.com/projects/jquery-ajaxy) project
+- Add a compilation test to ensure `.debug = false` and no `History.log` or `console.xxx` calls exist.
+
+It's likely these features and/or others have been included in the latest [dev branch](https://github.com/balupton/History.js/tree/dev). If you are wanting to fork and help out, then be sure to work on the dev branch and not master.
View
351 admin/thirdparty/history-js/cli
@@ -0,0 +1,351 @@
+#!/usr/bin/env ruby
+
+# == Name
+# cli - BalCMS Command Line Interface
+#
+# == Synopsis
+# cli check-env
+# cli birth
+# cli init-commit
+# cli init-new
+# cli init-existing
+# cli configure
+# cli install
+# cli permissions
+# cli setup
+# cli cron
+#
+# cli add
+# cli stable
+# cli master
+# cli upgrade
+# cli update
+# cli deploy
+#
+# cli clean
+# cli clean-media
+# cli clean-config
+# cli clean-styles
+# cli clean-scripts
+#
+# cli [options]
+#
+# == Examples
+# cli check-env
+# Checks to see that our environment is properly configured and will support a BalCMS installation.
+#
+# cli birth
+# Executes: init-new, configure, install, init-commit
+#
+# cli init-commit
+# Performs the initial commit (commits new and modified files during the installation to the git repo).
+#
+# cli init-new
+# Initialises the repository as a new installation. Only run this once.
+#
+# TODO: finish this example section
+#
+# == Options
+# -h, --help Displays help message
+# -v, --version Display the version, then exit
+# -q, --quiet Output as little as possible, overrides verbose
+# -V, --verbose Verbose output
+#
+# == Author
+# Benjamin Arthur Lupton
+#
+# == Copyright
+# Copyright (c) 2008-2011 Benjamin Arthur Lupton
+# Licensed under the New BSD License
+# http://creativecommons.org/licenses/BSD/
+
+require 'optparse'
+require 'rdoc/usage'
+require 'ostruct'
+require 'date'
+
+class App
+ SOURCEMAP = './scripts/closure.map'
+ BUILDDIR = './.build'
+ UGLIFYURL = 'https://github.com/mishoo/UglifyJS/raw/master/bin/uglifyjs'
+ UGLIFYDIR = './.build/uglify'
+ UGLIFYFILE = './.build/uglify/uglify'
+ CLOSUREURL = 'http://closure-compiler.googlecode.com/files/compiler-latest.zip'
+ CLOSUREDIR = './.build/closure'
+ CLOSUREZIP = './.build/closure/compiler.zip'
+ CLOSUREFILE = './.build/closure/compiler.jar'
+ YUIURL = 'http://yuilibrary.com/downloads/yuicompressor/yuicompressor-2.4.2.zip'
+ YUIDIR = './.build/yui'
+ YUIZIP = './.build/yui/compiler.zip'
+ YUIFILE = './.build/yui/yuicompressor-2.4.2/build/yuicompressor-2.4.2.jar'
+
+ def initialize
+ init_env
+ end
+
+ def init_env
+ # Check for Requirements
+ reqs = ['mkdir','curl','tar','git']
+ reqs.each do |req|
+ has_req = `which #{req}`.strip
+ if has_req.empty?
+ abort("CLI requires the following binary which is not installed: #{req}")
+ end
+ end
+
+ # Check for Closure Compiler
+ if !File.exists?(CLOSUREFILE)
+ `mkdir -p #{CLOSUREDIR}`
+ puts "Downloading the Closure Compiler..."
+ download(CLOSUREURL, CLOSUREZIP)
+ extract(CLOSUREDIR, CLOSUREZIP)
+ `chmod +x #{CLOSUREFILE}`
+ end
+
+ # Check for Uglify
+ if !File.exists?(UGLIFYFILE)
+ `mkdir -p #{UGLIFYDIR}`
+ puts "Downloading the Uglify Compiler..."
+ download(UGLIFYURL, UGLIFYFILE)
+ `chmod +x #{UGLIFYFILE}`
+ end
+
+ # Check for YUI Compiler
+ if !File.exists?(YUIFILE)
+ `mkdir -p #{YUIDIR}`
+ puts "Downloading the YUI Compiler..."
+ download(YUIURL, (YUIZIP))
+ extract(YUIDIR, YUIZIP)
+ `chmod +x #{YUIFILE}`
+ end
+ end
+
+ def has_changes
+ result = `git status`
+ if result.include? 'Changed but not updated'
+ abort("You have un-committed changes that need to be committed before we can proceed.\n#{result}")
+ end
+ end
+
+ # ===========================================================================
+ # Helpers
+
+ def download ( url, file )
+ result = `curl -L #{url} -o #{file}`
+ end
+
+ def extract ( dir, file )
+ file = file.gsub(dir,'.')
+ result = `cd #{dir} ; tar -xf #{file} ; rm -Rf #{file}`
+ end
+
+ def compressJavascriptFile ( in_file, out_file )
+ # Calculate
+ in_file_size = File.size(in_file)
+
+ # Handle
+ if in_file.equal? out_file
+ out_file = out_file.gsub(/\.js$/, '.min.js')
+ compressFileUglify(in_file,out_file)
+ `rm #{in_file}`
+ `mv #{out_file} #{in_file}`
+ out_file = in_file
+ else
+ compressFileUglify(in_file,out_file)
+ out_file_size = File.size(out_file)
+ end
+
+ # Calculate
+ out_file_size = File.size(out_file)
+ ratio = Float(out_file_size)/Float(in_file_size)
+ reduction = ((1-ratio)*100).round
+
+ # Log
+ puts "Compressed the file [#{in_file}] to [#{out_file}] with a #{reduction}% reduction"
+ end
+
+ def compressFileUglify ( in_file, out_file )
+ result = `#{UGLIFYFILE} -o #{out_file} #{in_file}`
+ end
+
+ def compressFileClosure ( in_file, out_file )
+ result = `java -jar #{CLOSUREFILE} --js_output_file=#{out_file} --js=#{in_file}`
+ end
+
+ # ===========================================================================
+ # Installers
+
+ def build
+
+ end
+
+ # ===========================================================================
+ # Git Helpers
+
+ def add
+ puts \
+ ` git add -u;`
+ end
+
+ def stable
+ puts \
+ ` git checkout #{BRANCH_STABLE};`
+ end
+
+ def dev
+ puts \
+ ` git checkout #{BRANCH_DEV};`
+ end
+
+ def master
+ puts \
+ ` git checkout master;`
+ end
+
+ def upgrade
+ puts \
+ ` git checkout #{BRANCH_BALCMS};
+ git pull balcms #{BRANCH_STABLE};
+ git checkout #{BRANCH_DEV};
+ git merge #{BRANCH_BALCMS};`
+ end
+
+ def update
+ puts \
+ ` git pull;`
+ configure
+ end
+
+ def deploy
+ puts \
+ ` git checkout #{BRANCH_STABLE};
+ git merge #{BRANCH_DEV};
+ git checkout #{BRANCH_MASTER};
+ git merge #{BRANCH_STABLE};
+ git checkout #{BRANCH_DEV};
+ git push origin --all;`
+ end
+
+end
+
+# ===========================================================================
+# Booter
+
+class Booter
+ VERSION = :'0.0.1'
+
+ attr_reader :options
+
+ def initialize(arguments, stdin)
+ @arguments = arguments
+ @stdin = stdin
+
+ # Set defaults
+ @options = OpenStruct.new
+ @options.verbose = false
+ @options.quiet = false
+ # TO DO - add additional defaults
+ end
+
+ # Parse options, check arguments, then process the command
+ def run
+
+ if parsed_options? && arguments_valid?
+
+ puts "Start at #{DateTime.now}\n\n" if @options.verbose
+
+ output_options if @options.verbose # [Optional]
+
+ process_arguments
+ process_command
+
+ puts "\nFinished at #{DateTime.now}" if @options.verbose
+
+ else
+ output_usage
+ end
+
+ end
+
+ protected
+
+ def parsed_options?
+
+ # Specify options
+ opts = OptionParser.new
+ opts.on('-v', '--version') { output_version ; exit 0 }
+ opts.on('-h', '--help') { output_help }
+ opts.on('-V', '--verbose') { @options.verbose = true }
+ opts.on('-q', '--quiet') { @options.quiet = true }
+ # TO DO - add additional options
+
+ opts.parse!(@arguments) rescue return false
+
+ process_options
+ true
+ end
+
+ # Performs post-parse processing on options
+ def process_options
+ @options.verbose = false if @options.quiet
+ end
+
+ def output_options
+ puts :"Options:\n"
+
+ @options.marshal_dump.each do |name, val|
+ puts " #{name} = #{val}"
+ end
+ end
+
+ # True if required arguments were provided
+ def arguments_valid?
+ # TO DO - implement your real logic here
+ true if @arguments.length == 1
+ end
+
+ # Setup the arguments
+ def process_arguments
+ # TO DO - place in local vars, etc
+ end
+
+ def output_help
+ output_version
+ RDoc::usage() #exits app
+ end
+
+ def output_usage
+ RDoc::usage(:'usage') # gets usage from comments above
+ end
+
+ def output_version
+ puts "#{File.basename(__FILE__)} version #{VERSION}"
+ end
+
+ def process_command
+ # Create Application
+ app = App.new
+
+ # Fetch + Execute
+ command = @arguments[0].gsub('-','_')
+ unless app.respond_to?(command)
+ abort("Unknown command: #{command}")
+ end
+ app.send(command)
+ end
+
+ def process_standard_input
+ input = @stdin.read
+ # TO DO - process input
+
+ # [Optional]
+ #@stdin.each do |line|
+ # # TO DO - process each line
+ #end
+ end
+end
+
+
+# Create Booter
+booter = Booter.new(ARGV, STDIN)
+booter.run
View
58 admin/thirdparty/history-js/demo/bcherry-orig.html
@@ -0,0 +1,58 @@
+
+<!DOCTYPE html>
+<html lang="en">
+<head>
+ <meta charset="utf-8" />
+
+ <title>WebKit is Dropping HTML5 "popstate" Events</title>
+
+ <link rel="stylesheet" href="/static/lib/css/blueprint/blueprint.min.css" media="screen, projection" />
+ <link rel="stylesheet" href="/static/lib/css/blueprint/print.min.css" media="print" />
+ <!--[if lt IE 8]>
+ <link rel="stylesheet" href="/static/lib/css/blueprint/ie.min.css" media="screen, projection">
+ <![endif]-->
+ <link href="/static/lib/css/bcherry.css" rel="stylesheet" media="screen" />
+ <style>
+ #n {
+ font-size: 48px;
+ }
+ p {
+ padding: 0 20px;
+ }
+ </style>
+
+ <script type="text/javascript" src="../vendor/jquery.js"></script>
+ <script type="text/javascript" src="../scripts/uncompressed/history.adapter.jquery.js"></script>
+ <script type="text/javascript" src="../scripts/uncompressed/history.js"></script>
+
+</head>
+<body>
+ <div id="n"></div>
+ <p>There's a bug in the HTML5 "popstate" event, as implemented in WebKit (Safari and Chrome). View this page in one of those browsers. Your browser has had history entries added from #0 to #19 (you should start at #19). Hitting back/forward will navigate through these. On each URL, the large number above should reflect the hash value. If you hit back/forward quickly, you'll notice that your number gets out of sync with the URL. This is because WebKit is dropping popstate events (they are not firing). It seems to happen when outbound network requests are in progress when the user navigates in their browser happens. In this case, your browser is downloading an image that takes 1s to serve on every popstate, so you'll have to wait 1s between backs/forwards to have the feature work correctly. You could also cause constant network traffic by putting an image download in a setInterval, in which case your popstate events will never fire. This implementation simulates an AJAX application that makes a network request when you navigate between URLs using pushState/popstate. View the source for more info.</p>
+ <p>This was filed as <a href="https://bugs.webkit.org/show_bug.cgi?id=42940">Bug 42940</a> with WebKit on July 24, 2010. The Firefox 4 beta does not have this bug, which is good news.</p>
+ <p>This is put together by <a href="http://www.adequatelygood.com">Ben Cherry</a>. Ben is a front-end engineer at <a href="http://twitter.com/">Twitter</a>, and you can follow him at <a href="http://twitter.com/bcherry">@bcherry</a>.</p>
+ <script>
+ // Bind to popstate
+ $(window).bind("popstate", function(e) {
+ var State = e.state;
+
+ // log that this event was fired, and the current URL
+ if (window.console && window.console.log) {
+ console.log("popstate", State, window.location.href);
+ }
+ // update the page
+ $("#n").text(typeof State.n !== 'undefined' ? State.n : document.location.href);
+
+ // Make an outbound image request that will take 1s. This request seems to be the cause of dropped popstates.
+ // Removing this, or replacing it with something else, avoids the issue. Even if it's replaced with slow, blocking code (i.e. 1s of execution) events are not dropped.
+ (new Image()).src = "http://www.bcherry.net/playground/pushstate.jpg";
+ });
+
+ // Seed the browser history
+ for (var i = 0; i < 20; i++) {
+ window.history.pushState({n:i}, i, "?" + i);
+ $("#n").text(i);
+ }
+ </script>
+</body>
+</html>
View
62 admin/thirdparty/history-js/demo/bcherry.html
@@ -0,0 +1,62 @@
+
+<!DOCTYPE html>
+<html lang="en">
+<head>
+ <meta charset="utf-8" />
+
+ <title>WebKit is Dropping HTML5 "popstate" Events</title>
+
+ <link rel="stylesheet" href="/static/lib/css/blueprint/blueprint.min.css" media="screen, projection" />
+ <link rel="stylesheet" href="/static/lib/css/blueprint/print.min.css" media="print" />
+ <!--[if lt IE 8]>
+ <link rel="stylesheet" href="/static/lib/css/blueprint/ie.min.css" media="screen, projection">
+ <![endif]-->
+ <link href="/static/lib/css/bcherry.css" rel="stylesheet" media="screen" />
+ <style>
+ #n {
+ font-size: 48px;
+ }
+ p {
+ padding: 0 20px;
+ }
+ </style>
+
+ <script type="text/javascript" src="../vendor/jquery.js"></script>
+ <script type="text/javascript" src="../scripts/uncompressed/history.adapter.jquery.js"></script>
+ <script type="text/javascript" src="../scripts/uncompressed/history.js"></script>
+
+</head>
+<body>
+ <div id="n"></div>
+ <p>There's a bug in the HTML5 "popstate" event, as implemented in WebKit (Safari and Chrome). View this page in one of those browsers. Your browser has had history entries added from #0 to #19 (you should start at #19). Hitting back/forward will navigate through these. On each URL, the large number above should reflect the hash value. If you hit back/forward quickly, you'll notice that your number gets out of sync with the URL. This is because WebKit is dropping popstate events (they are not firing). It seems to happen when outbound network requests are in progress when the user navigates in their browser happens. In this case, your browser is downloading an image that takes 1s to serve on every popstate, so you'll have to wait 1s between backs/forwards to have the feature work correctly. You could also cause constant network traffic by putting an image download in a setInterval, in which case your popstate events will never fire. This implementation simulates an AJAX application that makes a network request when you navigate between URLs using pushState/popstate. View the source for more info.</p>
+ <p>This was filed as <a href="https://bugs.webkit.org/show_bug.cgi?id=42940">Bug 42940</a> with WebKit on July 24, 2010. The Firefox 4 beta does not have this bug, which is good news.</p>
+ <p>This is put together by <a href="http://www.adequatelygood.com">Ben Cherry</a>. Ben is a front-end engineer at <a href="http://twitter.com/">Twitter</a>, and you can follow him at <a href="http://twitter.com/bcherry">@bcherry</a>.</p>
+ <p>This bug was fixed in <a href="http://github.com/balupton/history.js">History.js</a> by <a href="http://balupton.com">Benjamin Lupton</a>. Benjamin is a freelance web 2.0 consultant, and you can follow him at <a href="http://twitter.com/balupton">@balupton</a>.</p>
+ <script>
+ // Prepare
+ window.History.debug.enable = true;
+
+ // Bind to popstate
+ $(window).bind("statechange", function(e) {
+ var State = window.History.getState();
+
+ // log that this event was fired, and the current URL
+ if (window.console && window.console.log) {
+ console.log("popstate", State, window.location.href);
+ }
+ // update the page
+ $("#n").text(typeof State.data.n !== 'undefined' ? State.data.n : State.url);
+
+ // Make an outbound image request that will take 1s. This request seems to be the cause of dropped popstates.
+ // Removing this, or replacing it with something else, avoids the issue. Even if it's replaced with slow, blocking code (i.e. 1s of execution) events are not dropped.
+ (new Image()).src = "http://www.bcherry.net/playground/pushstate.jpg";
+ });
+
+ // Seed the browser history
+ for (var i = 0; i < 20; i++) {
+ window.History.pushState({n:i}, i, "?" + i);
+ $("#n").text(i);
+ }
+ </script>
+</body>
+</html>
View
37 admin/thirdparty/history-js/demo/chrome.html
@@ -0,0 +1,37 @@
+<html>
+<head>
+ <title>Chrome History API Data Artifact</title>
+</head>
+<body>
+ <p>This demo demonstrates an issue with Google Chrome versions 8-10 (possibly 11) where if you push a state with data, then do history.back to the initial state, the event.state will contain the pushed states data instead of being null.</p>
+ <p>Note: The issue requires a clean history list, as such this should always be opened in a new tab/window where there are no prior history items.</p>
+ <p>Reported by <a href="http://balupton.com">Benjamin Lupton</a> author of <a href="http://github.com/balupton/history.js">History.js</a></p>
+ <button id="bug">bug</button>
+ <button id="reset">reset</button>
+ <textarea id="log" style="width:100%;height:200px;margin-top:1em;"></textarea>
+ <script type="text/javascript">
+ (function(){
+
+ window.onpopstate = function(event) {
+ var message = ("onpopstate: location: " + document.location.href + ", data: " + JSON.stringify(event.state));
+ document.getElementById('log').innerHTML += message+"\n\n";
+ };
+
+ document.getElementById('bug').onclick = function(){
+ setTimeout(function(){
+ history.pushState({state:'new'},'New State','?new');
+ },1e3);
+
+ setTimeout(function(){
+ history.back();
+ },2e3);
+ };
+
+ document.getElementById('reset').onclick = function(){
+ document.location.href = document.location.href.replace(/[\#\?].*/,"");
+ };
+
+ })();
+ </script>
+</body>
+</html>
View
101 admin/thirdparty/history-js/demo/index.html
@@ -0,0 +1,101 @@
+<!DOCTYPE HTML>
+<html>
+<head>
+ <meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
+ <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
+ <title>
+ History.js
+ </title>
+</head>
+<body style="padding-bottom:40px">
+ <!-- Scripts -->
+ <script>if ( typeof window.JSON === 'undefined' ) { document.write('<script src="../scripts/uncompressed/json2.js"><\/script>'); }</script>
+ <script src="../vendor/jquery.js"></script>
+ <script src="../scripts/uncompressed/amplify.store.js"></script>
+ <script src="../scripts/uncompressed/history.adapter.jquery.js"></script>
+ <script src="../scripts/uncompressed/history.js"></script>
+ <script src="../scripts/uncompressed/history.html4.js"></script>
+
+ <!-- HTML -->
+ <div id="wrap">
+ <!-- Intro -->
+ <h1><a href="https://github.com/balupton/History.js">History.js</a> by <a href="http://balupton.com">Benjamin Lupton</a></h1>
+ <p>History.js gracefully supports the <a href="https://developer.mozilla.org/en/DOM/Manipulating_the_browser_history">HTML5 History/State APIs</a> (pushState, replaceState, onPopState) in all browsers. Including continued support for data, titles, replaceState. Supports <a href="http://jquery.com/">jQuery</a>, <a href="http://mootools.net">MooTools</a> and <a href="http://prototypejs.org">Prototype</a>. For HTML5 browsers this means that you can modify the URL directly, without needing to use hashes anymore. For HTML4 browsers it will revert back to using the old onhashchange functionality.</p>
+
+ <!-- Textarea for Logging -->
+ <textarea id="log" style="width:100%;height:400px"></textarea>
+
+ <!-- Note -->
+ <p>Click through the buttons in order and you'll get the results demonstrated in the <a href="../README.md">README.md</a> file.</p>
+
+ <!-- Buttons -->
+ <ul id="buttons">
+ </ul>
+
+ <!-- Subscribe to Updates -->
+ <h3 style="margin-top:30px">Subscribe to Updates</h3>
+ <p>You'll be the first to know when new releases come out. Yes this form actually works, it just isn't styled yet to keep things simple.</p>
+ <form action="http://balupton.createsend.com/t/r/s/phujuu/" method="post" id="subForm">
+ <div>
+ <label for="name">Name:</label><input type="text" name="cm-name" id="name" /><br />
+ <label for="phujuu-phujuu">Email:</label><input type="text" name="cm-phujuu-phujuu" id="phujuu-phujuu" /><br />
+ <label for="Website">Website:</label><input type="text" name="cm-f-kjqtu" id="Website" /><br />
+ <input type="submit" value="Subscribe" />
+ </div>
+ </form>
+
+ <!-- Our Script -->
+ <script>
+ (function(window,undefined){
+
+ // Check Location
+ if ( document.location.protocol === 'file:' ) {
+ alert('The HTML5 History API (and thus History.js) do not work on files, please upload it to a server.');
+ }
+
+ // Establish Variables
+ var
+ History = window.History, // Note: We are using a capital H instead of a lower h
+ State = History.getState(),
+ $log = $('#log');
+
+ // Log Initial State
+ History.log('initial:', State.data, State.title, State.url);
+
+ // Bind to State Change
+ History.Adapter.bind(window,'statechange',function(){ // Note: We are using statechange instead of popstate
+ // Log the State
+ var State = History.getState(); // Note: We are using History.getState() instead of event.state
+ History.log('statechange:', State.data, State.title, State.url);
+ });
+
+ // Prepare Buttons
+ var
+ buttons = document.getElementById('buttons'),
+ scripts = [
+ 'History.pushState({state:1,rand:Math.random()}, "State 1", "?state=1"); // logs {state:1,rand:"some random value"}, "State 1", "?state=1"',
+ 'History.pushState({state:2,rand:Math.random()}, "State 2", "?state=2"); // logs {state:2,rand:"some random value"}, "State 2", "?state=2"',
+ 'History.replaceState({state:3,rand:Math.random()}, "State 3", "?state=3"); // logs {state:3,rand:"some random value"}, "State 3", "?state=3"',
+ 'History.pushState(null, null, "?state=4"); // logs {}, "", "?state=4"',
+ 'History.back(); // logs {state:3}, "State 3", "?state=3"',
+ 'History.back(); // logs {state:1}, "State 1", "?state=1"',
+ 'History.back(); // logs {}, "The page you started at", "?"',
+ 'History.go(2); // logs {state:3}, "State 3", "?state=3"'
+ ],
+ buttonsHTML = ''
+ ;
+
+ // Add Buttons
+ for ( var i=0,n=scripts.length; i<n; ++i ) {
+ var _script = scripts[i];
+ buttonsHTML +=
+ '<li><button onclick=\'javascript:'+_script+'\'>'+_script+'</button></li>';
+ }
+ buttons.innerHTML = buttonsHTML;
+
+ })(window);
+ </script>
+ </div>
+
+</body>
+</html>
View
43 admin/thirdparty/history-js/demo/native-auto.html
@@ -0,0 +1,43 @@
+<html>
+<head>
+</head>
+<body>
+ <script type="text/javascript">
+ (function(){
+
+ window.onpopstate = function(event) {
+ console.log("onpopstate: location: " + document.location.href + ", data: " + JSON.stringify(event.state));
+ };
+ window.onhashchange = function(event) {
+ console.log("onhashchange: location: " + document.location.href);
+ };
+
+ setTimeout(function(){
+ history.pushState({page: 1}, "title 1", "?page=1");
+ },1e3);
+ setTimeout(function(){
+ history.pushState({page: 2}, "title 2", "?page=2");
+ },2e3);
+ setTimeout(function(){
+ history.replaceState({page: 3}, "title 3", "?page=3");
+ },3e3);
+ setTimeout(function(){
+ document.location.hash = 'asd';
+ },4e3);
+ setTimeout(function(){
+ history.back(); // alerts "location: http://example.com/example.html?page=3#asd, state: {"page":3}"
+ },5e3);
+ setTimeout(function(){
+ history.back(); // alerts "location: http://example.com/example.html?page=1, state: {"page":1}"
+ },6e3);
+ setTimeout(function(){
+ history.back(); // alerts "location: http://example.com/example.html, state: null
+ },7e3);
+ setTimeout(function(){
+ history.go(2); // alerts "location: http://example.com/example.html?page=3, state: {"page":3}
+ },8e3);
+
+ })();
+ </script>
+</body>
+</html>
View
62 admin/thirdparty/history-js/demo/native.html
@@ -0,0 +1,62 @@
+<html>
+<head>
+ <title>HTML5 History API Demo</title>
+</head>
+<body>
+ <textarea id="log" style="width:100%;height:400px;margin:1em;"></textarea>
+ <div id="url" style="border:1px black dotted;height:1em;margin:1em;"></div>
+ <div id="buttons" style="margin:1em;"></div>
+ <script type="text/javascript">
+ var $url = document.getElementById('url'), $log = document.getElementById('log');
+
+ window.onpopstate = function(event) {
+ var message =
+ "onpopstate: "+
+ "location: " + location.href + ", " +
+ "data: " + JSON.stringify(event.state) +
+ "\n\n"
+ ;
+
+ $url.innerHTML = location.href;
+ $log.innerHTML += message;
+ console.log(message);
+ };
+
+ window.onhashchange = function(event) {
+ var message =
+ "onhashchange: "+
+ "location: " + location.href + ", "+
+ "hash: " + location.hash +
+ "\n\n"
+ ;
+
+ $url.innerHTML = location.href;
+ $log.innerHTML += message;
+ console.log(message);
+ };
+
+ // Prepare Buttons
+ var
+ buttons = document.getElementById('buttons'),
+ scripts = [
+ 'history.pushState({state:1}, "State 1", "?state=1");',
+ 'history.pushState({state:2}, "State 2", "?state=2");',
+ 'history.replaceState({state:3}, "State 3", "?state=3");',
+ 'location.hash = Math.random();',
+ 'history.back();',
+ 'history.forward();',
+ 'document.location.href = document.location.href.replace(/[\#\?].*/,"");'
+ ],
+ buttonsHTML = ''
+ ;
+
+ // Add Buttons
+ for ( var i=0,n=scripts.length; i<n; ++i ) {
+ var _script = scripts[i];
+ buttonsHTML +=
+ '<li><button onclick=\'javascript:'+_script+'\'>'+_script+'</button></li>';
+ }
+ buttons.innerHTML = buttonsHTML;
+ </script>
+</body>
+</html>
View
23 admin/thirdparty/history-js/demo/navigator.html
@@ -0,0 +1,23 @@
+<!DOCTYPE HTML>
+<html>
+<head>
+ <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
+ <title>
+ Navigator Output
+ </title>
+ <style>
+ label { font-weight:bold; }
+ label:after { content: ":"; margin-right:5px; }
+ </style>
+</head>
+<body>
+ <div id="nav"></div>
+ <script>
+ var nav = document.getElementById('nav'), i,v;
+ for ( i in navigator ) {
+ var v = navigator[i];
+ nav.innerHTML += '<div><label>'+i+'</label>'+v+'</div>';
+ }
+ </script>
+</body>
+</html>
View
61 admin/thirdparty/history-js/demo/safari.html
@@ -0,0 +1,61 @@
+<html>
+<head>
+ <title>Safari Hash ReplaceState History Traversal Bug</title>
+</head>
+<body>
+ <p>This demo demonstrates an issue with Safari 5.0.4 (6533.20.27) handing of hashes and replace state. When a hash is set, and then replaced using replaceState the history list are then broken, when traversing back the hash does not change.</p>
+ <p>Note: The issue requires a clean history list, as such this should always be opened in a new tab/window where there are no prior history items.</p>
+ <p>Reported by <a href="http://balupton.com">Benjamin Lupton</a> author of <a href="http://github.com/balupton/history.js">History.js</a></p>
+ <button id="bug">bug</button>
+ <button id="workaround">workaround</button>
+ <button id="reset">reset</button>
+ <textarea id="log" style="width:100%;height:200px;margin-top:1em;"></textarea>
+ <script type="text/javascript">
+ (function(){
+
+ window.onpopstate = function(event) {
+ var message = ("onpopstate: location: " + document.location.href);
+ document.getElementById('log').innerHTML += message+"\n\n";
+ };
+
+ window.onhashchange = function(event) {
+ var message = ("onhashchange: location: " + document.location.href);
+ document.getElementById('log').innerHTML += message+"\n\n";
+ };
+
+ document.getElementById('bug').onclick = function(){
+ setTimeout(function(){
+ document.location.hash = Math.random();
+ },1e3);
+
+ setTimeout(function(){
+ history.replaceState(null,'','?blah');
+ },2e3);
+
+ setTimeout(function(){
+ history.back(); // should take us to the initial page, it doesn't
+ },3e3);
+ };
+
+ document.getElementById('workaround').onclick = function(){
+ setTimeout(function(){
+ history.pushState(null,'','#'+Math.random());
+ },1e3);
+
+ setTimeout(function(){
+ history.replaceState(null,'','?blah');
+ },2e3);
+
+ setTimeout(function(){
+ history.back(); // will take us to the initial page
+ },3e3);
+ };
+
+ document.getElementById('reset').onclick = function(){
+ document.location.href = document.location.href.replace(/[\#\?].*/,"");
+ };
+
+ })();
+ </script>
+</body>
+</html>
View
10 admin/thirdparty/history-js/license.txt
@@ -0,0 +1,10 @@
+Copyright (c) 2011, Benjamin Arthur Lupton
+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.
+ • Neither the name of Benjamin Arthur Lupton nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.
+
+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 HOLDER 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.
View
74 admin/thirdparty/history-js/package.json
@@ -0,0 +1,74 @@
+{
+ "name": "history.js",
+ "version": "1.6.0",
+ "description": "History.js gracefully supports the HTML5 History/State APIs (pushState, replaceState, onPopState) in all browsers. Including continued support for data, titles, replaceState. Supports jQuery, MooTools and Prototype. For HTML5 browsers this means that you can modify the URL directly, without needing to use hashes anymore. For HTML4 browsers it will revert back to using the old onhashchange functionality.",
+ "homepage": "https://github.com/balupton/history.js",
+ "keywords": [
+ "javascript",
+ "html5 history api",
+ "hashchange",
+ "popstate",
+ "pushstate",
+ "replacestate",
+ "hashes",
+ "hashbang"
+ ],
+ "author": {
+ "name": "Benjamin Lupton",
+ "email": "b@lupton.cc",
+ "web": "http://balupton.com"
+ },
+ "maintainers": [
+ {
+ "name": "Benjamin Lupton",
+ "email": "b@lupton.cc",
+ "web": "http://balupton.com"
+ }
+ ],
+ "contributors": [
+ {
+ "name": "Benjamin Lupton",
+ "email": "b@lupton.cc",
+ "web": "http://balupton.com"
+ }
+ ],
+ "bugs": {
+ "web": "https://github.com/balupton/history.js/issues"
+ },
+ "licenses": [
+ {
+ "type": "New-BSD",
+ "url": "http://creativecommons.org/licenses/BSD/"
+ }
+ ],
+ "repository" : {
+ "type" : "git",
+ "url" : "http://github.com/balupton/history.js.git"
+ },
+ "dependencies": {
+ },
+ "engines" : {
+ },
+ "directories": {
+ "out": "./scripts/compressed",
+ "src": "./scripts/uncompressed"
+ },
+ "buildr": {
+ "compress": {
+ "js": true,
+ "css": false,
+ "img": false,
+ "html": false
+ },
+ "bundle": false,
+ "directories": {
+ "out": "./scripts/compressed",
+ "src": "./scripts/uncompressed"
+ },
+ "files": {
+ "js": true,
+ "css": false,
+ "img": false
+ }
+ }
+}
View
1  admin/thirdparty/history-js/scripts/compressed/amplify.store.js
@@ -0,0 +1 @@
+(function(a,b){function d(a,d){var e=d.__amplify__?JSON.parse(d.__amplify__):{};c.addType(a,function(f,g,h){var i=g,j=(new Date).getTime(),k,l;if(!f){i={};for(f in e)k=d[f],l=k?JSON.parse(k):{expires:-1},l.expires&&l.expires<=j?(delete d[f],delete e[f]):i[f.replace(/^__amplify__/,"")]=l.data;d.__amplify__=JSON.stringify(e);return i}f="__amplify__"+f;if(g===b){if(e[f]){k=d[f],l=k?JSON.parse(k):{expires:-1};if(l.expires&&l.expires<=j)delete d[f],delete e[f];else return l.data}}else if(g===null)delete d[f],delete e[f];else{l=JSON.stringify({data:g,expires:h.expires?j+h.expires:null});try{d[f]=l,e[f]=!0}catch(m){c[a]();try{d[f]=l,e[f]=!0}catch(m){throw c.error()}}}d.__amplify__=JSON.stringify(e);return i})}JSON.stringify=JSON.stringify||JSON.encode,JSON.parse=JSON.parse||JSON.decode;var c=a.store=function(a,b,d,e){var e=c.type;d&&d.type&&d.type in c.types&&(e=d.type);return c.types[e](a,b,d||{})};c.types={},c.type=null,c.addType=function(a,b){c.type||(c.type=a),c.types[a]=b,c[a]=function(b,d,e){e=e||{},e.type=a;return c(b,d,e)}},c.error=function(){return"amplify.store quota exceeded"};for(var e in{localStorage:1,sessionStorage:1})try{window[e].getItem&&d(e,window[e])}catch(f){}window.globalStorage&&(d("globalStorage",window.globalStorage[window.location.hostname]),c.type==="sessionStorage"&&(c.type="globalStorage")),function(){var a=document.createElement("div"),d="amplify",e;a.style.display="none",document.getElementsByTagName("head")[0].appendChild(a),a.addBehavior&&(a.addBehavior("#default#userdata"),a.load(d),e=a.getAttribute(d)?JSON.parse(a.getAttribute(d)):{},c.addType("userData",function(f,g,h){var i=g,j=(new Date).getTime(),k,l,m;if(!f){i={};for(f in e)k=a.getAttribute(f),l=k?JSON.parse(k):{expires:-1},l.expires&&l.expires<=j?(a.removeAttribute(f),delete e[f]):i[f]=l.data;a.setAttribute(d,JSON.stringify(e)),a.save(d);return i}f=f.replace(/[^-._0-9A-Za-z\xb7\xc0-\xd6\xd8-\xf6\xf8-\u037d\u37f-\u1fff\u200c-\u200d\u203f\u2040\u2070-\u218f]/g,"-");if(g===b){if(f in e){k=a.getAttribute(f),l=k?JSON.parse(k):{expires:-1};if(l.expires&&l.expires<=j)a.removeAttribute(f),delete e[f];else return l.data}}else g===null?(a.removeAttribute(f),delete e[f]):(m=a.getAttribute(f),l=JSON.stringify({data:g,expires:h.expires?j+h.expires:null}),a.setAttribute(f,l),e[f]=!0);a.setAttribute(d,JSON.stringify(e));try{a.save(d)}catch(n){m===null?(a.removeAttribute(f),delete e[f]):a.setAttribute(f,m),c.userData();try{a.setAttribute(f,l),e[f]=!0,a.save(d)}catch(n){m===null?(a.removeAttribute(f),delete e[f]):a.setAttribute(f,m);throw c.error()}}return i}))}(),d("memory",{})})(this.amplify=this.amplify||{})
View
0  admin/thirdparty/history-js/scripts/compressed/history.adapter.dojo.js
No changes.
View
1  admin/thirdparty/history-js/scripts/compressed/history.adapter.jquery.js
@@ -0,0 +1 @@
+(function(a,b){var c=a.History=a.History||{},d=a.jQuery;if(typeof c.Adapter!="undefined")throw new Error("History.js Adapter has already been loaded...");c.Adapter={bind:function(a,b,c){d(a).bind(b,c)},trigger:function(a,b){d(a).trigger(b)},onDomLoad:function(a){d(a)}},typeof c.init!="undefined"&&c.init()})(window)
View
1  admin/thirdparty/history-js/scripts/compressed/history.adapter.mootools.js
@@ -0,0 +1 @@
+(function(a,b){var c=a.History=a.History||{},d=a.MooTools;if(typeof c.Adapter!="undefined")throw new Error("History.js Adapter has already been loaded...");Object.append(Element.NativeEvents,{popstate:2,hashchange:2}),c.Adapter={bind:function(a,b,c){var d=typeof a=="string"?document.id(a):a;d.addEvent(b,c)},trigger:function(a,b){var c=typeof a=="string"?document.id(a):a;c.fireEvent(b)},onDomLoad:function(b){a.addEvent("domready",b)}},typeof c.init!="undefined"&&c.init()})(window)
View
1  admin/thirdparty/history-js/scripts/compressed/history.adapter.prototype.js
@@ -0,0 +1 @@
+(function(a,b){var c=a.History=a.History||{},d=a.Prototype,e=a.Element,f=a.Event,g=a.$;if(typeof c.Adapter!="undefined")throw new Error("History.js Adapter has already been loaded...");typeof a.fireEvent=="undefined"&&typeof a.dispatchEvent=="undefined"?c.enable=!1:(function(){var a={HTMLEvents:/^(?:load|unload|abort|error|select|hashchange|popstate|change|submit|reset|focus|blur|resize|scroll)$/,MouseEvents:/^(?:click|mouse(?:down|up|over|move|out))$/},b={pointerX:0,pointerY:0,button:0,ctrlKey:!1,altKey:!1,shiftKey:!1,metaKey:!1,bubbles:!0,cancelable:!0};f.hasNativeEvent=function(b,c){var d=null,e;b=g(b);for(var f in a)if(a[f].test(c)){d=f;break}e=d?!0:!1;return e},f.bind=function(a,b,c){a=g(a);return e.hasNativeEvent(a,b)?e.observe(a,b,c):e.observe(a,"custom:"+b,c)},f.trigger=function(c,d){var f=Object.extend(b,arguments[2]||{}),h,i=null;c=g(c);var j;for(j in a)if(a[j].test(d)){i=j;break}if(!i)return e.fire(c,"custom:"+d);document.createEvent?(h=document.createEvent(i),i==="HTMLEvents"?h.initEvent(d,f.bubbles,f.cancelable):i&&h.initMouseEvent(d,f.bubbles,f.cancelable,document.defaultView,f.button,f.pointerX,f.pointerY,f.pointerX,f.pointerY,f.ctrlKey,f.altKey,f.shiftKey,f.metaKey,f.button,c)):document.createEventObject&&(f.clientX=f.pointerX,f.clientY=f.pointerY,h=Object.extend(document.createEventObject(),f));if(c.fireEvent)c.fireEvent("on"+d,h);else if(c.dispatchEvent)c.dispatchEvent(h);else throw new Error("Cannot dispatch the event");return c},e.addMethods({simulate:f.trigger,trigger:f.trigger,bind:f.bind,hasNativeEvent:f.hasNativeEvent})}(),c.Adapter={bind:function(a,b,c){e.bind(a,b,c)},trigger:function(a,b){e.trigger(a,b)},onDomLoad:function(b){f.observe(a.document,"dom:loaded",b)}},typeof c.init!="undefined"&&c.init())})(window)
View
1  admin/thirdparty/history-js/scripts/compressed/history.adapter.yui.js
@@ -0,0 +1 @@
+(function(a,b){var c=a.History=a.History||{},d=a.YUI;if(typeof c.Adapter!="undefined")throw new Error("History.js Adapter has already been loaded...");c.Adapter={bind:function(a,b,c){d().use("node-base",function(d){d.one(a).on(b,c)})},trigger:function(a,b){d().use("node-event-simulate",function(c){c.one(a).simulate(b)})},onDomLoad:function(a){d().use("event",function(b){b.on("domready",a)})}},typeof c.init!="undefined"&&c.init()})(window)
View
1  admin/thirdparty/history-js/scripts/compressed/history.adapter.zepto.js
@@ -0,0 +1 @@
+(function(a,b){var c=a.History=a.History||{},d=a.Zepto;if(typeof c.Adapter!="undefined")throw new Error("History.js Adapter has already been loaded...");c.Adapter={bind:function(a,b,c){d(a).bind(b,c)},trigger:function(a,b){d(a).trigger(b)},onDomLoad:function(a){d(a)}},typeof c.init!="undefined"&&c.init()})(window)
View
1  admin/thirdparty/history-js/scripts/compressed/history.html4.js
@@ -0,0 +1 @@
+(function(a,b){"use strict";var c=a.document,d=a.setTimeout||d,e=a.clearTimeout||e,f=a.setInterval||f,g=a.History=a.History||{};if(typeof g.initHtml4!="undefined")throw new Error("History.js HTML4 Support has already been loaded...");g.initHtml4=function(){if(typeof g.initHtml4.initialized!="undefined")return!1;g.initHtml4.initialized=!0,g.enabled=!0,g.savedHashes=[],g.isLastHash=function(a){var b=g.getHashByIndex(),c=a===b;return c},g.saveHash=function(a){if(g.isLastHash(a))return!1;g.savedHashes.push(a);return!0},g.getHashByIndex=function(a){var b=null;typeof a=="undefined"?b=g.savedHashes[g.savedHashes.length-1]:a<0?b=g.savedHashes[g.savedHashes.length+a]:b=g.savedHashes[a];return b},g.discardedHashes={},g.discardedStates={},g.discardState=function(a,b,c){var d=g.getHashByState(a),e={discardedState:a,backState:c,forwardState:b};g.discardedStates[d]=e;return!0},g.discardHash=function(a,b,c){var d={discardedHash:a,backState:c,forwardState:b};g.discardedHashes[a]=d;return!0},g.discardedState=function(a){var b=g.getHashByState(a),c=g.discardedStates[b]||!1;return c},g.discardedHash=function(a){var b=g.discardedHashes[a]||!1;return b},g.recycleState=function(a){var b=g.getHashByState(a);g.discardedState(a)&&delete g.discardedStates[b];return!0},g.emulated.hashChange&&(g.hashChangeInit=function(){g.checkerFunction=null;var b="";if(g.isInternetExplorer()){var d="historyjs-iframe",e=c.createElement("iframe");e.setAttribute("id",d),e.style.display="none",c.body.appendChild(e),e.contentWindow.document.open(),e.contentWindow.document.close();var h="",i=!1;g.checkerFunction=function(){if(i)return!1;i=!0;var c=g.getHash()||"",d=g.unescapeHash(e.contentWindow.document.location.hash)||"";c!==b?(b=c,d!==c&&(h=d=c,e.contentWindow.document.open(),e.contentWindow.document.close(),e.contentWindow.document.location.hash=g.escapeHash(c)),g.Adapter.trigger(a,"hashchange")):d!==h&&(h=d,g.setHash(d,!1)),i=!1;return!0}}else g.checkerFunction=function(){var c=g.getHash();c!==b&&(b=c,g.Adapter.trigger(a,"hashchange"));return!0};f(g.checkerFunction,g.options.hashChangeInterval);return!0},g.Adapter.onDomLoad(g.hashChangeInit)),g.emulated.pushState&&(g.onHashChange=function(b){var d=b&&b.newURL||c.location.href,e=g.getHashByUrl(d),f=null,h=null,i=null;if(g.isLastHash(e)){g.busy(!1);return!1}g.doubleCheckComplete(),g.saveHash(e);if(e&&g.isTraditionalAnchor(e)){g.Adapter.trigger(a,"anchorchange"),g.busy(!1);return!1}f=g.extractState(g.getFullUrl(e||c.location.href,!1),!0);if(g.isLastSavedState(f)){g.busy(!1);return!1}h=g.getHashByState(f);var j=g.discardedState(f);if(j){g.getHashByIndex(-2)===g.getHashByState(j.forwardState)?g.back(!1):g.forward(!1);return!1}g.pushState(f.data,f.title,f.url,!1);return!0},g.Adapter.bind(a,"hashchange",g.onHashChange),g.pushState=function(b,d,e,f){if(g.getHashByUrl(e))throw new Error("History.js does not support states with fragement-identifiers (hashes/anchors).");if(f!==!1&&g.busy()){g.pushQueue({scope:g,callback:g.pushState,args:arguments,queue:f});return!1}g.busy(!0);var h=g.createStateObject(b,d,e),i=g.getHashByState(h),j=g.getState(!1),k=g.getHashByState(j),l=g.getHash();g.storeState(h),g.expectedStateId=h.id,g.recycleState(h),g.setTitle(h);if(i===k){g.busy(!1);return!1}if(i!==l&&i!==g.getShortUrl(c.location.href)){g.setHash(i,!1);return!1}g.saveState(h),g.Adapter.trigger(a,"statechange"),g.busy(!1);return!0},g.replaceState=function(a,b,c,d){if(g.getHashByUrl(c))throw new Error("History.js does not support states with fragement-identifiers (hashes/anchors).");if(d!==!1&&g.busy()){g.pushQueue({scope:g,callback:g.replaceState,args:arguments,queue:d});return!1}g.busy(!0);var e=g.createStateObject(a,b,c),f=g.getState(!1),h=g.getStateByIndex(-2);g.discardState(f,e,h),g.pushState(e.data,e.title,e.url,!1);return!0},g.getHash()&&!g.emulated.hashChange&&g.Adapter.onDomLoad(function(){g.Adapter.trigger(a,"hashchange")}))},g.init()})(window)
View
1  admin/thirdparty/history-js/scripts/compressed/history.js
@@ -0,0 +1 @@
+(function(a,b){"use strict";var c=a.console||b,d=a.document,e=a.navigator,f=a.amplify||!1,g=a.setTimeout,h=a.clearTimeout,i=a.setInterval,j=a.JSON,k=a.History=a.History||{},l=a.history;j.stringify=j.stringify||j.encode,j.parse=j.parse||j.decode;if(typeof k.init!="undefined")throw new Error("History.js Core has already been loaded...");k.init=function(){if(typeof k.Adapter=="undefined")return!1;typeof k.initCore!="undefined"&&k.initCore(),typeof k.initHtml4!="undefined"&&k.initHtml4();return!0},k.initCore=function(){if(typeof k.initCore.initialized!="undefined")return!1;k.initCore.initialized=!0,k.options=k.options||{},k.options.hashChangeInterval=k.options.hashChangeInterval||100,k.options.safariPollInterval=k.options.safariPollInterval||500,k.options.doubleCheckInterval=k.options.doubleCheckInterval||500,k.options.storeInterval=k.options.storeInterval||1e3,k.options.busyDelay=k.options.busyDelay||250,k.options.debug=k.options.debug||!1,k.options.initialTitle=k.options.initialTitle||d.title,k.debug=function(){(k.options.debug||!1)&&k.log.apply(k,arguments)},k.log=function(){var a=typeof c!="undefined"&&typeof c.log!="undefined"&&typeof c.log.apply!="undefined",b=d.getElementById("log"),e,f,g;if(a){var h=Array.prototype.slice.call(arguments);e=h.shift(),typeof c.debug!="undefined"?c.debug.apply(c,[e,h]):c.log.apply(c,[e,h])}else e="\n"+arguments[0]+"\n";for(f=1,g=arguments.length;f<g;++f){var i=arguments[f];if(typeof i=="object"&&typeof j!="undefined")try{i=j.stringify(i)}catch(k){}e+="\n"+i+"\n"}b?(b.value+=e+"\n-----\n",b.scrollTop=b.scrollHeight-b.clientHeight):a||alert(e);return!0},k.getInternetExplorerMajorVersion=function(){var a=k.getInternetExplorerMajorVersion.cached=typeof k.getInternetExplorerMajorVersion.cached!="undefined"?k.getInternetExplorerMajorVersion.cached:function(){var a=3,b=d.createElement("div"),c=b.getElementsByTagName("i");while((b.innerHTML="<!--[if gt IE "+ ++a+"]><i></i><![endif]-->")&&c[0]);return a>4?a:!1}();return a},k.isInternetExplorer=function(){var a=k.isInternetExplorer.cached=typeof k.isInternetExplorer.cached!="undefined"?k.isInternetExplorer.cached:Boolean(k.getInternetExplorerMajorVersion());return a},k.emulated={pushState:!Boolean(a.history&&a.history.pushState&&a.history.replaceState&&!/ Mobile\/([1-7][a-z]|(8([abcde]|f(1[0-8]))))/i.test(e.userAgent)&&!/AppleWebKit\/5([0-2]|3[0-2])/i.test(e.userAgent)),hashChange:Boolean(!("onhashchange"in a||"onhashchange"in d)||k.isInternetExplorer()&&k.getInternetExplorerMajorVersion()<8)},k.enabled=!k.emulated.pushState,k.bugs={setHash:Boolean(!k.emulated.pushState&&e.vendor==="Apple Computer, Inc."&&/AppleWebKit\/5([0-2]|3[0-3])/.test(e.userAgent)),safariPoll:Boolean(!k.emulated.pushState&&e.vendor==="Apple Computer, Inc."&&/AppleWebKit\/5([0-2]|3[0-3])/.test(e.userAgent)),ieDoubleCheck:Boolean(k.isInternetExplorer()&&k.getInternetExplorerMajorVersion()<8),hashEscape:Boolean(k.isInternetExplorer()&&k.getInternetExplorerMajorVersion()<7)},k.isEmptyObject=function(a){for(var b in a)return!1;return!0},k.cloneObject=function(a){var b,c;a?(b=j.stringify(a),c=j.parse(b)):c={};return c},k.getRootUrl=function(){var a=d.location.protocol+"//"+(d.location.hostname||d.location.host);if(d.location.port||!1)a+=":"+d.location.port;a+="/";return a},k.getBaseHref=function(){var a=d.getElementsByTagName("base"),b=null,c="";a.length===1&&(b=a[0],c=b.href.replace(/[^\/]+$/,"")),c=c.replace(/\/+$/,""),c&&(c+="/");return c},k.getBaseUrl=function(){var a=k.getBaseHref()||k.getBasePageUrl()||k.getRootUrl();return a},k.getPageUrl=function(){var a=k.getState(!1,!1),b=(a||{}).url||d.location.href,c=b.replace(/\/+$/,"").replace(/[^\/]+$/,function(a,b,c){return/\./.test(a)?a:a+"/"});return c},k.getBasePageUrl=function(){var a=d.location.href.replace(/[#\?].*/,"").replace(/[^\/]+$/,function(a,b,c){return/[^\/]$/.test(a)?"":a}).replace(/\/+$/,"")+"/";return a},k.getFullUrl=function(a,b){var c=a,d=a.substring(0,1);b=typeof b=="undefined"?!0:b,/[a-z]+\:\/\//.test(a)||(d==="/"?c=k.getRootUrl()+a.replace(/^\/+/,""):d==="#"?c=k.getPageUrl().replace(/#.*/,"")+a:d==="?"?c=k.getPageUrl().replace(/[\?#].*/,"")+a:b?c=k.getBaseUrl()+a.replace(/^(\.\/)+/,""):c=k.getBasePageUrl()+a.replace(/^(\.\/)+/,""));return c.replace(/\#$/,"")},k.getShortUrl=function(a){var b=a,c=k.getBaseUrl(),d=k.getRootUrl();k.emulated.pushState&&(b=b.replace(c,"")),b=b.replace(d,"/"),k.isTraditionalAnchor(b)&&(b="./"+b),b=b.replace(/^(\.\/)+/g,"./").replace(/\#$/,"");return b},k.store=f?f.store("History.store")||{}:{},k.store.idToState=k.store.idToState||{},k.store.urlToId=k.store.urlToId||{},k.store.stateToId=k.store.stateToId||{},k.idToState=k.idToState||{},k.stateToId=k.stateToId||{},k.urlToId=k.urlToId||{},k.storedStates=k.storedStates||[],k.savedStates=k.savedStates||[],k.getState=function(a,b){typeof a=="undefined"&&(a=!0),typeof b=="undefined"&&(b=!0);var c=k.getLastSavedState();!c&&b&&(c=k.createStateObject()),a&&(c=k.cloneObject(c),c.url=c.cleanUrl||c.url);return c},k.getIdByState=function(a){var b=k.extractId(a.url);if(!b){var c=k.getStateString(a);if(typeof k.stateToId[c]!="undefined")b=k.stateToId[c];else if(typeof k.store.stateToId[c]!="undefined")b=k.store.stateToId[c];else{for(;;){b=String(Math.floor(Math.random()*1e3));if(typeof k.idToState[b]=="undefined"&&typeof k.store.idToState[b]=="undefined")break}k.stateToId[c]=b,k.idToState[b]=a}}return b},k.normalizeState=function(a){if(!a||typeof a!="object")a={};if(typeof a.normalized!="undefined")return a;if(!a.data||typeof a.data!="object")a.data={};var b={};b.normalized=!0,b.title=a.title||"",b.url=k.getFullUrl(k.unescapeString(a.url||d.location.href)),b.hash=k.getShortUrl(b.url),b.data=k.cloneObject(a.data),b.id=k.getIdByState(b),b.cleanUrl=b.url.replace(/\??\&_suid.*/,""),b.url=b.cleanUrl;var c=!k.isEmptyObject(b.data);if(b.title||c)b.hash=k.getShortUrl(b.url).replace(/\??\&_suid.*/,""),/\?/.test(b.hash)||(b.hash+="?"),b.hash+="&_suid="+b.id;b.hashedUrl=k.getFullUrl(b.hash),(k.emulated.pushState||k.bugs.safariPoll)&&k.hasUrlDuplicate(b)&&(b.url=b.hashedUrl);return b},k.createStateObject=function(a,b,c){var d={data:a,title:b,url:c};d=k.normalizeState(d);return d},k.getStateById=function(a){a=String(a);var c=k.idToState[a]||k.store.idToState[a]||b;return c},k.getStateString=function(a){var b=k.normalizeState(a),c={data:b.data,title:a.title,url:a.url},d=j.stringify(c);return d},k.getStateId=function(a){var b=k.normalizeState(a),c=b.id;return c},k.getHashByState=function(a){var b,c=k.normalizeState(a);b=c.hash;return b},k.extractId=function(a){var b,c,d;c=/(.*)\&_suid=([0-9]+)$/.exec(a),d=c?c[1]||a:a,b=c?String(c[2]||""):"";return b||!1},k.isTraditionalAnchor=function(a){var b=!/[\/\?\.]/.test(a);return b},k.extractState=function(a,b){var c=null;b=b||!1;var d=k.extractId(a);d&&(c=k.getStateById(d));if(!c){var e=k.getFullUrl(a);d=k.getIdByUrl(e)||!1,d&&(c=k.getStateById(d)),!c&&b&&!k.isTraditionalAnchor(a)&&(c=k.createStateObject(null,null,e))}return c},k.getIdByUrl=function(a){var c=k.urlToId[a]||k.store.urlToId[a]||b;return c},k.getLastSavedState=function(){return k.savedStates[k.savedStates.length-1]||b},k.getLastStoredState=function(){return k.storedStates[k.storedStates.length-1]||b},k.hasUrlDuplicate=function(a){var b=!1,c=k.extractState(a.url);b=c&&c.id!==a.id;return b},k.storeState=function(a){k.urlToId[a.url]=a.id,k.storedStates.push(k.cloneObject(a));return a},k.isLastSavedState=function(a){var b=!1;if(k.savedStates.length){var c=a.id,d=k.getLastSavedState(),e=d.id;b=c===e}return b},k.saveState=function(a){if(k.isLastSavedState(a))return!1;k.savedStates.push(k.cloneObject(a));return!0},k.getStateByIndex=function(a){var b=null;typeof a=="undefined"?b=k.savedStates[k.savedStates.length-1]:a<0?b=k.savedStates[k.savedStates.length+a]:b=k.savedStates[a];return b},k.getHash=function(){var a=k.unescapeHash(d.location.hash);return a},k.unescapeString=function(b){var c=b,d;for(;;){d=a.unescape(c);if(d===c)break;c=d}return c},k.unescapeHash=function(a){var b=k.normalizeHash(a);b=k.unescapeString(b);return b},k.normalizeHash=function(a){var b=a.replace(/[^#]*#/,"").replace(/#.*/,"");return b},k.setHash=function(a,b){if(b!==!1&&k.busy()){k.pushQueue({scope:k,callback:k.setHash,args:arguments,queue:b});return!1}var c=k.escapeHash(a);k.busy(!0);var e=k.extractState(a,!0);if(e&&!k.emulated.pushState)k.pushState(e.data,e.title,e.url,!1);else if(d.location.hash!==c)if(k.bugs.setHash){var f=k.getPageUrl();k.pushState(null,null,f+"#"+c,!1)}else d.location.hash=c;return k},k.escapeHash=function(b){var c=k.normalizeHash(b);c=a.escape(c),k.bugs.hashEscape||(c=c.replace(/\%21/g,"!").replace(/\%26/g,"&").replace(/\%3D/g,"=").replace(/\%3F/g,"?"));return c},k.getHashByUrl=function(a){var b=String(a).replace(/([^#]*)#?([^#]*)#?(.*)/,"$2");b=k.unescapeHash(b);return b},k.setTitle=function(a){var b=a.title;if(!b){var c=k.getStateByIndex(0);c&&c.url===a.url&&(b=c.title||k.options.initialTitle)}try{d.getElementsByTagName("title")[0].innerHTML=b.replace("<","&lt;").replace(">","&gt;").replace(" & "," &amp; ")}catch(e){}d.title=b;return k},k.queues=[],k.busy=function(a){typeof a!="undefined"?k.busy.flag=a:typeof k.busy.flag=="undefined"&&(k.busy.flag=!1);if(!k.busy.flag){h(k.busy.timeout);var b=function(){if(!k.busy.flag)for(var a=k.queues.length-1;a>=0;--a){var c=k.queues[a];if(c.length===0)continue;var d=c.shift();k.fireQueueItem(d),k.busy.timeout=g(b,k.options.busyDelay)}};k.busy.timeout=g(b,k.options.busyDelay)}return k.busy.flag},k.fireQueueItem=function(a){return a.callback.apply(a.scope||k,a.args||[])},k.pushQueue=function(a){k.queues[a.queue||0]=k.queues[a.queue||0]||[],k.queues[a.queue||0].push(a);return k},k.queue=function(a,b){typeof a=="function"&&(a={callback:a}),typeof b!="undefined"&&(a.queue=b),k.busy()?k.pushQueue(a):k.fireQueueItem(a);return k},k.clearQueue=function(){k.busy.flag=!1,k.queues=[];return k},k.stateChanged=!1,k.doubleChecker=!1,k.doubleCheckComplete=function(){k.stateChanged=!0,k.doubleCheckClear();return k},k.doubleCheckClear=function(){k.doubleChecker&&(h(k.doubleChecker),k.doubleChecker=!1);return k},k.doubleCheck=function(a){k.stateChanged=!1,k.doubleCheckClear(),k.bugs.ieDoubleCheck&&(k.doubleChecker=g(function(){k.doubleCheckClear(),k.stateChanged||a();return!0},k.options.doubleCheckInterval));return k},k.safariStatePoll=function(){var b=k.extractState(d.location.href),c;if(!k.isLastSavedState(b))c=b;else return;c||(c=k.createStateObject()),k.Adapter.trigger(a,"popstate");return k},k.back=function(a){if(a!==!1&&k.busy()){k.pushQueue({scope:k,callback:k.back,args:arguments,queue:a});return!1}k.busy(!0),k.doubleCheck(function(){k.back(!1)}),l.go(-1);return!0},k.forward=function(a){if(a!==!1&&k.busy()){k.pushQueue({scope:k,callback:k.forward,args:arguments,queue:a});return!1}k.busy(!0),k.doubleCheck(function(){k.forward(!1)}),l.go(1);return!0},k.go=function(a,b){var c;if(a>0)for(c=1;c<=a;++c)k.forward(b);else{if(!(a<0))throw new Error("History.go: History.go requires a positive or negative integer passed.");for(c=-1;c>=a;--c)k.back(b)}return k},k.saveState(k.storeState(k.extractState(d.location.href,!0))),f&&(k.onUnload=function(){var a=f.store("History.store")||{},b;a.idToState=a.idToState||{},a.urlToId=a.urlToId||{},a.stateToId=a.stateToId||{};for(b in k.idToState){if(!k.idToState.hasOwnProperty(b))continue;a.idToState[b]=k.idToState[b]}for(b in k.urlToId){if(!k.urlToId.hasOwnProperty(b))continue;a.urlToId[b]=k.urlToId[b]}for(b in k.stateToId){if(!k.stateToId.hasOwnProperty(b))continue;a.stateToId[b]=k.stateToId[b]}k.store=a,f.store("History.store",a)},i(k.onUnload,k.options.storeInterval),k.Adapter.bind(a,"beforeunload",k.onUnload),k.Adapter.bind(a,"unload",k.onUnload));if(k.emulated.pushState){var m=function(){};k.pushState=k.pushState||m,k.replaceState=k.replaceState||m}else{k.onPopState=function(b){k.doubleCheckComplete();var c=k.getHash();if(c){var e=k.extractState(c||d.location.href,!0);e?k.replaceState(e.data,e.title,e.url,!1):(k.Adapter.trigger(a,"anchorchange"),k.busy(!1)),k.expectedStateId=!1;return!1}var f=!1;b=b||{},typeof b.state=="undefined"&&(typeof b.originalEvent!="undefined"&&typeof b.originalEvent.state!="undefined"?b.state=b.originalEvent.state||!1:typeof b.event!="undefined"&&typeof b.event.state!="undefined"&&(b.state=b.event.state||!1)),b.state=b.state||!1,b.state?f=k.getStateById(b.state):k.expectedStateId?f=k.getStateById(k.expectedStateId):f=k.extractState(d.location.href),f||(f=k.createStateObject(null,null,d.location.href)),k.expectedStateId=!1;if(k.isLastSavedState(f)){k.busy(!1);return!1}k.storeState(f),k.saveState(f),k.setTitle(f),k.Adapter.trigger(a,"statechange"),k.busy(!1);return!0},k.Adapter.bind(a,"popstate",k.onPopState),k.pushState=function(b,c,d,e){if(k.getHashByUrl(d)&&k.emulated.pushState)throw new Error("History.js does not support states with fragement-identifiers (hashes/anchors).");if(e!==!1&&k.busy()){k.pushQueue({scope:k,callback:k.pushState,args:arguments,queue:e});return!1}k.busy(!0);var f=k.createStateObject(b,c,d);k.isLastSavedState(f)?k.busy(!1):(k.storeState(f),k.expectedStateId=f.id,l.pushState(f.id,f.title,f.url),k.Adapter.trigger(a,"popstate"));return!0},k.replaceState=function(b,c,d,e){if(k.getHashByUrl(d)&&k.emulated.pushState)throw new Error("History.js does not support states with fragement-identifiers (hashes/anchors).");if(e!==!1&&k.busy()){k.pushQueue({scope:k,callback:k.replaceState,args:arguments,queue:e});return!1}k.busy(!0);var f=k.createStateObject(b,c,d);k.isLastSavedState(f)?k.busy(!1):(k.storeState(f),k.expectedStateId=f.id,l.replaceState(f.id,f.title,f.url),k.Adapter.trigger(a,"popstate"));return!0},k.bugs.safariPoll&&i(k.safariStatePoll,k.options.safariPollInterval);if(e.vendor==="Apple Computer, Inc."||(e.appCodeName||"")==="Mozilla")k.Adapter.bind(a,"hashchange",function(){k.Adapter.trigger(a,"popstate")}),k.getHash()&&k.Adapter.onDomLoad(function(){k.Adapter.trigger(a,"hashchange")})}},k.init()})(window)
View
1  admin/thirdparty/history-js/scripts/compressed/json2.js
@@ -0,0 +1 @@
+var JSON;JSON||(JSON={}),function(){function str(a,b){var c,d,e,f,g=gap,h,i=b[a];i&&typeof i=="object"&&typeof i.toJSON=="function"&&(i=i.toJSON(a)),typeof rep=="function"&&(i=rep.call(b,a,i));switch(typeof i){case"string":return quote(i);case"number":return isFinite(i)?String(i):"null";case"boolean":case"null":return String(i);case"object":if(!i)return"null";gap+=indent,h=[];if(Object.prototype.toString.apply(i)==="[object Array]"){f=i.length;for(c=0;c<f;c+=1)h[c]=str(c,i)||"null";e=h.length===0?"[]":gap?"[\n"+gap+h.join(",\n"+gap)+"\n"+g+"]":"["+h.join(",")+"]",gap=g;return e}if(rep&&typeof rep=="object"){f=rep.length;for(c=0;c<f;c+=1)d=rep[c],typeof d=="string"&&(e=str(d,i),e&&h.push(quote(d)+(gap?": ":":")+e))}else for(d in i)Object.hasOwnProperty.call(i,d)&&(e=str(d,i),e&&h.push(quote(d)+(gap?": ":":")+e));e=h.length===0?"{}":gap?"{\n"+gap+h.join(",\n"+gap)+"\n"+g+"}":"{"+h.join(",")+"}",gap=g;return e}}function quote(a){escapable.lastIndex=0;return escapable.test(a)?'"'+a.replace(escapable,function(a){var b=meta[a];return typeof b=="string"?b:"\\u"+("0000"+a.charCodeAt(0).toString(16)).slice(-4)})+'"':'"'+a+'"'}function f(a){return a<10?"0"+a:a}"use strict",typeof Date.prototype.toJSON!="function"&&(Date.prototype.toJSON=function(a){return isFinite(this.valueOf())?this.getUTCFullYear()+"-"+f(this.getUTCMonth()+1)+"-"+f(this.getUTCDate())+"T"+f(this.getUTCHours())+":"+f(this.getUTCMinutes())+":"+f(this.getUTCSeconds())+"Z":null},String.prototype.toJSON=Number.prototype.toJSON=Boolean.prototype.toJSON=function(a){return this.valueOf()});var cx=/[\u0000\u00ad\u0600-\u0604\u070f\u17b4\u17b5\u200c-\u200f\u2028-\u202f\u2060-\u206f\ufeff\ufff0-\uffff]/g,escapable=/[\\\"\x00-\x1f\x7f-\x9f\u00ad\u0600-\u0604\u070f\u17b4\u17b5\u200c-\u200f\u2028-\u202f\u2060-\u206f\ufeff\ufff0-\uffff]/g,gap,indent,meta={"\b":"\\b","\t":"\\t","\n":"\\n","\f":"\\f","\r":"\\r",'"':'\\"',"\\":"\\\\"},rep;typeof JSON.stringify!="function"&&(JSON.stringify=function(a,b,c){var d;gap="",indent="";if(typeof c=="number")for(d=0;d<c;d+=1)indent+=" ";else typeof c=="string"&&(indent=c);rep=b;if(b&&typeof b!="function"&&(typeof b!="object"||typeof b.length!="number"))throw new Error("JSON.stringify");return str("",{"":a})}),typeof JSON.parse!="function"&&(JSON.parse=function(text,reviver){function walk(a,b){var c,d,e=a[b];if(e&&typeof e=="object")for(c in e)Object.hasOwnProperty.call(e,c)&&(d=walk(e,c),d!==undefined?e[c]=d:delete e[c]);return reviver.call(a,b,e)}var j;text=String(text),cx.lastIndex=0,cx.test(text)&&(text=text.replace(cx,function(a){return"\\u"+("0000"+a.charCodeAt(0).toString(16)).slice(-4)}));if(/^[\],:{}\s]*$/.test(text.replace(/\\(?:["\\\/bfnrt]|u[0-9a-fA-F]{4})/g,"@").replace(/"[^"\\\n\r]*"|true|false|null|-?\d+(?:\.\d*)?(?:[eE][+\-]?\d+)?/g,"]").replace(/(?:^|:|,)(?:\s*\[)+/g,""))){j=eval("("+text+")");return typeof reviver=="function"?walk({"":j},""):j}throw new SyntaxError("JSON.parse")})}()
View
247 admin/thirdparty/history-js/scripts/uncompressed/amplify.store.js
@@ -0,0 +1,247 @@
+/*!
+ * Amplify Store - Persistent Client-Side Storage @VERSION
+ *
+ * Copyright 2011 appendTo LLC. (http://appendto.com/team)
+ * Dual licensed under the MIT or GPL licenses.
+ * http://appendto.com/open-source-licenses
+ *
+ * http://amplifyjs.com
+ */
+(function( amplify, undefined ) {
+
+// MooTools Compatibility
+JSON.stringify = JSON.stringify||JSON.encode;
+JSON.parse = JSON.parse||JSON.decode;
+
+var store = amplify.store = function( key, value, options, type ) {
+ var type = store.type;
+ if ( options && options.type && options.type in store.types ) {
+ type = options.type;
+ }
+ return store.types[ type ]( key, value, options || {} );
+};
+
+store.types = {};
+store.type = null;
+store.addType = function( type, storage ) {
+ if ( !store.type ) {
+ store.type = type;
+ }
+
+ store.types[ type ] = storage;
+ store[ type ] = function( key, value, options ) {
+ options = options || {};
+ options.type = type;
+ return store( key, value, options );
+ };
+}
+store.error = function() {
+ return "amplify.store quota exceeded";
+};
+
+function createSimpleStorage( storageType, storage ) {
+ var values = storage.__amplify__ ? JSON.parse( storage.__amplify__ ) : {};
+ store.addType( storageType, function( key, value, options ) {
+ var ret = value,
+ now = (new Date()).getTime(),
+ storedValue,
+ parsed;
+
+ if ( !key ) {
+ ret = {};
+ for ( key in values ) {
+ storedValue = storage[ key ];
+ parsed = storedValue ? JSON.parse( storedValue ) : { expires: -1 };
+ if ( parsed.expires && parsed.expires <= now ) {
+ delete storage[ key ];
+ delete values[ key ];
+ } else {
+ ret[ key.replace( /^__amplify__/, "" ) ] = parsed.data;
+ }
+ }
+ storage.__amplify__ = JSON.stringify( values );
+ return ret;
+ }
+
+ // protect against overwriting built-in properties
+ key = "__amplify__" + key;
+
+ if ( value === undefined ) {
+ if ( values[ key ] ) {
+ storedValue = storage[ key ];
+ parsed = storedValue ? JSON.parse( storedValue ) : { expires: -1 };
+ if ( parsed.expires && parsed.expires <= now ) {
+ delete storage[ key ];
+ delete values[ key ];
+ } else {
+ return parsed.data;
+ }
+ }
+ } else {
+ if ( value === null ) {
+ delete storage[ key ];
+ delete values[ key ];
+ } else {
+ parsed = JSON.stringify({
+ data: value,
+ expires: options.expires ? now + options.expires : null
+ });
+ try {
+ storage[ key ] = parsed;
+ values[ key ] = true;
+ // quota exceeded
+ } catch( error ) {
+ // expire old data and try again
+ store[ storageType ]();
+ try {
+ storage[ key ] = parsed;
+ values[ key ] = true;
+ } catch( error ) {
+ throw store.error();
+ }
+ }
+ }
+ }
+
+ storage.__amplify__ = JSON.stringify( values );
+ return ret;
+ });
+}
+
+// localStorage + sessionStorage
+// IE 8+, Firefox 3.5+, Safari 4+, Chrome 4+, Opera 10.5+, iPhone 2+, Android 2+
+for ( var webStorageType in { localStorage: 1, sessionStorage: 1 } ) {
+ // try/catch for file protocol in Firefox
+ try {
+ if ( window[ webStorageType ].getItem ) {
+ createSimpleStorage( webStorageType, window[ webStorageType ] );
+ }
+ } catch( e ) {}
+}
+
+// globalStorage
+// non-standard: Firefox 2+
+// https://developer.mozilla.org/en/dom/storage#globalStorage
+if ( window.globalStorage ) {
+ createSimpleStorage( "globalStorage",
+ window.globalStorage[ window.location.hostname ] );
+ // Firefox 2.0 and 3.0 have sessionStorage and globalStorage
+ // make sure we defualt to globalStorage
+ // but don't default to globalStorage in 3.5+ which also has localStorage
+ if ( store.type === "sessionStorage" ) {
+ store.type = "globalStorage";
+ }
+}
+
+// userData
+// non-standard: IE 5+
+// http://msdn.microsoft.com/en-us/library/ms531424(v=vs.85).aspx
+(function() {
+ // append to html instead of body so we can do this from the head
+ var div = document.createElement( "div" ),
+ attrKey = "amplify",
+ attrs;
+ div.style.display = "none";
+ document.getElementsByTagName( "head" )[ 0 ].appendChild( div );
+ if ( div.addBehavior ) {
+ div.addBehavior( "#default#userdata" );
+ div.load( attrKey );
+ attrs = div.getAttribute( attrKey ) ? JSON.parse( div.getAttribute( attrKey ) ) : {};
+
+ store.addType( "userData", function( key, value, options ) {
+ var ret = value,
+ now = (new Date()).getTime(),
+ attr,
+ parsed,
+ prevValue;
+
+ if ( !key ) {
+ ret = {};
+ for ( key in attrs ) {
+ attr = div.getAttribute( key );
+ parsed = attr ? JSON.parse( attr ) : { expires: -1 };
+ if ( parsed.expires && parsed.expires <= now ) {
+ div.removeAttribute( key );
+ delete attrs[ key ];
+ } else {
+ ret[ key ] = parsed.data;
+ }
+ }
+ div.setAttribute( attrKey, JSON.stringify( attrs ) );
+ div.save( attrKey );
+ return ret;
+ }
+
+ // convert invalid characters to dashes
+ // http://www.w3.org/TR/REC-xml/#NT-Name
+ // simplified to assume the starting character is valid
+ // also removed colon as it is invalid in HTML attribute names
+ key = key.replace( /[^-._0-9A-Za-z\xb7\xc0-\xd6\xd8-\xf6\xf8-\u037d\u37f-\u1fff\u200c-\u200d\u203f\u2040\u2070-\u218f]/g, "-" );
+
+ if ( value === undefined ) {
+ if ( key in attrs ) {
+ attr = div.getAttribute( key );
+ parsed = attr ? JSON.parse( attr ) : { expires: -1 };
+ if ( parsed.expires && parsed.expires <= now ) {
+ div.removeAttribute( key );
+ delete attrs[ key ];
+ } else {
+ return parsed.data;
+ }
+ }
+ } else {
+ if ( value === null ) {
+ div.removeAttribute( key );
+ delete attrs[ key ];
+ } else {
+ // we need to get the previous value in case we need to rollback
+ prevValue = div.getAttribute( key );
+ parsed = JSON.stringify({
+ data: value,
+ expires: (options.expires ? (now + options.expires) : null)
+ });
+ div.setAttribute( key, parsed );
+ attrs[ key ] = true;
+ }
+ }
+
+ div.setAttribute( attrKey, JSON.stringify( attrs ) );
+ try {
+ div.save( attrKey );
+ // quota exceeded
+ } catch ( error ) {
+ // roll the value back to the previous value
+ if ( prevValue === null ) {
+ div.removeAttribute( key );
+ delete attrs[ key ];
+ } else {
+ div.setAttribute( key, prevValue );
+ }
+
+ // expire old data and try again
+ store.userData();
+ try {
+ div.setAttribute( key, parsed );
+ attrs[ key ] = true;
+ div.save( attrKey );
+ } catch ( error ) {
+ // roll the value back to the previous value
+ if ( prevValue === null ) {
+ div.removeAttribute( key );
+ delete attrs[ key ];
+ } else {
+ div.setAttribute( key, prevValue );
+ }
+ throw store.error();
+ }
+ }
+ return ret;
+ });
+ }
+}() );
+
+// in-memory storage
+// fallback for all browsers to enable the API even if we can't persist data
+createSimpleStorage( "memory", {} );
+
+}( this.amplify = this.amplify || {} ) );
View
1  admin/thirdparty/history-js/scripts/uncompressed/history.adapter.dojo.js
@@ -0,0 +1 @@
+// If you know dojo - then this is your canvas
View
58 admin/thirdparty/history-js/scripts/uncompressed/history.adapter.jquery.js
@@ -0,0 +1,58 @@
+/**
+ * History.js jQuery Adapter
+ * @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/>
+ */
+
+// Closure
+(function(window,undefined){
+ // Localise Globals
+ var
+ History = window.History = window.History||{},
+ jQuery = window.jQuery;
+
+ // Check Existence
+ if ( typeof History.Adapter !== 'undefined' ) {
+ throw new Error('History.js Adapter has already been loaded...');
+ }
+
+ // Add the Adapter
+ History.Adapter = {
+ /**
+ * History.Adapter.bind(el,event,callback)
+ * @param {Element|Selector} el
+ * @param {String} event - custom and standard events
+ * @param {Function} callback
+ * @return
+ */
+ bind: function(el,event,callback){
+ jQuery(el).bind(event,callback);
+ },
+
+ /**
+ * History.Adapter.trigger(el,event)
+ * @param {Element|Selector} el
+ * @param {String} event - custom and standard events
+ * @return
+ */
+ trigger: function(el,event){
+ jQuery(el).trigger(event);
+ },
+
+ /**
+ * History.Adapter.trigger(el,event,data)
+ * @param {Function} callback
+ * @return
+ */
+ onDomLoad: function(callback) {
+ jQuery(callback);
+ }
+ };
+
+ // Try and Initialise History
+ if ( typeof History.init !== 'undefined' ) {
+ History.init();
+ }
+
+})(window);
View
66 admin/thirdparty/history-js/scripts/uncompressed/history.adapter.mootools.js
@@ -0,0 +1,66 @@
+/**
+ * History.js jQuery Adapter
+ * @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/>
+ */
+
+// Closure
+(function(window,undefined){
+ // Localise Globals
+ var
+ History = window.History = window.History||{},
+ MooTools = window.MooTools;
+
+ // Check Existence
+ if ( typeof History.Adapter !== 'undefined' ) {
+ throw new Error('History.js Adapter has already been loaded...');
+ }
+
+ // Make MooTools aware of History.js Events
+ Object.append(Element.NativeEvents,{
+ 'popstate':2,
+ 'hashchange':2
+ });
+
+ // Add the Adapter
+ History.Adapter = {
+ /**
+ * History.Adapter.bind(el,event,callback)
+ * @param {Element|Selector} el
+ * @param {String} event - custom and standard events
+ * @param {Function} callback
+ * @return
+ */
+ bind: function(el,event,callback){
+ var El = typeof el === 'string' ? document.id(el) : el;
+ El.addEvent(event,callback);
+ },
+
+ /**
+ * History.Adapter.trigger(el,event)
+ * @param {Element|Selector} el
+ * @param {String} event - custom and standard events
+ * @return
+ */
+ trigger: function(el,event){
+ var El = typeof el === 'string' ? document.id(el) : el;
+ El.fireEvent(event);
+ },
+
+ /**
+ * History.Adapter.trigger(el,event)
+ * @param {Function} callback
+ * @return
+ */
+ onDomLoad: function(callback) {
+ window.addEvent('domready',callback);
+ }
+ };
+
+ // Try and Initialise History
+ if ( typeof History.init !== 'undefined' ) {
+ History.init();
+ }
+
+})(window);
View
197 admin/thirdparty/history-js/scripts/uncompressed/history.adapter.prototype.js
@@ -0,0 +1,197 @@
+/**
+ * History.js Prototype Adapter
+ * @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/>
+ */
+
+// Closure
+(function(window,undefined){
+ // Localise Globals
+ var
+ History = window.History = window.History||{},
+ Prototype = window.Prototype,
+ Element = window.Element,
+ Event = window.Event,
+ $ = window.$;
+
+ // Check Existence
+ if ( typeof History.Adapter !== 'undefined' ) {
+ throw new Error('History.js Adapter has already been loaded...');
+ }
+
+ // Prototype does not support event binding to the window element in IE6-8
+ if ( typeof window.fireEvent === 'undefined' && typeof window.dispatchEvent === 'undefined' ) {
+ History.enable = false;
+ return;
+ }
+
+ /**
+ * Bind and Trigger custom and native events in Prototype
+ * @author Juriy Zaytsev (kangax)
+ * @author Benjamin Arthur Lupton <contact@balupton.com>
+ * @copyright MIT license <http://creativecommons.org/licenses/MIT/>
+ */
+ (function(){
+ // Prepare
+ var
+ eventMatchers = {
+ 'HTMLEvents': /^(?:load|unload|abort|error|select|hashchange|popstate|change|submit|reset|focus|blur|resize|scroll)$/,
+ 'MouseEvents': /^(?:click|mouse(?:down|up|over|move|out))$/
+ },
+ defaultOptions = {
+ pointerX: 0,
+ pointerY: 0,
+ button: 0,
+ ctrlKey: false,
+ altKey: false,
+ shiftKey: false,
+ metaKey: false,
+ bubbles: true,
+ cancelable: true
+ };
+
+ // Check for Native Event
+ Event.hasNativeEvent = function(element, eventName) {
+ // Prepare
+ var eventType = null, result;
+ element = $(element);
+
+ // Cycle
+ for (var name in eventMatchers) {
+ if ( eventMatchers[name].test(eventName) ) {
+ eventType = name;
+ break;
+ }
+ }
+
+ // Evaluate
+ result = eventType ? true : false;
+
+ // Return result
+ return result;
+ };
+
+ // Bind a Native or Custom Event
+ Event.bind = function(element, eventName, eventHandler) {
+ // Prepare
+ element = $(element);
+
+ // Native Event?
+ if ( Element.hasNativeEvent(element,eventName) ) {
+ return Element.observe(element,eventName,eventHandler);
+ }
+
+ // Custom Event?
+ else {
+ return Element.observe(element,'custom:'+eventName,eventHandler);
+ }
+
+ // Return element
+ return element;
+ };
+
+ // Trigger
+ Event.trigger = function(element, eventName) {
+ // Prepare
+ var options = Object.extend(defaultOptions, arguments[2] || { });
+ var oEvent, eventType = null;
+ element = $(element);
+
+ // Check for Native Event
+ var name; for (name in eventMatchers) {
+ if (eventMatchers[name].test(eventName)) { eventType = name; break; }
+ }
+
+ // Custom Event?
+ if ( !eventType ) {
+ return Element.fire(element,'custom:'+eventName);
+ }
+
+ // Create Event
+ if ( document.createEvent ) {
+ // Firefox + Others
+ oEvent = document.createEvent(eventType);
+
+ // Normal Event?
+ if ( eventType === 'HTMLEvents' ) {
+ oEvent.initEvent(eventName, options.bubbles, options.cancelable);
+ }
+ // Mouse Event?
+ else if ( eventType ) {
+ oEvent.initMouseEvent(eventName, options.bubbles, options.cancelable, document.defaultView,
+ options.button, options.pointerX, options.pointerY, options.pointerX, options.pointerY,
+ options.ctrlKey, options.altKey, options.shiftKey, options.metaKey, options.button, element);
+ }
+ }
+ else if ( document.createEventObject ) {
+ // Internet Explorer
+ options.clientX = options.pointerX;
+ options.clientY = options.pointerY;
+ oEvent = Object.extend(document.createEventObject(), options);
+ }
+
+ // Fire Event
+ if ( element.fireEvent ) {
+ element.fireEvent('on'+eventName,oEvent);
+ }
+ else if ( element.dispatchEvent ) {
+ element.dispatchEvent(oEvent);
+ }
+ else {
+ throw new Error('Cannot dispatch the event');
+ }
+
+ // Return
+ return element;
+ };
+
+ // Amend Element Prototype
+ Element.addMethods({
+ simulate: Event.trigger,
+ trigger: Event.trigger,
+ bind: Event.bind,
+ hasNativeEvent: Event.hasNativeEvent
+ });
+ })();
+
+ // Add the Adapter
+ History.Adapter = {
+
+ /**
+ * History.Adapter.bind(el,event,callback)
+ * @param {Element|Selector} el
+ * @param {String} event - custom and standard events
+ * @param {Function} callback
+ * @return
+ */
+ bind: function(el,event,callback){
+ Element.bind(el,event,callback);
+ },
+
+ /**
+ * History.Adapter.trigger(el,event)
+ * @param {Element|Selector} el
+ * @param {String} event - custom and standard events
+ * @return
+ */
+ trigger: function(el,event){
+ Element.trigger(el,event);
+ },
+
+ /**
+ * History.Adapter.trigger(el,event,data)
+ * @param {Function} callback
+ * @return
+ */
+ onDomLoad: function(callback) {
+ Event.observe(window.document, 'dom:loaded', callback);
+ }
+ };
+
+ // Try and Initialise History
+ if ( typeof History.init !== 'undefined' ) {
+ History.init();
+ }
+
+})(window);
View
64 admin/thirdparty/history-js/scripts/uncompressed/history.adapter.yui.js
@@ -0,0 +1,64 @@
+/**
+ * History.js YUI Adapter [NOT WORKING]
+ * @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/>
+ */
+
+// Closure
+(function(window,undefined){
+ // Localise Globals
+ var
+ History = window.History = window.History||{},
+ YUI = window.YUI;
+
+ // Check Existence
+ if ( typeof History.Adapter !== 'undefined' ) {
+ throw new Error('History.js Adapter has already been loaded...');
+ }
+
+ // Add the Adapter
+ History.Adapter = {
+ /**
+ * History.Adapter.bind(el,event,callback)
+ * @param {Element|Selector} el
+ * @param {String} event - custom and standard events
+ * @param {Function} callback
+ * @return {element}
+ */
+ bind: function(el,event,callback){
+ YUI().use('node-base', function(Y){
+ Y.one(el).on(event,callback);
+ });
+ },
+
+ /**
+ * History.Adapter.trigger(el,event)
+ * @param {Element|Selector} el
+ * @param {String} event - custom and standard events
+ * @return {element}
+ */
+ trigger: function(el,event){
+ YUI().use('node-event-simulate', function(Y){
+ Y.one(el).simulate(event);
+ });
+ },
+
+ /**
+ * History.Adapter.trigger(el,event,data)
+ * @param {Function} callback
+ * @return {true}
+ */
+ onDomLoad: function(callback) {
+ YUI().use('event', function(Y){
+ Y.on('domready', callback);
+ });
+ }
+ };
+
+ // Try and Initialise History
+ if ( typeof History.init !== 'undefined' ) {
+ History.init();
+ }
+
+})(window);
View
58 admin/thirdparty/history-js/scripts/uncompressed/history.adapter.zepto.js
@@ -0,0 +1,58 @@
+/**
+ * History.js Zepto Adapter
+ * @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/>
+ */
+
+// Closure
+(function(window,undefined){
+ // Localise Globals
+ var
+ History = window.History = window.History||{},
+ Zepto = window.Zepto;
+
+ // Check Existence
+ if ( typeof History.Adapter !== 'undefined' ) {
+ throw new Error('History.js Adapter has already been loaded...');
+ }
+
+ // Add the Adapter
+ History.Adapter = {
+ /**
+ * History.Adapter.bind(el,event,callback)
+ * @param {Element|Selector} el
+ * @param {String} event - custom and standard events
+ * @param {Function} callback
+ * @return
+ */
+ bind: function(el,event,callback){
+ Zepto(el).bind(event,callback);
+ },
+
+ /**
+ * History.Adapter.trigger(el,event)
+ * @param {Element|Selector} el
+ * @param {String} event - custom and standard events
+ * @return
+ */
+ trigger: function(el,event){
+ Zepto(el).trigger(event);
+ },
+
+ /**
+ * History.Adapter.trigger(el,event,data)
+ * @param {Function} callback
+ * @return
+ */
+ onDomLoad: function(callback) {
+ Zepto(callback);
+ }
+ };
+
+ // Try and Initialise History
+ if ( typeof History.init !== 'undefined' ) {
+ History.init();
+ }
+
+})(window);
View
606 admin/thirdparty/history-js/scripts/uncompressed/history.html4.js
@@ -0,0 +1,606 @@
+/**
+ * History.js HTML4 Support
+ * Depends on the 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(window,undefined){
+ "use strict";
+
+ // --------------------------------------------------------------------------
+ // Initialise
+
+ // Localise Globals
+ var
+ document = window.document, // Make sure we are using the correct document
+ setTimeout = window.setTimeout||setTimeout,
+ clearTimeout = window.clearTimeout||clearTimeout,
+ setInterval = window.setInterval||setInterval,
+ History = window.History = window.History||{}; // Public History Object
+
+ // Check Existence
+ if ( typeof History.initHtml4 !== 'undefined' ) {
+ throw new Error('History.js HTML4 Support has already been loaded...');
+ }
+
+ // --------------------------------------------------------------------------
+ // Initialise HTML4 Support
+
+ // Initialise HTML4 Support
+ History.initHtml4 = function(){
+ // Initialise
+ if ( typeof History.initHtml4.initialized !== 'undefined' ) {
+ // Already Loaded
+ return false;
+ }
+ else {
+ History.initHtml4.initialized = true;
+ }
+
+ // ----------------------------------------------------------------------
+ // Properties
+
+ /**
+ * History.enabled
+ * Is History enabled?
+ */
+ History.enabled = true;
+
+
+ // ----------------------------------------------------------------------
+ // Hash Storage
+
+ /**
+ * History.savedHashes
+ * Store the hashes in an array
+ */
+ History.savedHashes = [];
+
+ /**
+ * History.isLastHash(newHash)
+ * Checks if the hash is the last hash
+ * @param {string} newHash
+ * @return {boolean} true
+ */
+ History.isLastHash = function(newHash){
+ // Prepare
+ var oldHash = History.getHashByIndex();
+
+ // Check
+ var isLast = newHash === oldHash;
+
+ // Return isLast
+ return isLast;
+ };
+
+ /**
+ * History.saveHash(newHash)
+ * Push a Hash
+ * @param {string} newHash
+ * @return {boolean} true
+ */
+ History.saveHash = function(newHash){
+ // Check Hash
+ if ( History.isLastHash(newHash) ) {
+ return false;
+ }
+
+ // Push the Hash
+ History.savedHashes.push(newHash);
+
+ // Return true
+ return true;
+ };
+
+ /**
+ * History.getHashByIndex()
+ * Gets a hash by the index
+ * @param {integer} index
+ * @return {string}
+ */
+ History.getHashByIndex = function(index){
+ // Prepare
+ var hash = null;
+
+ // Handle
+ if ( typeof index === 'undefined' ) {
+ // Get the last inserted
+ hash = History.savedHashes[History.savedHashes.length-1];
+ }
+ else if ( index < 0 ) {
+ // Get from the end
+ hash = History.savedHashes[History.savedHashes.length+index];
+ }
+ else {
+ // Get from the beginning
+ hash = History.savedHashes[index];
+ }
+
+ // Return hash
+ return hash;
+ };
+
+ // ----------------------------------------------------------------------
+ // Discarded States
+
+ /**
+ * History.discardedHashes
+ * A hashed array of discarded hashes
+ */
+ History.discardedHashes = {};
+
+ /**
+ * History.discardedStates
+ * A hashed array of discarded states
+ */
+ History.discardedStates = {};
+
+ /**
+ * History.discardState(State)
+ * Discards the state by ignoring it through History
+ * @param {object} State
+ * @return {true}
+ */
+ History.discardState = function(discardedState,forwardState,backState){
+ //History.debug('History.discardState', arguments);
+ // Prepare
+ var discardedStateHash = History.getHashByState(discardedState);
+
+ // Create Discard Object
+ var discardObject = {
+ 'discardedState': discardedState,
+ 'backState': backState,
+ 'forwardState': forwardState
+ };
+
+ // Add to DiscardedStates
+ History.discardedStates[discardedStateHash] = discardObject;
+
+ // Return true
+ return true;
+ };
+
+ /**
+ * History.discardHash(hash)
+ * Discards the hash by ignoring it through History
+ * @param {string} hash
+ * @return {true}
+ */
+ History.discardHash = function(discardedHash,forwardState,backState){
+ //History.debug('History.discardState', arguments);
+ // Create Discard Object
+ var discardObject = {
+ 'discardedHash': discardedHash,
+ 'backState': backState,
+ 'forwardState': forwardState
+ };
+
+ // Add to discardedHash
+ History.discardedHashes[discardedHash] = discardObject;
+
+ // Return true
+ return true;
+ };
+
+ /**
+ * History.discardState(State)
+ * Checks to see if the state is discarded
+ * @param {object} State
+ * @return {bool}
+ */
+ History.discardedState = function(State){
+ // Prepare
+ var StateHash = History.getHashByState(State);
+
+ // Check
+ var discarded = History.discardedStates[StateHash]||false;
+
+ // Return true
+ return discarded;
+ };
+
+ /**
+ * History.discardedHash(hash)
+ * Checks to see if the state is discarded
+ * @param {string} State
+ * @return {bool}
+ */
+ History.discardedHash = function(hash){
+ // Check
+ var discarded = History.discardedHashes[hash]||false;
+
+ // Return true
+ return discarded;
+ };
+
+ /**
+ * History.recycleState(State)
+ * Allows a discarded state to be used again
+ * @param {object} data
+ * @param {string} title
+ * @param {string} url
+ * @return {true}
+ */
+ History.recycleState = function(State){
+ //History.debug('History.recycleState', arguments);
+ // Prepare
+ var StateHash = History.getHashByState(State);
+
+ // Remove from DiscardedStates
+ if ( History.discardedState(State) ) {
+ delete History.discardedStates[StateHash];
+ }
+
+ // Return true
+ return true;
+ };
+
+ // ----------------------------------------------------------------------
+ // HTML4 HashChange Support
+
+ if ( History.emulated.hashChange ) {
+ /*
+ * We must emulate the HTML4 HashChange Support by manually checking for hash changes
+ */
+
+ /**
+ * History.hashChangeInit()
+ * Init the HashChange Emulation
+ */
+ History.hashChangeInit = function(){
+ // Define our Checker Function
+ History.checkerFunction = null;
+
+ // Define some variables that will help in our checker function
+ var
+ lastDocumentHash = '';
+
+ // Handle depending on the browser
+ if ( History.isInternetExplorer() ) {
+ // IE6 and IE7
+ // We need to use an iframe to emulate the back and forward buttons
+
+ // Create iFrame
+ var
+ iframeId = 'historyjs-iframe',
+ iframe = document.createElement('iframe');
+
+ // Adjust iFarme
+ iframe.setAttribute('id', iframeId);
+ iframe.style.display = 'none';
+
+ // Append iFrame
+ document.body.appendChild(iframe);
+
+ // Create initial history entry
+ iframe.contentWindow.document.open();
+ iframe.contentWindow.document.close();
+
+ // Define some variables that will help in our checker function
+ var
+ lastIframeHash = '',
+ checkerRunning = false;
+
+ // Define the checker function
+ History.checkerFunction = function(){
+ // Check Running
+ if ( checkerRunning ) {
+ return false;
+ }
+
+ // Update Running
+ checkerRunning = true;
+
+ // Fetch