PageSourceSearch

https://isecretshop.com/assets/ea2d9160/jquery.pjax.js

js isecretshop.com collected 2026-09-24 09:51:14 UTC 29,506 bytes, 1,025 lines download raw bytes

1/*!
2 * Copyright 2012, Chris Wanstrath
3 * Released under the MIT License
4 * https://github.com/defunkt/jquery-pjax
5 */
6
7(function($){
8
9// When called on a container with a selector, fetches the href with
10// ajax into the container or with the data-pjax attribute on the link
11// itself.
12//
13// Tries to make sure the back button and ctrl+click work the way
14// you'd expect.
15//
16// Exported as $.fn.pjax
17//
18// Accepts a jQuery ajax options object that may include these
19// pjax specific options:
20//
21//
22//               container - String selector for the element where to place the response body.
23//                    push - Whether to pushState the URL. Defaults to true (of course).
24//                 replace - Want to use replaceState instead? That's cool.
25//                 history - Work with window.history. Defaults to true
26//                   cache - Whether to cache pages HTML. Defaults to true
27//            pushRedirect - Whether to add a browser history entry upon redirect. Defaults to false.
28//         replaceRedirect - Whether to replace URL without adding a browser history entry upon redirect. Defaults to true.
29//     skipOuterContainers - When pjax containers are nested and this option is true,
30//                           the closest pjax block will handle the event. Otherwise, the top
31//                           container will handle the event. Defaults to false.
32// ieRedirectCompatibility - Whether to add `X-Ie-Redirect-Compatibility` header for the request on IE.
33//                           See https://github.com/yiisoft/jquery-pjax/issues/37
34//
35// For convenience the second parameter can be either the container or
36// the options object.
37//
38// Returns the jQuery object
39function fnPjax(selector, container, options) {
40  options = optionsFor(container, options)
41  var handler = function(event) {
42      var opts = options
43      if (!opts.container) {
44          opts = $.extend({history: true}, options)
45          opts.container = $(this).attr('data-pjax')
46      }
47      handleClick(event, opts)
48  }
49  $(selector).removeClass('data-pjax');
50  return this
51      .off('click.pjax', selector, handler)
52      .on('click.pjax', selector, handler);
53}
54
55// Public: pjax on click handler
56//
57// Exported as $.pjax.click.
58//
59// event   - "click" jQuery.Event
60// options - pjax options
61//
62// If the click event target has 'data-pjax="0"' attribute, the event is ignored, and no pjax call is made.
63//
64// Examples
65//
66//   $(document).on('click', 'a', $.pjax.click)
67//   // is the same as
68//   $(document).pjax('a')
69//
70// Returns nothing.
71function handleClick(event, container, options) {
72  options = optionsFor(container, options)
73
74  var link = event.currentTarget
75  var $link = $(link)
76
77  // Ignore links with data-pjax="0"
78  if (parseInt($link.data('pjax')) === 0) {
79    return
80  }
81
82  if (link.tagName.toUpperCase() !== 'A')
83    throw "$.fn.pjax or $.pjax.click requires an anchor element"
84
85  // Middle click, cmd click, and ctrl click should open
86  // links in a new tab as normal.
87  if ( event.which > 1 || event.metaKey || event.ctrlKey || event.shiftKey || event.altKey )
88    return
89
90  // Ignore cross origin links
91  if ( location.protocol !== link.protocol || location.hostname !== link.hostname )
92    return
93
94  // Ignore case when a hash is being tacked on the current URL
95  if ( link.href.indexOf('#') > -1 && stripHash(link) == stripHash(location) )
96    return
97
98  // Ignore event with default prevented
99  if (event.isDefaultPrevented())
100    return
101
102  var defaults = {
103    url: link.href,
104    container: $link.attr('data-pjax'),
105    target: link
106  }
107
108  var opts = $.extend({}, defaults, options)
109  var clickEvent = $.Event('pjax:click')
110  $link.trigger(clickEvent, [opts])
111
112  if (!clickEvent.isDefaultPrevented()) {
113    pjax(opts)
114    event.preventDefault()
115    $link.trigger('pjax:clicked', [opts])
116  }
117}
118
119// Public: pjax on form submit handler
120//
121// Exported as $.pjax.submit
122//
123// event   - "click" jQuery.Event
124// options - pjax options
125//
126// Examples
127//
128//  $(document).on('submit', 'form', function(event) {
129//    $.pjax.submit(event, '[data-pjax-container]')
130//  })
131//
132// Returns nothing.
133function handleSubmit(event, container, options) {
134  // check result of previous handlers
135  if (event.result === false)
136    return false;
137
138  options = optionsFor(container, options)
139
140  var form = event.currentTarget
141  var $form = $(form)
142
143  if (form.tagName.toUpperCase() !== 'FORM')
144    throw "$.pjax.submit requires a form element"
145
146  var defaults = {
147    type: ($form.attr('method') || 'GET').toUpperCase(),
148    url: $form.attr('action'),
149    container: $form.attr('data-pjax'),
150    target: form
151  }
152
153  if (defaults.type !== 'GET' && window.FormData !== undefined) {
154    defaults.data = new FormData(form)
155    defaults.processData = false
156    defaults.contentType = false
157  } else {
158    // Can't handle file uploads, exit
159    if ($form.find(':file').length) {
160      return
161    }
162
163    // Fallback to manually serializing the fields
164    defaults.data = $form.serializeArray()
165  }
166
167  pjax($.extend({}, defaults, options))
168
169  event.preventDefault()
170}
171
172// Loads a URL with ajax, puts the response body inside a container,
173// then pushState()'s the loaded URL.
174//
175// Works just like $.ajax in that it accepts a jQuery ajax
176// settings object (with keys like url, type, data, etc).
177//
178// Accepts these extra keys:
179//
180// container - String selector for where to stick the response body.
181//      push - Whether to pushState the URL. Defaults to true (of course).
182//   replace - Want to use replaceState instead? That's cool.
183//
184// Use it just like $.ajax:
185//
186//   var xhr = $.pjax({ url: this.href, container: '#main' })
187//   console.log( xhr.readyState )
188//
189// Returns whatever $.ajax returns.
190function pjax(options) {
191  options = $.extend(true, {}, $.ajaxSettings, pjax.defaults, options)
192
193  if ($.isFunction(options.url)) {
194    options.url = options.url()
195  }
196
197  var hash = parseURL(options.url).hash
198
199  var containerType = $.type(options.container)
200  if (containerType !== 'string') {
201    throw "expected string value for 'container' option; got " + containerType
202  }
203  var context = options.context = $(options.container)
204  if (!context.length) {
205    throw "the container selector '" + options.container + "' did not match anything"
206  }
207
208  // We want the browser to maintain two separate internal caches: one
209  // for pjax'd partial page loads and one for normal page loads.
210  // Without adding this secret parameter, some browsers will often
211  // confuse the two.
212  if (!options.data) options.data = {}
213  if ($.isArray(options.data)) {
214    options.data = $.grep(options.data, function(obj) { return '_pjax' !== obj.name })
215    options.data.push({name: '_pjax', value: options.container})
216  } else {
217    options.data._pjax = options.container
218  }
219
220  function fire(type, args, props) {
221    if (!props) props = {}
222    props.relatedTarget = options.target
223    var event = $.Event(type, props)
224    context.trigger(event, args)
225    return !event.isDefaultPrevented()
226  }
227
228  var timeoutTimer
229
230  options.beforeSend = function(xhr, settings) {
231    // No timeout for non-GET requests
232    // Its not safe to request the resource again with a fallback method.
233    if (settings.type !== 'GET') {
234      settings.timeout = 0
235    }
236
237    xhr.setRequestHeader('X-PJAX', 'true')
238    xhr.setRequestHeader('X-PJAX-Container', options.container)
239
240    if (settings.ieRedirectCompatibility) {
241      var ua = window.navigator.userAgent
242      if (ua.indexOf('MSIE ') > 0 || ua.indexOf('Trident/') > 0 || ua.indexOf('Edge/') > 0) {
243        xhr.setRequestHeader('X-Ie-Redirect-Compatibility', 'true')
244      }
245    }
246
247    if (!fire('pjax:beforeSend', [xhr, settings]))
248      return false
249
250    if (settings.timeout > 0) {
251      timeoutTimer = setTimeout(function() {
252        if (fire('pjax:timeout', [xhr, options]))
253          xhr.abort('timeout')
254      }, settings.timeout)
255
256      // Clear timeout setting so jquerys internal timeout isn't invoked
257      settings.timeout = 0
258    }
259
260    var url = parseURL(settings.url)
261    if (hash) url.hash = hash
262    options.requestUrl = stripInternalParams(url)
263
264    if (typeof (options.async) !== 'undefined' && !options.async) {
265      fire('pjax:start', [xhr, options])
266      fire('pjax:send', [xhr, options])
267    }
268  }
269
270  options.complete = function(xhr, textStatus) {
271    if (timeoutTimer)
272      clearTimeout(timeoutTimer)
273
274    fire('pjax:complete', [xhr, textStatus, options])
275
276    fire('pjax:end', [xhr, options])
277  }
278
279  options.error = function(xhr, textStatus, errorThrown) {
280    var container = extractContainer("", xhr, options)
281    // Check redirect status code
282    var redirect = xhr.status >= 301 && xhr.status <= 303
283    // Do not fire pjax::error in case of redirect
284    var allowed = redirect || fire('pjax:error', [xhr, textStatus, errorThrown, options])
285    if (redirect || options.type == 'GET' && textStatus !== 'abort' && allowed) {
286      if (options.replaceRedirect) {
287        locationReplace(container.url)
288      } else if (options.pushRedirect) {
289        window.history.pushState(null, "", container.url)
290        window.location.replace(container.url)
291      }
292    }
293  }
294
295  options.success = function(data, status, xhr) {
296    var previousState = pjax.state
297
298    // If $.pjax.defaults.version is a function, invoke it first.
299    // Otherwise it can be a static string.
300    var currentVersion = typeof $.pjax.defaults.version === 'function' ?
301      $.pjax.defaults.version() :
302      $.pjax.defaults.version
303
304    var latestVersion = xhr.getResponseHeader('X-PJAX-Version')
305
306    var container = extractContainer(data, xhr, options)
307
308    var url = parseURL(container.url)
309    if (hash) {
310      url.hash = hash
311      container.url = url.href
312    }
313
314    // If there is a layout version mismatch, hard load the new url
315    if (currentVersion && latestVersion && currentVersion !== latestVersion) {
316      locationReplace(container.url)
317      return
318    }
319
320    // If the new response is missing a body, hard load the page
321    if (!container.contents) {
322      locationReplace(container.url)
323      return
324    }
325
326    pjax.state = {
327      id: options.id || uniqueId(),
328      url: container.url,
329      title: container.title,
330      container: options.container,
331      fragment: options.fragment,
332      timeout: options.timeout,
333      cache: options.cache
334    }
335
336    if (options.history && (options.push || options.replace)) {
337      window.history.replaceState(pjax.state, container.title, container.url)
338    }
339
340    // Only blur the focus if the focused element is within the container.
341    var blurFocus = $.contains(context, document.activeElement)
342
343    // Clear out any focused controls before inserting new page contents.
344    if (blurFocus) {
345      try {
346        document.activeElement.blur()
347      } catch (e) { /* ignore */ }
348    }
349
350    if (container.title) document.title = container.title
351
352    fire('pjax:beforeReplace', [container.contents, options], {
353      state: pjax.state,
354      previousState: previousState
355    })
356    context.html(container.contents)
357
358    // FF bug: Won't autofocus fields that are inserted via JS.
359    // This behavior is incorrect. So if theres no current focus, autofocus
360    // the last field.
361    //
362    // http://www.w3.org/html/wg/drafts/html/master/forms.html
363    var autofocusEl = context.find('input[autofocus], textarea[autofocus]').last()[0]
364    if (autofocusEl && document.activeElement !== autofocusEl) {
365      autofocusEl.focus()
366    }
367
368    executeScriptTags(container.scripts, context)
369    loadLinkTags(container.links)
370
371    
372    if (typeof options.scrollTo === 'function') {
373        var scrollTo = options.scrollTo(context, hash)
374    } else {
375        var scrollTo = options.scrollTo
376        // Ensure browser scrolls to the element referenced by the URL anchor
377        if (hash || true === scrollTo) {
378          var name = decodeURIComponent(hash.slice(1))
379          var target = true === scrollTo ? context : (document.getElementById(name) || document.getElementsByName(name)[0])
380          if (target) scrollTo = $(target).offset().top
381        }
382    }
383
384    if (typeof options.scrollOffset === 'function')
385        var scrollOffset = options.scrollOffset(scrollTo)
386    else 
387        var scrollOffset = options.scrollOffset
388    
389    if (typeof scrollTo === 'number') {
390        scrollTo = scrollTo + scrollOffset;
391        if (scrollTo < 0) scrollTo = 0
392        $(window).scrollTop(scrollTo)
393    }
394
395    fire('pjax:success', [data, status, xhr, options])
396  }
397
398
399  // Initialize pjax.state for the initial page load. Assume we're
400  // using the container and options of the link we're loading for the
401  // back button to the initial page. This ensures good back button
402  // behavior.
403  if (!pjax.state) {
404    pjax.state = {
405      id: uniqueId(),
406      url: window.location.href,
407      title: document.title,
408      container: options.container,
409      fragment: options.fragment,
410      timeout: options.timeout,
411      cache: options.cache
412    }
413    if (options.history)
414      window.history.replaceState(pjax.state, document.title)
415  }
416
417  // New request can not override the existing one when option skipOuterContainers is set to true
418  if (pjax.xhr && pjax.xhr.readyState < 4 && pjax.options.skipOuterContainers
418) {
419    return
420  }
421  // Cancel the current request if we're already pjaxing
422  abortXHR(pjax.xhr)
423
424  pjax.options = options
425  var xhr = pjax.xhr = $.ajax(options)
426
427  if (xhr.readyState > 0) {
428    if (options.history && (options.push && !options.replace)) {
429      // Cache current container element before replacing it
430      cachePush(pjax.state.id, [options.container, cloneContents(context)])
431
432      window.history.pushState(null, "", options.requestUrl)
433    }
434
435    if (typeof (options.async) === 'undefined' || options.async) {
436      fire('pjax:start', [xhr, options])
437      fire('pjax:send', [xhr, options])
438    }
439  }
440
441  return pjax.xhr
442}
443
444// Public: Reload current page with pjax.
445//
446// Returns whatever $.pjax returns.
447function pjaxReload(container, options) {
448  var defaults = {
449    url: window.location.href,
450    push: false,
451    replace: true,
452    scrollTo: false
453  }
454
455  return pjax($.extend(defaults, optionsFor(container, options)))
456}
457
458// Internal: Hard replace current state with url.
459//
460// Work for around WebKit
461//   https://bugs.webkit.org/show_bug.cgi?id=93506
462//
463// Returns nothing.
464function locationReplace(url) {
465  if (!pjax.options.history) return
466  window.history.replaceState(null, "", pjax.state.url)
467  window.location.replace(url)
468}
469
470
471var initialPop = true
472var initialURL = window.location.href
473var initialState = window.history.state
474
475// Initialize $.pjax.state if possible
476// Happens when reloading a page and coming forward from a different
477// session history.
478if (initialState && initialState.container) {
479  pjax.state = initialState
480}
481
482// Non-webkit browsers don't fire an initial popstate event
483if ('state' in window.history) {
484  initialPop = false
485}
486
487// popstate handler takes care of the back and forward buttons
488//
489// You probably shouldn't use pjax on pages with other pushState
490// stuff yet.
491function onPjaxPopstate(event) {
492
493  // Hitting back or forward should override any pending PJAX request.
494  if (!initialPop) {
495    abortXHR(pjax.xhr)
496  }
497
498  var previousState = pjax.state
499  var state = event.state
500  var direction
501
502  if (state && state.container) {
503    // When coming forward from a separate history session, will get an
504    // initial pop with a state we are already at. Skip reloading the current
505    // page.
506    if (initialPop && initialURL == state.url) return
507
508    if (previousState) {
509      // If popping back to the same state, just skip.
510      // Could be clicking back from hashchange rather than a pushState.
511      if (previousState.id === state.id) return
512
513      // Since state IDs always increase, we can deduce the navigation direction
514      direction = previousState.id < state.id ? 'forward' : 'back'
515    }
516
517    var cache = cacheMapping[state.id] || []
518    var containerSelector = cache[0] || state.container
519    var container = $(containerSelector), contents = cache[1]
520
521    if (container.length) {
522      var options = {
523        id: state.id,
524        url: state.url,
525        container: containerSelector,
526        push: false,
527        fragment: state.fragment,
528        timeout: state.timeout,
529        cache: state.cache,
530        scrollTo: false
531      }
532
533      if (previousState && options.cache) {
534        // Cache current container before replacement and inform the
535        // cache which direction the history shifted.
536        cachePop(direction, previousState.id, [containerSelector, cloneContents(container)])
537      }
538
539      var popstateEvent = $.Event('pjax:popstate', {
540        state: state,
541        direction: direction
542      })
543      container.trigger(popstateEvent)
544
545      if (contents) {
546        container.trigger('pjax:start', [null, options])
547
548        pjax.state = state
549        if (state.title) document.title = state.title
550        var beforeReplaceEvent = $.Event('pjax:beforeReplace', {
551          state: state,
552          previousState: previousState
553        })
554        container.trigger(beforeReplaceEvent, [contents, options])
555        container.html(contents)
556
557        container.trigger('pjax:end', [null, options])
558      } else {
559        pjax(options)
560      }
561
562      // Force reflow/relayout before the browser tries to restore the
563      // scroll position.
564      container[0].offsetHeight // eslint-disable-line no-unused-expressions
565    } else {
566      locationReplace(location.href)
567    }
568  }
569  initialPop = false
570}
571
572// Fallback version of main pjax function for browsers that don't
573// support pushState.
574//
575// Returns nothing since it retriggers a hard form submission.
576function fallbackPjax(options) {
577  var url = $.isFunction(options.url) ? options.url() : options.url,
578      method = options.type ? options.type.toUpperCase() : 'GET'
579
580  var form = $('<form>', {
581    method: method === 'GET' ? 'GET' : 'POST',
582    action: url,
583    style: 'display:none'
584  })
585
586  if (method !== 'GET' && method !== 'POST') {
587    form.append($('<input>', {
588      type: 'hidden',
589      name: '_method',
590      value: method.toLowerCase()
591    }))
592  }
593
594  var data = options.data
595  if (typeof data === 'string') {
596    $.each(data.split('&'), function(index, value) {
597      var pair = value.split('=')
598      form.append($('<input>', {type: 'hidden', name: pair[0], value: pair[1]}))
599    })
600  } else if ($.isArray(data)) {
601    $.each(data, function(index, value) {
602      form.append($('<input>', {type: 'hidden', name: value.name, value: value.value}))
603    })
604  } else if (typeof data === 'object') {
605    var key
606    for (key in data)
607      form.append($('<input>', {type: 'hidden', name: key, value: data[key]}))
608  }
609
610  $(document.body).append(form)
611  form.submit()
612}
613
614// Internal: Abort an XmlHttpRequest if it hasn't been completed,
615// also removing its event handlers.
616function abortXHR(xhr) {
617  if ( xhr && xhr.readyState < 4) {
618    xhr.onreadystatechange = $.noop
619    xhr.abort()
620  }
621}
622
623// Internal: Generate unique id for state object.
624//
625// Use a timestamp instead of a counter since ids should still be
626// unique across page loads.
627//
628// Returns Number.
629function uniqueId() {
630  return (new Date).getTime()
631}
632
633function cloneContents(container) {
634  var cloned = container.clone()
635  // Unmark script tags as already being eval'd so they can get executed again
636  // when restored from cache. HAXX: Uses jQuery internal method.
637  cloned.find('script').each(function(){
638    if (!this.src) $._data(this, 'globalEval', false)
639  })
640  return cloned.contents()
641}
642
643// Internal: Strip internal query params from parsed URL.
644//
645// Returns sanitized url.href String.
646function stripInternalParams(url) {
647  url.search = url.search.replace(/([?&])(_pjax|_)=[^&]*/g, '').replace(/^&/, '')
648  return url.href.replace(/\?($|#)/, '$1')
649}
650
651// Internal: Parse URL components and returns a Locationish object.
652//
653// url - String URL
654//
655// Returns HTMLAnchorElement that acts like Location.
656function parseURL(url) {
657  var a = document.createElement('a')
658  a.href = url
659  return a
660}
661
662// Internal: Return the `href` component of given URL object with the hash
663// portion removed.
664//
665// location - Location or HTMLAnchorElement
666//
667// Returns String
668function stripHash(location) {
669  return location.href.replace(/#.*/, '')
670}
671
672// Internal: Build options Object for arguments.
673//
674// For convenience the first parameter can be either the container or
675// the options object.
676//
677// Examples
678//
679//   optionsFor('#container')
680//   // => {container: '#container'}
681//
682//   optionsFor('#container', {push: true})
683//   // => {container: '#container', push: true}
684//
685//   optionsFor({container: '#container', push: true})
686//   // => {container: '#container', push: true}
687//
688// Returns options Object.
689function optionsFor(container, options) {
690  if (container && options) {
691    options = $.extend({}, options)
692    options.container = container
693    return options
694  } else if ($.isPlainObject(container)) {
695    return container
696  } else {
697    return {container: container}
698  }
699}
700
701// Internal: Filter and find all elements matching the selector.
702//
703// Where $.fn.find only matches descendants, findAll will test all the
704// top level elements in the jQuery object as well.
705//
706// elems    - jQuery object of Elements
707// selector - String selector to match
708//
709// Returns a jQuery object.
710function findAll(elems, selector) {
711  return elems.filter(selector).add(elems.find(selector))
712}
713
714function parseHTML(html) {
715  return $.parseHTML(html, document, true)
716}
717
718// Internal: Extracts container and metadata from response.
719//
720// 1. Extracts X-PJAX-URL header if set
721// 2. Extracts inline <title> tags
722// 3. Builds response Element and extracts fragment if set
723//
724// data    - String response data
725// xhr     - XHR response
726// options - pjax options Object
727//
728// Returns an Object with url, title, and contents keys.
729function extractContainer(data, xhr, options) {
730  var obj = {}, fullDocument = /<html/i.test(data)
731
732  // Prefer X-PJAX-URL header if it was set, otherwise fallback to
733  // using the original requested url.
734  var serverUrl = xhr.getResponseHeader('X-PJAX-URL')
735  obj.url = serverUrl ? stripInternalParams(parseURL(serverUrl)) : options.requestUrl
736
737  var $head, $body
738  // Attempt to parse response html into elements
739  if (fullDocument) {
740    $body = $(parseHTML(data.match(/<body[^>]*>([\s\S.]*)<\/body>/i)[0]))
741    var head = data.match(/<head[^>]*>([\s\S.]*)<\/head>/i)
742    $head = head != null ? $(parseHTML(head[0])) : $body
743  } else {
744    $head = $body = $(parseHTML(data))
745  }
746
747  // If response data is empty, return fast
748  if ($body.length === 0)
749    return obj
750
751  // If there's a <title> tag in the header, use it as
752  // the page's title.
753  obj.title = findAll($head, 'title').last().text()
754
755  if (options.fragment) {
756    var $fragment = $body
757    // If they specified a fragment, look for it in the response
758    // and pull it out.
759    if (options.fragment !== 'body') {
760      $fragment = findAll($fragment, options.fragment).first()
761    }
762
763    if ($fragment.length) {
764      obj.contents = options.fragment === 'body' ? $fragment : $fragment.contents()
765
766      // If there's no title, look for data-title and title attributes
767      // on the fragment
768      if (!obj.title)
769        obj.title = $fragment.attr('title') || $fragment.data('title')
770    }
771
772  } else if (!fullDocument) {
773    obj.contents = $body
774  }
775
776  // Clean up any <title> tags
777  if (obj.contents) {
778    // Remove any parent title elements
779    obj.contents = obj.contents.not(function() { return $(this).is('title') })
780
781    // Then scrub any titles from their descendants
782    obj.contents.find('title').remove()
783
784    // Gather all script elements
785    obj.scripts = findAll(obj.contents, 'script').remove()
786    obj.contents = obj.contents.not(obj.scripts)
787
788    // Gather all link[href] elements
789    obj.links = findAll(obj.contents, 'link[href]').remove()
790    obj.contents = obj.contents.not(obj.links)
791  }
792
793  // Trim any whitespace off the title
794  if (obj.title) obj.title = $.trim(obj.title)
795
796  return obj
797}
798
799// Load an execute scripts using standard script request.
800//
801// Avoids jQuery's traditional $.getScript which does a XHR request and
802// globalEval.
803//
804// scripts - jQuery object of script Elements
805// context - jQuery object whose context is `document` and has a selector
806//
807// Returns nothing.
808function executeScriptTags(scripts, context) {
809  if (!scripts) return
810
811  var existingScripts = $('script[src]')
812
813  var cb = function (next) {
814    var src = this.src
815    var matchedScripts = existingScripts.filter(function () {
816      return this.src === src
817    })
818
819    if (matchedScripts.length) {
820      next()
821      return
822    }
823
824    if (src) {
825      $.getScript(src).done(next).fail(next)
826      document.head.appendChild(this)
827    } else {
828      context.append(this)
829      next()
830    }
831  }
832
833  var i = 0
834  var next = function () {
835    if (i >= scripts.length) {
836      return
837    }
838    var script = scripts[i]
839    i++
840    cb.call(script, next)
841  }
842  next()
843}
844
845// Load an links using standard request.
846//
847// links - jQuery object of link Elements
848//
849// Returns nothing.
850function loadLinkTags(links) {
851    if (!links) return
852
853    var existingLinks = $('link[href]')
854
855    links.each(function() {
856        var href = this.href,
857            alreadyLoadedLinks = existingLinks.filter(function() {
858                return this.href === href
859            })
860        if (alreadyLoadedLinks.length) return
861
862        document.head.appendChild(this)
863    })
864}
865
866// Internal: History DOM caching class.
867var cacheMapping      = {}
868var cacheForwardStack = []
869var cacheBackStack    = []
870
871// Push previous state id and container contents into the history
872// cache. Should be called in conjunction with `pushState` to save the
873// previous container contents.
874//
875// id    - State ID Number
876// value - DOM Element to cache
877//
878// Returns nothing.
879function cachePush(id, value) {
880  if (!pjax.options.cache) {
881    return
882  }
883  cacheMapping[id] = value
884  cacheBackStack.push(id)
885
886  // Remove all entries in forward history stack after pushing a new page.
887  trimCacheStack(cacheForwardStack, 0)
888
889  // Trim back history stack to max cache length.
890  trimCacheStack(cacheBackStack, pjax.defaults.maxCacheLength)
891}
892
893// Shifts cache from directional history cache. Should be
894// called on `popstate` with the previous state id and container
895// contents.
896//
897// direction - "forward" or "back" String
898// id        - State ID Number
899// value     - DOM Element to cache
900//
901// Returns nothing.
902function cachePop(direction, id, value) {
903  var pushStack, popStack
904  cacheMapping[id] = value
905
906  if (direction === 'forward') {
907    pushStack = cacheBackStack
908    popStack  = cacheForwardStack
909  } else {
910    pushStack = cacheForwardStack
911    popStack  = cacheBackStack
912  }
913
914  pushStack.push(id)
915  id = popStack.pop()
916  if (id) delete cacheMapping[id]
917
918  // Trim whichever stack we just pushed to to max cache length.
919  trimCacheStack(pushStack, pjax.defaults.maxCacheLength)
920}
921
922// Trim a cache stack (either cacheBackStack or cacheForwardStack) to be no
923// longer than the specified length, deleting cached DOM elements as necessary.
924//
925// stack  - Array of state IDs
926// length - Maximum length to trim to
927//
928// Returns nothing.
929function trimCacheStack(stack, length) {
930  while (stack.length > length)
931    delete cacheMapping[stack.shift()]
932}
933
934// Public: Find version identifier for the initial page load.
935//
936// Returns String version or undefined.
937function findVersion() {
938  return $('meta').filter(function() {
939    var name = $(this).attr('http-equiv')
940    return name && name.toUpperCase() === 'X-PJAX-VERSION'
941  }).attr('content')
942}
943
944// Install pjax functions on $.pjax to enable pushState behavior.
945//
946// Does nothing if already enabled.
947//
948// Examples
949//
950//     $.pjax.enable()
951//
952// Returns nothing.
953function enable() {
954  $.fn.pjax = fnPjax
955  $.pjax = pjax
956  $.pjax.enable = $.noop
957  $.pjax.disable = disable
958  $.pjax.click = handleClick
959  $.pjax.submit = handleSubmit
960  $.pjax.reload = pjaxReload
961  $.pjax.defaults = {
962	history: true,
963	cache: true,
964    timeout: 650,
965    push: true,
966    replace: false,
967    type: 'GET',
968    dataType: 'html',
969    scrollTo: 0,
970    scrollOffset: 0,
971    maxCacheLength: 20,
972    version: findVersion,
973    pushRedirect: false,
974    replaceRedirect: true,
975    skipOuterContainers: false,
976    ieRedirectCompatibility: true
977  }
978  $(window).on('popstate.pjax', onPjaxPopstate)
979}
980
981// Disable pushState behavior.
982//
983// This is the case when a browser doesn't support pushState. It is
984// sometimes useful to disable pushState for debugging on a modern
985// browser.
986//
987// Examples
988//
989//     $.pjax.disable()
990//
991// Returns nothing.
992function disable() {
993  $.fn.pjax = function() { return this }
994  $.pjax = fallbackPjax
995  $.pjax.enable = enable
996  $.pjax.disable = $.noop
997  $.pjax.click = $.noop
998  $.pjax.submit = $.noop
999  $.pjax.reload = function() { window.location.reload() }
1000
1001  $(window).off('popstate.pjax', onPjaxPopstate)
1002}
1003
1004
1005// Add the state property to jQuery's event object so we can use it in
1006// $(window).bind('popstate')
1007if ($.event.props && $.inArray('state', $.event.props) < 0) {
1008  $.event.props.push('state')
1009} else if (!('state' in $.Event.prototype)) {
1010  $.event.addProp('state')
1011}
1012
1013// Is pjax supported by this browser?
1014$.support.pjax =
1015  window.history && window.history.pushState && window.history.replaceState &&
1016  // pushState isn't reliable on iOS until 5.
1017  !navigator.userAgent.match(/((iPod|iPhone|iPad).+\bOS\s+[1-4]\D|WebApps\/.+CFNetwork)/)
1018
1019if ($.support.pjax) {
1020  enable()
1021} else {
1022  disable()
1023}
1024
1025})(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.