Skip to content
This repository
Browse code

MINOR Added history.js dependency

  • Loading branch information...
commit a5f841764de94d768990f4776c905ecfe8daf201 1 parent 8378a9d
Ingo Schommer authored May 20, 2011

Showing 78 changed files with 27,308 additions and 0 deletions. Show diff stats Hide diff stats

  1. 8  admin/thirdparty/history-js/.piston.yml
  2. 311  admin/thirdparty/history-js/README.md
  3. 351  admin/thirdparty/history-js/cli
  4. 58  admin/thirdparty/history-js/demo/bcherry-orig.html
  5. 62  admin/thirdparty/history-js/demo/bcherry.html
  6. 37  admin/thirdparty/history-js/demo/chrome.html
  7. 101  admin/thirdparty/history-js/demo/index.html
  8. 43  admin/thirdparty/history-js/demo/native-auto.html
  9. 62  admin/thirdparty/history-js/demo/native.html
  10. 23  admin/thirdparty/history-js/demo/navigator.html
  11. 61  admin/thirdparty/history-js/demo/safari.html
  12. 10  admin/thirdparty/history-js/license.txt
  13. 74  admin/thirdparty/history-js/package.json
  14. 1  admin/thirdparty/history-js/scripts/compressed/amplify.store.js
  15. 0  admin/thirdparty/history-js/scripts/compressed/history.adapter.dojo.js
  16. 1  admin/thirdparty/history-js/scripts/compressed/history.adapter.jquery.js
  17. 1  admin/thirdparty/history-js/scripts/compressed/history.adapter.mootools.js
  18. 1  admin/thirdparty/history-js/scripts/compressed/history.adapter.prototype.js
  19. 1  admin/thirdparty/history-js/scripts/compressed/history.adapter.yui.js
  20. 1  admin/thirdparty/history-js/scripts/compressed/history.adapter.zepto.js
  21. 1  admin/thirdparty/history-js/scripts/compressed/history.html4.js
  22. 1  admin/thirdparty/history-js/scripts/compressed/history.js
  23. 1  admin/thirdparty/history-js/scripts/compressed/json2.js
  24. 247  admin/thirdparty/history-js/scripts/uncompressed/amplify.store.js
  25. 1  admin/thirdparty/history-js/scripts/uncompressed/history.adapter.dojo.js
  26. 58  admin/thirdparty/history-js/scripts/uncompressed/history.adapter.jquery.js
  27. 66  admin/thirdparty/history-js/scripts/uncompressed/history.adapter.mootools.js
  28. 197  admin/thirdparty/history-js/scripts/uncompressed/history.adapter.prototype.js
  29. 64  admin/thirdparty/history-js/scripts/uncompressed/history.adapter.yui.js
  30. 58  admin/thirdparty/history-js/scripts/uncompressed/history.adapter.zepto.js
  31. 606  admin/thirdparty/history-js/scripts/uncompressed/history.html4.js
  32. 1,867  admin/thirdparty/history-js/scripts/uncompressed/history.js
  33. 480  admin/thirdparty/history-js/scripts/uncompressed/json2.js
  34. 28  admin/thirdparty/history-js/tests.src/_header.php
  35. 59  admin/thirdparty/history-js/tests.src/all.php
  36. 62  admin/thirdparty/history-js/tests.src/each.php
  37. 25  admin/thirdparty/history-js/tests.src/index.php
  38. 13  admin/thirdparty/history-js/tests/.htaccess
  39. 47  admin/thirdparty/history-js/tests/compressed-html4-nonpersistant-jquery.html
  40. 47  admin/thirdparty/history-js/tests/compressed-html4-nonpersistant-mootools.html
  41. 47  admin/thirdparty/history-js/tests/compressed-html4-nonpersistant-prototype.html
  42. 47  admin/thirdparty/history-js/tests/compressed-html4-nonpersistant-zepto.html
  43. 48  admin/thirdparty/history-js/tests/compressed-html4-persistant-jquery.html
  44. 48  admin/thirdparty/history-js/tests/compressed-html4-persistant-mootools.html
  45. 48  admin/thirdparty/history-js/tests/compressed-html4-persistant-prototype.html
  46. 48  admin/thirdparty/history-js/tests/compressed-html4-persistant-zepto.html
  47. 46  admin/thirdparty/history-js/tests/compressed-html5-nonpersistant-jquery.html
  48. 46  admin/thirdparty/history-js/tests/compressed-html5-nonpersistant-mootools.html
  49. 46  admin/thirdparty/history-js/tests/compressed-html5-nonpersistant-prototype.html
  50. 46  admin/thirdparty/history-js/tests/compressed-html5-nonpersistant-zepto.html
  51. 47  admin/thirdparty/history-js/tests/compressed-html5-persistant-jquery.html
  52. 47  admin/thirdparty/history-js/tests/compressed-html5-persistant-mootools.html
  53. 47  admin/thirdparty/history-js/tests/compressed-html5-persistant-prototype.html
  54. 47  admin/thirdparty/history-js/tests/compressed-html5-persistant-zepto.html
  55. 3  admin/thirdparty/history-js/tests/image.php
  56. 28  admin/thirdparty/history-js/tests/index.html
  57. 254  admin/thirdparty/history-js/tests/tests.js
  58. 47  admin/thirdparty/history-js/tests/uncompressed-html4-nonpersistant-jquery.html
  59. 47  admin/thirdparty/history-js/tests/uncompressed-html4-nonpersistant-mootools.html
  60. 47  admin/thirdparty/history-js/tests/uncompressed-html4-nonpersistant-prototype.html
  61. 47  admin/thirdparty/history-js/tests/uncompressed-html4-nonpersistant-zepto.html
  62. 48  admin/thirdparty/history-js/tests/uncompressed-html4-persistant-jquery.html
  63. 48  admin/thirdparty/history-js/tests/uncompressed-html4-persistant-mootools.html
  64. 48  admin/thirdparty/history-js/tests/uncompressed-html4-persistant-prototype.html
  65. 48  admin/thirdparty/history-js/tests/uncompressed-html4-persistant-zepto.html
  66. 46  admin/thirdparty/history-js/tests/uncompressed-html5-nonpersistant-jquery.html
  67. 46  admin/thirdparty/history-js/tests/uncompressed-html5-nonpersistant-mootools.html
  68. 46  admin/thirdparty/history-js/tests/uncompressed-html5-nonpersistant-prototype.html
  69. 46  admin/thirdparty/history-js/tests/uncompressed-html5-nonpersistant-zepto.html
  70. 47  admin/thirdparty/history-js/tests/uncompressed-html5-persistant-jquery.html
  71. 47  admin/thirdparty/history-js/tests/uncompressed-html5-persistant-mootools.html
  72. 47  admin/thirdparty/history-js/tests/uncompressed-html5-persistant-prototype.html
  73. 47  admin/thirdparty/history-js/tests/uncompressed-html5-persistant-zepto.html
  74. 8,316  admin/thirdparty/history-js/vendor/jquery.js
  75. 5,491  admin/thirdparty/history-js/vendor/mootools.js
  76. 6,082  admin/thirdparty/history-js/vendor/prototype.js
  77. 13  admin/thirdparty/history-js/vendor/yui.js
  78. 576  admin/thirdparty/history-js/vendor/zepto.js
8  admin/thirdparty/history-js/.piston.yml
... ...
@@ -0,0 +1,8 @@
  1
+--- 
  2
+format: 1
  3
+handler: 
  4
+  commit: 861b4b1f7240b9d5e50d560ba5b94de78aa439e5
  5
+  branch: master
  6
+lock: false
  7
+repository_class: Piston::Git::Repository
  8
+repository_url: https://github.com/balupton/history.js.git
311  admin/thirdparty/history-js/README.md
Source Rendered
... ...
@@ -0,0 +1,311 @@
  1
+Welcome to History.js (v1.7.0 - April 01 2011)
  2
+==================
  3
+
  4
+
  5
+This project is the successor of [jQuery History](http://balupton.com/projects/jquery-history), it aims to:
  6
+
  7
+- Follow the [HTML5 History API](https://developer.mozilla.org/en/DOM/Manipulating_the_browser_history) as much as possible
  8
+- 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)
  9
+- 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)
  10
+- 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)
  11
+- 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/)
  12
+
  13
+Licensed under the [New BSD License](http://creativecommons.org/licenses/BSD/)
  14
+Copyright 2011 [Benjamin Arthur Lupton](http://balupton.com)
  15
+
  16
+
  17
+## Usage
  18
+
  19
+### Working with History.js:
  20
+
  21
+	(function(window,undefined){
  22
+
  23
+		// Prepare
  24
+		var History = window.History; // Note: We are using a capital H instead of a lower h
  25
+		if ( !History.enabled ) {
  26
+			 // History.js is disabled for this browser.
  27
+			 // This is because we can optionally choose to support HTML4 browsers or not.
  28
+			return false;
  29
+		}
  30
+
  31
+		// Bind to StateChange Event
  32
+		History.Adapter.bind(window,'statechange',function(){ // Note: We are using statechange instead of popstate
  33
+			var State = History.getState(); // Note: We are using History.getState() instead of event.state
  34
+			History.log(State.data, State.title, State.url);
  35
+		});
  36
+
  37
+		// Change our States
  38
+		History.pushState({state:1}, "State 1", "?state=1"); // logs {state:1}, "State 1", "?state=1"
  39
+		History.pushState({state:2}, "State 2", "?state=2"); // logs {state:2}, "State 2", "?state=2"
  40
+		History.replaceState({state:3}, "State 3", "?state=3"); // logs {state:3}, "State 3", "?state=3"
  41
+		History.pushState(null, null, "?state=4"); // logs {}, '', "?state=4"
  42
+		History.back(); // logs {state:3}, "State 3", "?state=3"
  43
+		History.back(); // logs {state:1}, "State 1", "?state=1"
  44
+		History.back(); // logs {}, "Home Page", "?"
  45
+		History.go(2); // logs {state:3}, "State 3", "?state=3"
  46
+
  47
+	})(window);
  48
+
  49
+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.
  50
+
  51
+### How would the above operations look in a HTML5 Browser?
  52
+
  53
+1. www.mysite.com
  54
+1. www.mysite.com/?state=1
  55
+1. www.mysite.com/?state=2
  56
+1. www.mysite.com/?state=3
  57
+1. www.mysite.com/?state=4
  58
+1. www.mysite.com/?state=3
  59
+1. www.mysite.com/?state=1
  60
+1. www.mysite.com
  61
+1. www.mysite.com/?state=3
  62
+
  63
+> 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).
  64
+
  65
+### How would they look in a HTML4 Browser?
  66
+
  67
+1. www.mysite.com
  68
+1. www.mysite.com/#?state=1&_suid=1
  69
+1. www.mysite.com/#?state=2&_suid=2
  70
+1. www.mysite.com/#?state=3&_suid=3
  71
+1. www.mysite.com/#?state=4
  72
+1. www.mysite.com/#?state=3&_suid=3
  73
+1. www.mysite.com/#?state=1&_suid=1
  74
+1. www.mysite.com
  75
+1. www.mysite.com/#?state=3&_suid=3
  76
+
  77
+> 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 :-)
  78
+>
  79
+> Note 2: These urls will be automatically url-encoded in IE6 to prevent certain browser-specific bugs.
  80
+>
  81
+> 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)
  82
+
  83
+### What's the deal with the SUIDs used in the HTML4 States?
  84
+
  85
+- 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).
  86
+- 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 :-)
  87
+- 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).
  88
+- It works with domains, subdomains, subdirectories, whatever - doesn't matter where you put it. It's smart.
  89
+- 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.
  90
+
  91
+### Is there a working demo?
  92
+
  93
+- Sure is, give it a download and navigate to the demo directory in your browser :-)
  94
+- 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.
  95
+
  96
+
  97
+## Download & Installation
  98
+
  99
+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)
  100
+
  101
+2. Include [JSON2](http://www.json.org/js.html) for HTML4 Browsers Only *(replace www.yourwebsite.com)*
  102
+
  103
+		<script>if ( typeof window.JSON === 'undefined' ) { document.write('<script src="http://www.yourwebsite.com/history.js/scripts/compressed/json2.js"><\/script>'); }</script>
  104
+
  105
+3. Include [Amplify.js Store](http://amplifyjs.com/) for Data Persistance and Synchronisation Support (optional but recommended)
  106
+
  107
+		<script src="http://www.yourwebsite.com/history.js/scripts/compressed/amplify.store.js"></script>
  108
+
  109
+4. Include the Adapter for your Framework:
  110
+
  111
+	- [jQuery](http://jquery.com/) v1.3+
  112
+
  113
+			<script src="http://www.yourwebsite.com/history.js/scripts/compressed/history.adapter.jquery.js"></script>
  114
+
  115
+	- [Mootools](http://mootools.net/) v1.3+
  116
+
  117
+			<script src="http://www.yourwebsite.com/history.js/scripts/compressed/history.adapter.mootools.js"></script>
  118
+
  119
+	- [Prototype](http://www.prototypejs.org/) v1.7+ (does not support versions of IE prior to 9 due to a bug in the prototype library)
  120
+
  121
+			<script src="http://www.yourwebsite.com/history.js/scripts/compressed/history.adapter.prototype.js"></script>
  122
+
  123
+	- [Zepto](http://zeptojs.com/) v0.5+
  124
+
  125
+			<script src="http://www.yourwebsite.com/history.js/scripts/compressed/history.adapter.zepto.js"></script>
  126
+
  127
+	- _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) :-)_
  128
+
  129
+5. Include History.js
  130
+
  131
+		<script src="http://www.yourwebsite.com/history.js/scripts/compressed/history.js"></script>
  132
+		<script src="http://www.yourwebsite.com/history.js/scripts/compressed/history.html4.js"></script>
  133
+
  134
+> 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)
  135
+
  136
+
  137
+## Subscribe to Updates
  138
+
  139
+- For Email Updates:
  140
+	- You can subscribe via the subscription form included in the demo page
  141
+- For Commit RSS/Atom Updates:
  142
+	- You can subscribe via the [GitHub Commit Atom Feed](https://github.com/balupton/History.js/commits/master.atom)
  143
+- For GitHub News Feed Updates:
  144
+	- You can click the "watch" button up the top right of History.js's [GitHub Project Page](https://github.com/balupton/History.js)
  145
+
  146
+
  147
+## Getting Support
  148
+
  149
+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).
  150
+
  151
+
  152
+## Giving Support
  153
+
  154
+If you'd love to give some support back and make a difference; here are a few great ways you can give back!
  155
+
  156
+- 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)
  157
+- 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!
  158
+- Spread the word via tweets, blogs, tumblr, whatever - the more people talking about it the better!
  159
+- Donate via the donation form at the bottom right of [balupton.com](http://balupton.com) - every cent truly does help!
  160
+- Make it easier for me to let you know about future releases and updates by subscribing via the signup form inside the demo page
  161
+- Watch it via clicking the "watch" button up the top of its [Project Page](https://github.com/balupton/History.js)
  162
+
  163
+Thanks! every bit of help really does make a difference. Again thank you.
  164
+
  165
+
  166
+## Browsers: Tested and Working In
  167
+
  168
+### HTML5 Browsers
  169
+
  170
+- Chrome 8,9,10
  171
+- Firefox 4
  172
+- Safari 5
  173
+- Safari iOS 4.3
  174
+
  175
+### HTML4 Browsers
  176
+
  177
+- IE 6,7,8,9
  178
+- Firefox 3
  179
+- Opera 10,11
  180
+- Safari 4
  181
+- Safari iOS prior to version 4.3
  182
+
  183
+
  184
+## Exposed API
  185
+
  186
+### Functions
  187
+
  188
+- `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
  189
+- `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
  190
+- `History.getState()` <br/> Gets the current state of the browser, returns an object with `data`, `title` and `url`
  191
+- `History.getHash()` <br/> Gets the current hash of the browser
  192
+- `History.Adapter.bind(element,event,callback)` <br/> A framework independent event binder, you may either use this or your framework's native event binder.
  193
+- `History.Adapter.trigger(element,event)` <br/> A framework independent event trigger, you may either use this or your framework's native event trigger.
  194
+- `History.Adapter.onDomLoad(callback)` <br/> A framework independent onDomLoad binder, you may either use this or your framework's native onDomLoad binder.
  195
+- `History.back()` <br/> Go back once through the history (same as hitting the browser's back button)
  196
+- `History.forward()` <br/> Go forward once through the history (same as hitting the browser's forward button)
  197
+- `History.go(X)` <br/> If X is negative go back through history X times, if X is positive go forwards through history X times
  198
+- `History.log(...)` <br/> Logs messages to the console, the log element, and fallbacks to alert if neither of those two exist
  199
+- `History.debug(...)` <br/> Same as `History.log` but only runs if `History.debug.enable === true`
  200
+
  201
+### Events
  202
+
  203
+- `window.onstatechange` <br/> Fired when the state of the page changes (does not include hash changes)
  204
+- `window.onanchorchange` <br/> Fired when the anchor of the page changes (does not include state hashes)
  205
+
  206
+
  207
+## Notes on Compatibility
  208
+
  209
+- History.js **solves** the following browser bugs:
  210
+	- HTML5 Browsers
  211
+		- Chrome 8 sometimes does not contain the correct state data when traversing back to the initial state
  212
+		- Safari 5, Safari iOS 4 and Firefox 3 and 4 do not fire the `onhashchange` event when the page is loaded with a hash
  213
+		- Safari 5 and Safari iOS 4 do not fire the `onpopstate` event when the hash has changed unlike the other browsers
  214
+		- 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)
  215
+		- 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)
  216
+		- 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/)
  217
+		- 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
  218
+		- None of the HTML5 browsers actually utilise the `title` argument to the `pushState` and `replaceState` calls
  219
+	- HTML4 Browsers
  220
+		- Old browsers like MSIE 6,7 and Firefox 2 do not have a `onhashchange` event
  221
+		- MSIE 6 and 7 sometimes do not apply a hash even it was told to (requiring a second call to the apply function)
  222
+		- Non-Opera HTML4 browsers sometimes do not apply the hash when the hash is not `urlencoded`
  223
+	- All Browsers
  224
+		- State data and titles do not persist once the site is left and then returned (includes page refreshes)
  225
+		- State titles are never applied to the `document.title`
  226
+- 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
  227
+- 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.
  228
+- 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.
  229
+- 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:
  230
+	- `window.onstatechange`: this is the same as the `onpopstate` event except it does not fire for traditional anchors
  231
+	- `window.onanchorchange`: this is the same as the `onhashchange` event except it does not fire for states
  232
+- Known Issues
  233
+	- 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
  234
+	- Mercury iOS fails to apply url changes (hashes and HTML5 History API states) - there is nothing we can do about this
  235
+
  236
+
  237
+## Changelog
  238
+
  239
+- v1.7.0 - April 01 2011
  240
+	- 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`.
  241
+	- 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)
  242
+	- 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/)
  243
+	- 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)
  244
+	- Fixed URL Encoding Issue - [Reported](https://github.com/balupton/history.js/issues/#issue/33) by [Rob Madole](http://robmadole.com/)
  245
+	- 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/)
  246
+	- URLs in the State Hashes for HTML4 Browsers are now even shorter - [Discussion](https://github.com/balupton/history.js/issues#issue/28)
  247
+	- Fixed a issue with the MooTools Adapter and JSON with IE7 and IE8
  248
+
  249
+- v1.6.0 - March 22 2011
  250
+	- Added Zepto adapter thanks to [Matt Garrett](http://twitter.com/#!/matthewgarrett)
  251
+	- The readme now references the supported versions of the libraries we use
  252
+	- Updated vendors to the most recent versions. jQuery 1.5.1 and Mootools 1.3.1
  253
+	- Reverted versions of Safari iOS prior to version 4.3 to be HTML4 browsers, Safari iOS 4.3 is a HTML5 browser
  254
+	- Refined code in History.js and its adapters
  255
+	- 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/)
  256
+	- 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)
  257
+	- 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)
  258
+	- 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/)
  259
+	- 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/)
  260
+	- **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.
  261
+
  262
+- v1.5.0 - February 12 2011
  263
+	- Moved to UglifyJS instead of Google Closure
  264
+	- Split HTML4 functionality from HTML5 functionality
  265
+	- Installation details have changed (the filenames are different)
  266
+
  267
+- v1.4.1 - February 10 2011
  268
+	- Added HTML History API Support for Safari 5 and Safari iOS 4.2.1
  269
+	- Cleaned code a bit (mostly with unit tests)
  270
+
  271
+- v1.4.0 - February 10 2011
  272
+	- Unit Testing now uses [QUnit](http://docs.jquery.com/Qunit)
  273
+	- Corrected Safari 5 Support
  274
+	- Now uses queues instead of timeouts
  275
+		- This means the API works exactly as expected, no more need to wrap calls in timeouts
  276
+	- Included a Subscribe Form in the Demo for Version Updates via Email
  277
+	- Small updates to Documentation
  278
+
  279
+- v1.3.1 - February 04 2011
  280
+	- Improved Documentation
  281
+
  282
+- v1.3.0 - January 31 2011
  283
+	- Support for cleaner HTML4 States
  284
+
  285
+- v1.2.1 - January 30 2011
  286
+	- Fixed History.log always being called - [reported by dlee](https://github.com/balupton/History.js/issues/#issue/2)
  287
+	- Re-Added `History.go(index)` support
  288
+
  289
+- v1.2.0 - January 25 2011
  290
+	- Support for HTML4 States in HTML5 Browsers (added test)
  291
+	- Updates of Documentation
  292
+
  293
+- v1.1.0 - January 24 2011
  294
+	- Developed a series of automated test cases
  295
+	- Fixed issue with traditional anchors
  296
+	- Fixed issue with differing replaceState functionality in HTML4 Browsers
  297
+	- Fixed issue with Google Chrome artefacts being carried over to the initial state
  298
+	- Provided `onstatechange` and `onanchorchange` events
  299
+
  300
+- v1.0.0 - January 22 2011
  301
+	- Supported `History.pushState` and `History.replaceState` degradation
  302
+	- Supported jQuery, MooTools and Prototype Frameworks
  303
+
  304
+
  305
+## Todo for Upcoming Releases
  306
+
  307
+- Allow for url to be optional in `pushState` and `replaceState` calls
  308
+- Add an Ajax extension to succeed the [jQuery Ajaxy](http://balupton.com/projects/jquery-ajaxy) project
  309
+- Add a compilation test to ensure `.debug = false` and no `History.log` or `console.xxx` calls exist.
  310
+
  311
+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.
351  admin/thirdparty/history-js/cli
... ...
@@ -0,0 +1,351 @@
  1
+#!/usr/bin/env ruby
  2
+
  3
+# == Name
  4
+#   cli - BalCMS Command Line Interface
  5
+#
  6
+# == Synopsis
  7
+#   cli check-env
  8
+#   cli birth
  9
+#   cli init-commit
  10
+#   cli init-new
  11
+#   cli init-existing
  12
+#   cli configure
  13
+#   cli install
  14
+#   cli permissions
  15
+#   cli setup
  16
+#   cli cron
  17
+#
  18
+#   cli add
  19
+#   cli stable
  20
+#   cli master
  21
+#   cli upgrade
  22
+#   cli update
  23
+#   cli deploy
  24
+#
  25
+#   cli clean
  26
+#   cli clean-media
  27
+#   cli clean-config
  28
+#   cli clean-styles
  29
+#   cli clean-scripts
  30
+#
  31
+#   cli [options]
  32
+#
  33
+# == Examples
  34
+#   cli check-env
  35
+#     Checks to see that our environment is properly configured and will support a BalCMS installation.
  36
+#
  37
+#   cli birth
  38
+#     Executes: init-new, configure, install, init-commit
  39
+#
  40
+#   cli init-commit
  41
+#     Performs the initial commit (commits new and modified files during the installation to the git repo).
  42
+#
  43
+#   cli init-new
  44
+#     Initialises the repository as a new installation. Only run this once.
  45
+#
  46
+#   TODO: finish this example section
  47
+#
  48
+# == Options
  49
+#   -h, --help          Displays help message
  50
+#   -v, --version       Display the version, then exit
  51
+#   -q, --quiet         Output as little as possible, overrides verbose
  52
+#   -V, --verbose       Verbose output
  53
+#
  54
+# == Author
  55
+#   Benjamin Arthur Lupton
  56
+#
  57
+# == Copyright
  58
+#   Copyright (c) 2008-2011 Benjamin Arthur Lupton
  59
+#   Licensed under the New BSD License
  60
+#   http://creativecommons.org/licenses/BSD/
  61
+
  62
+require 'optparse'
  63
+require 'rdoc/usage'
  64
+require 'ostruct'
  65
+require 'date'
  66
+
  67
+class App
  68
+	SOURCEMAP		= './scripts/closure.map'
  69
+	BUILDDIR		= './.build'
  70
+	UGLIFYURL		= 'https://github.com/mishoo/UglifyJS/raw/master/bin/uglifyjs'
  71
+	UGLIFYDIR		= './.build/uglify'
  72
+	UGLIFYFILE	= './.build/uglify/uglify'
  73
+	CLOSUREURL	= 'http://closure-compiler.googlecode.com/files/compiler-latest.zip'
  74
+	CLOSUREDIR	= './.build/closure'
  75
+	CLOSUREZIP	= './.build/closure/compiler.zip'
  76
+	CLOSUREFILE	= './.build/closure/compiler.jar'
  77
+	YUIURL			= 'http://yuilibrary.com/downloads/yuicompressor/yuicompressor-2.4.2.zip'
  78
+	YUIDIR			= './.build/yui'
  79
+	YUIZIP			= './.build/yui/compiler.zip'
  80
+	YUIFILE			= './.build/yui/yuicompressor-2.4.2/build/yuicompressor-2.4.2.jar'
  81
+
  82
+	def initialize
  83
+		init_env
  84
+	end
  85
+
  86
+	def init_env
  87
+		# Check for Requirements
  88
+		reqs = ['mkdir','curl','tar','git']
  89
+		reqs.each do |req|
  90
+		  has_req = `which #{req}`.strip
  91
+		  if has_req.empty?
  92
+		    abort("CLI requires the following binary which is not installed: #{req}")
  93
+		  end
  94
+		end
  95
+
  96
+		# Check for Closure Compiler
  97
+		if !File.exists?(CLOSUREFILE)
  98
+			`mkdir -p #{CLOSUREDIR}`
  99
+			puts "Downloading the Closure Compiler..."
  100
+			download(CLOSUREURL, CLOSUREZIP)
  101
+			extract(CLOSUREDIR, CLOSUREZIP)
  102
+			`chmod +x #{CLOSUREFILE}`
  103
+		end
  104
+
  105
+		# Check for Uglify
  106
+		if !File.exists?(UGLIFYFILE)
  107
+			`mkdir -p #{UGLIFYDIR}`
  108
+			puts "Downloading the Uglify Compiler..."
  109
+			download(UGLIFYURL, UGLIFYFILE)
  110
+			`chmod +x #{UGLIFYFILE}`
  111
+		end
  112
+
  113
+		# Check for YUI Compiler
  114
+		if !File.exists?(YUIFILE)
  115
+			`mkdir -p #{YUIDIR}`
  116
+			puts "Downloading the YUI Compiler..."
  117
+			download(YUIURL, (YUIZIP))
  118
+			extract(YUIDIR, YUIZIP)
  119
+			`chmod +x #{YUIFILE}`
  120
+		end
  121
+	end
  122
+
  123
+	def has_changes
  124
+		result = `git status`
  125
+		if result.include? 'Changed but not updated'
  126
+		  abort("You have un-committed changes that need to be committed before we can proceed.\n#{result}")
  127
+		end
  128
+	end
  129
+
  130
+	# ===========================================================================
  131
+	# Helpers
  132
+
  133
+	def download ( url, file )
  134
+		result = `curl -L #{url} -o #{file}`
  135
+	end
  136
+
  137
+	def extract ( dir, file )
  138
+		file = file.gsub(dir,'.')
  139
+		result = `cd #{dir} ; tar -xf #{file} ; rm -Rf #{file}`
  140
+	end
  141
+
  142
+	def compressJavascriptFile ( in_file, out_file )
  143
+		# Calculate
  144
+		in_file_size = File.size(in_file)
  145
+
  146
+		# Handle
  147
+		if in_file.equal? out_file
  148
+			out_file = out_file.gsub(/\.js$/, '.min.js')
  149
+			compressFileUglify(in_file,out_file)
  150
+			`rm #{in_file}`
  151
+			`mv #{out_file} #{in_file}`
  152
+			out_file = in_file
  153
+		else
  154
+			compressFileUglify(in_file,out_file)
  155
+			out_file_size = File.size(out_file)
  156
+		end
  157
+
  158
+		# Calculate
  159
+		out_file_size = File.size(out_file)
  160
+		ratio = Float(out_file_size)/Float(in_file_size)
  161
+		reduction = ((1-ratio)*100).round
  162
+
  163
+		# Log
  164
+		puts "Compressed the file [#{in_file}] to [#{out_file}] with a #{reduction}% reduction"
  165
+	end
  166
+
  167
+	def compressFileUglify ( in_file, out_file )
  168
+		result = `#{UGLIFYFILE} -o #{out_file} #{in_file}`
  169
+	end
  170
+
  171
+	def compressFileClosure ( in_file, out_file )
  172
+		result = `java -jar #{CLOSUREFILE} --js_output_file=#{out_file} --js=#{in_file}`
  173
+	end
  174
+
  175
+	# ===========================================================================
  176
+	# Installers
  177
+
  178
+	def build
  179
+
  180
+	end
  181
+
  182
+	# ===========================================================================
  183
+	# Git Helpers
  184
+
  185
+	def add
  186
+		puts \
  187
+		` git add -u;`
  188
+	end
  189
+
  190
+	def stable
  191
+		puts \
  192
+		` git checkout #{BRANCH_STABLE};`
  193
+	end
  194
+
  195
+	def dev
  196
+		puts \
  197
+		` git checkout #{BRANCH_DEV};`
  198
+	end
  199
+
  200
+	def master
  201
+		puts \
  202
+		` git checkout master;`
  203
+	end
  204
+
  205
+	def upgrade
  206
+		puts \
  207
+		` git checkout #{BRANCH_BALCMS};
  208
+		  git pull balcms #{BRANCH_STABLE};
  209
+		  git checkout #{BRANCH_DEV};
  210
+		  git merge #{BRANCH_BALCMS};`
  211
+	end
  212
+
  213
+	def update
  214
+		puts \
  215
+		` git pull;`
  216
+		configure
  217
+	end
  218
+
  219
+	def deploy
  220
+		puts \
  221
+		` git checkout #{BRANCH_STABLE};
  222
+		  git merge #{BRANCH_DEV};
  223
+		  git checkout #{BRANCH_MASTER};
  224
+		  git merge #{BRANCH_STABLE};
  225
+		  git checkout #{BRANCH_DEV};
  226
+		  git push origin --all;`
  227
+	end
  228
+
  229
+end
  230
+
  231
+# ===========================================================================
  232
+# Booter
  233
+
  234
+class Booter
  235
+	VERSION = :'0.0.1'
  236
+
  237
+	attr_reader :options
  238
+
  239
+	def initialize(arguments, stdin)
  240
+		@arguments = arguments
  241
+		@stdin = stdin
  242
+
  243
+		# Set defaults
  244
+		@options = OpenStruct.new
  245
+		@options.verbose = false
  246
+		@options.quiet = false
  247
+		# TO DO - add additional defaults
  248
+	end
  249
+
  250
+	# Parse options, check arguments, then process the command
  251
+	def run
  252
+
  253
+		if parsed_options? && arguments_valid?
  254
+
  255
+		  puts "Start at #{DateTime.now}\n\n" if @options.verbose
  256
+
  257
+		  output_options if @options.verbose # [Optional]
  258
+
  259
+		  process_arguments
  260
+		  process_command
  261
+
  262
+		  puts "\nFinished at #{DateTime.now}" if @options.verbose
  263
+
  264
+		else
  265
+		  output_usage
  266
+		end
  267
+
  268
+	end
  269
+
  270
+	protected
  271
+
  272
+		def parsed_options?
  273
+
  274
+		  # Specify options
  275
+		  opts = OptionParser.new
  276
+		  opts.on('-v', '--version')    { output_version ; exit 0 }
  277
+		  opts.on('-h', '--help')       { output_help }
  278
+		  opts.on('-V', '--verbose')    { @options.verbose = true }
  279
+		  opts.on('-q', '--quiet')      { @options.quiet = true }
  280
+		  # TO DO - add additional options
  281
+
  282
+		  opts.parse!(@arguments) rescue return false
  283
+
  284
+		  process_options
  285
+		  true
  286
+		end
  287
+
  288
+		# Performs post-parse processing on options
  289
+		def process_options
  290
+		  @options.verbose = false if @options.quiet
  291
+		end
  292
+
  293
+		def output_options
  294
+		  puts :"Options:\n"
  295
+
  296
+		  @options.marshal_dump.each do |name, val|
  297
+		    puts "  #{name} = #{val}"
  298
+		  end
  299
+		end
  300
+
  301
+		# True if required arguments were provided
  302
+		def arguments_valid?
  303
+		  # TO DO - implement your real logic here
  304
+		  true if @arguments.length == 1
  305
+		end
  306
+
  307
+		# Setup the arguments
  308
+		def process_arguments
  309
+		  # TO DO - place in local vars, etc
  310
+		end
  311
+
  312
+		def output_help
  313
+		  output_version
  314
+		  RDoc::usage() #exits app
  315
+		end
  316
+
  317
+		def output_usage
  318
+		  RDoc::usage(:'usage') # gets usage from comments above
  319
+		end
  320
+
  321
+		def output_version
  322
+		  puts "#{File.basename(__FILE__)} version #{VERSION}"
  323
+		end
  324
+
  325
+		def process_command
  326
+		  # Create Application
  327
+		  app = App.new
  328
+
  329
+		  # Fetch + Execute
  330
+		  command = @arguments[0].gsub('-','_')
  331
+		  unless app.respond_to?(command)
  332
+		    abort("Unknown command: #{command}")
  333
+		  end
  334
+		  app.send(command)
  335
+		end
  336
+
  337
+		def process_standard_input
  338
+		  input = @stdin.read
  339
+		  # TO DO - process input
  340
+
  341
+		  # [Optional]
  342
+		  #@stdin.each do |line|
  343
+		  #  # TO DO - process each line
  344
+		  #end
  345
+		end
  346
+end
  347
+
  348
+
  349
+# Create Booter
  350
+booter = Booter.new(ARGV, STDIN)
  351
+booter.run
58  admin/thirdparty/history-js/demo/bcherry-orig.html
... ...
@@ -0,0 +1,58 @@
  1
+
  2
+<!DOCTYPE html>
  3
+<html lang="en">
  4
+<head>
  5
+  <meta charset="utf-8" />
  6
+
  7
+  <title>WebKit is Dropping HTML5 "popstate" Events</title>
  8
+
  9
+  <link rel="stylesheet" href="/static/lib/css/blueprint/blueprint.min.css" media="screen, projection" />
  10
+  <link rel="stylesheet" href="/static/lib/css/blueprint/print.min.css" media="print" />
  11
+  <!--[if lt IE 8]>
  12
+    <link rel="stylesheet" href="/static/lib/css/blueprint/ie.min.css" media="screen, projection">
  13
+  <![endif]-->
  14
+  <link href="/static/lib/css/bcherry.css" rel="stylesheet" media="screen" />
  15
+  <style>
  16
+    #n {
  17
+      font-size: 48px;
  18
+    }
  19
+    p {
  20
+      padding: 0 20px;
  21
+    }
  22
+  </style>
  23
+
  24
+  <script type="text/javascript" src="../vendor/jquery.js"></script>
  25
+	<script type="text/javascript" src="../scripts/uncompressed/history.adapter.jquery.js"></script>
  26
+	<script type="text/javascript" src="../scripts/uncompressed/history.js"></script>
  27
+
  28
+</head>
  29
+<body>
  30
+  <div id="n"></div>
  31
+  <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>
  32
+  <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>
  33
+  <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>
  34
+  <script>
  35
+    // Bind to popstate
  36
+    $(window).bind("popstate", function(e) {
  37
+    	var State = e.state;
  38
+
  39
+      // log that this event was fired, and the current URL
  40
+      if (window.console && window.console.log) {
  41
+        console.log("popstate", State, window.location.href);
  42
+      }
  43
+      // update the page
  44
+      $("#n").text(typeof State.n !== 'undefined' ? State.n : document.location.href);
  45
+
  46
+      // Make an outbound image request that will take 1s. This request seems to be the cause of dropped popstates.
  47
+      // 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.
  48
+      (new Image()).src = "http://www.bcherry.net/playground/pushstate.jpg";
  49
+    });
  50
+
  51
+    // Seed the browser history
  52
+    for (var i = 0; i < 20; i++) {
  53
+      window.history.pushState({n:i}, i, "?" + i);
  54
+      $("#n").text(i);
  55
+    }
  56
+  </script>
  57
+</body>
  58
+</html>
62  admin/thirdparty/history-js/demo/bcherry.html
... ...
@@ -0,0 +1,62 @@
  1
+
  2
+<!DOCTYPE html>
  3
+<html lang="en">
  4
+<head>
  5
+  <meta charset="utf-8" />
  6
+
  7
+  <title>WebKit is Dropping HTML5 "popstate" Events</title>
  8
+
  9
+  <link rel="stylesheet" href="/static/lib/css/blueprint/blueprint.min.css" media="screen, projection" />
  10
+  <link rel="stylesheet" href="/static/lib/css/blueprint/print.min.css" media="print" />
  11
+  <!--[if lt IE 8]>
  12
+    <link rel="stylesheet" href="/static/lib/css/blueprint/ie.min.css" media="screen, projection">
  13
+  <![endif]-->
  14
+  <link href="/static/lib/css/bcherry.css" rel="stylesheet" media="screen" />
  15
+  <style>
  16
+    #n {
  17
+      font-size: 48px;
  18
+    }
  19
+    p {
  20
+      padding: 0 20px;
  21
+    }
  22
+  </style>
  23
+
  24
+  <script type="text/javascript" src="../vendor/jquery.js"></script>
  25
+	<script type="text/javascript" src="../scripts/uncompressed/history.adapter.jquery.js"></script>
  26
+	<script type="text/javascript" src="../scripts/uncompressed/history.js"></script>
  27
+
  28
+</head>
  29
+<body>
  30
+  <div id="n"></div>
  31
+  <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>
  32
+  <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>
  33
+  <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>
  34
+  <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>
  35
+  <script>
  36
+  	// Prepare
  37
+		window.History.debug.enable = true;
  38
+
  39
+    // Bind to popstate
  40
+    $(window).bind("statechange", function(e) {
  41
+    	var State = window.History.getState();
  42
+
  43
+      // log that this event was fired, and the current URL
  44
+      if (window.console && window.console.log) {
  45
+        console.log("popstate", State, window.location.href);
  46
+      }
  47
+      // update the page
  48
+      $("#n").text(typeof State.data.n !== 'undefined' ? State.data.n : State.url);
  49
+
  50
+      // Make an outbound image request that will take 1s. This request seems to be the cause of dropped popstates.
  51
+      // 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.
  52
+      (new Image()).src = "http://www.bcherry.net/playground/pushstate.jpg";
  53
+    });
  54
+
  55
+    // Seed the browser history
  56
+    for (var i = 0; i < 20; i++) {
  57
+      window.History.pushState({n:i}, i, "?" + i);
  58
+      $("#n").text(i);
  59
+    }
  60
+  </script>
  61
+</body>
  62
+</html>
37  admin/thirdparty/history-js/demo/chrome.html
... ...
@@ -0,0 +1,37 @@
  1
+<html>
  2
+<head>
  3
+	<title>Chrome History API Data Artifact</title>
  4
+</head>
  5
+<body>
  6
+	<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>
  7
+	<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>
  8
+	<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>
  9
+	<button id="bug">bug</button>
  10
+	<button id="reset">reset</button>
  11
+	<textarea id="log" style="width:100%;height:200px;margin-top:1em;"></textarea>
  12
+	<script type="text/javascript">
  13
+		(function(){
  14
+
  15
+			window.onpopstate = function(event) {
  16
+				var message = ("onpopstate: location: " + document.location.href + ", data: " + JSON.stringify(event.state));
  17
+				document.getElementById('log').innerHTML += message+"\n\n";
  18
+			};
  19
+
  20
+			document.getElementById('bug').onclick = function(){
  21
+				setTimeout(function(){
  22
+					history.pushState({state:'new'},'New State','?new');
  23
+				},1e3);
  24
+
  25
+				setTimeout(function(){
  26
+					history.back();
  27
+				},2e3);
  28
+			};
  29
+
  30
+			document.getElementById('reset').onclick = function(){
  31
+				document.location.href = document.location.href.replace(/[\#\?].*/,"");
  32
+			};
  33
+
  34
+		})();
  35
+	</script>
  36
+</body>
  37
+</html>
101  admin/thirdparty/history-js/demo/index.html
... ...
@@ -0,0 +1,101 @@
  1
+<!DOCTYPE HTML>
  2
+<html>
  3
+<head>
  4
+	<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
  5
+	<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
  6
+	<title>
  7
+		History.js
  8
+	</title>
  9
+</head>
  10
+<body style="padding-bottom:40px">
  11
+	<!-- Scripts -->
  12
+	<script>if ( typeof window.JSON === 'undefined' ) { document.write('<script src="../scripts/uncompressed/json2.js"><\/script>'); }</script>
  13
+	<script src="../vendor/jquery.js"></script>
  14
+	<script src="../scripts/uncompressed/amplify.store.js"></script>
  15
+	<script src="../scripts/uncompressed/history.adapter.jquery.js"></script>
  16
+	<script src="../scripts/uncompressed/history.js"></script>
  17
+	<script src="../scripts/uncompressed/history.html4.js"></script>
  18
+
  19
+	<!-- HTML -->
  20
+	<div id="wrap">
  21
+		<!-- Intro -->
  22
+		<h1><a href="https://github.com/balupton/History.js">History.js</a> by <a href="http://balupton.com">Benjamin Lupton</a></h1>
  23
+		<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>
  24
+
  25
+		<!-- Textarea for Logging -->
  26
+		<textarea id="log" style="width:100%;height:400px"></textarea>
  27
+
  28
+		<!-- Note -->
  29
+		<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>
  30
+
  31
+		<!-- Buttons -->
  32
+		<ul id="buttons">
  33
+		</ul>
  34
+
  35
+		<!-- Subscribe to Updates -->
  36
+		<h3 style="margin-top:30px">Subscribe to Updates</h3>
  37
+		<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>
  38
+		<form action="http://balupton.createsend.com/t/r/s/phujuu/" method="post" id="subForm">
  39
+		<div>
  40
+		<label for="name">Name:</label><input type="text" name="cm-name" id="name" /><br />
  41
+		<label for="phujuu-phujuu">Email:</label><input type="text" name="cm-phujuu-phujuu" id="phujuu-phujuu" /><br />
  42
+		<label for="Website">Website:</label><input type="text" name="cm-f-kjqtu" id="Website" /><br />
  43
+		<input type="submit" value="Subscribe" />
  44
+		</div>
  45
+		</form>
  46
+
  47
+		<!-- Our Script -->
  48
+		<script>
  49
+			(function(window,undefined){
  50
+
  51
+				// Check Location
  52
+				if ( document.location.protocol === 'file:' ) {
  53
+					alert('The HTML5 History API (and thus History.js) do not work on files, please upload it to a server.');
  54
+				}
  55
+
  56
+				// Establish Variables
  57
+				var
  58
+					History = window.History, // Note: We are using a capital H instead of a lower h
  59
+					State = History.getState(),
  60
+					$log = $('#log');
  61
+
  62
+				// Log Initial State
  63
+				History.log('initial:', State.data, State.title, State.url);
  64
+
  65
+				// Bind to State Change
  66
+				History.Adapter.bind(window,'statechange',function(){ // Note: We are using statechange instead of popstate
  67
+					// Log the State
  68
+					var State = History.getState(); // Note: We are using History.getState() instead of event.state
  69
+					History.log('statechange:', State.data, State.title, State.url);
  70
+				});
  71
+
  72
+				// Prepare Buttons
  73
+				var
  74
+					buttons = document.getElementById('buttons'),
  75
+					scripts = [
  76
+						'History.pushState({state:1,rand:Math.random()}, "State 1", "?state=1"); // logs {state:1,rand:"some random value"}, "State 1", "?state=1"',
  77
+						'History.pushState({state:2,rand:Math.random()}, "State 2", "?state=2"); // logs {state:2,rand:"some random value"}, "State 2", "?state=2"',
  78
+						'History.replaceState({state:3,rand:Math.random()}, "State 3", "?state=3"); // logs {state:3,rand:"some random value"}, "State 3", "?state=3"',
  79
+						'History.pushState(null, null, "?state=4"); // logs {}, "", "?state=4"',
  80
+						'History.back(); // logs {state:3}, "State 3", "?state=3"',
  81
+						'History.back(); // logs {state:1}, "State 1", "?state=1"',
  82
+						'History.back(); // logs {}, "The page you started at", "?"',
  83
+						'History.go(2); // logs {state:3}, "State 3", "?state=3"'
  84
+					],
  85
+					buttonsHTML = ''
  86
+					;
  87
+
  88
+				// Add Buttons
  89
+				for ( var i=0,n=scripts.length; i<n; ++i ) {
  90
+					var _script = scripts[i];
  91
+					buttonsHTML +=
  92
+						'<li><button onclick=\'javascript:'+_script+'\'>'+_script+'</button></li>';
  93
+				}
  94
+				buttons.innerHTML = buttonsHTML;
  95
+
  96
+			})(window);
  97
+		</script>
  98
+	</div>
  99
+
  100
+</body>
  101
+</html>
43  admin/thirdparty/history-js/demo/native-auto.html
... ...
@@ -0,0 +1,43 @@
  1
+<html>
  2
+<head>
  3
+</head>
  4
+<body>
  5
+	<script type="text/javascript">
  6
+		(function(){
  7
+
  8
+			window.onpopstate = function(event) {
  9
+				console.log("onpopstate: location: " + document.location.href + ", data: " + JSON.stringify(event.state));
  10
+			};
  11
+			window.onhashchange = function(event) {
  12
+				console.log("onhashchange: location: " + document.location.href);
  13
+			};
  14
+
  15
+			setTimeout(function(){
  16
+				history.pushState({page: 1}, "title 1", "?page=1");
  17
+			},1e3);
  18
+			setTimeout(function(){
  19
+				history.pushState({page: 2}, "title 2", "?page=2");
  20
+			},2e3);
  21
+			setTimeout(function(){
  22
+				history.replaceState({page: 3}, "title 3", "?page=3");
  23
+			},3e3);
  24
+			setTimeout(function(){
  25
+				document.location.hash = 'asd';
  26
+			},4e3);
  27
+			setTimeout(function(){
  28
+				history.back(); // alerts "location: http://example.com/example.html?page=3#asd, state: {"page":3}"
  29
+			},5e3);
  30
+			setTimeout(function(){
  31
+				history.back(); // alerts "location: http://example.com/example.html?page=1, state: {"page":1}"
  32
+			},6e3);
  33
+			setTimeout(function(){
  34
+				history.back(); // alerts "location: http://example.com/example.html, state: null
  35
+			},7e3);
  36
+			setTimeout(function(){
  37
+				history.go(2);  // alerts "location: http://example.com/example.html?page=3, state: {"page":3}
  38
+			},8e3);
  39
+
  40
+		})();
  41
+	</script>
  42
+</body>
  43
+</html>
62  admin/thirdparty/history-js/demo/native.html
... ...
@@ -0,0 +1,62 @@
  1
+<html>
  2
+<head>
  3
+	<title>HTML5 History API Demo</title>
  4
+</head>
  5
+<body>
  6
+	<textarea id="log" style="width:100%;height:400px;margin:1em;"></textarea>
  7
+	<div id="url" style="border:1px black dotted;height:1em;margin:1em;"></div>
  8
+	<div id="buttons" style="margin:1em;"></div>
  9
+	<script type="text/javascript">
  10
+			var $url = document.getElementById('url'), $log = document.getElementById('log');
  11
+
  12
+			window.onpopstate = function(event) {
  13
+				var message =
  14
+					"onpopstate: "+
  15
+					"location: " + location.href + ", " +
  16
+					"data: " + JSON.stringify(event.state) +
  17
+					"\n\n"