1/*! 2 * jQuery hashchange event, v1.4, 2013-11-29 3 * https://github.com/georgekosmidis/jquery-hashchange 4 * 5 * Copyright (c) 2010 "Cowboy" Ben Alman 6 * Dual licensed under the MIT and GPL licenses. 7 * http://benalman.com/about/license/ 8 * 9 * GitHub - https://github.com/georgekosmidis/jquery-hashchange 10 * Source - https://raw.github.com/georgekosmidis/jquery-hashchange/master/jquery.hashchange.js 11 * (Minified) - https://raw.github.com/georgekosmidis/jquery-hashchange/master/jquery.hashchange.min.js 12 * 13 * 14 * Forked to correct bugs created by jQuery 1.9 version 15 * For usage, please visit creator site http://benalman.com/projects/jquery-hashchange-plugin/ 16 */ 17 18(function($,window,undefined){ 19 '$:nomunge'; // Used by YUI compressor. 20 21 // Reused string. 22 var str_hashchange = 'hashchange', 23 24 // Method / object references. 25 doc = document, 26 fake_onhashchange, 27 special = $.event.special, 28 29 // Does the browser support window.onhashchange? Note that IE8 running in 30 // IE7 compatibility mode reports true for 'onhashchange' in window, even 31 // though the event isn't supported, so also test document.documentMode. 32 doc_mode = doc.documentMode, 33 supports_onhashchange = 'on' + str_hashchange in window && ( doc_mode === undefined || doc_mode > 7 ); 34 35 // Get location.hash (or what you'd expect location.hash to be) sans any 36 // leading #. Thanks for making this necessary, Firefox! 37 function get_fragment( url ) { 38 url = url || location.href; 39 return '#' + url.replace( /^[^#]*#?(.*)$/, '$1' ); 40 }; 41 42 // Method: jQuery.fn.hashchange 43 // 44 // Bind a handler to the window.onhashchange event or trigger all bound 45 // window.onhashchange event handlers. This behavior is consistent with 46 // jQuery's built-in event handlers. 47 // 48 // Usage: 49 // 50 // > jQuery(window).hashchange( [ handler ] ); 51 // 52 // Arguments: 53 // 54 // handler - (Function) Optional handler to be bound to the hashchange 55 // event. This is a "shortcut" for the more verbose form: 56 // jQuery(window).bind( 'hashchange', handler ). If handler is omitted, 57 // all bound window.onhashchange event handlers will be triggered. This 58 // is a shortcut for the more verbose 59 // jQuery(window).trigger( 'hashchange' ). These forms are described in 60 // the <hashchange event> section. 61 // 62 // Returns: 63 // 64 // (jQuery) The initial jQuery collection of elements. 65 66 // Allow the "shortcut" format $(elem).hashchange( fn ) for binding and 67 // $(elem).hashchange() for triggering, like jQuery does for built-in events. 68 $.fn[ str_hashchange ] = function( fn ) { 69 return fn ? this.bind( str_hashchange, fn ) : this.trigger( str_hashchange ); 70 }; 71 72 // Property: jQuery.fn.hashchange.delay 73 // 74 // The numeric interval (in milliseconds) at which the <hashchange event> 75 // polling loop executes. Defaults to 50. 76 77 // Property: jQuery.fn.hashchange.domain 78 // 79 // If you're setting document.domain in your JavaScript, and you want hash 80 // history to work in IE6/7, not only must this property be set, but you must 81 // also set document.domain BEFORE jQuery is loaded into the page. This 82 // property is only applicable if you are supporting IE6/7 (or IE8 operating 83 // in "IE7 compatibility" mode). 84 // 85 // In addition, the <jQuery.fn.hashchange.src> property must be set to the 86 // path of the included "document-domain.html" file, which can be renamed or 87 // modified if necessary (note that the document.domain specified must be the 88 // same in both your main JavaScript as well as in this file). 89 // 90 // Usage: 91 // 92 // jQuery.fn.hashchange.domain = document.domain; 93 94 // Property: jQuery.fn.hashchange.src 95 // 96 // If, for some reason, you need to specify an Iframe src file (for example, 97 // when setting document.domain as in <jQuery.fn.hashchange.domain>), you can 98 // do so using this property. Note that when using this property, history 99 // won't be recorded in IE6/7 until the Iframe src file loads. This property 100 // is only applicable if you are supporting IE6/7 (or IE8 operating in "IE7 101 // compatibility" mode). 102 // 103 // Usage: 104 // 105 // jQuery.fn.hashchange.src = 'path/to/file.html'; 106 107 $.fn[ str_hashchange ].delay = 50; 108 /* 109 $.fn[ str_hashchange ].domain = null; 110 $.fn[ str_hashchange ].src = null; 111 */ 112 113 // Event: hashchange event 114 // 115 // Fired when location.hash changes. In browsers that support it, the native 116 // HTML5 window.onhashchange event is used, otherwise a polling loop is 117 // initialized, running every <jQuery.fn.hashchange.delay> milliseconds to 118 // see if the hash has changed. In IE6/7 (and IE8 operating in "IE7 119 // compatibility" mode), a hidden Iframe is created to allow the back button 120 // and hash-based history to work. 121 //
122 // Usage as described in <jQuery.fn.hashchange>: 123 // 124 // > // Bind an event handler. 125 // > jQuery(window).hashchange( function(e) { 126 // > var hash = location.hash; 127 // > ... 128 // > }); 129 // > 130 // > // Manually trigger the event handler. 131 // > jQuery(window).hashchange(); 132 // 133 // A more verbose usage that allows for event namespacing: 134 // 135 // > // Bind an event handler. 136 // > jQuery(window).bind( 'hashchange', function(e) { 137 // > var hash = location.hash; 138 // > ... 139 // > }); 140 // > 141 // > // Manually trigger the event handler. 142 // > jQuery(window).trigger( 'hashchange' ); 143 // 144 // Additional Notes: 145 // 146 // * The polling loop and Iframe are not created until at least one handler 147 // is actually bound to the 'hashchange' event. 148 // * If you need the bound handler(s) to execute immediately, in cases where 149 // a location.hash exists on page load, via bookmark or page refresh for 150 // example, use jQuery(window).hashchange() or the more verbose 151 // jQuery(window).trigger( 'hashchange' ). 152 // * The event can be bound before DOM ready, but since it won't be usable 153 // before then in IE6/7 (due to the necessary Iframe), recommended usage is 154 // to bind it inside a DOM ready handler. 155 156 // Override existing $.event.special.hashchange methods (allowing this plugin 157 // to be defined after jQuery BBQ in BBQ's source code). 158 special[ str_hashchange ] = $.extend( special[ str_hashchange ], { 159 160 // Called only when the first 'hashchange' event is bound to window. 161 setup: function() { 162 // If window.onhashchange is supported natively, there's nothing to do.. 163 if ( supports_onhashchange ) { return false; } 164 165 // Otherwise, we need to create our own. And we don't want to call this 166 // until the user binds to the event, just in case they never do, since it 167 // will create a polling loop and possibly even a hidden Iframe. 168 $( fake_onhashchange.start ); 169 }, 170 171 // Called only when the last 'hashchange' event is unbound from window. 172 teardown: function() { 173 // If window.onhashchange is supported natively, there's nothing to do.. 174 if ( supports_onhashchange ) { return false; } 175 176 // Otherwise, we need to stop ours (if possible). 177 $( fake_onhashchange.stop ); 178 } 179 180 }); 181 182 // fake_onhashchange does all the work of triggering the window.onhashchange 183 // event for browsers that don't natively support it, including creating a
184 // polling loop to watch for hash changes and in IE 6/7 creating a hidden 185 // Iframe to enable back and forward. 186 fake_onhashchange = (function(){ 187 var self = {}, 188 timeout_id, 189 190 // Remember the initial hash so it doesn't get triggered immediately. 191 last_hash = get_fragment(), 192 193 fn_retval = function(val){ return val; }, 194 history_set = fn_retval, 195 history_get = fn_retval; 196 197 // Start the polling loop. 198 self.start = function() { 199 timeout_id || poll(); 200 }; 201 202 // Stop the polling loop. 203 self.stop = function() { 204 timeout_id && clearTimeout( timeout_id ); 205 timeout_id = undefined; 206 }; 207 208 // This polling loop checks every $.fn.hashchange.delay milliseconds to see 209 // if location.hash has changed, and triggers the 'hashchange' event on 210 // window when necessary. 211 function poll() { 212 var hash = get_fragment(), 213 history_hash = history_get( last_hash ); 214 215 if ( hash !== last_hash ) { 216 history_set( last_hash = hash, history_hash ); 217 218 $(window).trigger( str_hashchange ); 219 220 } else if ( history_hash !== last_hash ) { 221 location.href = location.href.replace( /#.*/, '' ) + history_hash; 222 } 223 224 timeout_id = setTimeout( poll, $.fn[ str_hashchange ].delay ); 225 }; 226 227 // vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv 228 // vvvvvvvvvvvvvvvvvvv REMOVE IF NOT SUPPORTING IE6/7/8 vvvvvvvvvvvvvvvvvvv 229 // vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv 230 var ie = (function(){ 231 232 var undef, 233 v = 3, 234 div = document.createElement('div'), 235 all = div.getElementsByTagName('i'); 236 237 while ( 238 div.innerHTML = '<!--[if gt IE ' + (++v) + ']><i></i><![endif]-->', 239 all[0] 240 ); 241 242 return v > 4 ? v : undef; 243 244 }()); 245 ie && !supports_onhashchange && (function(){ 246 // Not only do IE6/7 need the "magical" Iframe treatment, but so does IE8 247 // when running in "IE7 compatibility" mode. 248 249 var iframe, 250 iframe_src; 251 252 // When the event is bound and polling starts in IE 6/7, create a hidden 253 // Iframe for history handling. 254 self.start = function(){ 255 if ( !iframe ) { 256 iframe_src = $.fn[ str_hashchange ].src; 257 iframe_src = iframe_src && iframe_src + get_fragment(); 258 259 // Create hidden Iframe. Attempt to make Iframe as hidden as possible 260 // by using techniques from http://www.paciellogroup.com/blog/?p=604. 261 iframe = $('<iframe tabindex="-1" title="empty"/>').hide() 262 263 // When Iframe has completely loaded, initialize the history and 264 // start polling. 265 .one( 'load', function(){ 266 iframe_src || history_set( get_fragment() ); 267 poll(); 268 }) 269 270 // Load Iframe src if specified, otherwise nothing. 271 .attr( 'src', iframe_src || 'javascript:0' ) 272 273 // Append Iframe after the end of the body to prevent unnecessary 274 // initial page scrolling (yes, this works). 275 .insertAfter( 'body' )[0].contentWindow; 276 277 // Whenever `document.title` changes, update the Iframe's title to 278 // prettify the back/next history menu entries. Since IE sometimes 279 // errors with "Unspecified error" the very first time this is set 280 // (yes, very useful) wrap this with a try/catch block. 281 doc.onpropertychange = function(){ 282 try { 283 if ( event.propertyName === 'title' ) { 284 iframe.document.title = doc.title; 285 } 286 } catch(e) {} 287 }; 288 289 } 290 }; 291 292 // Override the "stop" method since an IE6/7 Iframe was created. Even 293 // if there are no longer any bound event handlers, the polling loop 294 // is still necessary for back/next to work at all! 295 self.stop = fn_retval; 296 297 // Get history by looking at the hidden Iframe's location.hash. 298 history_get = function() { 299 return get_fragment( iframe.location.href ); 300 }; 301 302 // Set a new history item by opening and then closing the Iframe 303 // document, *then* setting its location.hash. If document.domain has 304 // been set, update that as well. 305 history_set = function( hash, history_hash ) { 306 var iframe_doc = iframe.document, 307 domain = $.fn[ str_hashchange ].domain; 308 309 if ( hash !== history_hash ) { 310 // Update Iframe with any initial `document.title` that might be set. 311 iframe_doc.title = doc.title; 312 313 // Opening the Iframe's document after it has been closed is what 314 // actually adds a history entry. 315 iframe_doc.open(); 316 317 // Set document.domain for the Iframe document as well, if necessary. 318 domain && iframe_doc.write( '<script>document.domain="' + domain + '"</script>' ); 319 320 iframe_doc.close(); 321 322 // Update the Iframe's hash, for great justice. 323 iframe.location.hash = hash; 324 } 325 }; 326 327 })(); 328 // ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ 329 // ^^^^^^^^^^^^^^^^^^^ REMOVE IF NOT SUPPORTING IE6/7/8 ^^^^^^^^^^^^^^^^^^^ 330 // ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ 331 332 return self; 333 })(); 334 335})(jQuery,this);
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.