/** * jQuery hashchange 1.0.0 * * (based on jquery.history) * * modified by net.itcast.cn,make it easy to use * * Copyright (c) 2008 Chris Leishman (chrisleishman.com) * Dual licensed under the MIT (MIT-LICENSE.txt) * and GPL (GPL-LICENSE.txt) licenses. */ (function($) { $.fn.extend({ hashchange: function(callback) { this.bind('hashchange', callback); if (location.hash)//if location.hash is not empty,fire the event when load,make ajax easy { callback(); } }, openOnClick: function(href) { if (href === undefined || href.length == 0) href = '#'; return this.click(function(ev) { if (href && href.charAt(0) == '#') { // execute load in separate call stack window.setTimeout(function() { $.locationHash(href) }, 0); } else { window.location(href); } ev.stopPropagation(); return false; }); } }); // IE 8 introduces the hashchange event natively - so nothing more to do /* if ($.browser.msie && document.documentMode && document.documentMode >= 8) { $.extend({ locationHash: function(hash) { if (!hash)//get hash value { if (location.hash.charAt(0) == '#') { return location.hash.substr(1, location.hash.length-1); } return location.hash; } if (!hash) hash = '#'; else if (hash.charAt(0) != '#') hash = '#' + hash; location.hash = hash; } }); return; }*/ var curHash; // hidden iframe for IE (earlier than 8) var iframe; $.extend({ locationHash: function(hash) { if (!hash)//get hash value { if (location.hash.charAt(0) == '#') { return location.hash.substr(1, location.hash.length - 1); } return location.hash; } if (curHash === undefined) return; if (!hash) hash = '#'; else if (hash.charAt(0) != '#') hash = '#' + hash; location.hash = hash; if (curHash == hash) return; curHash = hash; if ($.browser.msie) updateIEFrame(hash); $.event.trigger('hashchange'); } }); $(document).ready(function() { curHash = location.hash; /* if ($.browser.msie) { // stop the callback firing twice during init if no hash present if (curHash == '') curHash = '#'; // add hidden iframe for IE iframe = $('<iframe />').hide().get(0); $('body').prepend(iframe); updateIEFrame(location.hash); setInterval(checkHashIE, 100); } else { setInterval(checkHash, 100); }*/ }); $(window).unload(function() { iframe = null }); function checkHash() { var hash = location.hash; if (hash != curHash) { curHash = hash; $.event.trigger('hashchange'); } } /* if ($.browser.msie) { // Attach a live handler for any anchor links $('a[href^=#]').live('click', function() { var hash = $(this).attr('href'); // Don't intercept the click if there is an existing anchor on the page // that matches this hash if ($(hash).length == 0 && $('a[name=' + hash.slice(1) + ']').length == 0) { $.locationHash(hash); return false; } }); }*/ function checkHashIE() { // On IE, check for location.hash of iframe var idoc = iframe.contentDocument || iframe.contentWindow.document; var hash = idoc.location.hash; if (hash == '') hash = '#'; if (hash != curHash) { if (location.hash != hash) location.hash = hash; curHash = hash; $.event.trigger('hashchange'); } } function updateIEFrame(hash) { if (hash == '#') hash = ''; var idoc = iframe.contentWindow.document; idoc.open(); idoc.close(); if (idoc.location.hash != hash) idoc.location.hash = hash; } })(jQuery);
JQuery HashChange插件修改
在做AJAX的时候前进、后退按钮的处理是比较重要的,可以使用location.hash来解决这个问题。原理这里不再重复,为了方便,我使用了JQuery的HashChange插件,不过这个插件用起来不好:$.locationHash()方法只能设置hash,不能读取hash,不符合JQuery的风格;hashchange事件在用户通过地址栏直接敲“a.htm?#a”这种方式的时候不会触发,必须在ready的时候做处理。
我对这个插件做了修改代码如下:
(function($) {
$.fn.extend({
hashchange: function(callback) {
this.bind('hashchange', callback);
if (location.hash)//if location.hash is not empty,fire the event when load,make ajax easy
{
callback();
}
},
openOnClick: function(href) {
if (href === undefined || href.length == 0)
href = '#';
return this.click(function(ev) {
if (href && href.charAt(0) == '#') {
// execute load in separate call stack
window.setTimeout(function() { $.locationHash(href) }, 0);
} else {
window.location(href);
}
ev.stopPropagation();
return false;
});
}
});
// IE 8 introduces the hashchange event natively - so nothing more to do
if ($.browser.msie && document.documentMode && document.documentMode >= 8) {
$.extend({
locationHash: function(hash) {
if (!hash)//get hash value
{
if (location.hash.charAt(0) == '#') {
return location.hash.substr(1, location.hash.length-1);
}
return location.hash;
}
if (!hash) hash = '#';
else if (hash.charAt(0) != '#') hash = '#' + hash;
location.hash = hash;
}
});
return;
}
var curHash;
// hidden iframe for IE (earlier than 8)
var iframe;
$.extend({
locationHash: function(hash) {
if (!hash)//get hash value
{
if (location.hash.charAt(0) == '#') {
return location.hash.substr(1, location.hash.length - 1);
}
return location.hash;
}
if (curHash === undefined) return;
if (!hash) hash = '#';
else if (hash.charAt(0) != '#') hash = '#' + hash;
location.hash = hash;
if (curHash == hash) return;
curHash = hash;
if ($.browser.msie) updateIEFrame(hash);
$.event.trigger('hashchange');
}
});
$(document).ready(function() {
curHash = location.hash;
if ($.browser.msie) {
// stop the callback firing twice during init if no hash present
if (curHash == '') curHash = '#';
// add hidden iframe for IE
iframe = $('<iframe />').hide().get(0);
$('body').prepend(iframe);
updateIEFrame(location.hash);
setInterval(checkHashIE, 100);
} else {
setInterval(checkHash, 100);
}
});
$(window).unload(function() { iframe = null });
function checkHash() {
var hash = location.hash;
if (hash != curHash) {
curHash = hash;
$.event.trigger('hashchange');
}
}
if ($.browser.msie) {
// Attach a live handler for any anchor links
$('a[href^=#]').live('click', function() {
var hash = $(this).attr('href');
// Don't intercept the click if there is an existing anchor on the page
// that matches this hash
if ($(hash).length == 0 && $('a[name=' + hash.slice(1) + ']').length == 0) {
$.locationHash(hash);
return false;
}
});
}
function checkHashIE() {
// On IE, check for location.hash of iframe
var idoc = iframe.contentDocument || iframe.contentWindow.document;
var hash = idoc.location.hash;
if (hash == '') hash = '#';
if (hash != curHash) {
if (location.hash != hash) location.hash = hash;
curHash = hash;
$.event.trigger('hashchange');
}
}
function updateIEFrame(hash) {
if (hash == '#') hash = '';
var idoc = iframe.contentWindow.document;
idoc.open();
idoc.close();
if (idoc.location.hash != hash) idoc.location.hash = hash;
}
})(jQuery);
$.locationHash()是读取当前页面的hash,$.locationHash("a")是设置当前页面的hash,$(window).hashchange()监听hash改变事件(在第一次绑定事件的时候如果页面有hash值,则立即触发一次事件)。
例子:
$(window).hashchange(function() {
alert($.locationHash());
});
$("input").click(function() {
$.locationHash($(this).val());
});
完整的例子,一个在服务器端进行数字加倍运算:
<script type="text/javascript">
var calcFinish = function(data) {
$("#msg").text(data);
}
$(function() {
$("#btn1").click(function() {
//改变hash
$.locationHash($("#txt1").val());
});
$(window).hashchange(function() {
var i = $.locationHash();//获得hash
if (i) {//发出计算请求
$.post("CalcService.ashx", {"i":i},calcFinish);
}
});
});
</script>
<input type="text" id="txt1" /><span id="msg"></span>
<input type="button" id="btn1" value="calc" />
使用的时候注意前进、后退按钮和地址栏的变化。