2 YUI 3.13.0 (build 508226d)
3 Copyright 2013 Yahoo! Inc. All rights reserved.
4 Licensed under the BSD License.
5 http://yuilibrary.com/license/
8 YUI.add('history-hash-ie', function (Y, NAME) {
11 * Improves IE6/7 support in history-hash by using a hidden iframe to create
12 * entries in IE's browser history. This module is only needed if IE6/7 support
13 * is necessary; it's not needed for any other browser.
16 * @submodule history-hash-ie
20 // Combination of a UA sniff to ensure this is IE (or a browser that wants us to
21 // treat it like IE) and feature detection for native hashchange support (false
22 // for IE < 8 or IE8/9 in IE7 mode).
23 if (Y.UA.ie && !Y.HistoryBase.nativeHashChange) {
25 GlobalEnv = YUI.namespace('Env.HistoryHash'),
26 HistoryHash = Y.HistoryHash,
28 iframe = GlobalEnv._iframe,
32 * Gets the raw (not decoded) current location hash from the IE iframe,
33 * minus the preceding '#' character and the hashPrefix (if one is set).
35 * @method getIframeHash
36 * @return {String} current iframe hash
39 HistoryHash.getIframeHash = function () {
40 if (!iframe || !iframe.contentWindow) {
44 var prefix = HistoryHash.hashPrefix,
45 hash = iframe.contentWindow.location.hash.substr(1);
47 return prefix && hash.indexOf(prefix) === 0 ?
48 hash.replace(prefix, '') : hash;
52 * Updates the history iframe with the specified hash.
54 * @method _updateIframe
55 * @param {String} hash location hash
56 * @param {Boolean} replace (optional) if <code>true</code>, the current
57 * history state will be replaced without adding a new history entry
62 HistoryHash._updateIframe = function (hash, replace) {
63 var iframeDoc = iframe && iframe.contentWindow && iframe.contentWindow.document,
64 iframeLocation = iframeDoc && iframeDoc.location;
66 if (!iframeDoc || !iframeLocation) {
70 Y.log('updating history iframe: ' + hash + ', replace: ' + !!replace, 'info', 'history');
73 iframeLocation.replace(hash.charAt(0) === '#' ? hash : '#' + hash);
75 iframeDoc.open().close();
76 iframeLocation.hash = hash;
80 Do.before(HistoryHash._updateIframe, HistoryHash, 'replaceHash', HistoryHash, true);
83 Y.on('domready', function () {
84 var lastUrlHash = HistoryHash.getHash();
86 // Create a hidden iframe to store history state, following the
87 // iframe-hiding recommendations from
88 // http://www.paciellogroup.com/blog/?p=604.
90 // This iframe will allow history navigation within the current page
91 // context. After navigating to another page, all but the most
92 // recent history state will be lost.
94 // Earlier versions of the YUI History Utility attempted to work
95 // around this limitation by having the iframe load a static
96 // resource. This workaround was extremely fragile and tended to
97 // break frequently (and silently) since it was entirely dependent
98 // on IE's inconsistent handling of iframe history.
100 // Since this workaround didn't work much of the time anyway and
101 // added significant complexity, it has been removed, and IE6 and 7
102 // now get slightly degraded history support.
103 Y.log('creating dynamic history iframe', 'info', 'history');
105 iframe = GlobalEnv._iframe = Y.Node.getDOMNode(Y.Node.create(
106 '<iframe src="javascript:0" style="display:none" height="0" width="0" tabindex="-1" title="empty"/>'
109 // Append the iframe to the documentElement rather than the body.
110 // Keeping it outside the body prevents scrolling on the initial
111 // page load (hat tip to Ben Alman and jQuery BBQ for this
113 Y.config.doc.documentElement.appendChild(iframe);
115 // Update the iframe with the initial location hash, if any. This
116 // will create an initial history entry that the user can return to
117 // after the state has changed.
118 HistoryHash._updateIframe(lastUrlHash || '#');
120 // Listen for hashchange events and keep the iframe's hash in sync
121 // with the parent frame's hash.
122 Y.on('hashchange', function (e) {
123 lastUrlHash = e.newHash;
125 if (HistoryHash.getIframeHash() !== lastUrlHash) {
126 Y.log('updating iframe hash to match URL hash', 'info', 'history');
127 HistoryHash._updateIframe(lastUrlHash);
131 // Watch the iframe hash in order to detect back/forward navigation.
132 Y.later(50, null, function () {
133 var iframeHash = HistoryHash.getIframeHash();
135 if (iframeHash !== lastUrlHash) {
136 Y.log('updating URL hash to match iframe hash', 'info', 'history');
137 HistoryHash.setHash(iframeHash);
145 }, '3.13.0', {"requires": ["history-hash", "node-base"]});