/* * jQuery Address Plugin v1.1 * http://www.asual.com/jquery/address/ * * Copyright (c) 2009 Rostislav Hristov * Dual licensed under the MIT and GPL licenses. * http://docs.jquery.com/License * * Date: 2009-12-23 14:27:00 +0200 (Wed, 23 Dec 2009) */ (function ($) { $.address = (function () { var _trigger = function(name) { $(this).trigger( $.extend($.Event(name), (function() { var event = { value: this.value(), path: this.path(), pathNames: this.pathNames(), parameterNames: this.parameterNames(), parameters: {}, queryString: this.queryString() }; for (var i = 0, l = event.parameterNames.length; i < l; i++) event.parameters[event.parameterNames[i]] = this.parameter(event.parameterNames[i]); return event; }).call(this) ) ); }; var _init = function() { _trigger.call($.address, 'init'); }; var _change = function() { _trigger.call($.address, 'change'); }; var _getHash = function() { var index = _l.href.indexOf('#'); return index != -1 ? _ec(_dc(_l.href.substr(index + 1))) : ''; }; var _getWindow = function() { try { return top.document != undefined ? top : window; } catch (e) { return window; } }; var _strictCheck = function(value, force) { if (_opts.strict) value = force ? (value.substr(0, 1) != '/' ? '/' + value : value) : (value == '' ? '/' : value); return value; }; var _ieLocal = function(value, direction) { return (_msie && _l.protocol == 'file:') ? (direction ? _value.replace(/\?/, '%3F') : _value.replace(/%253F/, '?')) : value; }; var _searchScript = function(el) { for (var i = 0, l = el.childNodes.length, s; i < l; i++) { if (el.childNodes[i].src) _url = String(el.childNodes[i].src); if (s = _searchScript(el.childNodes[i])) return s; } }; var _listen = function() { if (!_silent) { var hash = _getHash(); var diff = !(_value == hash); if (_safari && _version < 523) { if (_length != _h.length) { _length = _h.length; if (typeof _stack[_length - 1] != UNDEFINED) _value = _stack[_length - 1]; _update(false); } } else if (_msie && _version < 7 && diff) { _l.reload(); } else if (diff) { _value = hash; _update(false); } } }; var _update = function(internal) { _change(); if (internal) { _trigger.call($.address, 'internalChange'); } else { _trigger.call($.address, 'externalChange'); } _st(_track, 10); }; var _track = function() { var value = (_l.pathname + (/\/$/.test(_l.pathname) ? '' : '/') + _getters.value()).replace(/\/\//, '/').replace(/^\/$/, ''); var fn = window[_opts.tracker]; if (typeof fn == FUNCTION) fn(value); else if (typeof pageTracker != UNDEFINED && typeof pageTracker._trackPageview == FUNCTION) pageTracker._trackPageview(value); else if (typeof urchinTracker == FUNCTION) urchinTracker(value); }; var _htmlWrite = function() { var doc = _frame.contentWindow.document; doc.open(); doc.write('' + _d.title + ''); doc.close(); }; var _load = function() { if (!_loaded) { _loaded = TRUE; if (_msie && _version < 8) { var frameset = _d.getElementsByTagName('frameset')[0]; _frame = _d.createElement((frameset ? '' : 'i') + 'frame'); if (frameset) { frameset.insertAdjacentElement('beforeEnd', _frame); frameset[frameset.cols ? 'cols' : 'rows'] += ',0'; _frame.src = 'javascript:false'; _frame.noResize = true; _frame.frameBorder = _frame.frameSpacing = 0; } else { _frame.src = 'javascript:false'; _frame.style.display = 'none'; _d.body.insertAdjacentElement('afterBegin', _frame); } _st(function() { $(_frame).bind('load', function() { var win = _frame.contentWindow; var src = win.location.href; _value = (typeof win[ID] != UNDEFINED ? win[ID] : ''); if (_value != _getHash()) { _update(false); _l.hash = _ieLocal(_value, TRUE); } }); if (typeof _frame.contentWindow[ID] == UNDEFINED) _htmlWrite(); }, 50); } else if (_safari) { if (_version < 418) { $(_d.body).append('
'); _form = _d.getElementById(ID); } if (typeof _l[ID] == UNDEFINED) _l[ID] = {}; if (typeof _l[ID][_l.pathname] != UNDEFINED) _stack = _l[ID][_l.pathname].split(','); } _st(function() { _init(); _update(false); }, 1); if (_msie && _version >= 8) _d.body.onhashchange = _listen; else _si(_listen, 50); $('a[rel*=address:]').address(); } }; var _getters = { baseURL: function() { var url = _l.href; if (url.indexOf('#') != -1) url = url.substr(0, url.indexOf('#')); if (url.substr(url.length - 1) == '/') url = url.substr(0, url.length - 1); return url; }, strict: function() { return _opts.strict; }, history: function() { return _opts.history; }, tracker: function() { return _opts.tracker; }, title: function() { return _d.title; }, value: function() { if (!_supported) return null; return _dc(_strictCheck(_ieLocal(_value, FALSE), FALSE)); }, path: function() { var value = this.value(); return (value.indexOf('?') != -1) ? value.split('?')[0] : value; }, pathNames: function() { var path = this.path(); var names = path.split('/'); if (path.substr(0, 1) == '/' || path.length == 0) names.splice(0, 1); if (path.substr(path.length - 1, 1) == '/') names.splice(names.length - 1, 1); return names; }, queryString: function() { var value = this.value(); var index = value.indexOf('?'); if (index != -1 && index < value.length) return value.substr(index + 1); }, parameter: function(param) { var value = this.value(); var index = value.indexOf('?'); if (index != -1) { value = value.substr(index + 1); var params = value.split('&'); var p, i = params.length, r = []; while(i--) { p = params[i].split('='); if (p[0] == param) r.push(p[1]); } if (r.length != 0) return r.length != 1 ? r : r[0]; } }, parameterNames: function() { var value = this.value(); var index = value.indexOf('?'); var names = []; if (index != -1) { value = value.substr(index + 1); if (value != '' && value.indexOf('=') != -1) { var params = value.split('&'); var i = 0; while(i < params.length) { names.push(params[i].split('=')[0]); i++; } } } return names; } }; var _setters = { strict: function(strict) { _opts.strict = strict; }, history: function(history) { _opts.history = history; }, tracker: function(tracker) { _opts.tracker = tracker; }, title: function(title) { title = _dc(title); _st(function() { _title = _d.title = title; if (_juststart && _frame && _frame.contentWindow && _frame.contentWindow.document) { _frame.contentWindow.document.title = title; _juststart = FALSE; } if (!_justset && _mozilla) _l.replace(_l.href.indexOf('#') != -1 ? _l.href : _l.href + '#'); _justset = FALSE; }, 50); }, value: function(value) { value = _ec(_dc(_strictCheck(value, TRUE))); if (value == '/') value = ''; if (_value == value) return; _justset = TRUE; _value = value; _silent = TRUE; _update(true); _stack[_h.length] = _value; if (_safari) { if (_opts.history) { _l[ID][_l.pathname] = _stack.toString(); _length = _h.length + 1; if (_version < 418) { if (_l.search == '') { _form.action = '#' + _value; _form.submit(); } } else if (_version < 523 || _value == '') { var evt = _d.createEvent('MouseEvents'); evt.initEvent('click', TRUE, TRUE); var anchor = _d.createElement('a'); anchor.href = '#' + _value; anchor.dispatchEvent(evt); } else { _l.hash = '#' + _value; } } else { _l.replace('#' + _value); } } else if (_value != _getHash()) { if (_opts.history) _l.hash = '#' + _ieLocal(_value, TRUE); else _l.replace('#' + _value); } if ((_msie && _version < 8) && _opts.history) { _st(_htmlWrite, 50); } if (_safari) _st(function(){ _silent = FALSE; }, 1); else _silent = FALSE; } }; var ID = 'jQueryAddress', FUNCTION = 'function', UNDEFINED = 'undefined', TRUE = true, FALSE = false, _browser = $.browser, _version = parseFloat($.browser.version), _mozilla = _browser.mozilla, _msie = _browser.msie, _opera = _browser.opera, _safari = _browser.safari, _supported = FALSE, _t = _getWindow(), _d = _t.document, _h = _t.history, _l = _t.location, _si = setInterval, _st = setTimeout, _dc = decodeURI, _ec = encodeURI, _agent = navigator.userAgent, _frame, _form, _url, _title = _d.title, _length = _h.length, _silent = FALSE, _loaded = FALSE, _justset = TRUE, _juststart = TRUE, _stack = [], _listeners = {}, _value = _getHash(), _api = {}, _opts = {history: TRUE, strict: TRUE}; if (_msie) { _version = parseFloat(_agent.substr(_agent.indexOf('MSIE') + 4)); if (_d.documentMode && _d.documentMode != _version) _version = _d.documentMode != 8 ? 7 : 8; } _supported = (_mozilla && _version >= 1) || (_msie && _version >= 6) || (_opera && _version >= 9.5) || (_safari && _version >= 312); if (_supported) { for (var i = 1; i < _length; i++) _stack.push(''); _stack.push(_getHash()); if (_msie && _l.hash != _getHash()) _l.hash = '#' + _ieLocal(_getHash(), TRUE); if (_opera) history.navigationMode = 'compatible'; _searchScript(document); var _qi = _url.indexOf('?'); if (_url && _qi > -1) { var param, params = _url.substr(_qi + 1).split('&'); for (var i = 0, p; p = params[i]; i++) { param = p.split('='); if (/^(history|strict)$/.test(param[0])) { _opts[param[0]] = (isNaN(param[1]) ? /^(true|yes)$/i.test(param[1]) : (parseInt(param[1]) != 0)); } if (/^tracker$/.test(param[0])) _opts[param[0]] = param[1]; } } $(_load); } else if ((!_supported && _l.href.indexOf('#') != -1) || (_safari && _version < 418 && _l.href.indexOf('#') != -1 && _l.search != '')){ _d.open(); _d.write(''); _d.close(); } else { _track(); } $.each(('init,change,internalChange,externalChange').split(','), function(i, name){ _api[name] = function(data, fn){ $($.address).bind(name, fn || data, fn && data); return this; }; }); $.each(('strict,history,tracker,title,value').split(','), function(i, name){ _api[name] = function(value){ if (typeof value != 'undefined') { if (_supported) _setters[name](value); return $.address; } else { return _getters[name](); } }; }); $.each(('baseURL,path,pathNames,queryString,parameter,parameterNames').split(','), function(i, name){ _api[name] = function(value){ return _getters[name](value); }; }); return _api; })(); $.fn.address = function (fn) { $(this).click(function() { var value = fn ? fn.call(this) : /address:/.test($(this).attr('rel')) ? $(this).attr('rel').split('address:')[1].split(' ')[0] : $(this).attr('href').replace(/^#/, ''); $.address.value(value); return false; }); }; }(jQuery));