1/* 2 * jQuery history plugin 3 * 4 * The MIT License 5 * 6 * Copyright (c) 2006-2009 Taku Sano (Mikage Sawatari) 7 * Copyright (c) 2010 Takayuki Miwa 8 * 9 * Permission is hereby granted, free of charge, to any person obtaining a copy 10 * of this software and associated documentation files (the "Software"), to deal 11 * in the Software without restriction, including without limitation the rights 12 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 13 * copies of the Software, and to permit persons to whom the Software is 14 * furnished to do so, subject to the following conditions: 15 * 16 * The above copyright notice and this permission notice shall be included in 17 * all copies or substantial portions of the Software. 18 * 19 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 20 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 21 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 22 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 23 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 24 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 25 * THE SOFTWARE. 26 */ 27 28(function($) { 29 var locationWrapper = { 30 put: function(hash, win) { 31 (win || window).location.hash = this.encoder(hash); 32 }, 33 get: function(win) { 34 var hash = ((win || window).location.hash).replace(/^#/, ''); 35 try { 36 return $.browser.mozilla ? hash : decodeURIComponent(hash); 37 } 38 catch (error) { 39 return hash; 40 } 41 }, 42 encoder: encodeURIComponent 43 }; 44 45 var iframeWrapper = { 46 id: "__jQuery_history", 47 init: function() { 48 var html = '<iframe id="'+ this.id +'" style="display:none" src="javascript:false;" />'; 49 $("body").prepend(html); 50 return this; 51 }, 52 _document: function() { 53 return $("#"+ this.id)[0].contentWindow.document; 54 }, 55 put: function(hash) { 56 var doc = this._document(); 57 doc.open(); 58 doc.close(); 59 locationWrapper.put(hash, doc); 60 }, 61 get: function() { 62 return locationWrapper.get(this._document()); 63 } 64 }; 65 66 function initObjects(options) { 67 options = $.extend({ 68 unescape: false 69 }, options || {}); 70 71 locationWrapper.encoder = encoder(options.unescape); 72 73 function encoder(unescape_) { 74 if(unescape_ === true) { 75 return function(hash){ return hash; }; 76 } 77 if(typeof unescape_ == "string" && 78 (unescape_ = partialDecoder(unescape_.split(""))) 79 || typeof unescape_ == "function") { 80 return function(hash) { return unescape_(encodeURIComponent(hash)); }; 81 } 82 return encodeURIComponent; 83 } 84 85 function partialDecoder(chars) { 86 var re = new RegExp($.map(chars, encodeURIComponent).join("|"), "ig"); 87 return function(enc) { return enc.replace(re, decodeURIComponent); }; 88 } 89 } 90 91 var implementations = {}; 92 93 implementations.base = { 94 callback: undefined, 95 type: undefined, 96 97 check: function() {}, 98 load: function(hash) {}, 99 init: function(callback, options) { 100 initObjects(options); 101 self.callback = callback; 102 self._options = options; 103 self._init(); 104 }, 105 106 _init: function() {}, 107 _options: {} 108 }; 109 110 implementations.timer = { 111 _appState: undefined, 112 _init: function() { 113 var current_hash = locationWrapper.get(); 114 self._appState = current_hash; 115 self.callback(current_hash); 116 setInterval(self.check, 100); 117 }, 118 check: function() { 119 var current_hash = locationWrapper.get(); 120 if(current_hash != self._appState) { 121 self._appState = current_hash; 122 self.callback(current_hash); 123 } 124 }, 125 load: function(hash) { 126 if(hash != self._appState) {
127 locationWrapper.put(hash); 128 self._appState = hash; 129 self.callback(hash); 130 } 131 } 132 }; 133 134 implementations.iframeTimer = { 135 _appState: undefined, 136 _init: function() { 137 var current_hash = locationWrapper.get(); 138 self._appState = current_hash; 139 iframeWrapper.init().put(current_hash); 140 self.callback(current_hash); 141 setInterval(self.check, 100); 142 }, 143 check: function() { 144 var iframe_hash = iframeWrapper.get(), 145 location_hash = locationWrapper.get(); 146 147 if (location_hash != iframe_hash) { 148 if (location_hash == self._appState) { // user used Back or Forward button 149 self._appState = iframe_hash; 150 locationWrapper.put(iframe_hash); 151 self.callback(iframe_hash); 152 } else { // user loaded new bookmark 153 self._appState = location_hash; 154 iframeWrapper.put(location_hash); 155 self.callback(location_hash); 156 } 157 } 158 }, 159 load: function(hash) { 160 if(hash != self._appState) { 161 locationWrapper.put(hash); 162 iframeWrapper.put(hash); 163 self._appState = hash; 164 self.callback(hash); 165 } 166 } 167 }; 168 169 implementations.hashchangeEvent = { 170 _init: function() { 171 self.callback(locationWrapper.get()); 172 $(window).bind('hashchange', self.check); 173 }, 174 check: function() { 175 self.callback(locationWrapper.get()); 176 }, 177 load: function(hash) { 178 locationWrapper.put(hash); 179 } 180 }; 181 182 var self = $.extend({}, implementations.base); 183 184 if($.browser.msie && ($.browser.version < 8 || document.documentMode < 8)) { 185 self.type = 'iframeTimer'; 186 } else if("onhashchange" in window) { 187 self.type = 'hashchangeEvent'; 188 } else { 189 self.type = 'timer'; 190 } 191 192 $.extend(self, implementations[self.type]); 193 $.history = self; 194})(jQuery);
Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.