File: history/js/history-hash-ie.js
- /**
- * Improves IE6/7 support in history-hash by using a hidden iframe to create
- * entries in IE's browser history. This module is only needed if IE6/7 support
- * is necessary; it's not needed for any other browser.
- *
- * @module history
- * @submodule history-hash-ie
- * @since 3.2.0
- */
- // Combination of a UA sniff to ensure this is IE (or a browser that wants us to
- // treat it like IE) and feature detection for native hashchange support (false
- // for IE < 8 or IE8/9 in IE7 mode).
- if (Y.UA.ie && !Y.HistoryBase.nativeHashChange) {
- var Do = Y.Do,
- GlobalEnv = YUI.namespace('Env.HistoryHash'),
- HistoryHash = Y.HistoryHash,
- iframe = GlobalEnv._iframe,
- win = Y.config.win;
- /**
- * Gets the raw (not decoded) current location hash from the IE iframe,
- * minus the preceding '#' character and the hashPrefix (if one is set).
- *
- * @method getIframeHash
- * @return {String} current iframe hash
- * @static
- */
- HistoryHash.getIframeHash = function () {
- if (!iframe || !iframe.contentWindow) {
- return '';
- }
- var prefix = HistoryHash.hashPrefix,
- hash = iframe.contentWindow.location.hash.substr(1);
- return prefix && hash.indexOf(prefix) === 0 ?
- hash.replace(prefix, '') : hash;
- };
- /**
- * Updates the history iframe with the specified hash.
- *
- * @method _updateIframe
- * @param {String} hash location hash
- * @param {Boolean} replace (optional) if <code>true</code>, the current
- * history state will be replaced without adding a new history entry
- * @protected
- * @static
- * @for HistoryHash
- */
- HistoryHash._updateIframe = function (hash, replace) {
- var iframeDoc = iframe && iframe.contentWindow && iframe.contentWindow.document,
- iframeLocation = iframeDoc && iframeDoc.location;
- if (!iframeDoc || !iframeLocation) {
- return;
- }
- Y.log('updating history iframe: ' + hash + ', replace: ' + !!replace, 'info', 'history');
- if (replace) {
- iframeLocation.replace(hash.charAt(0) === '#' ? hash : '#' + hash);
- } else {
- iframeDoc.open().close();
- iframeLocation.hash = hash;
- }
- };
- Do.before(HistoryHash._updateIframe, HistoryHash, 'replaceHash', HistoryHash, true);
- if (!iframe) {
- Y.on('domready', function () {
- var lastUrlHash = HistoryHash.getHash();
- // Create a hidden iframe to store history state, following the
- // iframe-hiding recommendations from
- // http://www.paciellogroup.com/blog/?p=604.
- //
- // This iframe will allow history navigation within the current page
- // context. After navigating to another page, all but the most
- // recent history state will be lost.
- //
- // Earlier versions of the YUI History Utility attempted to work
- // around this limitation by having the iframe load a static
- // resource. This workaround was extremely fragile and tended to
- // break frequently (and silently) since it was entirely dependent
- // on IE's inconsistent handling of iframe history.
- //
- // Since this workaround didn't work much of the time anyway and
- // added significant complexity, it has been removed, and IE6 and 7
- // now get slightly degraded history support.
- Y.log('creating dynamic history iframe', 'info', 'history');
- iframe = GlobalEnv._iframe = Y.Node.getDOMNode(Y.Node.create(
- '<iframe src="javascript:0" style="display:none" height="0" width="0" tabindex="-1" title="empty"/>'
- ));
- // Append the iframe to the documentElement rather than the body.
- // Keeping it outside the body prevents scrolling on the initial
- // page load (hat tip to Ben Alman and jQuery BBQ for this
- // technique).
- Y.config.doc.documentElement.appendChild(iframe);
- // Update the iframe with the initial location hash, if any. This
- // will create an initial history entry that the user can return to
- // after the state has changed.
- HistoryHash._updateIframe(lastUrlHash || '#');
- // Listen for hashchange events and keep the iframe's hash in sync
- // with the parent frame's hash.
- Y.on('hashchange', function (e) {
- lastUrlHash = e.newHash;
- if (HistoryHash.getIframeHash() !== lastUrlHash) {
- Y.log('updating iframe hash to match URL hash', 'info', 'history');
- HistoryHash._updateIframe(lastUrlHash);
- }
- }, win);
- // Watch the iframe hash in order to detect back/forward navigation.
- Y.later(50, null, function () {
- var iframeHash = HistoryHash.getIframeHash();
- if (iframeHash !== lastUrlHash) {
- Y.log('updating URL hash to match iframe hash', 'info', 'history');
- HistoryHash.setHash(iframeHash);
- }
- }, null, true);
- });
- }
- }
-