问题
My goal is to support AJAX history for HTML5 browsers only. However, I would like my site to work with HTML4 browsers, but without AJAX history.
Many of the History.js examples include the following check before performing any operations:
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;
}
This would seem to work except for the fact that older browser such as IE7 do not support native JSON and the History.js plugin requires JSON.parse
and JSON.stringify
.
The suggested solution is to include json2.js (link). This seems kind of strange to me since HTML5 browsers that support pushState()
and popState()
should also support native JSON. Also, I do not want to include yet another library that I do not really need. My solution is to conditionally include History.js as follows:
var nativeJSON = (typeof JSON === 'object') && (typeof JSON.parse === 'function') && (typeof JSON.stringify === 'function');
if (nativeJSON) {
/// Include contents of: balupton-history.js-e84ad00\scripts\bundled\html5\jquery.history.js
} else {
window.History = { enabled: false };
}
This seems to work, but feels like a hack. Is there a better way to do this?
EDIT: 7/31/2012
If I do not include history.html4.js it still gives me an error on IE7. It appears that including json2.js is simply a requirement of this plugin at the moment. An improvement could probably be made to silently check for JSON support and disable the plugin if there is none, but for now I have a workaround. Here is a snippit from History.js:
/**
* History.js Core
* @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
console = window.console||undefined, // Prevent a JSLint complain
document = window.document, // Make sure we are using the correct document
navigator = window.navigator, // Make sure we are using the correct navigator
sessionStorage = window.sessionStorage||false, // sessionStorage
setTimeout = window.setTimeout,
clearTimeout = window.clearTimeout,
setInterval = window.setInterval,
clearInterval = window.clearInterval,
JSON = window.JSON,
alert = window.alert,
History = window.History = window.History||{}, // Public History Object
history = window.history; // Old History Object
// MooTools Compatibility
JSON.stringify = JSON.stringify||JSON.encode;
JSON.parse = JSON.parse||JSON.decode;
If window.JSON is undefined, referencing window.JSON.stringify will simply cause an error.
回答1:
The following works for me in IE7 with no errors:
<html>
<head>
<title>Testing</title>
<script type="text/javascript" src="https://ajax.googleapis.com/ajax/libs/jquery/1.7.2/jquery.min.js"></script>
<script>
// Tell us whether History is enabled
var alertHistory = function() {
alert(History.enabled ? 'enabled' : 'disabled');
}
var nativeJSON = (typeof JSON === 'object') && (typeof JSON.parse === 'function') && (typeof JSON.stringify === 'function');
if (nativeJSON) {
// Native JSON is present, add History.js
var historyJs = document.createElement('script');
historyJs.type = 'text/javascript';
historyJs.src = 'https://raw.github.com/browserstate/history.js/master/scripts/bundled/html5/jquery.history.js';
historyJs.onload = alertHistory;
document.getElementsByTagName("head")[0].appendChild(historyJs);
} else {
window.History = { enabled: false };
alertHistory();
}
</script>
</head>
<body>
</body>
</html>
回答2:
Here is how I solved it for my case. I wanted to use public CDNs when possible and combine all other JS code for my site into a single include file. Here is what the code looks like.
Page.html
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" >
<head>
<title>Page Title</title>
<!-- JS Files Hosted on CDN(s) -->
<script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1.7.1/jquery.min.js"></script>
<script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jqueryui/1.8.16/jquery-ui.min.js"></script>
<script type="text/javascript" src="http://maps.googleapis.com/maps/api/js?sensor=false"></script>
<!-- Combined Custom JS File -->
<script type="text/javascript" src="js/site.js"></script>
</head>
<body>
</body>
</html>
The single JS include file combines all needed plugins and any custom code needed to run the site.
Site.js
// History.js plugin
var nativeJSON = (typeof JSON === 'object') && (typeof JSON.parse === 'function') && (typeof JSON.stringify === 'function');
if (nativeJSON) {
// contents of browserstate-history.js-e84ad00\scripts\bundled\html5\jquery.history.js
} else {
window.History = { enabled: false };
}
/*
Watermark v3.1.3 (March 22, 2011) plugin for jQuery
http://jquery-watermark.googlecode.com/
Copyright (c) 2009-2011 Todd Northrop
http://www.speednet.biz/
Dual licensed under the MIT or GPL Version 2 licenses.
*/
// contents of jquery.watermark.min.js
// INCLUDE more plugins here
// Custom JS Code here
Chances are I will want to send down at least some custom JS code and this allows me to send it all in 1 payload. From what I understand it is good practice to combine resource files.
EDIT: 2013-06-25
In subsequent projects I have simply included a minified version of json2.js
into my combined JS file. Using Google's Closure Compiler you can get it down to about 3K (before HTTP compression) which seems acceptable.
来源:https://stackoverflow.com/questions/11549661/history-js-for-html5-hack-needed-to-not-break-ie7