Changeset 90326 in spip-zone


Ignore:
Timestamp:
Jun 17, 2015, 5:06:49 PM (4 years ago)
Author:
real3t@…
Message:

Mise à jour de jquery en 1.11.3
Mise à jour de jquery.form dans sa dernière version.
Mise à jour de jquery.html5uploader dans sa dernière version
Modification des js pour ne plus détecter explicitement IE (mais faire du feature detection)

Le handle de redimensionnement fait double emploi avec celui de FireFox?. Est-ce qu'on en a vraiment encore besoin (oui, je vais voir si ça peut faire l'objet d'une feature detection).

L'upload de document marche aussi (mais disparait dès qu'on sort la souris de la zone).

Location:
_plugins_/crayons
Files:
1 added
2 deleted
6 edited

Legend:

Unmodified
Added
Removed
  • _plugins_/crayons/crayons.js.html

    r47958 r90326  
    2626[(#CHEMIN{js/resizehandle.js}|pack_cQuery)]
    2727
    28 [(#CHEMIN{js/jquery.html5uploader.min.js}|pack_cQuery)]
     28[(#CHEMIN{js/jquery.html5uploader.js}|pack_cQuery)]
    2929
    3030[(#CONFIG{crayons}|match{s:11:"yellow_fade";s:2:"on";}|?{' ',''})
  • _plugins_/crayons/js/crayons.js

    r81231 r90326  
    115115                                'ww': (window.innerWidth ? window.innerWidth : (document.documentElement.clientWidth ? document.documentElement.clientWidth : document.body.offsetWidth)),
    116116                                'wh': (window.innerHeight ? window.innerHeight : (document.documentElement.clientHeight ? document.documentElement.clientHeight : document.body.offsetHeight)),
    117                                 'em': $(this).px('fontSize'), // eviter un bug MSIE sur fontSize
     117                                'em': $(this).css('fontSize'), // Bug de jquery resolu : http://bugs.jquery.com/ticket/760
    118118                                'class': me.className,
    119119                                'color': $(this).css('color'),
    120                                 'font-size': $(this).px('fontSize'),
     120                                'font-size': $(this).css('fontSize'),
    121121                                'font-family': $(this).css('fontFamily'),
    122122                                'font-weight': $(this).css('fontWeight'),
     
    167167                                        .find('>.crayon-icones')
    168168                                                .attr('rel','crayon_'+id_crayon);
    169                                         if ($.browser.msie) $(me).css({'zoom':1});
     169                                        // Detection IE sur sa capacite a gerer zoom :
     170                                        // http://www.sitepoint.com/detect-css3-property-browser-support/
     171                                        if (document.createElement("detect").style.zoom === "") {
     172                                                $(me).css({'zoom':1});
     173                                        }
    170174                                        var pos = $(me).offset();
    171175                                        $('<div class="crayon-html" id="crayon_'+id_crayon+'"></div>')
  • _plugins_/crayons/js/jquery.form.js

    r47460 r90326  
    11/*!
    22 * jQuery Form Plugin
    3  * version: 2.73 (03-MAY-2011)
    4  * @requires jQuery v1.3.2 or later
    5  *
     3 * version: 3.51.0-2014.06.20
     4 * Requires jQuery v1.5 or later
     5 * Copyright (c) 2014 M. Alsup
    66 * Examples and documentation at: http://malsup.com/jquery/form/
    7  * Dual licensed under the MIT and GPL licenses:
    8  *   http://www.opensource.org/licenses/mit-license.php
    9  *   http://www.gnu.org/licenses/gpl.html
    10  */
    11 ;(function($) {
     7 * Project repository: https://github.com/malsup/form
     8 * Dual licensed under the MIT and GPL licenses.
     9 * https://github.com/malsup/form#copyright-and-license
     10 */
     11/*global ActiveXObject */
     12
     13// AMD support
     14(function (factory) {
     15    "use strict";
     16    if (typeof define === 'function' && define.amd) {
     17        // using AMD; register as anon module
     18        define(['jquery'], factory);
     19    } else {
     20        // no AMD; invoke directly
     21        factory( (typeof(jQuery) != 'undefined') ? jQuery : window.Zepto );
     22    }
     23}
     24
     25(function($) {
     26"use strict";
    1227
    1328/*
    14         Usage Note:
    15         -----------
    16         Do not use both ajaxSubmit and ajaxForm on the same form.  These
    17         functions are intended to be exclusive.  Use ajaxSubmit if you want
    18         to bind your own submit handler to the form.  For example,
    19 
    20         $(document).ready(function() {
    21                 $('#myForm').bind('submit', function(e) {
    22                         e.preventDefault(); // <-- important
    23                         $(this).ajaxSubmit({
    24                                 target: '#output'
    25                         });
    26                 });
    27         });
    28 
    29         Use ajaxForm when you want the plugin to manage all the event binding
    30         for you.  For example,
    31 
    32         $(document).ready(function() {
    33                 $('#myForm').ajaxForm({
    34                         target: '#output'
    35                 });
    36         });
    37 
    38         When using ajaxForm, the ajaxSubmit function will be invoked for you
    39         at the appropriate time.
     29    Usage Note:
     30    -----------
     31    Do not use both ajaxSubmit and ajaxForm on the same form.  These
     32    functions are mutually exclusive.  Use ajaxSubmit if you want
     33    to bind your own submit handler to the form.  For example,
     34
     35    $(document).ready(function() {
     36        $('#myForm').on('submit', function(e) {
     37            e.preventDefault(); // <-- important
     38            $(this).ajaxSubmit({
     39                target: '#output'
     40            });
     41        });
     42    });
     43
     44    Use ajaxForm when you want the plugin to manage all the event binding
     45    for you.  For example,
     46
     47    $(document).ready(function() {
     48        $('#myForm').ajaxForm({
     49            target: '#output'
     50        });
     51    });
     52
     53    You can also use ajaxForm with delegation (requires jQuery v1.7+), so the
     54    form does not have to exist when you invoke ajaxForm:
     55
     56    $('#myForm').ajaxForm({
     57        delegation: true,
     58        target: '#output'
     59    });
     60
     61    When using ajaxForm, the ajaxSubmit function will be invoked for you
     62    at the appropriate time.
    4063*/
     64
     65/**
     66 * Feature detection
     67 */
     68var feature = {};
     69feature.fileapi = $("<input type='file'/>").get(0).files !== undefined;
     70feature.formdata = window.FormData !== undefined;
     71
     72var hasProp = !!$.fn.prop;
     73
     74// attr2 uses prop when it can but checks the return type for
     75// an expected string.  this accounts for the case where a form
     76// contains inputs with names like "action" or "method"; in those
     77// cases "prop" returns the element
     78$.fn.attr2 = function() {
     79    if ( ! hasProp ) {
     80        return this.attr.apply(this, arguments);
     81    }
     82    var val = this.prop.apply(this, arguments);
     83    if ( ( val && val.jquery ) || typeof val === 'string' ) {
     84        return val;
     85    }
     86    return this.attr.apply(this, arguments);
     87};
    4188
    4289/**
     
    4592 */
    4693$.fn.ajaxSubmit = function(options) {
    47         // fast fail if nothing selected (http://dev.jquery.com/ticket/2752)
    48         if (!this.length) {
    49                 log('ajaxSubmit: skipping submit process - no element selected');
    50                 return this;
    51         }
    52 
    53         if (typeof options == 'function') {
    54                 options = { success: options };
    55         }
    56 
    57         var action = this.attr('action');
    58         var url = (typeof action === 'string') ? $.trim(action) : '';
    59         if (url) {
    60                 // clean url (don't include hash vaue)
    61                 url = (url.match(/^([^#]+)/)||[])[1];
    62         }
    63         url = url || window.location.href || '';
    64 
    65         options = $.extend(true, {
    66                 url:  url,
    67                 success: $.ajaxSettings.success,
    68                 type: this[0].getAttribute('method') || 'GET', // IE7 massage (see issue 57)
    69                 iframeSrc: /^https/i.test(window.location.href || '') ? 'javascript:false' : 'about:blank'
    70         }, options);
    71 
    72         // hook for manipulating the form data before it is extracted;
    73         // convenient for use with rich editors like tinyMCE or FCKEditor
    74         var veto = {};
    75         this.trigger('form-pre-serialize', [this, options, veto]);
    76         if (veto.veto) {
    77                 log('ajaxSubmit: submit vetoed via form-pre-serialize trigger');
    78                 return this;
    79         }
    80 
    81         // provide opportunity to alter form data before it is serialized
    82         if (options.beforeSerialize && options.beforeSerialize(this, options) === false) {
    83                 log('ajaxSubmit: submit aborted via beforeSerialize callback');
    84                 return this;
    85         }
    86 
    87         var n,v,a = this.formToArray(options.semantic);
    88         if (options.data) {
    89                 options.extraData = options.data;
    90                 for (n in options.data) {
    91                         if(options.data[n] instanceof Array) {
    92                                 for (var k in options.data[n]) {
    93                                         a.push( { name: n, value: options.data[n][k] } );
    94                                 }
    95                         }
    96                         else {
    97                                 v = options.data[n];
    98                                 v = $.isFunction(v) ? v() : v; // if value is fn, invoke it
    99                                 a.push( { name: n, value: v } );
    100                         }
    101                 }
    102         }
    103 
    104         // give pre-submit callback an opportunity to abort the submit
    105         if (options.beforeSubmit && options.beforeSubmit(a, this, options) === false) {
    106                 log('ajaxSubmit: submit aborted via beforeSubmit callback');
    107                 return this;
    108         }
    109 
    110         // fire vetoable 'validate' event
    111         this.trigger('form-submit-validate', [a, this, options, veto]);
    112         if (veto.veto) {
    113                 log('ajaxSubmit: submit vetoed via form-submit-validate trigger');
    114                 return this;
    115         }
    116 
    117         var q = $.param(a);
    118 
    119         if (options.type.toUpperCase() == 'GET') {
    120                 options.url += (options.url.indexOf('?') >= 0 ? '&' : '?') + q;
    121                 options.data = null;  // data is null for 'get'
    122         }
    123         else {
    124                 options.data = q; // data is the query string for 'post'
    125         }
    126 
    127         var $form = this, callbacks = [];
    128         if (options.resetForm) {
    129                 callbacks.push(function() { $form.resetForm(); });
    130         }
    131         if (options.clearForm) {
    132                 callbacks.push(function() { $form.clearForm(); });
    133         }
    134 
    135         // perform a load on the target only if dataType is not provided
    136         if (!options.dataType && options.target) {
    137                 var oldSuccess = options.success || function(){};
    138                 callbacks.push(function(data) {
    139                         var fn = options.replaceTarget ? 'replaceWith' : 'html';
    140                         $(options.target)[fn](data).each(oldSuccess, arguments);
    141                 });
    142         }
    143         else if (options.success) {
    144                 callbacks.push(options.success);
    145         }
    146 
    147         options.success = function(data, status, xhr) { // jQuery 1.4+ passes xhr as 3rd arg
    148                 var context = options.context || options;   // jQuery 1.4+ supports scope context
    149                 for (var i=0, max=callbacks.length; i < max; i++) {
    150                         callbacks[i].apply(context, [data, status, xhr || $form, $form]);
    151                 }
    152         };
    153 
    154         // are there files to upload?
    155         var fileInputs = $('input:file', this).length > 0;
    156         var mp = 'multipart/form-data';
    157         var multipart = ($form.attr('enctype') == mp || $form.attr('encoding') == mp);
    158 
    159         // options.iframe allows user to force iframe mode
    160         // 06-NOV-09: now defaulting to iframe mode if file input is detected
    161    if (options.iframe !== false && (fileInputs || options.iframe || multipart)) {
    162            // hack to fix Safari hang (thanks to Tim Molendijk for this)
    163            // see:  http://groups.google.com/group/jquery-dev/browse_thread/thread/36395b7ab510dd5d
    164            if (options.closeKeepAlive) {
    165                    $.get(options.closeKeepAlive, fileUpload);
    166                 }
    167            else {
    168                    fileUpload();
    169                 }
    170    }
    171    else {
    172                 $.ajax(options);
    173    }
    174 
    175         // fire 'notify' event
    176         this.trigger('form-submit-notify', [this, options]);
    177         return this;
    178 
    179 
    180         // private function for handling file uploads (hat tip to YAHOO!)
    181         function fileUpload() {
    182                 var form = $form[0];
    183 
    184                 if ($(':input[name=submit],:input[id=submit]', form).length) {
    185                         // if there is an input with a name or id of 'submit' then we won't be
    186                         // able to invoke the submit fn on the form (at least not x-browser)
    187                         alert('Error: Form elements must not have name or id of "submit".');
    188                         return;
    189                 }
    190                
    191                 var s = $.extend(true, {}, $.ajaxSettings, options);
    192                 s.context = s.context || s;
    193                 var id = 'jqFormIO' + (new Date().getTime()), fn = '_'+id;
    194                 var $io = $('<iframe id="' + id + '" name="' + id + '" src="'+ s.iframeSrc +'" />');
    195                 var io = $io[0];
    196 
    197                 $io.css({ position: 'absolute', top: '-1000px', left: '-1000px' });
    198 
    199                 var xhr = { // mock object
    200                         aborted: 0,
    201                         responseText: null,
    202                         responseXML: null,
    203                         status: 0,
    204                         statusText: 'n/a',
    205                         getAllResponseHeaders: function() {},
    206                         getResponseHeader: function() {},
    207                         setRequestHeader: function() {},
    208                         abort: function(status) {
    209                                 var e = (status === 'timeout' ? 'timeout' : 'aborted');
    210                                 log('aborting upload... ' + e);
    211                                 this.aborted = 1;
    212                                 $io.attr('src', s.iframeSrc); // abort op in progress
    213                                 xhr.error = e;
    214                                 s.error && s.error.call(s.context, xhr, e, e);
    215                                 g && $.event.trigger("ajaxError", [xhr, s, e]);
    216                                 s.complete && s.complete.call(s.context, xhr, e);
    217                         }
    218                 };
    219 
    220                 var g = s.global;
    221                 // trigger ajax global events so that activity/block indicators work like normal
    222                 if (g && ! $.active++) {
    223                         $.event.trigger("ajaxStart");
    224                 }
    225                 if (g) {
    226                         $.event.trigger("ajaxSend", [xhr, s]);
    227                 }
    228 
    229                 if (s.beforeSend && s.beforeSend.call(s.context, xhr, s) === false) {
    230                         if (s.global) {
    231                                 $.active--;
    232                         }
    233                         return;
    234                 }
    235                 if (xhr.aborted) {
    236                         return;
    237                 }
    238 
    239                 var timedOut = 0, timeoutHandle;
    240 
    241                 // add submitting element to data if we know it
    242                 var sub = form.clk;
    243                 if (sub) {
    244                         var n = sub.name;
    245                         if (n && !sub.disabled) {
    246                                 s.extraData = s.extraData || {};
    247                                 s.extraData[n] = sub.value;
    248                                 if (sub.type == "image") {
    249                                         s.extraData[n+'.x'] = form.clk_x;
    250                                         s.extraData[n+'.y'] = form.clk_y;
    251                                 }
    252                         }
    253                 }
    254 
    255                 // take a breath so that pending repaints get some cpu time before the upload starts
    256                 function doSubmit() {
    257                         // make sure form attrs are set
    258                         var t = $form.attr('target'), a = $form.attr('action');
    259 
    260                         // update form attrs in IE friendly way
    261                         form.setAttribute('target',id);
    262                         if (form.getAttribute('method') != 'POST') {
    263                                 form.setAttribute('method', 'POST');
    264                         }
    265                         if (form.getAttribute('action') != s.url) {
    266                                 form.setAttribute('action', s.url);
    267                         }
    268 
    269                         // ie borks in some cases when setting encoding
    270                         if (! s.skipEncodingOverride) {
    271                                 $form.attr({
    272                                         encoding: 'multipart/form-data',
    273                                         enctype:  'multipart/form-data'
    274                                 });
    275                         }
    276 
    277                         // support timout
    278                         if (s.timeout) {
    279                                 timeoutHandle = setTimeout(function() { timedOut = true; cb(true); }, s.timeout);
    280                         }
    281 
    282                         // add "extra" data to form if provided in options
    283                         var extraInputs = [];
    284                         try {
    285                                 if (s.extraData) {
    286                                         for (var n in s.extraData) {
    287                                                 extraInputs.push(
    288                                                         $('<input type="hidden" name="'+n+'" value="'+s.extraData[n]+'" />')
    289                                                                 .appendTo(form)[0]);
    290                                         }
    291                                 }
    292 
    293                                 // add iframe to doc and submit the form
    294                                 $io.appendTo('body');
    295                 io.attachEvent ? io.attachEvent('onload', cb) : io.addEventListener('load', cb, false);
    296                                 form.submit();
    297                         }
    298                         finally {
    299                                 // reset attrs and remove "extra" input elements
    300                                 form.setAttribute('action',a);
    301                                 if(t) {
    302                                         form.setAttribute('target', t);
    303                                 } else {
    304                                         $form.removeAttr('target');
    305                                 }
    306                                 $(extraInputs).remove();
    307                         }
    308                 }
    309 
    310                 if (s.forceSync) {
    311                         doSubmit();
    312                 }
    313                 else {
    314                         setTimeout(doSubmit, 10); // this lets dom updates render
    315                 }
    316        
    317                 var data, doc, domCheckCount = 50, callbackProcessed;
    318 
    319                 function cb(e) {
    320                         if (xhr.aborted || callbackProcessed) {
    321                                 return;
    322                         }
    323                         if (e === true && xhr) {
    324                                 xhr.abort('timeout');
    325                                 return;
    326                         }
    327                        
    328                         var doc = io.contentWindow ? io.contentWindow.document : io.contentDocument ? io.contentDocument : io.document;
    329                         if (!doc || doc.location.href == s.iframeSrc) {
    330                                 // response not received yet
    331                                 if (!timedOut)
    332                                         return;
    333                         }
    334             io.detachEvent ? io.detachEvent('onload', cb) : io.removeEventListener('load', cb, false);
    335 
    336                         var ok = true;
    337                         try {
    338                                 if (timedOut) {
    339                                         throw 'timeout';
    340                                 }
    341 
    342                                 var isXml = s.dataType == 'xml' || doc.XMLDocument || $.isXMLDoc(doc);
    343                                 log('isXml='+isXml);
    344                                 if (!isXml && window.opera && (doc.body == null || doc.body.innerHTML == '')) {
    345                                         if (--domCheckCount) {
    346                                                 // in some browsers (Opera) the iframe DOM is not always traversable when
    347                                                 // the onload callback fires, so we loop a bit to accommodate
    348                                                 log('requeing onLoad callback, DOM not available');
    349                                                 setTimeout(cb, 250);
    350                                                 return;
    351                                         }
    352                                         // let this fall through because server response could be an empty document
    353                                         //log('Could not access iframe DOM after mutiple tries.');
    354                                         //throw 'DOMException: not available';
    355                                 }
    356 
    357                                 //log('response detected');
    358                                 xhr.responseText = doc.body ? doc.body.innerHTML : doc.documentElement ? doc.documentElement.innerHTML : null;
    359                                 xhr.responseXML = doc.XMLDocument ? doc.XMLDocument : doc;
    360                                 if (isXml)
    361                                         s.dataType = 'xml';
    362                                 xhr.getResponseHeader = function(header){
    363                                         var headers = {'content-type': s.dataType};
    364                                         return headers[header];
    365                                 };
    366 
    367                                 var scr = /(json|script|text)/.test(s.dataType);
    368                                 if (scr || s.textarea) {
    369                                         // see if user embedded response in textarea
    370                                         var ta = doc.getElementsByTagName('textarea')[0];
    371                                         if (ta) {
    372                                                 xhr.responseText = ta.value;
    373                                         }
    374                                         else if (scr) {
    375                                                 // account for browsers injecting pre around json response
    376                                                 var pre = doc.getElementsByTagName('pre')[0];
    377                                                 var b = doc.getElementsByTagName('body')[0];
    378                                                 if (pre) {
    379                                                         xhr.responseText = pre.textContent;
    380                                                 }
    381                                                 else if (b) {
    382                                                         xhr.responseText = b.innerHTML;
    383                                                 }
    384                                         }                         
    385                                 }
    386                                 else if (s.dataType == 'xml' && !xhr.responseXML && xhr.responseText != null) {
    387                                         xhr.responseXML = toXml(xhr.responseText);
    388                                 }
    389                                
    390                                 data = httpData(xhr, s.dataType, s);
    391                         }
    392                         catch(e){
    393                                 log('error caught:',e);
    394                                 ok = false;
    395                                 xhr.error = e;
    396                                 s.error && s.error.call(s.context, xhr, 'error', e);
    397                                 g && $.event.trigger("ajaxError", [xhr, s, e]);
    398                         }
    399                        
    400                         if (xhr.aborted) {
    401                                 log('upload aborted');
    402                                 ok = false;
    403                         }
    404 
    405                         // ordering of these callbacks/triggers is odd, but that's how $.ajax does it
    406                         if (ok) {
    407                                 s.success && s.success.call(s.context, data, 'success', xhr);
    408                                 g && $.event.trigger("ajaxSuccess", [xhr, s]);
    409                         }
    410                        
    411                         g && $.event.trigger("ajaxComplete", [xhr, s]);
    412 
    413                         if (g && ! --$.active) {
    414                                 $.event.trigger("ajaxStop");
    415                         }
    416                        
    417                         s.complete && s.complete.call(s.context, xhr, ok ? 'success' : 'error');
    418 
    419                         callbackProcessed = true;
    420                         if (s.timeout)
    421                                 clearTimeout(timeoutHandle);
    422 
    423                         // clean up
    424                         setTimeout(function() {
    425                                 $io.removeData('form-plugin-onload');
    426                                 $io.remove();
    427                                 xhr.responseXML = null;
    428                         }, 100);
    429                 }
    430 
    431                 var toXml = $.parseXML || function(s, doc) { // use parseXML if available (jQuery 1.5+)
    432                         if (window.ActiveXObject) {
    433                                 doc = new ActiveXObject('Microsoft.XMLDOM');
    434                                 doc.async = 'false';
    435                                 doc.loadXML(s);
    436                         }
    437                         else {
    438                                 doc = (new DOMParser()).parseFromString(s, 'text/xml');
    439                         }
    440                         return (doc && doc.documentElement && doc.documentElement.nodeName != 'parsererror') ? doc : null;
    441                 };
    442                 var parseJSON = $.parseJSON || function(s) {
    443                         return window['eval']('(' + s + ')');
    444                 };
    445                
    446                 var httpData = function( xhr, type, s ) { // mostly lifted from jq1.4.4
    447                         var ct = xhr.getResponseHeader('content-type') || '',
    448                                 xml = type === 'xml' || !type && ct.indexOf('xml') >= 0,
    449                                 data = xml ? xhr.responseXML : xhr.responseText;
    450 
    451                         if (xml && data.documentElement.nodeName === 'parsererror') {
    452                                 $.error && $.error('parsererror');
    453                         }
    454                         if (s && s.dataFilter) {
    455                                 data = s.dataFilter(data, type);
    456                         }
    457                         if (typeof data === 'string') {
    458                                 if (type === 'json' || !type && ct.indexOf('json') >= 0) {
    459                                         data = parseJSON(data);
    460                                 } else if (type === "script" || !type && ct.indexOf("javascript") >= 0) {
    461                                         $.globalEval(data);
    462                                 }
    463                         }
    464                         return data;
    465                 };
    466         }
     94    /*jshint scripturl:true */
     95
     96    // fast fail if nothing selected (http://dev.jquery.com/ticket/2752)
     97    if (!this.length) {
     98        log('ajaxSubmit: skipping submit process - no element selected');
     99        return this;
     100    }
     101
     102    var method, action, url, $form = this;
     103
     104    if (typeof options == 'function') {
     105        options = { success: options };
     106    }
     107    else if ( options === undefined ) {
     108        options = {};
     109    }
     110
     111    method = options.type || this.attr2('method');
     112    action = options.url  || this.attr2('action');
     113
     114    url = (typeof action === 'string') ? $.trim(action) : '';
     115    url = url || window.location.href || '';
     116    if (url) {
     117        // clean url (don't include hash vaue)
     118        url = (url.match(/^([^#]+)/)||[])[1];
     119    }
     120
     121    options = $.extend(true, {
     122        url:  url,
     123        success: $.ajaxSettings.success,
     124        type: method || $.ajaxSettings.type,
     125        iframeSrc: /^https/i.test(window.location.href || '') ? 'javascript:false' : 'about:blank'
     126    }, options);
     127
     128    // hook for manipulating the form data before it is extracted;
     129    // convenient for use with rich editors like tinyMCE or FCKEditor
     130    var veto = {};
     131    this.trigger('form-pre-serialize', [this, options, veto]);
     132    if (veto.veto) {
     133        log('ajaxSubmit: submit vetoed via form-pre-serialize trigger');
     134        return this;
     135    }
     136
     137    // provide opportunity to alter form data before it is serialized
     138    if (options.beforeSerialize && options.beforeSerialize(this, options) === false) {
     139        log('ajaxSubmit: submit aborted via beforeSerialize callback');
     140        return this;
     141    }
     142
     143    var traditional = options.traditional;
     144    if ( traditional === undefined ) {
     145        traditional = $.ajaxSettings.traditional;
     146    }
     147
     148    var elements = [];
     149    var qx, a = this.formToArray(options.semantic, elements);
     150    if (options.data) {
     151        options.extraData = options.data;
     152        qx = $.param(options.data, traditional);
     153    }
     154
     155    // give pre-submit callback an opportunity to abort the submit
     156    if (options.beforeSubmit && options.beforeSubmit(a, this, options) === false) {
     157        log('ajaxSubmit: submit aborted via beforeSubmit callback');
     158        return this;
     159    }
     160
     161    // fire vetoable 'validate' event
     162    this.trigger('form-submit-validate', [a, this, options, veto]);
     163    if (veto.veto) {
     164        log('ajaxSubmit: submit vetoed via form-submit-validate trigger');
     165        return this;
     166    }
     167
     168    var q = $.param(a, traditional);
     169    if (qx) {
     170        q = ( q ? (q + '&' + qx) : qx );
     171    }
     172    if (options.type.toUpperCase() == 'GET') {
     173        options.url += (options.url.indexOf('?') >= 0 ? '&' : '?') + q;
     174        options.data = null;  // data is null for 'get'
     175    }
     176    else {
     177        options.data = q; // data is the query string for 'post'
     178    }
     179
     180    var callbacks = [];
     181    if (options.resetForm) {
     182        callbacks.push(function() { $form.resetForm(); });
     183    }
     184    if (options.clearForm) {
     185        callbacks.push(function() { $form.clearForm(options.includeHidden); });
     186    }
     187
     188    // perform a load on the target only if dataType is not provided
     189    if (!options.dataType && options.target) {
     190        var oldSuccess = options.success || function(){};
     191        callbacks.push(function(data) {
     192            var fn = options.replaceTarget ? 'replaceWith' : 'html';
     193            $(options.target)[fn](data).each(oldSuccess, arguments);
     194        });
     195    }
     196    else if (options.success) {
     197        callbacks.push(options.success);
     198    }
     199
     200    options.success = function(data, status, xhr) { // jQuery 1.4+ passes xhr as 3rd arg
     201        var context = options.context || this ;    // jQuery 1.4+ supports scope context
     202        for (var i=0, max=callbacks.length; i < max; i++) {
     203            callbacks[i].apply(context, [data, status, xhr || $form, $form]);
     204        }
     205    };
     206
     207    if (options.error) {
     208        var oldError = options.error;
     209        options.error = function(xhr, status, error) {
     210            var context = options.context || this;
     211            oldError.apply(context, [xhr, status, error, $form]);
     212        };
     213    }
     214
     215     if (options.complete) {
     216        var oldComplete = options.complete;
     217        options.complete = function(xhr, status) {
     218            var context = options.context || this;
     219            oldComplete.apply(context, [xhr, status, $form]);
     220        };
     221    }
     222
     223    // are there files to upload?
     224
     225    // [value] (issue #113), also see comment:
     226    // https://github.com/malsup/form/commit/588306aedba1de01388032d5f42a60159eea9228#commitcomment-2180219
     227    var fileInputs = $('input[type=file]:enabled', this).filter(function() { return $(this).val() !== ''; });
     228
     229    var hasFileInputs = fileInputs.length > 0;
     230    var mp = 'multipart/form-data';
     231    var multipart = ($form.attr('enctype') == mp || $form.attr('encoding') == mp);
     232
     233    var fileAPI = feature.fileapi && feature.formdata;
     234    log("fileAPI :" + fileAPI);
     235    var shouldUseFrame = (hasFileInputs || multipart) && !fileAPI;
     236
     237    var jqxhr;
     238
     239    // options.iframe allows user to force iframe mode
     240    // 06-NOV-09: now defaulting to iframe mode if file input is detected
     241    if (options.iframe !== false && (options.iframe || shouldUseFrame)) {
     242        // hack to fix Safari hang (thanks to Tim Molendijk for this)
     243        // see:  http://groups.google.com/group/jquery-dev/browse_thread/thread/36395b7ab510dd5d
     244        if (options.closeKeepAlive) {
     245            $.get(options.closeKeepAlive, function() {
     246                jqxhr = fileUploadIframe(a);
     247            });
     248        }
     249        else {
     250            jqxhr = fileUploadIframe(a);
     251        }
     252    }
     253    else if ((hasFileInputs || multipart) && fileAPI) {
     254        jqxhr = fileUploadXhr(a);
     255    }
     256    else {
     257        jqxhr = $.ajax(options);
     258    }
     259
     260    $form.removeData('jqxhr').data('jqxhr', jqxhr);
     261
     262    // clear element array
     263    for (var k=0; k < elements.length; k++) {
     264        elements[k] = null;
     265    }
     266
     267    // fire 'notify' event
     268    this.trigger('form-submit-notify', [this, options]);
     269    return this;
     270
     271    // utility fn for deep serialization
     272    function deepSerialize(extraData){
     273        var serialized = $.param(extraData, options.traditional).split('&');
     274        var len = serialized.length;
     275        var result = [];
     276        var i, part;
     277        for (i=0; i < len; i++) {
     278            // #252; undo param space replacement
     279            serialized[i] = serialized[i].replace(/\+/g,' ');
     280            part = serialized[i].split('=');
     281            // #278; use array instead of object storage, favoring array serializations
     282            result.push([decodeURIComponent(part[0]), decodeURIComponent(part[1])]);
     283        }
     284        return result;
     285    }
     286
     287     // XMLHttpRequest Level 2 file uploads (big hat tip to francois2metz)
     288    function fileUploadXhr(a) {
     289        var formdata = new FormData();
     290
     291        for (var i=0; i < a.length; i++) {
     292            formdata.append(a[i].name, a[i].value);
     293        }
     294
     295        if (options.extraData) {
     296            var serializedData = deepSerialize(options.extraData);
     297            for (i=0; i < serializedData.length; i++) {
     298                if (serializedData[i]) {
     299                    formdata.append(serializedData[i][0], serializedData[i][1]);
     300                }
     301            }
     302        }
     303
     304        options.data = null;
     305
     306        var s = $.extend(true, {}, $.ajaxSettings, options, {
     307            contentType: false,
     308            processData: false,
     309            cache: false,
     310            type: method || 'POST'
     311        });
     312
     313        if (options.uploadProgress) {
     314            // workaround because jqXHR does not expose upload property
     315            s.xhr = function() {
     316                var xhr = $.ajaxSettings.xhr();
     317                if (xhr.upload) {
     318                    xhr.upload.addEventListener('progress', function(event) {
     319                        var percent = 0;
     320                        var position = event.loaded || event.position; /*event.position is deprecated*/
     321                        var total = event.total;
     322                        if (event.lengthComputable) {
     323                            percent = Math.ceil(position / total * 100);
     324                        }
     325                        options.uploadProgress(event, position, total, percent);
     326                    }, false);
     327                }
     328                return xhr;
     329            };
     330        }
     331
     332        s.data = null;
     333        var beforeSend = s.beforeSend;
     334        s.beforeSend = function(xhr, o) {
     335            //Send FormData() provided by user
     336            if (options.formData) {
     337                o.data = options.formData;
     338            }
     339            else {
     340                o.data = formdata;
     341            }
     342            if(beforeSend) {
     343                beforeSend.call(this, xhr, o);
     344            }
     345        };
     346        return $.ajax(s);
     347    }
     348
     349    // private function for handling file uploads (hat tip to YAHOO!)
     350    function fileUploadIframe(a) {
     351        var form = $form[0], el, i, s, g, id, $io, io, xhr, sub, n, timedOut, timeoutHandle;
     352        var deferred = $.Deferred();
     353
     354        // #341
     355        deferred.abort = function(status) {
     356            xhr.abort(status);
     357        };
     358
     359        if (a) {
     360            // ensure that every serialized input is still enabled
     361            for (i=0; i < elements.length; i++) {
     362                el = $(elements[i]);
     363                if ( hasProp ) {
     364                    el.prop('disabled', false);
     365                }
     366                else {
     367                    el.removeAttr('disabled');
     368                }
     369            }
     370        }
     371
     372        s = $.extend(true, {}, $.ajaxSettings, options);
     373        s.context = s.context || s;
     374        id = 'jqFormIO' + (new Date().getTime());
     375        if (s.iframeTarget) {
     376            $io = $(s.iframeTarget);
     377            n = $io.attr2('name');
     378            if (!n) {
     379                $io.attr2('name', id);
     380            }
     381            else {
     382                id = n;
     383            }
     384        }
     385        else {
     386            $io = $('<iframe name="' + id + '" src="'+ s.iframeSrc +'" />');
     387            $io.css({ position: 'absolute', top: '-1000px', left: '-1000px' });
     388        }
     389        io = $io[0];
     390
     391
     392        xhr = { // mock object
     393            aborted: 0,
     394            responseText: null,
     395            responseXML: null,
     396            status: 0,
     397            statusText: 'n/a',
     398            getAllResponseHeaders: function() {},
     399            getResponseHeader: function() {},
     400            setRequestHeader: function() {},
     401            abort: function(status) {
     402                var e = (status === 'timeout' ? 'timeout' : 'aborted');
     403                log('aborting upload... ' + e);
     404                this.aborted = 1;
     405
     406                try { // #214, #257
     407                    if (io.contentWindow.document.execCommand) {
     408                        io.contentWindow.document.execCommand('Stop');
     409                    }
     410                }
     411                catch(ignore) {}
     412
     413                $io.attr('src', s.iframeSrc); // abort op in progress
     414                xhr.error = e;
     415                if (s.error) {
     416                    s.error.call(s.context, xhr, e, status);
     417                }
     418                if (g) {
     419                    $.event.trigger("ajaxError", [xhr, s, e]);
     420                }
     421                if (s.complete) {
     422                    s.complete.call(s.context, xhr, e);
     423                }
     424            }
     425        };
     426
     427        g = s.global;
     428        // trigger ajax global events so that activity/block indicators work like normal
     429        if (g && 0 === $.active++) {
     430            $.event.trigger("ajaxStart");
     431        }
     432        if (g) {
     433            $.event.trigger("ajaxSend", [xhr, s]);
     434        }
     435
     436        if (s.beforeSend && s.beforeSend.call(s.context, xhr, s) === false) {
     437            if (s.global) {
     438                $.active--;
     439            }
     440            deferred.reject();
     441            return deferred;
     442        }
     443        if (xhr.aborted) {
     444            deferred.reject();
     445            return deferred;
     446        }
     447
     448        // add submitting element to data if we know it
     449        sub = form.clk;
     450        if (sub) {
     451            n = sub.name;
     452            if (n && !sub.disabled) {
     453                s.extraData = s.extraData || {};
     454                s.extraData[n] = sub.value;
     455                if (sub.type == "image") {
     456                    s.extraData[n+'.x'] = form.clk_x;
     457                    s.extraData[n+'.y'] = form.clk_y;
     458                }
     459            }
     460        }
     461
     462        var CLIENT_TIMEOUT_ABORT = 1;
     463        var SERVER_ABORT = 2;
     464               
     465        function getDoc(frame) {
     466            /* it looks like contentWindow or contentDocument do not
     467             * carry the protocol property in ie8, when running under ssl
     468             * frame.document is the only valid response document, since
     469             * the protocol is know but not on the other two objects. strange?
     470             * "Same origin policy" http://en.wikipedia.org/wiki/Same_origin_policy
     471             */
     472           
     473            var doc = null;
     474           
     475            // IE8 cascading access check
     476            try {
     477                if (frame.contentWindow) {
     478                    doc = frame.contentWindow.document;
     479                }
     480            } catch(err) {
     481                // IE8 access denied under ssl & missing protocol
     482                log('cannot get iframe.contentWindow document: ' + err);
     483            }
     484
     485            if (doc) { // successful getting content
     486                return doc;
     487            }
     488
     489            try { // simply checking may throw in ie8 under ssl or mismatched protocol
     490                doc = frame.contentDocument ? frame.contentDocument : frame.document;
     491            } catch(err) {
     492                // last attempt
     493                log('cannot get iframe.contentDocument: ' + err);
     494                doc = frame.document;
     495            }
     496            return doc;
     497        }
     498
     499        // Rails CSRF hack (thanks to Yvan Barthelemy)
     500        var csrf_token = $('meta[name=csrf-token]').attr('content');
     501        var csrf_param = $('meta[name=csrf-param]').attr('content');
     502        if (csrf_param && csrf_token) {
     503            s.extraData = s.extraData || {};
     504            s.extraData[csrf_param] = csrf_token;
     505        }
     506
     507        // take a breath so that pending repaints get some cpu time before the upload starts
     508        function doSubmit() {
     509            // make sure form attrs are set
     510            var t = $form.attr2('target'),
     511                a = $form.attr2('action'),
     512                mp = 'multipart/form-data',
     513                et = $form.attr('enctype') || $form.attr('encoding') || mp;
     514
     515            // update form attrs in IE friendly way
     516            form.setAttribute('target',id);
     517            if (!method || /post/i.test(method) ) {
     518                form.setAttribute('method', 'POST');
     519            }
     520            if (a != s.url) {
     521                form.setAttribute('action', s.url);
     522            }
     523
     524            // ie borks in some cases when setting encoding
     525            if (! s.skipEncodingOverride && (!method || /post/i.test(method))) {
     526                $form.attr({
     527                    encoding: 'multipart/form-data',
     528                    enctype:  'multipart/form-data'
     529                });
     530            }
     531
     532            // support timout
     533            if (s.timeout) {
     534                timeoutHandle = setTimeout(function() { timedOut = true; cb(CLIENT_TIMEOUT_ABORT); }, s.timeout);
     535            }
     536
     537            // look for server aborts
     538            function checkState() {
     539                try {
     540                    var state = getDoc(io).readyState;
     541                    log('state = ' + state);
     542                    if (state && state.toLowerCase() == 'uninitialized') {
     543                        setTimeout(checkState,50);
     544                    }
     545                }
     546                catch(e) {
     547                    log('Server abort: ' , e, ' (', e.name, ')');
     548                    cb(SERVER_ABORT);
     549                    if (timeoutHandle) {
     550                        clearTimeout(timeoutHandle);
     551                    }
     552                    timeoutHandle = undefined;
     553                }
     554            }
     555
     556            // add "extra" data to form if provided in options
     557            var extraInputs = [];
     558            try {
     559                if (s.extraData) {
     560                    for (var n in s.extraData) {
     561                        if (s.extraData.hasOwnProperty(n)) {
     562                           // if using the $.param format that allows for multiple values with the same name
     563                           if($.isPlainObject(s.extraData[n]) && s.extraData[n].hasOwnProperty('name') && s.extraData[n].hasOwnProperty('value')) {
     564                               extraInputs.push(
     565                               $('<input type="hidden" name="'+s.extraData[n].name+'">').val(s.extraData[n].value)
     566                                   .appendTo(form)[0]);
     567                           } else {
     568                               extraInputs.push(
     569                               $('<input type="hidden" name="'+n+'">').val(s.extraData[n])
     570                                   .appendTo(form)[0]);
     571                           }
     572                        }
     573                    }
     574                }
     575
     576                if (!s.iframeTarget) {
     577                    // add iframe to doc and submit the form
     578                    $io.appendTo('body');
     579                }
     580                if (io.attachEvent) {
     581                    io.attachEvent('onload', cb);
     582                }
     583                else {
     584                    io.addEventListener('load', cb, false);
     585                }
     586                setTimeout(checkState,15);
     587
     588                try {
     589                    form.submit();
     590                } catch(err) {
     591                    // just in case form has element with name/id of 'submit'
     592                    var submitFn = document.createElement('form').submit;
     593                    submitFn.apply(form);
     594                }
     595            }
     596            finally {
     597                // reset attrs and remove "extra" input elements
     598                form.setAttribute('action',a);
     599                form.setAttribute('enctype', et); // #380
     600                if(t) {
     601                    form.setAttribute('target', t);
     602                } else {
     603                    $form.removeAttr('target');
     604                }
     605                $(extraInputs).remove();
     606            }
     607        }
     608
     609        if (s.forceSync) {
     610            doSubmit();
     611        }
     612        else {
     613            setTimeout(doSubmit, 10); // this lets dom updates render
     614        }
     615
     616        var data, doc, domCheckCount = 50, callbackProcessed;
     617
     618        function cb(e) {
     619            if (xhr.aborted || callbackProcessed) {
     620                return;
     621            }
     622           
     623            doc = getDoc(io);
     624            if(!doc) {
     625                log('cannot access response document');
     626                e = SERVER_ABORT;
     627            }
     628            if (e === CLIENT_TIMEOUT_ABORT && xhr) {
     629                xhr.abort('timeout');
     630                deferred.reject(xhr, 'timeout');
     631                return;
     632            }
     633            else if (e == SERVER_ABORT && xhr) {
     634                xhr.abort('server abort');
     635                deferred.reject(xhr, 'error', 'server abort');
     636                return;
     637            }
     638
     639            if (!doc || doc.location.href == s.iframeSrc) {
     640                // response not received yet
     641                if (!timedOut) {
     642                    return;
     643                }
     644            }
     645            if (io.detachEvent) {
     646                io.detachEvent('onload', cb);
     647            }
     648            else {
     649                io.removeEventListener('load', cb, false);
     650            }
     651
     652            var status = 'success', errMsg;
     653            try {
     654                if (timedOut) {
     655                    throw 'timeout';
     656                }
     657
     658                var isXml = s.dataType == 'xml' || doc.XMLDocument || $.isXMLDoc(doc);
     659                log('isXml='+isXml);
     660                if (!isXml && window.opera && (doc.body === null || !doc.body.innerHTML)) {
     661                    if (--domCheckCount) {
     662                        // in some browsers (Opera) the iframe DOM is not always traversable when
     663                        // the onload callback fires, so we loop a bit to accommodate
     664                        log('requeing onLoad callback, DOM not available');
     665                        setTimeout(cb, 250);
     666                        return;
     667                    }
     668                    // let this fall through because server response could be an empty document
     669                    //log('Could not access iframe DOM after mutiple tries.');
     670                    //throw 'DOMException: not available';
     671                }
     672
     673                //log('response detected');
     674                var docRoot = doc.body ? doc.body : doc.documentElement;
     675                xhr.responseText = docRoot ? docRoot.innerHTML : null;
     676                xhr.responseXML = doc.XMLDocument ? doc.XMLDocument : doc;
     677                if (isXml) {
     678                    s.dataType = 'xml';
     679                }
     680                xhr.getResponseHeader = function(header){
     681                    var headers = {'content-type': s.dataType};
     682                    return headers[header.toLowerCase()];
     683                };
     684                // support for XHR 'status' & 'statusText' emulation :
     685                if (docRoot) {
     686                    xhr.status = Number( docRoot.getAttribute('status') ) || xhr.status;
     687                    xhr.statusText = docRoot.getAttribute('statusText') || xhr.statusText;
     688                }
     689
     690                var dt = (s.dataType || '').toLowerCase();
     691                var scr = /(json|script|text)/.test(dt);
     692                if (scr || s.textarea) {
     693                    // see if user embedded response in textarea
     694                    var ta = doc.getElementsByTagName('textarea')[0];
     695                    if (ta) {
     696                        xhr.responseText = ta.value;
     697                        // support for XHR 'status' & 'statusText' emulation :
     698                        xhr.status = Number( ta.getAttribute('status') ) || xhr.status;
     699                        xhr.statusText = ta.getAttribute('statusText') || xhr.statusText;
     700                    }
     701                    else if (scr) {
     702                        // account for browsers injecting pre around json response
     703                        var pre = doc.getElementsByTagName('pre')[0];
     704                        var b = doc.getElementsByTagName('body')[0];
     705                        if (pre) {
     706                            xhr.responseText = pre.textContent ? pre.textContent : pre.innerText;
     707                        }
     708                        else if (b) {
     709                            xhr.responseText = b.textContent ? b.textContent : b.innerText;
     710                        }
     711                    }
     712                }
     713                else if (dt == 'xml' && !xhr.responseXML && xhr.responseText) {
     714                    xhr.responseXML = toXml(xhr.responseText);
     715                }
     716
     717                try {
     718                    data = httpData(xhr, dt, s);
     719                }
     720                catch (err) {
     721                    status = 'parsererror';
     722                    xhr.error = errMsg = (err || status);
     723                }
     724            }
     725            catch (err) {
     726                log('error caught: ',err);
     727                status = 'error';
     728                xhr.error = errMsg = (err || status);
     729            }
     730
     731            if (xhr.aborted) {
     732                log('upload aborted');
     733                status = null;
     734            }
     735
     736            if (xhr.status) { // we've set xhr.status
     737                status = (xhr.status >= 200 && xhr.status < 300 || xhr.status === 304) ? 'success' : 'error';
     738            }
     739
     740            // ordering of these callbacks/triggers is odd, but that's how $.ajax does it
     741            if (status === 'success') {
     742                if (s.success) {
     743                    s.success.call(s.context, data, 'success', xhr);
     744                }
     745                deferred.resolve(xhr.responseText, 'success', xhr);
     746                if (g) {
     747                    $.event.trigger("ajaxSuccess", [xhr, s]);
     748                }
     749            }
     750            else if (status) {
     751                if (errMsg === undefined) {
     752                    errMsg = xhr.statusText;
     753                }
     754                if (s.error) {
     755                    s.error.call(s.context, xhr, status, errMsg);
     756                }
     757                deferred.reject(xhr, 'error', errMsg);
     758                if (g) {
     759                    $.event.trigger("ajaxError", [xhr, s, errMsg]);
     760                }
     761            }
     762
     763            if (g) {
     764                $.event.trigger("ajaxComplete", [xhr, s]);
     765            }
     766
     767            if (g && ! --$.active) {
     768                $.event.trigger("ajaxStop");
     769            }
     770
     771            if (s.complete) {
     772                s.complete.call(s.context, xhr, status);
     773            }
     774
     775            callbackProcessed = true;
     776            if (s.timeout) {
     777                clearTimeout(timeoutHandle);
     778            }
     779
     780            // clean up
     781            setTimeout(function() {
     782                if (!s.iframeTarget) {
     783                    $io.remove();
     784                }
     785                else { //adding else to clean up existing iframe response.
     786                    $io.attr('src', s.iframeSrc);
     787                }
     788                xhr.responseXML = null;
     789            }, 100);
     790        }
     791
     792        var toXml = $.parseXML || function(s, doc) { // use parseXML if available (jQuery 1.5+)
     793            if (window.ActiveXObject) {
     794                doc = new ActiveXObject('Microsoft.XMLDOM');
     795                doc.async = 'false';
     796                doc.loadXML(s);
     797            }
     798            else {
     799                doc = (new DOMParser()).parseFromString(s, 'text/xml');
     800            }
     801            return (doc && doc.documentElement && doc.documentElement.nodeName != 'parsererror') ? doc : null;
     802        };
     803        var parseJSON = $.parseJSON || function(s) {
     804            /*jslint evil:true */
     805            return window['eval']('(' + s + ')');
     806        };
     807
     808        var httpData = function( xhr, type, s ) { // mostly lifted from jq1.4.4
     809
     810            var ct = xhr.getResponseHeader('content-type') || '',
     811                xml = type === 'xml' || !type && ct.indexOf('xml') >= 0,
     812                data = xml ? xhr.responseXML : xhr.responseText;
     813
     814            if (xml && data.documentElement.nodeName === 'parsererror') {
     815                if ($.error) {
     816                    $.error('parsererror');
     817                }
     818            }
     819            if (s && s.dataFilter) {
     820                data = s.dataFilter(data, type);
     821            }
     822            if (typeof data === 'string') {
     823                if (type === 'json' || !type && ct.indexOf('json') >= 0) {
     824                    data = parseJSON(data);
     825                } else if (type === "script" || !type && ct.indexOf("javascript") >= 0) {
     826                    $.globalEval(data);
     827                }
     828            }
     829            return data;
     830        };
     831
     832        return deferred;
     833    }
    467834};
    468835
     
    473840 *
    474841 * 1: This method will include coordinates for <input type="image" /> elements (if the element
    475  *      is used to submit the form).
     842 *    is used to submit the form).
    476843 * 2. This method will include the submit element's name/value data (for the element that was
    477  *      used to submit the form).
     844 *    used to submit the form).
    478845 * 3. This method binds the submit() method to the form for you.
    479846 *
     
    483850 */
    484851$.fn.ajaxForm = function(options) {
    485         // in jQuery 1.3+ we can fix mistakes with the ready state
    486         if (this.length === 0) {
    487                 var o = { s: this.selector, c: this.context };
    488                 if (!$.isReady && o.s) {
    489                         log('DOM not ready, queuing ajaxForm');
    490                         $(function() {
    491                                 $(o.s,o.c).ajaxForm(options);
    492                         });
    493                         return this;
    494                 }
    495                 // is your DOM ready?  http://docs.jquery.com/Tutorials:Introducing_$(document).ready()
    496                 log('terminating; zero elements found by selector' + ($.isReady ? '' : ' (DOM not ready)'));
    497                 return this;
    498         }
    499        
    500         return this.ajaxFormUnbind().bind('submit.form-plugin', function(e) {
    501                 if (!e.isDefaultPrevented()) { // if event has been canceled, don't proceed
    502                         e.preventDefault();
    503                         $(this).ajaxSubmit(options);
    504                 }
    505         }).bind('click.form-plugin', function(e) {
    506                 var target = e.target;
    507                 var $el = $(target);
    508                 if (!($el.is(":submit,input:image"))) {
    509                         // is this a child element of the submit el?  (ex: a span within a button)
    510                         var t = $el.closest(':submit');
    511                         if (t.length == 0) {
    512                                 return;
    513                         }
    514                         target = t[0];
    515                 }
    516                 var form = this;
    517                 form.clk = target;
    518                 if (target.type == 'image') {
    519                         if (e.offsetX != undefined) {
    520                                 form.clk_x = e.offsetX;
    521                                 form.clk_y = e.offsetY;
    522                         } else if (typeof $.fn.offset == 'function') { // try to use dimensions plugin
    523                                 var offset = $el.offset();
    524                                 form.clk_x = e.pageX - offset.left;
    525                                 form.clk_y = e.pageY - offset.top;
    526                         } else {
    527                                 form.clk_x = e.pageX - target.offsetLeft;
    528                                 form.clk_y = e.pageY - target.offsetTop;
    529                         }
    530                 }
    531                 // clear form vars
    532                 setTimeout(function() { form.clk = form.clk_x = form.clk_y = null; }, 100);
    533         });
    534 };
     852    options = options || {};
     853    options.delegation = options.delegation && $.isFunction($.fn.on);
     854
     855    // in jQuery 1.3+ we can fix mistakes with the ready state
     856    if (!options.delegation && this.length === 0) {
     857        var o = { s: this.selector, c: this.context };
     858        if (!$.isReady && o.s) {
     859            log('DOM not ready, queuing ajaxForm');
     860            $(function() {
     861                $(o.s,o.c).ajaxForm(options);
     862            });
     863            return this;
     864        }
     865        // is your DOM ready?  http://docs.jquery.com/Tutorials:Introducing_$(document).ready()
     866        log('terminating; zero elements found by selector' + ($.isReady ? '' : ' (DOM not ready)'));
     867        return this;
     868    }
     869
     870    if ( options.delegation ) {
     871        $(document)
     872            .off('submit.form-plugin', this.selector, doAjaxSubmit)
     873            .off('click.form-plugin', this.selector, captureSubmittingElement)
     874            .on('submit.form-plugin', this.selector, options, doAjaxSubmit)
     875            .on('click.form-plugin', this.selector, options, captureSubmittingElement);
     876        return this;
     877    }
     878
     879    return this.ajaxFormUnbind()
     880        .bind('submit.form-plugin', options, doAjaxSubmit)
     881        .bind('click.form-plugin', options, captureSubmittingElement);
     882};
     883
     884// private event handlers
     885function doAjaxSubmit(e) {
     886    /*jshint validthis:true */
     887    var options = e.data;
     888    if (!e.isDefaultPrevented()) { // if event has been canceled, don't proceed
     889        e.preventDefault();
     890        $(e.target).ajaxSubmit(options); // #365
     891    }
     892}
     893
     894function captureSubmittingElement(e) {
     895    /*jshint validthis:true */
     896    var target = e.target;
     897    var $el = $(target);
     898    if (!($el.is("[type=submit],[type=image]"))) {
     899        // is this a child element of the submit el?  (ex: a span within a button)
     900        var t = $el.closest('[type=submit]');
     901        if (t.length === 0) {
     902            return;
     903        }
     904        target = t[0];
     905    }
     906    var form = this;
     907    form.clk = target;
     908    if (target.type == 'image') {
     909        if (e.offsetX !== undefined) {
     910            form.clk_x = e.offsetX;
     911            form.clk_y = e.offsetY;
     912        } else if (typeof $.fn.offset == 'function') {
     913            var offset = $el.offset();
     914            form.clk_x = e.pageX - offset.left;
     915            form.clk_y = e.pageY - offset.top;
     916        } else {
     917            form.clk_x = e.pageX - target.offsetLeft;
     918            form.clk_y = e.pageY - target.offsetTop;
     919        }
     920    }
     921    // clear form vars
     922    setTimeout(function() { form.clk = form.clk_x = form.clk_y = null; }, 100);
     923}
     924
    535925
    536926// ajaxFormUnbind unbinds the event handlers that were bound by ajaxForm
    537927$.fn.ajaxFormUnbind = function() {
    538         return this.unbind('submit.form-plugin click.form-plugin');
     928    return this.unbind('submit.form-plugin click.form-plugin');
    539929};
    540930
     
    550940 * ajaxSubmit() and ajaxForm() methods.
    551941 */
    552 $.fn.formToArray = function(semantic) {
    553         var a = [];
    554         if (this.length === 0) {
    555                 return a;
    556         }
    557 
    558         var form = this[0];
    559         var els = semantic ? form.getElementsByTagName('*') : form.elements;
    560         if (!els) {
    561                 return a;
    562         }
    563        
    564         var i,j,n,v,el,max,jmax;
    565         for(i=0, max=els.length; i < max; i++) {
    566                 el = els[i];
    567                 n = el.name;
    568                 if (!n) {
    569                         continue;
    570                 }
    571 
    572                 if (semantic && form.clk && el.type == "image") {
    573                         // handle image inputs on the fly when semantic == true
    574                         if(!el.disabled && form.clk == el) {
    575                                 a.push({name: n, value: $(el).val()});
    576                                 a.push({name: n+'.x', value: form.clk_x}, {name: n+'.y', value: form.clk_y});
    577                         }
    578                         continue;
    579                 }
    580 
    581                 v = $.fieldValue(el, true);
    582                 if (v && v.constructor == Array) {
    583                         for(j=0, jmax=v.length; j < jmax; j++) {
    584                                 a.push({name: n, value: v[j]});
    585                         }
    586                 }
    587                 else if (v !== null && typeof v != 'undefined') {
    588                         a.push({name: n, value: v});
    589                 }
    590         }
    591 
    592         if (!semantic && form.clk) {
    593                 // input type=='image' are not found in elements array! handle it here
    594                 var $input = $(form.clk), input = $input[0];
    595                 n = input.name;
    596                 if (n && !input.disabled && input.type == 'image') {
    597                         a.push({name: n, value: $input.val()});
    598                         a.push({name: n+'.x', value: form.clk_x}, {name: n+'.y', value: form.clk_y});
    599                 }
    600         }
    601         return a;
     942$.fn.formToArray = function(semantic, elements) {
     943    var a = [];
     944    if (this.length === 0) {
     945        return a;
     946    }
     947
     948    var form = this[0];
     949    var formId = this.attr('id');
     950    var els = semantic ? form.getElementsByTagName('*') : form.elements;
     951    var els2;
     952
     953    if (els && !/MSIE [678]/.test(navigator.userAgent)) { // #390
     954        els = $(els).get();  // convert to standard array
     955    }
     956
     957    // #386; account for inputs outside the form which use the 'form' attribute
     958    if ( formId ) {
     959        els2 = $(':input[form="' + formId + '"]').get(); // hat tip @thet
     960        if ( els2.length ) {
     961            els = (els || []).concat(els2);
     962        }
     963    }
     964
     965    if (!els || !els.length) {
     966        return a;
     967    }
     968
     969    var i,j,n,v,el,max,jmax;
     970    for(i=0, max=els.length; i < max; i++) {
     971        el = els[i];
     972        n = el.name;
     973        if (!n || el.disabled) {
     974            continue;
     975        }
     976
     977        if (semantic && form.clk && el.type == "image") {
     978            // handle image inputs on the fly when semantic == true
     979            if(form.clk == el) {
     980                a.push({name: n, value: $(el).val(), type: el.type });
     981                a.push({name: n+'.x', value: form.clk_x}, {name: n+'.y', value: form.clk_y});
     982            }
     983            continue;
     984        }
     985
     986        v = $.fieldValue(el, true);
     987        if (v && v.constructor == Array) {
     988            if (elements) {
     989                elements.push(el);
     990            }
     991            for(j=0, jmax=v.length; j < jmax; j++) {
     992                a.push({name: n, value: v[j]});
     993            }
     994        }
     995        else if (feature.fileapi && el.type == 'file') {
     996            if (elements) {
     997                elements.push(el);
     998            }
     999            var files = el.files;
     1000            if (files.length) {
     1001                for (j=0; j < files.length; j++) {
     1002                    a.push({name: n, value: files[j], type: el.type});
     1003                }
     1004            }
     1005            else {
     1006                // #180
     1007                a.push({ name: n, value: '', type: el.type });
     1008            }
     1009        }
     1010        else if (v !== null && typeof v != 'undefined') {
     1011            if (elements) {
     1012                elements.push(el);
     1013            }
     1014            a.push({name: n, value: v, type: el.type, required: el.required});
     1015        }
     1016    }
     1017
     1018    if (!semantic && form.clk) {
     1019        // input type=='image' are not found in elements array! handle it here
     1020        var $input = $(form.clk), input = $input[0];
     1021        n = input.name;
     1022        if (n && !input.disabled && input.type == 'image') {
     1023            a.push({name: n, value: $input.val()});
     1024            a.push({name: n+'.x', value: form.clk_x}, {name: n+'.y', value: form.clk_y});
     1025        }
     1026    }
     1027    return a;
    6021028};
    6031029
     
    6071033 */
    6081034$.fn.formSerialize = function(semantic) {
    609         //hand off to jQuery.param for proper encoding
    610         return $.param(this.formToArray(semantic));
     1035    //hand off to jQuery.param for proper encoding
     1036    return $.param(this.formToArray(semantic));
    6111037};
    6121038
     
    6161042 */
    6171043$.fn.fieldSerialize = function(successful) {
    618         var a = [];
    619         this.each(function() {
    620                 var n = this.name;
    621                 if (!n) {
    622                         return;
    623                 }
    624                 var v = $.fieldValue(this, successful);
    625                 if (v && v.constructor == Array) {
    626                         for (var i=0,max=v.length; i < max; i++) {
    627                                 a.push({name: n, value: v[i]});
    628                         }
    629                 }
    630                 else if (v !== null && typeof v != 'undefined') {
    631                         a.push({name: this.name, value: v});
    632                 }
    633         });
    634         //hand off to jQuery.param for proper encoding
    635         return $.param(a);
     1044    var a = [];
     1045    this.each(function() {
     1046        var n = this.name;
     1047        if (!n) {
     1048            return;
     1049        }
     1050        var v = $.fieldValue(this, successful);
     1051        if (v && v.constructor == Array) {
     1052            for (var i=0,max=v.length; i < max; i++) {
     1053                a.push({name: n, value: v[i]});
     1054            }
     1055        }
     1056        else if (v !== null && typeof v != 'undefined') {
     1057            a.push({name: this.name, value: v});
     1058        }
     1059    });
     1060    //hand off to jQuery.param for proper encoding
     1061    return $.param(a);
    6361062};
    6371063
     
    6401066 *
    6411067 *  <form><fieldset>
    642  *        <input name="A" type="text" />
    643  *        <input name="A" type="text" />
    644  *        <input name="B" type="checkbox" value="B1" />
    645  *        <input name="B" type="checkbox" value="B2"/>
    646  *        <input name="C" type="radio" value="C1" />
    647  *        <input name="C" type="radio" value="C2" />
     1068 *      <input name="A" type="text" />
     1069 *      <input name="A" type="text" />
     1070 *      <input name="B" type="checkbox" value="B1" />
     1071 *      <input name="B" type="checkbox" value="B2"/>
     1072 *      <input name="C" type="radio" value="C1" />
     1073 *      <input name="C" type="radio" value="C2" />
    6481074 *  </fieldset></form>
    6491075 *
    650  *  var v = $(':text').fieldValue();
     1076 *  var v = $('input[type=text]').fieldValue();
    6511077 *  // if no values are entered into the text inputs
    6521078 *  v == ['','']
     
    6541080 *  v == ['foo','bar']
    6551081 *
    656  *  var v = $(':checkbox').fieldValue();
     1082 *  var v = $('input[type=checkbox]').fieldValue();
    6571083 *  // if neither checkbox is checked
    6581084 *  v === undefined
     
    6601086 *  v == ['B1', 'B2']
    6611087 *
    662  *  var v = $(':radio').fieldValue();
     1088 *  var v = $('input[type=radio]').fieldValue();
    6631089 *  // if neither radio is checked
    6641090 *  v === undefined
     
    6721098 *
    6731099 * Note: This method *always* returns an array.  If no valid value can be determined the
    674  *         array will be empty, otherwise it will contain one or more values.
     1100 *    array will be empty, otherwise it will contain one or more values.
    6751101 */
    6761102$.fn.fieldValue = function(successful) {
    677         for (var val=[], i=0, max=this.length; i < max; i++) {
    678                 var el = this[i];
    679                 var v = $.fieldValue(el, successful);
    680                 if (v === null || typeof v == 'undefined' || (v.constructor == Array && !v.length)) {
    681                         continue;
    682                 }
    683                 v.constructor == Array ? $.merge(val, v) : val.push(v);
    684         }
    685         return val;
     1103    for (var val=[], i=0, max=this.length; i < max; i++) {
     1104        var el = this[i];
     1105        var v = $.fieldValue(el, successful);
     1106        if (v === null || typeof v == 'undefined' || (v.constructor == Array && !v.length)) {
     1107            continue;
     1108        }
     1109        if (v.constructor == Array) {
     1110            $.merge(val, v);
     1111        }
     1112        else {
     1113            val.push(v);
     1114        }
     1115    }
     1116    return val;
    6861117};
    6871118
     
    6901121 */
    6911122$.fieldValue = function(el, successful) {
    692         var n = el.name, t = el.type, tag = el.tagName.toLowerCase();
    693         if (successful === undefined) {
    694                 successful = true;
    695         }
    696 
    697         if (successful && (!n || el.disabled || t == 'reset' || t == 'button' ||
    698                 (t == 'checkbox' || t == 'radio') && !el.checked ||
    699                 (t == 'submit' || t == 'image') && el.form && el.form.clk != el ||
    700                 tag == 'select' && el.selectedIndex == -1)) {
    701                         return null;
    702         }
    703 
    704         if (tag == 'select') {
    705                 var index = el.selectedIndex;
    706                 if (index < 0) {
    707                         return null;
    708                 }
    709                 var a = [], ops = el.options;
    710                 var one = (t == 'select-one');
    711                 var max = (one ? index+1 : ops.length);
    712                 for(var i=(one ? index : 0); i < max; i++) {
    713                         var op = ops[i];
    714                         if (op.selected) {
    715                                 var v = op.value;
    716                                 if (!v) { // extra pain for IE...
    717                                         v = (op.attributes && op.attributes['value'] && !(op.attributes['value'].specified)) ? op.text : op.value;
    718                                 }
    719                                 if (one) {
    720                                         return v;
    721                                 }
    722                                 a.push(v);
    723                         }
    724                 }
    725                 return a;
    726         }
    727         return $(el).val();
     1123    var n = el.name, t = el.type, tag = el.tagName.toLowerCase();
     1124    if (successful === undefined) {
     1125        successful = true;
     1126    }
     1127
     1128    if (successful && (!n || el.disabled || t == 'reset' || t == 'button' ||
     1129        (t == 'checkbox' || t == 'radio') && !el.checked ||
     1130        (t == 'submit' || t == 'image') && el.form && el.form.clk != el ||
     1131        tag == 'select' && el.selectedIndex == -1)) {
     1132            return null;
     1133    }
     1134
     1135    if (tag == 'select') {
     1136        var index = el.selectedIndex;
     1137        if (index < 0) {
     1138            return null;
     1139        }
     1140        var a = [], ops = el.options;
     1141        var one = (t == 'select-one');
     1142        var max = (one ? index+1 : ops.length);
     1143        for(var i=(one ? index : 0); i < max; i++) {
     1144            var op = ops[i];
     1145            if (op.selected) {
     1146                var v = op.value;
     1147                if (!v) { // extra pain for IE...
     1148                    v = (op.attributes && op.attributes.value && !(op.attributes.value.specified)) ? op.text : op.value;
     1149                }
     1150                if (one) {
     1151                    return v;
     1152                }
     1153                a.push(v);
     1154            }
     1155        }
     1156        return a;
     1157    }
     1158    return $(el).val();
    7281159};
    7291160
     
    7361167 *  - button elements will *not* be effected
    7371168 */
    738 $.fn.clearForm = function() {
    739         return this.each(function() {
    740                 $('input,select,textarea', this).clearFields();
    741         });
     1169$.fn.clearForm = function(includeHidden) {
     1170    return this.each(function() {
     1171        $('input,select,textarea', this).clearFields(includeHidden);
     1172    });
    7421173};
    7431174
     
    7451176 * Clears the selected form elements.
    7461177 */
    747 $.fn.clearFields = $.fn.clearInputs = function() {
    748         return this.each(function() {
    749                 var t = this.type, tag = this.tagName.toLowerCase();
    750                 if (t == 'text' || t == 'password' || tag == 'textarea') {
    751                         this.value = '';
    752                 }
    753                 else if (t == 'checkbox' || t == 'radio') {
    754                         this.checked = false;
    755                 }
    756                 else if (tag == 'select') {
    757                         this.selectedIndex = -1;
    758                 }
    759         });
     1178$.fn.clearFields = $.fn.clearInputs = function(includeHidden) {
     1179    var re = /^(?:color|date|datetime|email|month|number|password|range|search|tel|text|time|url|week)$/i; // 'hidden' is not in this list
     1180    return this.each(function() {
     1181        var t = this.type, tag = this.tagName.toLowerCase();
     1182        if (re.test(t) || tag == 'textarea') {
     1183            this.value = '';
     1184        }
     1185        else if (t == 'checkbox' || t == 'radio') {
     1186            this.checked = false;
     1187        }
     1188        else if (tag == 'select') {
     1189            this.selectedIndex = -1;
     1190        }
     1191        else if (t == "file") {
     1192            if (/MSIE/.test(navigator.userAgent)) {
     1193                $(this).replaceWith($(this).clone(true));
     1194            } else {
     1195                $(this).val('');
     1196            }
     1197        }
     1198        else if (includeHidden) {
     1199            // includeHidden can be the value true, or it can be a selector string
     1200            // indicating a special test; for example:
     1201            //  $('#myForm').clearForm('.special:hidden')
     1202            // the above would clean hidden inputs that have the class of 'special'
     1203            if ( (includeHidden === true && /hidden/.test(t)) ||
     1204                 (typeof includeHidden == 'string' && $(this).is(includeHidden)) ) {
     1205                this.value = '';
     1206            }
     1207        }
     1208    });
    7601209};
    7611210
     
    7641213 */
    7651214$.fn.resetForm = function() {
    766         return this.each(function() {
    767                 // guard against an input with the name of 'reset'
    768                 // note that IE reports the reset function as an 'object'
    769                 if (typeof this.reset == 'function' || (typeof this.reset == 'object' && !this.reset.nodeType)) {
    770                         this.reset();
    771                 }
    772         });
     1215    return this.each(function() {
     1216        // guard against an input with the name of 'reset'
     1217        // note that IE reports the reset function as an 'object'
     1218        if (typeof this.reset == 'function' || (typeof this.reset == 'object' && !this.reset.nodeType)) {
     1219            this.reset();
     1220        }
     1221    });
    7731222};
    7741223
     
    7771226 */
    7781227$.fn.enable = function(b) {
    779         if (b === undefined) {
    780                 b = true;
    781         }
    782         return this.each(function() {
    783                 this.disabled = !b;
    784         });
     1228    if (b === undefined) {
     1229        b = true;
     1230    }
     1231    return this.each(function() {
     1232        this.disabled = !b;
     1233    });
    7851234};
    7861235
     
    7901239 */
    7911240$.fn.selected = function(select) {
    792         if (select === undefined) {
    793                 select = true;
    794         }
    795         return this.each(function() {
    796                 var t = this.type;
    797                 if (t == 'checkbox' || t == 'radio') {
    798                         this.checked = select;
    799                 }
    800                 else if (this.tagName.toLowerCase() == 'option') {
    801                         var $sel = $(this).parent('select');
    802                         if (select && $sel[0] && $sel[0].type == 'select-one') {
    803                                 // deselect all other options
    804                                 $sel.find('option').selected(false);
    805                         }
    806                         this.selected = select;
    807                 }
    808         });
    809 };
     1241    if (select === undefined) {
     1242        select = true;
     1243    }
     1244    return this.each(function() {
     1245        var t = this.type;
     1246        if (t == 'checkbox' || t == 'radio') {
     1247            this.checked = select;
     1248        }
     1249        else if (this.tagName.toLowerCase() == 'option') {
     1250            var $sel = $(this).parent('select');
     1251            if (select && $sel[0] && $sel[0].type == 'select-one') {
     1252                // deselect all other options
     1253                $sel.find('option').selected(false);
     1254            }
     1255            this.selected = select;
     1256        }
     1257    });
     1258};
     1259
     1260// expose debug var
     1261$.fn.ajaxSubmit.debug = false;
    8101262
    8111263// helper fn for console logging
    812 // set $.fn.ajaxSubmit.debug to true to enable debug logging
    8131264function log() {
    814         if ($.fn.ajaxSubmit.debug) {
    815                 var msg = '[jquery.form] ' + Array.prototype.join.call(arguments,'');
    816                 if (window.console && window.console.log) {
    817                         window.console.log(msg);
    818                 }
    819                 else if (window.opera && window.opera.postError) {
    820                         window.opera.postError(msg);
    821                 }
    822         }
    823 };
    824 
    825 })(jQuery);
     1265    if (!$.fn.ajaxSubmit.debug) {
     1266        return;
     1267    }
     1268    var msg = '[jquery.form] ' + Array.prototype.join.call(arguments,'');
     1269    if (window.console && window.console.log) {
     1270        window.console.log(msg);
     1271    }
     1272    else if (window.opera && window.opera.postError) {
     1273        window.opera.postError(msg);
     1274    }
     1275}
     1276
     1277}));
  • _plugins_/crayons/js/jquery.js

    r47460 r90326  
    11/*!
    2  * jQuery JavaScript Library v1.6
     2 * jQuery JavaScript Library v1.11.3
    33 * http://jquery.com/
    4  *
    5  * Copyright 2011, John Resig
    6  * Dual licensed under the MIT or GPL Version 2 licenses.
    7  * http://jquery.org/license
    84 *
    95 * Includes Sizzle.js
    106 * http://sizzlejs.com/
    11  * Copyright 2011, The Dojo Foundation
    12  * Released under the MIT, BSD, and GPL Licenses.
    137 *
    14  * Date: Mon May 2 13:50:00 2011 -0400
     8 * Copyright 2005, 2014 jQuery Foundation, Inc. and other contributors
     9 * Released under the MIT license
     10 * http://jquery.org/license
     11 *
     12 * Date: 2015-04-28T16:19Z
    1513 */
    16 (function( window, undefined ) {
    17 
    18 // Use the correct document accordingly with window argument (sandbox)
    19 var document = window.document,
    20         navigator = window.navigator,
    21         location = window.location;
    22 var jQuery = (function() {
    23 
    24 // Define a local copy of jQuery
    25 var jQuery = function( selector, context ) {
     14
     15(function( global, factory ) {
     16
     17        if ( typeof module === "object" && typeof module.exports === "object" ) {
     18                // For CommonJS and CommonJS-like environments where a proper window is present,
     19                // execute the factory and get jQuery
     20                // For environments that do not inherently posses a window with a document
     21                // (such as Node.js), expose a jQuery-making factory as module.exports
     22                // This accentuates the need for the creation of a real window
     23                // e.g. var jQuery = require("jquery")(window);
     24                // See ticket #14549 for more info
     25                module.exports = global.document ?
     26                        factory( global, true ) :
     27                        function( w ) {
     28                                if ( !w.document ) {
     29                                        throw new Error( "jQuery requires a window with a document" );
     30                                }
     31                                return factory( w );
     32                        };
     33        } else {
     34                factory( global );
     35        }
     36
     37// Pass this if window is not defined yet
     38}(typeof window !== "undefined" ? window : this, function( window, noGlobal ) {
     39
     40// Can't do this because several apps including ASP.NET trace
     41// the stack via arguments.caller.callee and Firefox dies if
     42// you try to trace through "use strict" call chains. (#13335)
     43// Support: Firefox 18+
     44//
     45
     46var deletedIds = [];
     47
     48var slice = deletedIds.slice;
     49
     50var concat = deletedIds.concat;
     51
     52var push = deletedIds.push;
     53
     54var indexOf = deletedIds.indexOf;
     55
     56var class2type = {};
     57
     58var toString = class2type.toString;
     59
     60var hasOwn = class2type.hasOwnProperty;
     61
     62var support = {};
     63
     64
     65
     66var
     67        version = "1.11.3",
     68
     69        // Define a local copy of jQuery
     70        jQuery = function( selector, context ) {
    2671                // The jQuery object is actually just the init constructor 'enhanced'
    27                 return new jQuery.fn.init( selector, context, rootjQuery );
    28         },
    29 
    30         // Map over jQuery in case of overwrite
    31         _jQuery = window.jQuery,
    32 
    33         // Map over the $ in case of overwrite
    34         _$ = window.$,
    35 
    36         // A central reference to the root jQuery(document)
    37         rootjQuery,
    38 
    39         // A simple way to check for HTML strings or ID strings
    40         // (both of which we optimize for)
    41         quickExpr = /^(?:[^<]*(<[\w\W]+>)[^>]*$|#([\w\-]*)$)/,
    42 
    43         // Check if a string has a non-whitespace character in it
    44         rnotwhite = /\S/,
    45 
    46         // Used for trimming whitespace
    47         trimLeft = /^\s+/,
    48         trimRight = /\s+$/,
    49 
    50         // Check for digits
    51         rdigit = /\d/,
    52 
    53         // Match a standalone tag
    54         rsingleTag = /^<(\w+)\s*\/?>(?:<\/\1>)?$/,
    55 
    56         // JSON RegExp
    57         rvalidchars = /^[\],:{}\s]*$/,
    58         rvalidescape = /\\(?:["\\\/bfnrt]|u[0-9a-fA-F]{4})/g,
    59         rvalidtokens = /"[^"\\\n\r]*"|true|false|null|-?\d+(?:\.\d*)?(?:[eE][+\-]?\d+)?/g,
    60         rvalidbraces = /(?:^|:|,)(?:\s*\[)+/g,
    61 
    62         // Useragent RegExp
    63         rwebkit = /(webkit)[ \/]([\w.]+)/,
    64         ropera = /(opera)(?:.*version)?[ \/]([\w.]+)/,
    65         rmsie = /(msie) ([\w.]+)/,
    66         rmozilla = /(mozilla)(?:.*? rv:([\w.]+))?/,
    67 
    68         // Keep a UserAgent string for use with jQuery.browser
    69         userAgent = navigator.userAgent,
    70 
    71         // For matching the engine and version of the browser
    72         browserMatch,
    73 
    74         // The deferred used on DOM ready
    75         readyList,
    76 
    77         // The ready event handler
    78         DOMContentLoaded,
    79 
    80         // Save a reference to some core methods
    81         toString = Object.prototype.toString,
    82         hasOwn = Object.prototype.hasOwnProperty,
    83         push = Array.prototype.push,
    84         slice = Array.prototype.slice,
    85         trim = String.prototype.trim,
    86         indexOf = Array.prototype.indexOf,
    87 
    88         // [[Class]] -> type pairs
    89         class2type = {};
     72                // Need init if jQuery is called (just allow error to be thrown if not included)
     73                return new jQuery.fn.init( selector, context );
     74        },
     75
     76        // Support: Android<4.1, IE<9
     77        // Make sure we trim BOM and NBSP
     78        rtrim = /^[\s\uFEFF\xA0]+|[\s\uFEFF\xA0]+$/g,
     79
     80        // Matches dashed string for camelizing
     81        rmsPrefix = /^-ms-/,
     82        rdashAlpha = /-([\da-z])/gi,
     83
     84        // Used by jQuery.camelCase as callback to replace()
     85        fcamelCase = function( all, letter ) {
     86                return letter.toUpperCase();
     87        };
    9088
    9189jQuery.fn = jQuery.prototype = {
     90        // The current version of jQuery being used
     91        jquery: version,
     92
    9293        constructor: jQuery,
    93         init: function( selector, context, rootjQuery ) {
    94                 var match, elem, ret, doc;
    95 
    96                 // Handle $(""), $(null), or $(undefined)
     94
     95        // Start with an empty selector
     96        selector: "",
     97
     98        // The default length of a jQuery object is 0
     99        length: 0,
     100
     101        toArray: function() {
     102                return slice.call( this );
     103        },
     104
     105        // Get the Nth element in the matched element set OR
     106        // Get the whole matched element set as a clean array
     107        get: function( num ) {
     108                return num != null ?
     109
     110                        // Return just the one element from the set
     111                        ( num < 0 ? this[ num + this.length ] : this[ num ] ) :
     112
     113                        // Return all the elements in a clean array
     114                        slice.call( this );
     115        },
     116
     117        // Take an array of elements and push it onto the stack
     118        // (returning the new matched element set)
     119        pushStack: function( elems ) {
     120
     121                // Build a new jQuery matched element set
     122                var ret = jQuery.merge( this.constructor(), elems );
     123
     124                // Add the old object onto the stack (as a reference)
     125                ret.prevObject = this;
     126                ret.context = this.context;
     127
     128                // Return the newly-formed element set
     129                return ret;
     130        },
     131
     132        // Execute a callback for every element in the matched set.
     133        // (You can seed the arguments with an array of args, but this is
     134        // only used internally.)
     135        each: function( callback, args ) {
     136                return jQuery.each( this, callback, args );
     137        },
     138
     139        map: function( callback ) {
     140                return this.pushStack( jQuery.map(this, function( elem, i ) {
     141                        return callback.call( elem, i, elem );
     142                }));
     143        },
     144
     145        slice: function() {
     146                return this.pushStack( slice.apply( this, arguments ) );
     147        },
     148
     149        first: function() {
     150                return this.eq( 0 );
     151        },
     152
     153        last: function() {
     154                return this.eq( -1 );
     155        },
     156
     157        eq: function( i ) {
     158                var len = this.length,
     159                        j = +i + ( i < 0 ? len : 0 );
     160                return this.pushStack( j >= 0 && j < len ? [ this[j] ] : [] );
     161        },
     162
     163        end: function() {
     164                return this.prevObject || this.constructor(null);
     165        },
     166
     167        // For internal use only.
     168        // Behaves like an Array's method, not like a jQuery method.
     169        push: push,
     170        sort: deletedIds.sort,
     171        splice: deletedIds.splice
     172};
     173
     174jQuery.extend = jQuery.fn.extend = function() {
     175        var src, copyIsArray, copy, name, options, clone,
     176                target = arguments[0] || {},
     177                i = 1,
     178                length = arguments.length,
     179                deep = false;
     180
     181        // Handle a deep copy situation
     182        if ( typeof target === "boolean" ) {
     183                deep = target;
     184
     185                // skip the boolean and the target
     186                target = arguments[ i ] || {};
     187                i++;
     188        }
     189
     190        // Handle case when target is a string or something (possible in deep copy)
     191        if ( typeof target !== "object" && !jQuery.isFunction(target) ) {
     192                target = {};
     193        }
     194
     195        // extend jQuery itself if only one argument is passed
     196        if ( i === length ) {
     197                target = this;
     198                i--;
     199        }
     200
     201        for ( ; i < length; i++ ) {
     202                // Only deal with non-null/undefined values
     203                if ( (options = arguments[ i ]) != null ) {
     204                        // Extend the base object
     205                        for ( name in options ) {
     206                                src = target[ name ];
     207                                copy = options[ name ];
     208
     209                                // Prevent never-ending loop
     210                                if ( target === copy ) {
     211                                        continue;
     212                                }
     213
     214                                // Recurse if we're merging plain objects or arrays
     215                                if ( deep && copy && ( jQuery.isPlainObject(copy) || (copyIsArray = jQuery.isArray(copy)) ) ) {
     216                                        if ( copyIsArray ) {
     217                                                copyIsArray = false;
     218                                                clone = src && jQuery.isArray(src) ? src : [];
     219
     220                                        } else {
     221                                                clone = src && jQuery.isPlainObject(src) ? src : {};
     222                                        }
     223
     224                                        // Never move original objects, clone them
     225                                        target[ name ] = jQuery.extend( deep, clone, copy );
     226
     227                                // Don't bring in undefined values
     228                                } else if ( copy !== undefined ) {
     229                                        target[ name ] = copy;
     230                                }
     231                        }
     232                }
     233        }
     234
     235        // Return the modified object
     236        return target;
     237};
     238
     239jQuery.extend({
     240        // Unique for each copy of jQuery on the page
     241        expando: "jQuery" + ( version + Math.random() ).replace( /\D/g, "" ),
     242
     243        // Assume jQuery is ready without the ready module
     244        isReady: true,
     245
     246        error: function( msg ) {
     247                throw new Error( msg );
     248        },
     249
     250        noop: function() {},
     251
     252        // See test/unit/core.js for details concerning isFunction.
     253        // Since version 1.3, DOM methods and functions like alert
     254        // aren't supported. They return false on IE (#2968).
     255        isFunction: function( obj ) {
     256                return jQuery.type(obj) === "function";
     257        },
     258
     259        isArray: Array.isArray || function( obj ) {
     260                return jQuery.type(obj) === "array";
     261        },
     262
     263        isWindow: function( obj ) {
     264                /* jshint eqeqeq: false */
     265                return obj != null && obj == obj.window;
     266        },
     267
     268        isNumeric: function( obj ) {
     269                // parseFloat NaNs numeric-cast false positives (null|true|false|"")
     270                // ...but misinterprets leading-number strings, particularly hex literals ("0x...")
     271                // subtraction forces infinities to NaN
     272                // adding 1 corrects loss of precision from parseFloat (#15100)
     273                return !jQuery.isArray( obj ) && (obj - parseFloat( obj ) + 1) >= 0;
     274        },
     275
     276        isEmptyObject: function( obj ) {
     277                var name;
     278                for ( name in obj ) {
     279                        return false;
     280                }
     281                return true;
     282        },
     283
     284        isPlainObject: function( obj ) {
     285                var key;
     286
     287                // Must be an Object.
     288                // Because of IE, we also have to check the presence of the constructor property.
     289                // Make sure that DOM nodes and window objects don't pass through, as well
     290                if ( !obj || jQuery.type(obj) !== "object" || obj.nodeType || jQuery.isWindow( obj ) ) {
     291                        return false;
     292                }
     293
     294                try {
     295                        // Not own constructor property must be Object
     296                        if ( obj.constructor &&
     297                                !hasOwn.call(obj, "constructor") &&
     298                                !hasOwn.call(obj.constructor.prototype, "isPrototypeOf") ) {
     299                                return false;
     300                        }
     301                } catch ( e ) {
     302                        // IE8,9 Will throw exceptions on certain host objects #9897
     303                        return false;
     304                }
     305
     306                // Support: IE<9
     307                // Handle iteration over inherited properties before own properties.
     308                if ( support.ownLast ) {
     309                        for ( key in obj ) {
     310                                return hasOwn.call( obj, key );
     311                        }
     312                }
     313
     314                // Own properties are enumerated firstly, so to speed up,
     315                // if last one is own, then all properties are own.
     316                for ( key in obj ) {}
     317
     318                return key === undefined || hasOwn.call( obj, key );
     319        },
     320
     321        type: function( obj ) {
     322                if ( obj == null ) {
     323                        return obj + "";
     324                }
     325                return typeof obj === "object" || typeof obj === "function" ?
     326                        class2type[ toString.call(obj) ] || "object" :
     327                        typeof obj;
     328        },
     329
     330        // Evaluates a script in a global context
     331        // Workarounds based on findings by Jim Driscoll
     332        // http://weblogs.java.net/blog/driscoll/archive/2009/09/08/eval-javascript-global-context
     333        globalEval: function( data ) {
     334                if ( data && jQuery.trim( data ) ) {
     335                        // We use execScript on Internet Explorer
     336                        // We use an anonymous function so that context is window
     337                        // rather than jQuery in Firefox
     338                        ( window.execScript || function( data ) {
     339                                window[ "eval" ].call( window, data );
     340                        } )( data );
     341                }
     342        },
     343
     344        // Convert dashed to camelCase; used by the css and data modules
     345        // Microsoft forgot to hump their vendor prefix (#9572)
     346        camelCase: function( string ) {
     347                return string.replace( rmsPrefix, "ms-" ).replace( rdashAlpha, fcamelCase );
     348        },
     349
     350        nodeName: function( elem, name ) {
     351                return elem.nodeName && elem.nodeName.toLowerCase() === name.toLowerCase();
     352        },
     353
     354        // args is for internal usage only
     355        each: function( obj, callback, args ) {
     356                var value,
     357                        i = 0,
     358                        length = obj.length,
     359                        isArray = isArraylike( obj );
     360
     361                if ( args ) {
     362                        if ( isArray ) {
     363                                for ( ; i < length; i++ ) {
     364                                        value = callback.apply( obj[ i ], args );
     365
     366                                        if ( value === false ) {
     367                                                break;
     368                                        }
     369                                }
     370                        } else {
     371                                for ( i in obj ) {
     372                                        value = callback.apply( obj[ i ], args );
     373
     374                                        if ( value === false ) {
     375                                                break;
     376                                        }
     377                                }
     378                        }
     379
     380                // A special, fast, case for the most common use of each
     381                } else {
     382                        if ( isArray ) {
     383                                for ( ; i < length; i++ ) {
     384                                        value = callback.call( obj[ i ], i, obj[ i ] );
     385
     386                                        if ( value === false ) {
     387                                                break;
     388                                        }
     389                                }
     390                        } else {
     391                                for ( i in obj ) {
     392                                        value = callback.call( obj[ i ], i, obj[ i ] );
     393
     394                                        if ( value === false ) {
     395                                                break;
     396                                        }
     397                                }
     398                        }
     399                }
     400
     401                return obj;
     402        },
     403
     404        // Support: Android<4.1, IE<9
     405        trim: function( text ) {
     406                return text == null ?
     407                        "" :
     408                        ( text + "" ).replace( rtrim, "" );
     409        },
     410
     411        // results is for internal usage only
     412        makeArray: function( arr, results ) {
     413                var ret = results || [];
     414
     415                if ( arr != null ) {
     416                        if ( isArraylike( Object(arr) ) ) {
     417                                jQuery.merge( ret,
     418                                        typeof arr === "string" ?
     419                                        [ arr ] : arr
     420                                );
     421                        } else {
     422                                push.call( ret, arr );
     423                        }
     424                }
     425
     426                return ret;
     427        },
     428
     429        inArray: function( elem, arr, i ) {
     430                var len;
     431
     432                if ( arr ) {
     433                        if ( indexOf ) {
     434                                return indexOf.call( arr, elem, i );
     435                        }
     436
     437                        len = arr.length;
     438                        i = i ? i < 0 ? Math.max( 0, len + i ) : i : 0;
     439
     440                        for ( ; i < len; i++ ) {
     441                                // Skip accessing in sparse arrays
     442                                if ( i in arr && arr[ i ] === elem ) {
     443                                        return i;
     444                                }
     445                        }
     446                }
     447
     448                return -1;
     449        },
     450
     451        merge: function( first, second ) {
     452                var len = +second.length,
     453                        j = 0,
     454                        i = first.length;
     455
     456                while ( j < len ) {
     457                        first[ i++ ] = second[ j++ ];
     458                }
     459
     460                // Support: IE<9
     461                // Workaround casting of .length to NaN on otherwise arraylike objects (e.g., NodeLists)
     462                if ( len !== len ) {
     463                        while ( second[j] !== undefined ) {
     464                                first[ i++ ] = second[ j++ ];
     465                        }
     466                }
     467
     468                first.length = i;
     469
     470                return first;
     471        },
     472
     473        grep: function( elems, callback, invert ) {
     474                var callbackInverse,
     475                        matches = [],
     476                        i = 0,
     477                        length = elems.length,
     478                        callbackExpect = !invert;
     479
     480                // Go through the array, only saving the items
     481                // that pass the validator function
     482                for ( ; i < length; i++ ) {
     483                        callbackInverse = !callback( elems[ i ], i );
     484                        if ( callbackInverse !== callbackExpect ) {
     485                                matches.push( elems[ i ] );
     486                        }
     487                }
     488
     489                return matches;
     490        },
     491
     492        // arg is for internal usage only
     493        map: function( elems, callback, arg ) {
     494                var value,
     495                        i = 0,
     496                        length = elems.length,
     497                        isArray = isArraylike( elems ),
     498                        ret = [];
     499
     500                // Go through the array, translating each of the items to their new values
     501                if ( isArray ) {
     502                        for ( ; i < length; i++ ) {
     503                                value = callback( elems[ i ], i, arg );
     504
     505                                if ( value != null ) {
     506                                        ret.push( value );
     507                                }
     508                        }
     509
     510                // Go through every key on the object,
     511                } else {
     512                        for ( i in elems ) {
     513                                value = callback( elems[ i ], i, arg );
     514
     515                                if ( value != null ) {
     516                                        ret.push( value );
     517                                }
     518                        }
     519                }
     520
     521                // Flatten any nested arrays
     522                return concat.apply( [], ret );
     523        },
     524
     525        // A global GUID counter for objects
     526        guid: 1,
     527
     528        // Bind a function to a context, optionally partially applying any
     529        // arguments.
     530        proxy: function( fn, context ) {
     531                var args, proxy, tmp;
     532
     533                if ( typeof context === "string" ) {
     534                        tmp = fn[ context ];
     535                        context = fn;
     536                        fn = tmp;
     537                }
     538
     539                // Quick check to determine if target is callable, in the spec
     540                // this throws a TypeError, but we will just return undefined.
     541                if ( !jQuery.isFunction( fn ) ) {
     542                        return undefined;
     543                }
     544
     545                // Simulated bind
     546                args = slice.call( arguments, 2 );
     547                proxy = function() {
     548                        return fn.apply( context || this, args.concat( slice.call( arguments ) ) );
     549                };
     550
     551                // Set the guid of unique handler to the same of original handler, so it can be removed
     552                proxy.guid = fn.guid = fn.guid || jQuery.guid++;
     553
     554                return proxy;
     555        },
     556
     557        now: function() {
     558                return +( new Date() );
     559        },
     560
     561        // jQuery.support is not used in Core but other projects attach their
     562        // properties to it so it needs to exist.
     563        support: support
     564});
     565
     566// Populate the class2type map
     567jQuery.each("Boolean Number String Function Array Date RegExp Object Error".split(" "), function(i, name) {
     568        class2type[ "[object " + name + "]" ] = name.toLowerCase();
     569});
     570
     571function isArraylike( obj ) {
     572
     573        // Support: iOS 8.2 (not reproducible in simulator)
     574        // `in` check used to prevent JIT error (gh-2145)
     575        // hasOwn isn't used here due to false negatives
     576        // regarding Nodelist length in IE
     577        var length = "length" in obj && obj.length,
     578                type = jQuery.type( obj );
     579
     580        if ( type === "function" || jQuery.isWindow( obj ) ) {
     581                return false;
     582        }
     583
     584        if ( obj.nodeType === 1 && length ) {
     585                return true;
     586        }
     587
     588        return type === "array" || length === 0 ||
     589                typeof length === "number" && length > 0 && ( length - 1 ) in obj;
     590}
     591var Sizzle =
     592/*!
     593 * Sizzle CSS Selector Engine v2.2.0-pre
     594 * http://sizzlejs.com/
     595 *
     596 * Copyright 2008, 2014 jQuery Foundation, Inc. and other contributors
     597 * Released under the MIT license
     598 * http://jquery.org/license
     599 *
     600 * Date: 2014-12-16
     601 */
     602(function( window ) {
     603
     604var i,
     605        support,
     606        Expr,
     607        getText,
     608        isXML,
     609        tokenize,
     610        compile,
     611        select,
     612        outermostContext,
     613        sortInput,
     614        hasDuplicate,
     615
     616        // Local document vars
     617        setDocument,
     618        document,
     619        docElem,
     620        documentIsHTML,
     621        rbuggyQSA,
     622        rbuggyMatches,
     623        matches,
     624        contains,
     625
     626        // Instance-specific data
     627        expando = "sizzle" + 1 * new Date(),
     628        preferredDoc = window.document,
     629        dirruns = 0,
     630        done = 0,
     631        classCache = createCache(),
     632        tokenCache = createCache(),
     633        compilerCache = createCache(),
     634        sortOrder = function( a, b ) {
     635                if ( a === b ) {
     636                        hasDuplicate = true;
     637                }
     638                return 0;
     639        },
     640
     641        // General-purpose constants
     642        MAX_NEGATIVE = 1 << 31,
     643
     644        // Instance methods
     645        hasOwn = ({}).hasOwnProperty,
     646        arr = [],
     647        pop = arr.pop,
     648        push_native = arr.push,
     649        push = arr.push,
     650        slice = arr.slice,
     651        // Use a stripped-down indexOf as it's faster than native
     652        // http://jsperf.com/thor-indexof-vs-for/5
     653        indexOf = function( list, elem ) {
     654                var i = 0,
     655                        len = list.length;
     656                for ( ; i < len; i++ ) {
     657                        if ( list[i] === elem ) {
     658                                return i;
     659                        }
     660                }
     661                return -1;
     662        },
     663
     664        booleans = "checked|selected|async|autofocus|autoplay|controls|defer|disabled|hidden|ismap|loop|multiple|open|readonly|required|scoped",
     665
     666        // Regular expressions
     667
     668        // Whitespace characters http://www.w3.org/TR/css3-selectors/#whitespace
     669        whitespace = "[\\x20\\t\\r\\n\\f]",
     670        // http://www.w3.org/TR/css3-syntax/#characters
     671        characterEncoding = "(?:\\\\.|[\\w-]|[^\\x00-\\xa0])+",
     672
     673        // Loosely modeled on CSS identifier characters
     674        // An unquoted value should be a CSS identifier http://www.w3.org/TR/css3-selectors/#attribute-selectors
     675        // Proper syntax: http://www.w3.org/TR/CSS21/syndata.html#value-def-identifier
     676        identifier = characterEncoding.replace( "w", "w#" ),
     677
     678        // Attribute selectors: http://www.w3.org/TR/selectors/#attribute-selectors
     679        attributes = "\\[" + whitespace + "*(" + characterEncoding + ")(?:" + whitespace +
     680                // Operator (capture 2)
     681                "*([*^$|!~]?=)" + whitespace +
     682                // "Attribute values must be CSS identifiers [capture 5] or strings [capture 3 or capture 4]"
     683                "*(?:'((?:\\\\.|[^\\\\'])*)'|\"((?:\\\\.|[^\\\\\"])*)\"|(" + identifier + "))|)" + whitespace +
     684                "*\\]",
     685
     686        pseudos = ":(" + characterEncoding + ")(?:\\((" +
     687                // To reduce the number of selectors needing tokenize in the preFilter, prefer arguments:
     688                // 1. quoted (capture 3; capture 4 or capture 5)
     689                "('((?:\\\\.|[^\\\\'])*)'|\"((?:\\\\.|[^\\\\\"])*)\")|" +
     690                // 2. simple (capture 6)
     691                "((?:\\\\.|[^\\\\()[\\]]|" + attributes + ")*)|" +
     692                // 3. anything else (capture 2)
     693                ".*" +
     694                ")\\)|)",
     695
     696        // Leading and non-escaped trailing whitespace, capturing some non-whitespace characters preceding the latter
     697        rwhitespace = new RegExp( whitespace + "+", "g" ),
     698        rtrim = new RegExp( "^" + whitespace + "+|((?:^|[^\\\\])(?:\\\\.)*)" + whitespace + "+$", "g" ),
     699
     700        rcomma = new RegExp( "^" + whitespace + "*," + whitespace + "*" ),
     701        rcombinators = new RegExp( "^" + whitespace + "*([>+~]|" + whitespace + ")" + whitespace + "*" ),
     702
     703        rattributeQuotes = new RegExp( "=" + whitespace + "*([^\\]'\"]*?)" + whitespace + "*\\]", "g" ),
     704
     705        rpseudo = new RegExp( pseudos ),
     706        ridentifier = new RegExp( "^" + identifier + "$" ),
     707
     708        matchExpr = {
     709                "ID": new RegExp( "^#(" + characterEncoding + ")" ),
     710                "CLASS": new RegExp( "^\\.(" + characterEncoding + ")" ),
     711                "TAG": new RegExp( "^(" + characterEncoding.replace( "w", "w*" ) + ")" ),
     712                "ATTR": new RegExp( "^" + attributes ),
     713                "PSEUDO": new RegExp( "^" + pseudos ),
     714                "CHILD": new RegExp( "^:(only|first|last|nth|nth-last)-(child|of-type)(?:\\(" + whitespace +
     715                        "*(even|odd|(([+-]|)(\\d*)n|)" + whitespace + "*(?:([+-]|)" + whitespace +
     716                        "*(\\d+)|))" + whitespace + "*\\)|)", "i" ),
     717                "bool": new RegExp( "^(?:" + booleans + ")$", "i" ),
     718                // For use in libraries implementing .is()
     719                // We use this for POS matching in `select`
     720                "needsContext": new RegExp( "^" + whitespace + "*[>+~]|:(even|odd|eq|gt|lt|nth|first|last)(?:\\(" +
     721                        whitespace + "*((?:-\\d)?\\d*)" + whitespace + "*\\)|)(?=[^-]|$)", "i" )
     722        },
     723
     724        rinputs = /^(?:input|select|textarea|button)$/i,
     725        rheader = /^h\d$/i,
     726
     727        rnative = /^[^{]+\{\s*\[native \w/,
     728
     729        // Easily-parseable/retrievable ID or TAG or CLASS selectors
     730        rquickExpr = /^(?:#([\w-]+)|(\w+)|\.([\w-]+))$/,
     731
     732        rsibling = /[+~]/,
     733        rescape = /'|\\/g,
     734
     735        // CSS escapes http://www.w3.org/TR/CSS21/syndata.html#escaped-characters
     736        runescape = new RegExp( "\\\\([\\da-f]{1,6}" + whitespace + "?|(" + whitespace + ")|.)", "ig" ),
     737        funescape = function( _, escaped, escapedWhitespace ) {
     738                var high = "0x" + escaped - 0x10000;
     739                // NaN means non-codepoint
     740                // Support: Firefox<24
     741                // Workaround erroneous numeric interpretation of +"0x"
     742                return high !== high || escapedWhitespace ?
     743                        escaped :
     744                        high < 0 ?
     745                                // BMP codepoint
     746                                String.fromCharCode( high + 0x10000 ) :
     747                                // Supplemental Plane codepoint (surrogate pair)
     748                                String.fromCharCode( high >> 10 | 0xD800, high & 0x3FF | 0xDC00 );
     749        },
     750
     751        // Used for iframes
     752        // See setDocument()
     753        // Removing the function wrapper causes a "Permission Denied"
     754        // error in IE
     755        unloadHandler = function() {
     756                setDocument();
     757        };
     758
     759// Optimize for push.apply( _, NodeList )
     760try {
     761        push.apply(
     762                (arr = slice.call( preferredDoc.childNodes )),
     763                preferredDoc.childNodes
     764        );
     765        // Support: Android<4.0
     766        // Detect silently failing push.apply
     767        arr[ preferredDoc.childNodes.length ].nodeType;
     768} catch ( e ) {
     769        push = { apply: arr.length ?
     770
     771                // Leverage slice if possible
     772                function( target, els ) {
     773                        push_native.apply( target, slice.call(els) );
     774                } :
     775
     776                // Support: IE<9
     777                // Otherwise append directly
     778                function( target, els ) {
     779                        var j = target.length,
     780                                i = 0;
     781                        // Can't trust NodeList.length
     782                        while ( (target[j++] = els[i++]) ) {}
     783                        target.length = j - 1;
     784                }
     785        };
     786}
     787
     788function Sizzle( selector, context, results, seed ) {
     789        var match, elem, m, nodeType,
     790                // QSA vars
     791                i, groups, old, nid, newContext, newSelector;
     792
     793        if ( ( context ? context.ownerDocument || context : preferredDoc ) !== document ) {
     794                setDocument( context );
     795        }
     796
     797        context = context || document;
     798        results = results || [];
     799        nodeType = context.nodeType;
     800
     801        if ( typeof selector !== "string" || !selector ||
     802                nodeType !== 1 && nodeType !== 9 && nodeType !== 11 ) {
     803
     804                return results;
     805        }
     806
     807        if ( !seed && documentIsHTML ) {
     808
     809                // Try to shortcut find operations when possible (e.g., not under DocumentFragment)
     810                if ( nodeType !== 11 && (match = rquickExpr.exec( selector )) ) {
     811                        // Speed-up: Sizzle("#ID")
     812                        if ( (m = match[1]) ) {
     813                                if ( nodeType === 9 ) {
     814                                        elem = context.getElementById( m );
     815                                        // Check parentNode to catch when Blackberry 4.6 returns
     816                                        // nodes that are no longer in the document (jQuery #6963)
     817                                        if ( elem && elem.parentNode ) {
     818                                                // Handle the case where IE, Opera, and Webkit return items
     819                                                // by name instead of ID
     820                                                if ( elem.id === m ) {
     821                                                        results.push( elem );
     822                                                        return results;
     823                                                }
     824                                        } else {
     825                                                return results;
     826                                        }
     827                                } else {
     828                                        // Context is not a document
     829                                        if ( context.ownerDocument && (elem = context.ownerDocument.getElementById( m )) &&
     830                                                contains( context, elem ) && elem.id === m ) {
     831                                                results.push( elem );
     832                                                return results;
     833                                        }
     834                                }
     835
     836                        // Speed-up: Sizzle("TAG")
     837                        } else if ( match[2] ) {
     838                                push.apply( results, context.getElementsByTagName( selector ) );
     839                                return results;
     840
     841                        // Speed-up: Sizzle(".CLASS")
     842                        } else if ( (m = match[3]) && support.getElementsByClassName ) {
     843                                push.apply( results, context.getElementsByClassName( m ) );
     844                                return results;
     845                        }
     846                }
     847
     848                // QSA path
     849                if ( support.qsa && (!rbuggyQSA || !rbuggyQSA.test( selector )) ) {
     850                        nid = old = expando;
     851                        newContext = context;
     852                        newSelector = nodeType !== 1 && selector;
     853
     854                        // qSA works strangely on Element-rooted queries
     855                        // We can work around this by specifying an extra ID on the root
     856                        // and working up from there (Thanks to Andrew Dupont for the technique)
     857                        // IE 8 doesn't work on object elements
     858                        if ( nodeType === 1 && context.nodeName.toLowerCase() !== "object" ) {
     859                                groups = tokenize( selector );
     860
     861                                if ( (old = context.getAttribute("id")) ) {
     862                                        nid = old.replace( rescape, "\\$&" );
     863                                } else {
     864                                        context.setAttribute( "id", nid );
     865                                }
     866                                nid = "[id='" + nid + "'] ";
     867
     868                                i = groups.length;
     869                                while ( i-- ) {
     870                                        groups[i] = nid + toSelector( groups[i] );
     871                                }
     872                                newContext = rsibling.test( selector ) && testContext( context.parentNode ) || context;
     873                                newSelector = groups.join(",");
     874                        }
     875
     876                        if ( newSelector ) {
     877                                try {
     878                                        push.apply( results,
     879                                                newContext.querySelectorAll( newSelector )
     880                                        );
     881                                        return results;
     882                                } catch(qsaError) {
     883                                } finally {
     884                                        if ( !old ) {
     885                                                context.removeAttribute("id");
     886                                        }
     887                                }
     888                        }
     889                }
     890        }
     891
     892        // All others
     893        return select( selector.replace( rtrim, "$1" ), context, results, seed );
     894}
     895
     896/**
     897 * Create key-value caches of limited size
     898 * @returns {Function(string, Object)} Returns the Object data after storing it on itself with
     899 *      property name the (space-suffixed) string and (if the cache is larger than Expr.cacheLength)
     900 *      deleting the oldest entry
     901 */
     902function createCache() {
     903        var keys = [];
     904
     905        function cache( key, value ) {
     906                // Use (key + " ") to avoid collision with native prototype properties (see Issue #157)
     907                if ( keys.push( key + " " ) > Expr.cacheLength ) {
     908                        // Only keep the most recent entries
     909                        delete cache[ keys.shift() ];
     910                }
     911                return (cache[ key + " " ] = value);
     912        }
     913        return cache;
     914}
     915
     916/**
     917 * Mark a function for special use by Sizzle
     918 * @param {Function} fn The function to mark
     919 */
     920function markFunction( fn ) {
     921        fn[ expando ] = true;
     922        return fn;
     923}
     924
     925/**
     926 * Support testing using an element
     927 * @param {Function} fn Passed the created div and expects a boolean result
     928 */
     929function assert( fn ) {
     930        var div = document.createElement("div");
     931
     932        try {
     933                return !!fn( div );
     934        } catch (e) {
     935                return false;
     936        } finally {
     937                // Remove from its parent by default
     938                if ( div.parentNode ) {
     939                        div.parentNode.removeChild( div );
     940                }
     941                // release memory in IE
     942                div = null;
     943        }
     944}
     945
     946/**
     947 * Adds the same handler for all of the specified attrs
     948 * @param {String} attrs Pipe-separated list of attributes
     949 * @param {Function} handler The method that will be applied
     950 */
     951function addHandle( attrs, handler ) {
     952        var arr = attrs.split("|"),
     953                i = attrs.length;
     954
     955        while ( i-- ) {
     956                Expr.attrHandle[ arr[i] ] = handler;
     957        }
     958}
     959
     960/**
     961 * Checks document order of two siblings
     962 * @param {Element} a
     963 * @param {Element} b
     964 * @returns {Number} Returns less than 0 if a precedes b, greater than 0 if a follows b
     965 */
     966function siblingCheck( a, b ) {
     967        var cur = b && a,
     968                diff = cur && a.nodeType === 1 && b.nodeType === 1 &&
     969                        ( ~b.sourceIndex || MAX_NEGATIVE ) -
     970                        ( ~a.sourceIndex || MAX_NEGATIVE );
     971
     972        // Use IE sourceIndex if available on both nodes
     973        if ( diff ) {
     974                return diff;
     975        }
     976
     977        // Check if b follows a
     978        if ( cur ) {
     979                while ( (cur = cur.nextSibling) ) {
     980                        if ( cur === b ) {
     981                                return -1;
     982                        }
     983                }
     984        }
     985
     986        return a ? 1 : -1;
     987}
     988
     989/**
     990 * Returns a function to use in pseudos for input types
     991 * @param {String} type
     992 */
     993function createInputPseudo( type ) {
     994        return function( elem ) {
     995                var name = elem.nodeName.toLowerCase();
     996                return name === "input" && elem.type === type;
     997        };
     998}
     999
     1000/**
     1001 * Returns a function to use in pseudos for buttons
     1002 * @param {String} type
     1003 */
     1004function createButtonPseudo( type ) {
     1005        return function( elem ) {
     1006                var name = elem.nodeName.toLowerCase();
     1007                return (name === "input" || name === "button") && elem.type === type;
     1008        };
     1009}
     1010
     1011/**
     1012 * Returns a function to use in pseudos for positionals
     1013 * @param {Function} fn
     1014 */
     1015function createPositionalPseudo( fn ) {
     1016        return markFunction(function( argument ) {
     1017                argument = +argument;
     1018                return markFunction(function( seed, matches ) {
     1019                        var j,
     1020                                matchIndexes = fn( [], seed.length, argument ),
     1021                                i = matchIndexes.length;
     1022
     1023                        // Match elements found at the specified indexes
     1024                        while ( i-- ) {
     1025                                if ( seed[ (j = matchIndexes[i]) ] ) {
     1026                                        seed[j] = !(matches[j] = seed[j]);
     1027                                }
     1028                        }
     1029                });
     1030        });
     1031}
     1032
     1033/**
     1034 * Checks a node for validity as a Sizzle context
     1035 * @param {Element|Object=} context
     1036 * @returns {Element|Object|Boolean} The input node if acceptable, otherwise a falsy value
     1037 */
     1038function testContext( context ) {
     1039        return context && typeof context.getElementsByTagName !== "undefined" && context;
     1040}
     1041
     1042// Expose support vars for convenience
     1043support = Sizzle.support = {};
     1044
     1045/**
     1046 * Detects XML nodes
     1047 * @param {Element|Object} elem An element or a document
     1048 * @returns {Boolean} True iff elem is a non-HTML XML node
     1049 */
     1050isXML = Sizzle.isXML = function( elem ) {
     1051        // documentElement is verified for cases where it doesn't yet exist
     1052        // (such as loading iframes in IE - #4833)
     1053        var documentElement = elem && (elem.ownerDocument || elem).documentElement;
     1054        return documentElement ? documentElement.nodeName !== "HTML" : false;
     1055};
     1056
     1057/**
     1058 * Sets document-related variables once based on the current document
     1059 * @param {Element|Object} [doc] An element or document object to use to set the document
     1060 * @returns {Object} Returns the current document
     1061 */
     1062setDocument = Sizzle.setDocument = function( node ) {
     1063        var hasCompare, parent,
     1064                doc = node ? node.ownerDocument || node : preferredDoc;
     1065
     1066        // If no document and documentElement is available, return
     1067        if ( doc === document || doc.nodeType !== 9 || !doc.documentElement ) {
     1068                return document;
     1069        }
     1070
     1071        // Set our document
     1072        document = doc;
     1073        docElem = doc.documentElement;
     1074        parent = doc.defaultView;
     1075
     1076        // Support: IE>8
     1077        // If iframe document is assigned to "document" variable and if iframe has been reloaded,
     1078        // IE will throw "permission denied" error when accessing "document" variable, see jQuery #13936
     1079        // IE6-8 do not support the defaultView property so parent will be undefined
     1080        if ( parent && parent !== parent.top ) {
     1081                // IE11 does not have attachEvent, so all must suffer
     1082                if ( parent.addEventListener ) {
     1083                        parent.addEventListener( "unload", unloadHandler, false );
     1084                } else if ( parent.attachEvent ) {
     1085                        parent.attachEvent( "onunload", unloadHandler );
     1086                }
     1087        }
     1088
     1089        /* Support tests
     1090        ---------------------------------------------------------------------- */
     1091        documentIsHTML = !isXML( doc );
     1092
     1093        /* Attributes
     1094        ---------------------------------------------------------------------- */
     1095
     1096        // Support: IE<8
     1097        // Verify that getAttribute really returns attributes and not properties
     1098        // (excepting IE8 booleans)
     1099        support.attributes = assert(function( div ) {
     1100                div.className = "i";
     1101                return !div.getAttribute("className");
     1102        });
     1103
     1104        /* getElement(s)By*
     1105        ---------------------------------------------------------------------- */
     1106
     1107        // Check if getElementsByTagName("*") returns only elements
     1108        support.getElementsByTagName = assert(function( div ) {
     1109                div.appendChild( doc.createComment("") );
     1110                return !div.getElementsByTagName("*").length;
     1111        });
     1112
     1113        // Support: IE<9
     1114        support.getElementsByClassName = rnative.test( doc.getElementsByClassName );
     1115
     1116        // Support: IE<10
     1117        // Check if getElementById returns elements by name
     1118        // The broken getElementById methods don't pick up programatically-set names,
     1119        // so use a roundabout getElementsByName test
     1120        support.getById = assert(function( div ) {
     1121                docElem.appendChild( div ).id = expando;
     1122                return !doc.getElementsByName || !doc.getElementsByName( expando ).length;
     1123        });
     1124
     1125        // ID find and filter
     1126        if ( support.getById ) {
     1127                Expr.find["ID"] = function( id, context ) {
     1128                        if ( typeof context.getElementById !== "undefined" && documentIsHTML ) {
     1129                                var m = context.getElementById( id );
     1130                                // Check parentNode to catch when Blackberry 4.6 returns
     1131                                // nodes that are no longer in the document #6963
     1132                                return m && m.parentNode ? [ m ] : [];
     1133                        }
     1134                };
     1135                Expr.filter["ID"] = function( id ) {
     1136                        var attrId = id.replace( runescape, funescape );
     1137                        return function( elem ) {
     1138                                return elem.getAttribute("id") === attrId;
     1139                        };
     1140                };
     1141        } else {
     1142                // Support: IE6/7
     1143                // getElementById is not reliable as a find shortcut
     1144                delete Expr.find["ID"];
     1145
     1146                Expr.filter["ID"] =  function( id ) {
     1147                        var attrId = id.replace( runescape, funescape );
     1148                        return function( elem ) {
     1149                                var node = typeof elem.getAttributeNode !== "undefined" && elem.getAttributeNode("id");
     1150                                return node && node.value === attrId;
     1151                        };
     1152                };
     1153        }
     1154
     1155        // Tag
     1156        Expr.find["TAG"] = support.getElementsByTagName ?
     1157                function( tag, context ) {
     1158                        if ( typeof context.getElementsByTagName !== "undefined" ) {
     1159                                return context.getElementsByTagName( tag );
     1160
     1161                        // DocumentFragment nodes don't have gEBTN
     1162                        } else if ( support.qsa ) {
     1163                                return context.querySelectorAll( tag );
     1164                        }
     1165                } :
     1166
     1167                function( tag, context ) {
     1168                        var elem,
     1169                                tmp = [],
     1170                                i = 0,
     1171                                // By happy coincidence, a (broken) gEBTN appears on DocumentFragment nodes too
     1172                                results = context.getElementsByTagName( tag );
     1173
     1174                        // Filter out possible comments
     1175                        if ( tag === "*" ) {
     1176                                while ( (elem = results[i++]) ) {
     1177                                        if ( elem.nodeType === 1 ) {
     1178                                                tmp.push( elem );
     1179                                        }
     1180                                }
     1181
     1182                                return tmp;
     1183                        }
     1184                        return results;
     1185                };
     1186
     1187        // Class
     1188        Expr.find["CLASS"] = support.getElementsByClassName && function( className, context ) {
     1189                if ( documentIsHTML ) {
     1190                        return context.getElementsByClassName( className );
     1191                }
     1192        };
     1193
     1194        /* QSA/matchesSelector
     1195        ---------------------------------------------------------------------- */
     1196
     1197        // QSA and matchesSelector support
     1198
     1199        // matchesSelector(:active) reports false when true (IE9/Opera 11.5)
     1200        rbuggyMatches = [];
     1201
     1202        // qSa(:focus) reports false when true (Chrome 21)
     1203        // We allow this because of a bug in IE8/9 that throws an error
     1204        // whenever `document.activeElement` is accessed on an iframe
     1205        // So, we allow :focus to pass through QSA all the time to avoid the IE error
     1206        // See http://bugs.jquery.com/ticket/13378
     1207        rbuggyQSA = [];
     1208
     1209        if ( (support.qsa = rnative.test( doc.querySelectorAll )) ) {
     1210                // Build QSA regex
     1211                // Regex strategy adopted from Diego Perini
     1212                assert(function( div ) {
     1213                        // Select is set to empty string on purpose
     1214                        // This is to test IE's treatment of not explicitly
     1215                        // setting a boolean content attribute,
     1216                        // since its presence should be enough
     1217                        // http://bugs.jquery.com/ticket/12359
     1218                        docElem.appendChild( div ).innerHTML = "<a id='" + expando + "'></a>" +
     1219                                "<select id='" + expando + "-\f]' msallowcapture=''>" +
     1220                                "<option selected=''></option></select>";
     1221
     1222                        // Support: IE8, Opera 11-12.16
     1223                        // Nothing should be selected when empty strings follow ^= or $= or *=
     1224                        // The test attribute must be unknown in Opera but "safe" for WinRT
     1225                        // http://msdn.microsoft.com/en-us/library/ie/hh465388.aspx#attribute_section
     1226                        if ( div.querySelectorAll("[msallowcapture^='']").length ) {
     1227                                rbuggyQSA.push( "[*^$]=" + whitespace + "*(?:''|\"\")" );
     1228                        }
     1229
     1230                        // Support: IE8
     1231                        // Boolean attributes and "value" are not treated correctly
     1232                        if ( !div.querySelectorAll("[selected]").length ) {
     1233                                rbuggyQSA.push( "\\[" + whitespace + "*(?:value|" + booleans + ")" );
     1234                        }
     1235
     1236                        // Support: Chrome<29, Android<4.2+, Safari<7.0+, iOS<7.0+, PhantomJS<1.9.7+
     1237                        if ( !div.querySelectorAll( "[id~=" + expando + "-]" ).length ) {
     1238                                rbuggyQSA.push("~=");
     1239                        }
     1240
     1241                        // Webkit/Opera - :checked should return selected option elements
     1242                        // http://www.w3.org/TR/2011/REC-css3-selectors-20110929/#checked
     1243                        // IE8 throws error here and will not see later tests
     1244                        if ( !div.querySelectorAll(":checked").length ) {
     1245                                rbuggyQSA.push(":checked");
     1246                        }
     1247
     1248                        // Support: Safari 8+, iOS 8+
     1249                        // https://bugs.webkit.org/show_bug.cgi?id=136851
     1250                        // In-page `selector#id sibing-combinator selector` fails
     1251                        if ( !div.querySelectorAll( "a#" + expando + "+*" ).length ) {
     1252                                rbuggyQSA.push(".#.+[+~]");
     1253                        }
     1254                });
     1255
     1256                assert(function( div ) {
     1257                        // Support: Windows 8 Native Apps
     1258                        // The type and name attributes are restricted during .innerHTML assignment
     1259                        var input = doc.createElement("input");
     1260                        input.setAttribute( "type", "hidden" );
     1261                        div.appendChild( input ).setAttribute( "name", "D" );
     1262
     1263                        // Support: IE8
     1264                        // Enforce case-sensitivity of name attribute
     1265                        if ( div.querySelectorAll("[name=d]").length ) {
     1266                                rbuggyQSA.push( "name" + whitespace + "*[*^$|!~]?=" );
     1267                        }
     1268
     1269                        // FF 3.5 - :enabled/:disabled and hidden elements (hidden elements are still enabled)
     1270                        // IE8 throws error here and will not see later tests
     1271                        if ( !div.querySelectorAll(":enabled").length ) {
     1272                                rbuggyQSA.push( ":enabled", ":disabled" );
     1273                        }
     1274
     1275                        // Opera 10-11 does not throw on post-comma invalid pseudos
     1276                        div.querySelectorAll("*,:x");
     1277                        rbuggyQSA.push(",.*:");
     1278                });
     1279        }
     1280
     1281        if ( (support.matchesSelector = rnative.test( (matches = docElem.matches ||
     1282                docElem.webkitMatchesSelector ||
     1283                docElem.mozMatchesSelector ||
     1284                docElem.oMatchesSelector ||
     1285                docElem.msMatchesSelector) )) ) {
     1286
     1287                assert(function( div ) {
     1288                        // Check to see if it's possible to do matchesSelector
     1289                        // on a disconnected node (IE 9)
     1290                        support.disconnectedMatch = matches.call( div, "div" );
     1291
     1292                        // This should fail with an exception
     1293                        // Gecko does not error, returns false instead
     1294                        matches.call( div, "[s!='']:x" );
     1295                        rbuggyMatches.push( "!=", pseudos );
     1296                });
     1297        }
     1298
     1299        rbuggyQSA = rbuggyQSA.length && new RegExp( rbuggyQSA.join("|") );
     1300        rbuggyMatches = rbuggyMatches.length && new RegExp( rbuggyMatches.join("|") );
     1301
     1302        /* Contains
     1303        ---------------------------------------------------------------------- */
     1304        hasCompare = rnative.test( docElem.compareDocumentPosition );
     1305
     1306        // Element contains another
     1307        // Purposefully does not implement inclusive descendent
     1308        // As in, an element does not contain itself
     1309        contains = hasCompare || rnative.test( docElem.contains ) ?
     1310                function( a, b ) {
     1311                        var adown = a.nodeType === 9 ? a.documentElement : a,
     1312                                bup = b && b.parentNode;
     1313                        return a === bup || !!( bup && bup.nodeType === 1 && (
     1314                                adown.contains ?
     1315                                        adown.contains( bup ) :
     1316                                        a.compareDocumentPosition && a.compareDocumentPosition( bup ) & 16
     1317                        ));
     1318                } :
     1319                function( a, b ) {
     1320                        if ( b ) {
     1321                                while ( (b = b.parentNode) ) {
     1322                                        if ( b === a ) {
     1323                                                return true;
     1324                                        }
     1325                                }
     1326                        }
     1327                        return false;
     1328                };
     1329
     1330        /* Sorting
     1331        ---------------------------------------------------------------------- */
     1332
     1333        // Document order sorting
     1334        sortOrder = hasCompare ?
     1335        function( a, b ) {
     1336
     1337                // Flag for duplicate removal
     1338                if ( a === b ) {
     1339                        hasDuplicate = true;
     1340                        return 0;
     1341                }
     1342
     1343                // Sort on method existence if only one input has compareDocumentPosition
     1344                var compare = !a.compareDocumentPosition - !b.compareDocumentPosition;
     1345                if ( compare ) {
     1346                        return compare;
     1347                }
     1348
     1349                // Calculate position if both inputs belong to the same document
     1350                compare = ( a.ownerDocument || a ) === ( b.ownerDocument || b ) ?
     1351                        a.compareDocumentPosition( b ) :
     1352
     1353                        // Otherwise we know they are disconnected
     1354                        1;
     1355
     1356                // Disconnected nodes
     1357                if ( compare & 1 ||
     1358                        (!support.sortDetached && b.compareDocumentPosition( a ) === compare) ) {
     1359
     1360                        // Choose the first element that is related to our preferred document
     1361                        if ( a === doc || a.ownerDocument === preferredDoc && contains(preferredDoc, a) ) {
     1362                                return -1;
     1363                        }
     1364                        if ( b === doc || b.ownerDocument === preferredDoc && contains(preferredDoc, b) ) {
     1365                                return 1;
     1366                        }
     1367
     1368                        // Maintain original order
     1369                        return sortInput ?
     1370                                ( indexOf( sortInput, a ) - indexOf( sortInput, b ) ) :
     1371                                0;
     1372                }
     1373
     1374                return compare & 4 ? -1 : 1;
     1375        } :
     1376        function( a, b ) {
     1377                // Exit early if the nodes are identical
     1378                if ( a === b ) {
     1379                        hasDuplicate = true;
     1380                        return 0;
     1381                }
     1382
     1383                var cur,
     1384                        i = 0,
     1385                        aup = a.parentNode,
     1386                        bup = b.parentNode,
     1387                        ap = [ a ],
     1388                        bp = [ b ];
     1389
     1390                // Parentless nodes are either documents or disconnected
     1391                if ( !aup || !bup ) {
     1392                        return a === doc ? -1 :
     1393                                b === doc ? 1 :
     1394                                aup ? -1 :
     1395                                bup ? 1 :
     1396                                sortInput ?
     1397                                ( indexOf( sortInput, a ) - indexOf( sortInput, b ) ) :
     1398                                0;
     1399
     1400                // If the nodes are siblings, we can do a quick check
     1401                } else if ( aup === bup ) {
     1402                        return siblingCheck( a, b );
     1403                }
     1404
     1405                // Otherwise we need full lists of their ancestors for comparison
     1406                cur = a;
     1407                while ( (cur = cur.parentNode) ) {
     1408                        ap.unshift( cur );
     1409                }
     1410                cur = b;
     1411                while ( (cur = cur.parentNode) ) {
     1412                        bp.unshift( cur );
     1413                }
     1414
     1415                // Walk down the tree looking for a discrepancy
     1416                while ( ap[i] === bp[i] ) {
     1417                        i++;
     1418                }
     1419
     1420                return i ?
     1421                        // Do a sibling check if the nodes have a common ancestor
     1422                        siblingCheck( ap[i], bp[i] ) :
     1423
     1424                        // Otherwise nodes in our document sort first
     1425                        ap[i] === preferredDoc ? -1 :
     1426                        bp[i] === preferredDoc ? 1 :
     1427                        0;
     1428        };
     1429
     1430        return doc;
     1431};
     1432
     1433Sizzle.matches = function( expr, elements ) {
     1434        return Sizzle( expr, null, null, elements );
     1435};
     1436
     1437Sizzle.matchesSelector = function( elem, expr ) {
     1438        // Set document vars if needed
     1439        if ( ( elem.ownerDocument || elem ) !== document ) {
     1440                setDocument( elem );
     1441        }
     1442
     1443        // Make sure that attribute selectors are quoted
     1444        expr = expr.replace( rattributeQuotes, "='$1']" );
     1445
     1446        if ( support.matchesSelector && documentIsHTML &&
     1447                ( !rbuggyMatches || !rbuggyMatches.test( expr ) ) &&
     1448                ( !rbuggyQSA     || !rbuggyQSA.test( expr ) ) ) {
     1449
     1450                try {
     1451                        var ret = matches.call( elem, expr );
     1452
     1453                        // IE 9's matchesSelector returns false on disconnected nodes
     1454                        if ( ret || support.disconnectedMatch ||
     1455                                        // As well, disconnected nodes are said to be in a document
     1456                                        // fragment in IE 9
     1457                                        elem.document && elem.document.nodeType !== 11 ) {
     1458                                return ret;
     1459                        }
     1460                } catch (e) {}
     1461        }
     1462
     1463        return Sizzle( expr, document, null, [ elem ] ).length > 0;
     1464};
     1465
     1466Sizzle.contains = function( context, elem ) {
     1467        // Set document vars if needed
     1468        if ( ( context.ownerDocument || context ) !== document ) {
     1469                setDocument( context );
     1470        }
     1471        return contains( context, elem );
     1472};
     1473
     1474Sizzle.attr = function( elem, name ) {
     1475        // Set document vars if needed
     1476        if ( ( elem.ownerDocument || elem ) !== document ) {
     1477                setDocument( elem );
     1478        }
     1479
     1480        var fn = Expr.attrHandle[ name.toLowerCase() ],
     1481                // Don't get fooled by Object.prototype properties (jQuery #13807)
     1482                val = fn && hasOwn.call( Expr.attrHandle, name.toLowerCase() ) ?
     1483                        fn( elem, name, !documentIsHTML ) :
     1484                        undefined;
     1485
     1486        return val !== undefined ?
     1487                val :
     1488                support.attributes || !documentIsHTML ?
     1489                        elem.getAttribute( name ) :
     1490                        (val = elem.getAttributeNode(name)) && val.specified ?
     1491                                val.value :
     1492                                null;
     1493};
     1494
     1495Sizzle.error = function( msg ) {
     1496        throw new Error( "Syntax error, unrecognized expression: " + msg );
     1497};
     1498
     1499/**
     1500 * Document sorting and removing duplicates
     1501 * @param {ArrayLike} results
     1502 */
     1503Sizzle.uniqueSort = function( results ) {
     1504        var elem,
     1505                duplicates = [],
     1506                j = 0,
     1507                i = 0;
     1508
     1509        // Unless we *know* we can detect duplicates, assume their presence
     1510        hasDuplicate = !support.detectDuplicates;
     1511        sortInput = !support.sortStable && results.slice( 0 );
     1512        results.sort( sortOrder );
     1513
     1514        if ( hasDuplicate ) {
     1515                while ( (elem = results[i++]) ) {
     1516                        if ( elem === results[ i ] ) {
     1517                                j = duplicates.push( i );
     1518                        }
     1519                }
     1520                while ( j-- ) {
     1521                        results.splice( duplicates[ j ], 1 );
     1522                }
     1523        }
     1524
     1525        // Clear input after sorting to release objects
     1526        // See https://github.com/jquery/sizzle/pull/225
     1527        sortInput = null;
     1528
     1529        return results;
     1530};
     1531
     1532/**
     1533 * Utility function for retrieving the text value of an array of DOM nodes
     1534 * @param {Array|Element} elem
     1535 */
     1536getText = Sizzle.getText = function( elem ) {
     1537        var node,
     1538                ret = "",
     1539                i = 0,
     1540                nodeType = elem.nodeType;
     1541
     1542        if ( !nodeType ) {
     1543                // If no nodeType, this is expected to be an array
     1544                while ( (node = elem[i++]) ) {
     1545                        // Do not traverse comment nodes
     1546                        ret += getText( node );
     1547                }
     1548        } else if ( nodeType === 1 || nodeType === 9 || nodeType === 11 ) {
     1549                // Use textContent for elements
     1550                // innerText usage removed for consistency of new lines (jQuery #11153)
     1551                if ( typeof elem.textContent === "string" ) {
     1552                        return elem.textContent;
     1553                } else {
     1554                        // Traverse its children
     1555                        for ( elem = elem.firstChild; elem; elem = elem.nextSibling ) {
     1556                                ret += getText( elem );
     1557                        }
     1558                }
     1559        } else if ( nodeType === 3 || nodeType === 4 ) {
     1560                return elem.nodeValue;
     1561        }
     1562        // Do not include comment or processing instruction nodes
     1563
     1564        return ret;
     1565};
     1566
     1567Expr = Sizzle.selectors = {
     1568
     1569        // Can be adjusted by the user
     1570        cacheLength: 50,
     1571
     1572        createPseudo: markFunction,
     1573
     1574        match: matchExpr,
     1575
     1576        attrHandle: {},
     1577
     1578        find: {},
     1579
     1580        relative: {
     1581                ">": { dir: "parentNode", first: true },
     1582                " ": { dir: "parentNode" },
     1583                "+": { dir: "previousSibling", first: true },
     1584                "~": { dir: "previousSibling" }
     1585        },
     1586
     1587        preFilter: {
     1588                "ATTR": function( match ) {
     1589                        match[1] = match[1].replace( runescape, funescape );
     1590
     1591                        // Move the given value to match[3] whether quoted or unquoted
     1592                        match[3] = ( match[3] || match[4] || match[5] || "" ).replace( runescape, funescape );
     1593
     1594                        if ( match[2] === "~=" ) {
     1595                                match[3] = " " + match[3] + " ";
     1596                        }
     1597
     1598                        return match.slice( 0, 4 );
     1599                },
     1600
     1601                "CHILD": function( match ) {
     1602                        /* matches from matchExpr["CHILD"]
     1603                                1 type (only|nth|...)
     1604                                2 what (child|of-type)
     1605                                3 argument (even|odd|\d*|\d*n([+-]\d+)?|...)
     1606                                4 xn-component of xn+y argument ([+-]?\d*n|)
     1607                                5 sign of xn-component
     1608                                6 x of xn-component
     1609                                7 sign of y-component
     1610                                8 y of y-component
     1611                        */
     1612                        match[1] = match[1].toLowerCase();
     1613
     1614                        if ( match[1].slice( 0, 3 ) === "nth" ) {
     1615                                // nth-* requires argument
     1616                                if ( !match[3] ) {
     1617                                        Sizzle.error( match[0] );
     1618                                }
     1619
     1620                                // numeric x and y parameters for Expr.filter.CHILD
     1621                                // remember that false/true cast respectively to 0/1
     1622                                match[4] = +( match[4] ? match[5] + (match[6] || 1) : 2 * ( match[3] === "even" || match[3] === "odd" ) );
     1623                                match[5] = +( ( match[7] + match[8] ) || match[3] === "odd" );
     1624
     1625                        // other types prohibit arguments
     1626                        } else if ( match[3] ) {
     1627                                Sizzle.error( match[0] );
     1628                        }
     1629
     1630                        return match;
     1631                },
     1632
     1633                "PSEUDO": function( match ) {
     1634                        var excess,
     1635                                unquoted = !match[6] && match[2];
     1636
     1637                        if ( matchExpr["CHILD"].test( match[0] ) ) {
     1638                                return null;
     1639                        }
     1640
     1641                        // Accept quoted arguments as-is
     1642                        if ( match[3] ) {
     1643                                match[2] = match[4] || match[5] || "";
     1644
     1645                        // Strip excess characters from unquoted arguments
     1646                        } else if ( unquoted && rpseudo.test( unquoted ) &&
     1647                                // Get excess from tokenize (recursively)
     1648                                (excess = tokenize( unquoted, true )) &&
     1649                                // advance to the next closing parenthesis
     1650                                (excess = unquoted.indexOf( ")", unquoted.length - excess ) - unquoted.length) ) {
     1651
     1652                                // excess is a negative index
     1653                                match[0] = match[0].slice( 0, excess );
     1654                                match[2] = unquoted.slice( 0, excess );
     1655                        }
     1656
     1657                        // Return only captures needed by the pseudo filter method (type and argument)
     1658                        return match.slice( 0, 3 );
     1659                }
     1660        },
     1661
     1662        filter: {
     1663
     1664                "TAG": function( nodeNameSelector ) {
     1665                        var nodeName = nodeNameSelector.replace( runescape, funescape ).toLowerCase();
     1666                        return nodeNameSelector === "*" ?
     1667                                function() { return true; } :
     1668                                function( elem ) {
     1669                                        return elem.nodeName && elem.nodeName.toLowerCase() === nodeName;
     1670                                };
     1671                },
     1672
     1673                "CLASS": function( className ) {
     1674                        var pattern = classCache[ className + " " ];
     1675
     1676                        return pattern ||
     1677                                (pattern = new RegExp( "(^|" + whitespace + ")" + className + "(" + whitespace + "|$)" )) &&
     1678                                classCache( className, function( elem ) {
     1679                                        return pattern.test( typeof elem.className === "string" && elem.className || typeof elem.getAttribute !== "undefined" && elem.getAttribute("class") || "" );
     1680                                });
     1681                },
     1682
     1683                "ATTR": function( name, operator, check ) {
     1684                        return function( elem ) {
     1685                                var result = Sizzle.attr( elem, name );
     1686
     1687                                if ( result == null ) {
     1688                                        return operator === "!=";
     1689                                }
     1690                                if ( !operator ) {
     1691                                        return true;
     1692                                }
     1693
     1694                                result += "";
     1695
     1696                                return operator === "=" ? result === check :
     1697                                        operator === "!=" ? result !== check :
     1698                                        operator === "^=" ? check && result.indexOf( check ) === 0 :
     1699                                        operator === "*=" ? check && result.indexOf( check ) > -1 :
     1700                                        operator === "$=" ? check && result.slice( -check.length ) === check :
     1701                                        operator === "~=" ? ( " " + result.replace( rwhitespace, " " ) + " " ).indexOf( check ) > -1 :
     1702                                        operator === "|=" ? result === check || result.slice( 0, check.length + 1 ) === check + "-" :
     1703                                        false;
     1704                        };
     1705                },
     1706
     1707                "CHILD": function( type, what, argument, first, last ) {
     1708                        var simple = type.slice( 0, 3 ) !== "nth",
     1709                                forward = type.slice( -4 ) !== "last",
     1710                                ofType = what === "of-type";
     1711
     1712                        return first === 1 && last === 0 ?
     1713
     1714                                // Shortcut for :nth-*(n)
     1715                                function( elem ) {
     1716                                        return !!elem.parentNode;
     1717                                } :
     1718
     1719                                function( elem, context, xml ) {
     1720                                        var cache, outerCache, node, diff, nodeIndex, start,
     1721                                                dir = simple !== forward ? "nextSibling" : "previousSibling",
     1722                                                parent = elem.parentNode,
     1723                                                name = ofType && elem.nodeName.toLowerCase(),
     1724                                                useCache = !xml && !ofType;
     1725
     1726                                        if ( parent ) {
     1727
     1728                                                // :(first|last|only)-(child|of-type)
     1729                                                if ( simple ) {
     1730                                                        while ( dir ) {
     1731                                                                node = elem;
     1732                                                                while ( (node = node[ dir ]) ) {
     1733                                                                        if ( ofType ? node.nodeName.toLowerCase() === name : node.nodeType === 1 ) {
     1734                                                                                return false;
     1735                                                                        }
     1736                                                                }
     1737                                                                // Reverse direction for :only-* (if we haven't yet done so)
     1738                                                                start = dir = type === "only" && !start && "nextSibling";
     1739                                                        }
     1740                                                        return true;
     1741                                                }
     1742
     1743                                                start = [ forward ? parent.firstChild : parent.lastChild ];
     1744
     1745                                                // non-xml :nth-child(...) stores cache data on `parent`
     1746                                                if ( forward && useCache ) {
     1747                                                        // Seek `elem` from a previously-cached index
     1748                                                        outerCache = parent[ expando ] || (parent[ expando ] = {});
     1749                                                        cache = outerCache[ type ] || [];
     1750                                                        nodeIndex = cache[0] === dirruns && cache[1];
     1751                                                        diff = cache[0] === dirruns && cache[2];
     1752                                                        node = nodeIndex && parent.childNodes[ nodeIndex ];
     1753
     1754                                                        while ( (node = ++nodeIndex && node && node[ dir ] ||
     1755
     1756                                                                // Fallback to seeking `elem` from the start
     1757                                                                (diff = nodeIndex = 0) || start.pop()) ) {
     1758
     1759                                                                // When found, cache indexes on `parent` and break
     1760                                                                if ( node.nodeType === 1 && ++diff && node === elem ) {
     1761                                                                        outerCache[ type ] = [ dirruns, nodeIndex, diff ];
     1762                                                                        break;
     1763                                                                }
     1764                                                        }
     1765
     1766                                                // Use previously-cached element index if available
     1767                                                } else if ( useCache && (cache = (elem[ expando ] || (elem[ expando ] = {}))[ type ]) && cache[0] === dirruns ) {
     1768                                                        diff = cache[1];
     1769
     1770                                                // xml :nth-child(...) or :nth-last-child(...) or :nth(-last)?-of-type(...)
     1771                                                } else {
     1772                                                        // Use the same loop as above to seek `elem` from the start
     1773                                                        while ( (node = ++nodeIndex && node && node[ dir ] ||
     1774                                                                (diff = nodeIndex = 0) || start.pop()) ) {
     1775
     1776                                                                if ( ( ofType ? node.nodeName.toLowerCase() === name : node.nodeType === 1 ) && ++diff ) {
     1777                                                                        // Cache the index of each encountered element
     1778                                                                        if ( useCache ) {
     1779                                                                                (node[ expando ] || (node[ expando ] = {}))[ type ] = [ dirruns, diff ];
     1780                                                                        }
     1781
     1782                                                                        if ( node === elem ) {
     1783                                                                                break;
     1784                                                                        }
     1785                                                                }
     1786                                                        }
     1787                                                }
     1788
     1789                                                // Incorporate the offset, then check against cycle size
     1790                                                diff -= last;
     1791                                                return diff === first || ( diff % first === 0 && diff / first >= 0 );
     1792                                        }
     1793                                };
     1794                },
     1795
     1796                "PSEUDO": function( pseudo, argument ) {
     1797                        // pseudo-class names are case-insensitive
     1798                        // http://www.w3.org/TR/selectors/#pseudo-classes
     1799                        // Prioritize by case sensitivity in case custom pseudos are added with uppercase letters
     1800                        // Remember that setFilters inherits from pseudos
     1801                        var args,
     1802                                fn = Expr.pseudos[ pseudo ] || Expr.setFilters[ pseudo.toLowerCase() ] ||
     1803                                        Sizzle.error( "unsupported pseudo: " + pseudo );
     1804
     1805                        // The user may use createPseudo to indicate that
     1806                        // arguments are needed to create the filter function
     1807                        // just as Sizzle does
     1808                        if ( fn[ expando ] ) {
     1809                                return fn( argument );
     1810                        }
     1811
     1812                        // But maintain support for old signatures
     1813                        if ( fn.length > 1 ) {
     1814                                args = [ pseudo, pseudo, "", argument ];
     1815                                return Expr.setFilters.hasOwnProperty( pseudo.toLowerCase() ) ?
     1816                                        markFunction(function( seed, matches ) {
     1817                                                var idx,
     1818                                                        matched = fn( seed, argument ),
     1819                                                        i = matched.length;
     1820                                                while ( i-- ) {
     1821                                                        idx = indexOf( seed, matched[i] );
     1822                                                        seed[ idx ] = !( matches[ idx ] = matched[i] );
     1823                                                }
     1824                                        }) :
     1825                                        function( elem ) {
     1826                                                return fn( elem, 0, args );
     1827                                        };
     1828                        }
     1829
     1830                        return fn;
     1831                }
     1832        },
     1833
     1834        pseudos: {
     1835                // Potentially complex pseudos
     1836                "not": markFunction(function( selector ) {
     1837                        // Trim the selector passed to compile
     1838                        // to avoid treating leading and trailing
     1839                        // spaces as combinators
     1840                        var input = [],
     1841                                results = [],
     1842                                matcher = compile( selector.replace( rtrim, "$1" ) );
     1843
     1844                        return matcher[ expando ] ?
     1845                                markFunction(function( seed, matches, context, xml ) {
     1846                                        var elem,
     1847                                                unmatched = matcher( seed, null, xml, [] ),
     1848                                                i = seed.length;
     1849
     1850                                        // Match elements unmatched by `matcher`
     1851                                        while ( i-- ) {
     1852                                                if ( (elem = unmatched[i]) ) {
     1853                                                        seed[i] = !(matches[i] = elem);
     1854                                                }
     1855                                        }
     1856                                }) :
     1857                                function( elem, context, xml ) {
     1858                                        input[0] = elem;
     1859                                        matcher( input, null, xml, results );
     1860                                        // Don't keep the element (issue #299)
     1861                                        input[0] = null;
     1862                                        return !results.pop();
     1863                                };
     1864                }),
     1865
     1866                "has": markFunction(function( selector ) {
     1867                        return function( elem ) {
     1868                                return Sizzle( selector, elem ).length > 0;
     1869                        };
     1870                }),
     1871
     1872                "contains": markFunction(function( text ) {
     1873                        text = text.replace( runescape, funescape );
     1874                        return function( elem ) {
     1875                                return ( elem.textContent || elem.innerText || getText( elem ) ).indexOf( text ) > -1;
     1876                        };
     1877                }),
     1878
     1879                // "Whether an element is represented by a :lang() selector
     1880                // is based solely on the element's language value
     1881                // being equal to the identifier C,
     1882                // or beginning with the identifier C immediately followed by "-".
     1883                // The matching of C against the element's language value is performed case-insensitively.
     1884                // The identifier C does not have to be a valid language name."
     1885                // http://www.w3.org/TR/selectors/#lang-pseudo
     1886                "lang": markFunction( function( lang ) {
     1887                        // lang value must be a valid identifier
     1888                        if ( !ridentifier.test(lang || "") ) {
     1889                                Sizzle.error( "unsupported lang: " + lang );
     1890                        }
     1891                        lang = lang.replace( runescape, funescape ).toLowerCase();
     1892                        return function( elem ) {
     1893                                var elemLang;
     1894                                do {
     1895                                        if ( (elemLang = documentIsHTML ?
     1896                                                elem.lang :
     1897                                                elem.getAttribute("xml:lang") || elem.getAttribute("lang")) ) {
     1898
     1899                                                elemLang = elemLang.toLowerCase();
     1900                                                return elemLang === lang || elemLang.indexOf( lang + "-" ) === 0;
     1901                                        }
     1902                                } while ( (elem = elem.parentNode) && elem.nodeType === 1 );
     1903                                return false;
     1904                        };
     1905                }),
     1906
     1907                // Miscellaneous
     1908                "target": function( elem ) {
     1909                        var hash = window.location && window.location.hash;
     1910                        return hash && hash.slice( 1 ) === elem.id;
     1911                },
     1912
     1913                "root": function( elem ) {
     1914                        return elem === docElem;
     1915                },
     1916
     1917                "focus": function( elem ) {
     1918                        return elem === document.activeElement && (!document.hasFocus || document.hasFocus()) && !!(elem.type || elem.href || ~elem.tabIndex);
     1919                },
     1920
     1921                // Boolean properties
     1922                "enabled": function( elem ) {
     1923                        return elem.disabled === false;
     1924                },
     1925
     1926                "disabled": function( elem ) {
     1927                        return elem.disabled === true;
     1928                },
     1929
     1930                "checked": function( elem ) {
     1931                        // In CSS3, :checked should return both checked and selected elements
     1932                        // http://www.w3.org/TR/2011/REC-css3-selectors-20110929/#checked
     1933                        var nodeName = elem.nodeName.toLowerCase();
     1934                        return (nodeName === "input" && !!elem.checked) || (nodeName === "option" && !!elem.selected);
     1935                },
     1936
     1937                "selected": function( elem ) {
     1938                        // Accessing this property makes selected-by-default
     1939                        // options in Safari work properly
     1940                        if ( elem.parentNode ) {
     1941                                elem.parentNode.selectedIndex;
     1942                        }
     1943
     1944                        return elem.selected === true;
     1945                },
     1946
     1947                // Contents
     1948                "empty": function( elem ) {
     1949                        // http://www.w3.org/TR/selectors/#empty-pseudo
     1950                        // :empty is negated by element (1) or content nodes (text: 3; cdata: 4; entity ref: 5),
     1951                        //   but not by others (comment: 8; processing instruction: 7; etc.)
     1952                        // nodeType < 6 works because attributes (2) do not appear as children
     1953                        for ( elem = elem.firstChild; elem; elem = elem.nextSibling ) {
     1954                                if ( elem.nodeType < 6 ) {
     1955                                        return false;
     1956                                }
     1957                        }
     1958                        return true;
     1959                },
     1960
     1961                "parent": function( elem ) {
     1962                        return !Expr.pseudos["empty"]( elem );
     1963                },
     1964
     1965                // Element/input types
     1966                "header": function( elem ) {
     1967                        return rheader.test( elem.nodeName );
     1968                },
     1969
     1970                "input": function( elem ) {
     1971                        return rinputs.test( elem.nodeName );
     1972                },
     1973
     1974                "button": function( elem ) {
     1975                        var name = elem.nodeName.toLowerCase();
     1976                        return name === "input" && elem.type === "button" || name === "button";
     1977                },
     1978
     1979                "text": function( elem ) {
     1980                        var attr;
     1981                        return elem.nodeName.toLowerCase() === "input" &&
     1982                                elem.type === "text" &&
     1983
     1984                                // Support: IE<8
     1985                                // New HTML5 attribute values (e.g., "search") appear with elem.type === "text"
     1986                                ( (attr = elem.getAttribute("type")) == null || attr.toLowerCase() === "text" );
     1987                },
     1988
     1989                // Position-in-collection
     1990                "first": createPositionalPseudo(function() {
     1991                        return [ 0 ];
     1992                }),
     1993
     1994                "last": createPositionalPseudo(function( matchIndexes, length ) {
     1995                        return [ length - 1 ];
     1996                }),
     1997
     1998                "eq": createPositionalPseudo(function( matchIndexes, length, argument ) {
     1999                        return [ argument < 0 ? argument + length : argument ];
     2000                }),
     2001
     2002                "even": createPositionalPseudo(function( matchIndexes, length ) {
     2003                        var i = 0;
     2004                        for ( ; i < length; i += 2 ) {
     2005                                matchIndexes.push( i );
     2006                        }
     2007                        return matchIndexes;
     2008                }),
     2009
     2010                "odd": createPositionalPseudo(function( matchIndexes, length ) {
     2011                        var i = 1;
     2012                        for ( ; i < length; i += 2 ) {
     2013                                matchIndexes.push( i );
     2014                        }
     2015                        return matchIndexes;
     2016                }),
     2017
     2018                "lt": createPositionalPseudo(function( matchIndexes, length, argument ) {
     2019                        var i = argument < 0 ? argument + length : argument;
     2020                        for ( ; --i >= 0; ) {
     2021                                matchIndexes.push( i );
     2022                        }
     2023                        return matchIndexes;
     2024                }),
     2025
     2026                "gt": createPositionalPseudo(function( matchIndexes, length, argument ) {
     2027                        var i = argument < 0 ? argument + length : argument;
     2028                        for ( ; ++i < length; ) {
     2029                                matchIndexes.push( i );
     2030                        }
     2031                        return matchIndexes;
     2032                })
     2033        }
     2034};
     2035
     2036Expr.pseudos["nth"] = Expr.pseudos["eq"];
     2037
     2038// Add button/input type pseudos
     2039for ( i in { radio: true, checkbox: true, file: true, password: true, image: true } ) {
     2040        Expr.pseudos[ i ] = createInputPseudo( i );
     2041}
     2042for ( i in { submit: true, reset: true } ) {
     2043        Expr.pseudos[ i ] = createButtonPseudo( i );
     2044}
     2045
     2046// Easy API for creating new setFilters
     2047function setFilters() {}
     2048setFilters.prototype = Expr.filters = Expr.pseudos;
     2049Expr.setFilters = new setFilters();
     2050
     2051tokenize = Sizzle.tokenize = function( selector, parseOnly ) {
     2052        var matched, match, tokens, type,
     2053                soFar, groups, preFilters,
     2054                cached = tokenCache[ selector + " " ];
     2055
     2056        if ( cached ) {
     2057                return parseOnly ? 0 : cached.slice( 0 );
     2058        }
     2059
     2060        soFar = selector;
     2061        groups = [];
     2062        preFilters = Expr.preFilter;
     2063
     2064        while ( soFar ) {
     2065
     2066                // Comma and first run
     2067                if ( !matched || (match = rcomma.exec( soFar )) ) {
     2068                        if ( match ) {
     2069                                // Don't consume trailing commas as valid
     2070                                soFar = soFar.slice( match[0].length ) || soFar;
     2071                        }
     2072                        groups.push( (tokens = []) );
     2073                }
     2074
     2075                matched = false;
     2076
     2077                // Combinators
     2078                if ( (match = rcombinators.exec( soFar )) ) {
     2079                        matched = match.shift();
     2080                        tokens.push({
     2081                                value: matched,
     2082                                // Cast descendant combinators to space
     2083                                type: match[0].replace( rtrim, " " )
     2084                        });
     2085                        soFar = soFar.slice( matched.length );
     2086                }
     2087
     2088                // Filters
     2089                for ( type in Expr.filter ) {
     2090                        if ( (match = matchExpr[ type ].exec( soFar )) && (!preFilters[ type ] ||
     2091                                (match = preFilters[ type ]( match ))) ) {
     2092                                matched = match.shift();
     2093                                tokens.push({
     2094                                        value: matched,
     2095                                        type: type,
     2096                                        matches: match
     2097                                });
     2098                                soFar = soFar.slice( matched.length );
     2099                        }
     2100                }
     2101
     2102                if ( !matched ) {
     2103                        break;
     2104                }
     2105        }
     2106
     2107        // Return the length of the invalid excess
     2108        // if we're just parsing
     2109        // Otherwise, throw an error or return tokens
     2110        return parseOnly ?
     2111                soFar.length :
     2112                soFar ?
     2113                        Sizzle.error( selector ) :
     2114                        // Cache the tokens
     2115                        tokenCache( selector, groups ).slice( 0 );
     2116};
     2117
     2118function toSelector( tokens ) {
     2119        var i = 0,
     2120                len = tokens.length,
     2121                selector = "";
     2122        for ( ; i < len; i++ ) {
     2123                selector += tokens[i].value;
     2124        }
     2125        return selector;
     2126}
     2127
     2128function addCombinator( matcher, combinator, base ) {
     2129        var dir = combinator.dir,
     2130                checkNonElements = base && dir === "parentNode",
     2131                doneName = done++;
     2132
     2133        return combinator.first ?
     2134                // Check against closest ancestor/preceding element
     2135                function( elem, context, xml ) {
     2136                        while ( (elem = elem[ dir ]) ) {
     2137                                if ( elem.nodeType === 1 || checkNonElements ) {
     2138                                        return matcher( elem, context, xml );
     2139                                }
     2140                        }
     2141                } :
     2142
     2143                // Check against all ancestor/preceding elements
     2144                function( elem, context, xml ) {
     2145                        var oldCache, outerCache,
     2146                                newCache = [ dirruns, doneName ];
     2147
     2148                        // We can't set arbitrary data on XML nodes, so they don't benefit from dir caching
     2149                        if ( xml ) {
     2150                                while ( (elem = elem[ dir ]) ) {
     2151                                        if ( elem.nodeType === 1 || checkNonElements ) {
     2152                                                if ( matcher( elem, context, xml ) ) {
     2153                                                        return true;
     2154                                                }
     2155                                        }
     2156                                }
     2157                        } else {
     2158                                while ( (elem = elem[ dir ]) ) {
     2159                                        if ( elem.nodeType === 1 || checkNonElements ) {
     2160                                                outerCache = elem[ expando ] || (elem[ expando ] = {});
     2161                                                if ( (oldCache = outerCache[ dir ]) &&
     2162                                                        oldCache[ 0 ] === dirruns && oldCache[ 1 ] === doneName ) {
     2163
     2164                                                        // Assign to newCache so results back-propagate to previous elements
     2165                                                        return (newCache[ 2 ] = oldCache[ 2 ]);
     2166                                                } else {
     2167                                                        // Reuse newcache so results back-propagate to previous elements
     2168                                                        outerCache[ dir ] = newCache;
     2169
     2170                                                        // A match means we're done; a fail means we have to keep checking
     2171                                                        if ( (newCache[ 2 ] = matcher( elem, context, xml )) ) {
     2172                                                                return true;
     2173                                                        }
     2174                                                }
     2175                                        }
     2176                                }
     2177                        }
     2178                };
     2179}
     2180
     2181function elementMatcher( matchers ) {
     2182        return matchers.length > 1 ?
     2183                function( elem, context, xml ) {
     2184                        var i = matchers.length;
     2185                        while ( i-- ) {
     2186                                if ( !matchers[i]( elem, context, xml ) ) {
     2187                                        return false;
     2188                                }
     2189                        }
     2190                        return true;
     2191                } :
     2192                matchers[0];
     2193}
     2194
     2195function multipleContexts( selector, contexts, results ) {
     2196        var i = 0,
     2197                len = contexts.length;
     2198        for ( ; i < len; i++ ) {
     2199                Sizzle( selector, contexts[i], results );
     2200        }
     2201        return results;
     2202}
     2203
     2204function condense( unmatched, map, filter, context, xml ) {
     2205        var elem,
     2206                newUnmatched = [],
     2207                i = 0,
     2208                len = unmatched.length,
     2209                mapped = map != null;
     2210
     2211        for ( ; i < len; i++ ) {
     2212                if ( (elem = unmatched[i]) ) {
     2213                        if ( !filter || filter( elem, context, xml ) ) {
     2214                                newUnmatched.push( elem );
     2215                                if ( mapped ) {
     2216                                        map.push( i );
     2217                                }
     2218                        }
     2219                }
     2220        }
     2221
     2222        return newUnmatched;
     2223}
     2224
     2225function setMatcher( preFilter, selector, matcher, postFilter, postFinder, postSelector ) {
     2226        if ( postFilter && !postFilter[ expando ] ) {
     2227                postFilter = setMatcher( postFilter );
     2228        }
     2229        if ( postFinder && !postFinder[ expando ] ) {
     2230                postFinder = setMatcher( postFinder, postSelector );
     2231        }
     2232        return markFunction(function( seed, results, context, xml ) {
     2233                var temp, i, elem,
     2234                        preMap = [],
     2235                        postMap = [],
     2236                        preexisting = results.length,
     2237
     2238                        // Get initial elements from seed or context
     2239                        elems = seed || multipleContexts( selector || "*", context.nodeType ? [ context ] : context, [] ),
     2240
     2241                        // Prefilter to get matcher input, preserving a map for seed-results synchronization
     2242                        matcherIn = preFilter && ( seed || !selector ) ?
     2243                                condense( elems, preMap, preFilter, context, xml ) :
     2244                                elems,
     2245
     2246                        matcherOut = matcher ?
     2247                                // If we have a postFinder, or filtered seed, or non-seed postFilter or preexisting results,
     2248                                postFinder || ( seed ? preFilter : preexisting || postFilter ) ?
     2249
     2250                                        // ...intermediate processing is necessary
     2251                                        [] :
     2252
     2253                                        // ...otherwise use results directly
     2254                                        results :
     2255                                matcherIn;
     2256
     2257                // Find primary matches
     2258                if ( matcher ) {
     2259                        matcher( matcherIn, matcherOut, context, xml );
     2260                }
     2261
     2262                // Apply postFilter
     2263                if ( postFilter ) {
     2264                        temp = condense( matcherOut, postMap );
     2265                        postFilter( temp, [], context, xml );
     2266
     2267                        // Un-match failing elements by moving them back to matcherIn
     2268                        i = temp.length;
     2269                        while ( i-- ) {
     2270                                if ( (elem = temp[i]) ) {
     2271                                        matcherOut[ postMap[i] ] = !(matcherIn[ postMap[i] ] = elem);
     2272                                }
     2273                        }
     2274                }
     2275
     2276                if ( seed ) {
     2277                        if ( postFinder || preFilter ) {
     2278                                if ( postFinder ) {
     2279                                        // Get the final matcherOut by condensing this intermediate into postFinder contexts
     2280                                        temp = [];
     2281                                        i = matcherOut.length;
     2282                                        while ( i-- ) {
     2283                                                if ( (elem = matcherOut[i]) ) {
     2284                                                        // Restore matcherIn since elem is not yet a final match
     2285                                                        temp.push( (matcherIn[i] = elem) );
     2286                                                }
     2287                                        }
     2288                                        postFinder( null, (matcherOut = []), temp, xml );
     2289                                }
     2290
     2291                                // Move matched elements from seed to results to keep them synchronized
     2292                                i = matcherOut.length;
     2293                                while ( i-- ) {
     2294                                        if ( (elem = matcherOut[i]) &&
     2295                                                (temp = postFinder ? indexOf( seed, elem ) : preMap[i]) > -1 ) {
     2296
     2297                                                seed[temp] = !(results[temp] = elem);
     2298                                        }
     2299                                }
     2300                        }
     2301
     2302                // Add elements to results, through postFinder if defined
     2303                } else {
     2304                        matcherOut = condense(
     2305                                matcherOut === results ?
     2306                                        matcherOut.splice( preexisting, matcherOut.length ) :
     2307                                        matcherOut
     2308                        );
     2309                        if ( postFinder ) {
     2310                                postFinder( null, results, matcherOut, xml );
     2311                        } else {
     2312                                push.apply( results, matcherOut );
     2313                        }
     2314                }
     2315        });
     2316}
     2317
     2318function matcherFromTokens( tokens ) {
     2319        var checkContext, matcher, j,
     2320                len = tokens.length,
     2321                leadingRelative = Expr.relative[ tokens[0].type ],
     2322                implicitRelative = leadingRelative || Expr.relative[" "],
     2323                i = leadingRelative ? 1 : 0,
     2324
     2325                // The foundational matcher ensures that elements are reachable from top-level context(s)
     2326                matchContext = addCombinator( function( elem ) {
     2327                        return elem === checkContext;
     2328                }, implicitRelative, true ),
     2329                matchAnyContext = addCombinator( function( elem ) {
     2330                        return indexOf( checkContext, elem ) > -1;
     2331                }, implicitRelative, true ),
     2332                matchers = [ function( elem, context, xml ) {
     2333                        var ret = ( !leadingRelative && ( xml || context !== outermostContext ) ) || (
     2334                                (checkContext = context).nodeType ?
     2335                                        matchContext( elem, context, xml ) :
     2336                                        matchAnyContext( elem, context, xml ) );
     2337                        // Avoid hanging onto element (issue #299)
     2338                        checkContext = null;
     2339                        return ret;
     2340                } ];
     2341
     2342        for ( ; i < len; i++ ) {
     2343                if ( (matcher = Expr.relative[ tokens[i].type ]) ) {
     2344                        matchers = [ addCombinator(elementMatcher( matchers ), matcher) ];
     2345                } else {
     2346                        matcher = Expr.filter[ tokens[i].type ].apply( null, tokens[i].matches );
     2347
     2348                        // Return special upon seeing a positional matcher
     2349                        if ( matcher[ expando ] ) {
     2350                                // Find the next relative operator (if any) for proper handling
     2351                                j = ++i;
     2352                                for ( ; j < len; j++ ) {
     2353                                        if ( Expr.relative[ tokens[j].type ] ) {
     2354                                                break;
     2355                                        }
     2356                                }
     2357                                return setMatcher(
     2358                                        i > 1 && elementMatcher( matchers ),
     2359                                        i > 1 && toSelector(
     2360                                                // If the preceding token was a descendant combinator, insert an implicit any-element `*`
     2361                                                tokens.slice( 0, i - 1 ).concat({ value: tokens[ i - 2 ].type === " " ? "*" : "" })
     2362                                        ).replace( rtrim, "$1" ),
     2363                                        matcher,
     2364                                        i < j && matcherFromTokens( tokens.slice( i, j ) ),
     2365                                        j < len && matcherFromTokens( (tokens = tokens.slice( j )) ),
     2366                                        j < len && toSelector( tokens )
     2367                                );
     2368                        }
     2369                        matchers.push( matcher );
     2370                }
     2371        }
     2372
     2373        return elementMatcher( matchers );
     2374}
     2375
     2376function matcherFromGroupMatchers( elementMatchers, setMatchers ) {
     2377        var bySet = setMatchers.length > 0,
     2378                byElement = elementMatchers.length > 0,
     2379                superMatcher = function( seed, context, xml, results, outermost ) {
     2380                        var elem, j, matcher,
     2381                                matchedCount = 0,
     2382                                i = "0",
     2383                                unmatched = seed && [],
     2384                                setMatched = [],
     2385                                contextBackup = outermostContext,
     2386                                // We must always have either seed elements or outermost context
     2387                                elems = seed || byElement && Expr.find["TAG"]( "*", outermost ),
     2388                                // Use integer dirruns iff this is the outermost matcher
     2389                                dirrunsUnique = (dirruns += contextBackup == null ? 1 : Math.random() || 0.1),
     2390                                len = elems.length;
     2391
     2392                        if ( outermost ) {
     2393                                outermostContext = context !== document && context;
     2394                        }
     2395
     2396                        // Add elements passing elementMatchers directly to results
     2397                        // Keep `i` a string if there are no elements so `matchedCount` will be "00" below
     2398                        // Support: IE<9, Safari
     2399                        // Tolerate NodeList properties (IE: "length"; Safari: <number>) matching elements by id
     2400                        for ( ; i !== len && (elem = elems[i]) != null; i++ ) {
     2401                                if ( byElement && elem ) {
     2402                                        j = 0;
     2403                                        while ( (matcher = elementMatchers[j++]) ) {
     2404                                                if ( matcher( elem, context, xml ) ) {
     2405                                                        results.push( elem );
     2406                                                        break;
     2407                                                }
     2408                                        }
     2409                                        if ( outermost ) {
     2410                                                dirruns = dirrunsUnique;
     2411                                        }
     2412                                }
     2413
     2414                                // Track unmatched elements for set filters
     2415                                if ( bySet ) {
     2416                                        // They will have gone through all possible matchers
     2417                                        if ( (elem = !matcher && elem) ) {
     2418                                                matchedCount--;
     2419                                        }
     2420
     2421                                        // Lengthen the array for every element, matched or not
     2422                                        if ( seed ) {
     2423                                                unmatched.push( elem );
     2424                                        }
     2425                                }
     2426                        }
     2427
     2428                        // Apply set filters to unmatched elements
     2429                        matchedCount += i;
     2430                        if ( bySet && i !== matchedCount ) {
     2431                                j = 0;
     2432                                while ( (matcher = setMatchers[j++]) ) {
     2433                                        matcher( unmatched, setMatched, context, xml );
     2434                                }
     2435
     2436                                if ( seed ) {
     2437                                        // Reintegrate element matches to eliminate the need for sorting
     2438                                        if ( matchedCount > 0 ) {
     2439                                                while ( i-- ) {
     2440                                                        if ( !(unmatched[i] || setMatched[i]) ) {
     2441                                                                setMatched[i] = pop.call( results );
     2442                                                        }
     2443                                                }
     2444                                        }
     2445
     2446                                        // Discard index placeholder values to get only actual matches
     2447                                        setMatched = condense( setMatched );
     2448                                }
     2449
     2450                                // Add matches to results
     2451                                push.apply( results, setMatched );
     2452
     2453                                // Seedless set matches succeeding multiple successful matchers stipulate sorting
     2454                                if ( outermost && !seed && setMatched.length > 0 &&
     2455                                        ( matchedCount + setMatchers.length ) > 1 ) {
     2456
     2457                                        Sizzle.uniqueSort( results );
     2458                                }
     2459                        }
     2460
     2461                        // Override manipulation of globals by nested matchers
     2462                        if ( outermost ) {
     2463                                dirruns = dirrunsUnique;
     2464                                outermostContext = contextBackup;
     2465                        }
     2466
     2467                        return unmatched;
     2468                };
     2469
     2470        return bySet ?
     2471                markFunction( superMatcher ) :
     2472                superMatcher;
     2473}
     2474
     2475compile = Sizzle.compile = function( selector, match /* Internal Use Only */ ) {
     2476        var i,
     2477                setMatchers = [],
     2478                elementMatchers = [],
     2479                cached = compilerCache[ selector + " " ];
     2480
     2481        if ( !cached ) {
     2482                // Generate a function of recursive functions that can be used to check each element
     2483                if ( !match ) {
     2484                        match = tokenize( selector );
     2485                }
     2486                i = match.length;
     2487                while ( i-- ) {
     2488                        cached = matcherFromTokens( match[i] );
     2489                        if ( cached[ expando ] ) {
     2490                                setMatchers.push( cached );
     2491                        } else {
     2492                                elementMatchers.push( cached );
     2493                        }
     2494                }
     2495
     2496                // Cache the compiled function
     2497                cached = compilerCache( selector, matcherFromGroupMatchers( elementMatchers, setMatchers ) );
     2498
     2499                // Save selector and tokenization
     2500                cached.selector = selector;
     2501        }
     2502        return cached;
     2503};
     2504
     2505/**
     2506 * A low-level selection function that works with Sizzle's compiled
     2507 *  selector functions
     2508 * @param {String|Function} selector A selector or a pre-compiled
     2509 *  selector function built with Sizzle.compile
     2510 * @param {Element} context
     2511 * @param {Array} [results]
     2512 * @param {Array} [seed] A set of elements to match against
     2513 */
     2514select = Sizzle.select = function( selector, context, results, seed ) {
     2515        var i, tokens, token, type, find,
     2516                compiled = typeof selector === "function" && selector,
     2517                match = !seed && tokenize( (selector = compiled.selector || selector) );
     2518
     2519        results = results || [];
     2520
     2521        // Try to minimize operations if there is no seed and only one group
     2522        if ( match.length === 1 ) {
     2523
     2524                // Take a shortcut and set the context if the root selector is an ID
     2525                tokens = match[0] = match[0].slice( 0 );
     2526                if ( tokens.length > 2 && (token = tokens[0]).type === "ID" &&
     2527                                support.getById && context.nodeType === 9 && documentIsHTML &&
     2528                                Expr.relative[ tokens[1].type ] ) {
     2529
     2530                        context = ( Expr.find["ID"]( token.matches[0].replace(runescape, funescape), context ) || [] )[0];
     2531                        if ( !context ) {
     2532                                return results;
     2533
     2534                        // Precompiled matchers will still verify ancestry, so step up a level
     2535                        } else if ( compiled ) {
     2536                                context = context.parentNode;
     2537                        }
     2538
     2539                        selector = selector.slice( tokens.shift().value.length );
     2540                }
     2541
     2542                // Fetch a seed set for right-to-left matching
     2543                i = matchExpr["needsContext"].test( selector ) ? 0 : tokens.length;
     2544                while ( i-- ) {
     2545                        token = tokens[i];
     2546
     2547                        // Abort if we hit a combinator
     2548                        if ( Expr.relative[ (type = token.type) ] ) {
     2549                                break;
     2550                        }
     2551                        if ( (find = Expr.find[ type ]) ) {
     2552                                // Search, expanding context for leading sibling combinators
     2553                                if ( (seed = find(
     2554                                        token.matches[0].replace( runescape, funescape ),
     2555                                        rsibling.test( tokens[0].type ) && testContext( context.parentNode ) || context
     2556                                )) ) {
     2557
     2558                                        // If seed is empty or no tokens remain, we can return early
     2559                                        tokens.splice( i, 1 );
     2560                                        selector = seed.length && toSelector( tokens );
     2561                                        if ( !selector ) {
     2562                                                push.apply( results, seed );
     2563                                                return results;
     2564                                        }
     2565
     2566                                        break;
     2567                                }
     2568                        }
     2569                }
     2570        }
     2571
     2572        // Compile and execute a filtering function if one is not provided
     2573        // Provide `match` to avoid retokenization if we modified the selector above
     2574        ( compiled || compile( selector, match ) )(
     2575                seed,
     2576                context,
     2577                !documentIsHTML,
     2578                results,
     2579                rsibling.test( selector ) && testContext( context.parentNode ) || context
     2580        );
     2581        return results;
     2582};
     2583
     2584// One-time assignments
     2585
     2586// Sort stability
     2587support.sortStable = expando.split("").sort( sortOrder ).join("") === expando;
     2588
     2589// Support: Chrome 14-35+
     2590// Always assume duplicates if they aren't passed to the comparison function
     2591support.detectDuplicates = !!hasDuplicate;
     2592
     2593// Initialize against the default document
     2594setDocument();
     2595
     2596// Support: Webkit<537.32 - Safari 6.0.3/Chrome 25 (fixed in Chrome 27)
     2597// Detached nodes confoundingly follow *each other*
     2598support.sortDetached = assert(function( div1 ) {
     2599        // Should return 1, but returns 4 (following)
     2600        return div1.compareDocumentPosition( document.createElement("div") ) & 1;
     2601});
     2602
     2603// Support: IE<8
     2604// Prevent attribute/property "interpolation"
     2605// http://msdn.microsoft.com/en-us/library/ms536429%28VS.85%29.aspx
     2606if ( !assert(function( div ) {
     2607        div.innerHTML = "<a href='#'></a>";
     2608        return div.firstChild.getAttribute("href") === "#" ;
     2609}) ) {
     2610        addHandle( "type|href|height|width", function( elem, name, isXML ) {
     2611                if ( !isXML ) {
     2612                        return elem.getAttribute( name, name.toLowerCase() === "type" ? 1 : 2 );
     2613                }
     2614        });
     2615}
     2616
     2617// Support: IE<9
     2618// Use defaultValue in place of getAttribute("value")
     2619if ( !support.attributes || !assert(function( div ) {
     2620        div.innerHTML = "<input/>";
     2621        div.firstChild.setAttribute( "value", "" );
     2622        return div.firstChild.getAttribute( "value" ) === "";
     2623}) ) {
     2624        addHandle( "value", function( elem, name, isXML ) {
     2625                if ( !isXML && elem.nodeName.toLowerCase() === "input" ) {
     2626                        return elem.defaultValue;
     2627                }
     2628        });
     2629}
     2630
     2631// Support: IE<9
     2632// Use getAttributeNode to fetch booleans when getAttribute lies
     2633if ( !assert(function( div ) {
     2634        return div.getAttribute("disabled") == null;
     2635}) ) {
     2636        addHandle( booleans, function( elem, name, isXML ) {
     2637                var val;
     2638                if ( !isXML ) {
     2639                        return elem[ name ] === true ? name.toLowerCase() :
     2640                                        (val = elem.getAttributeNode( name )) && val.specified ?
     2641                                        val.value :
     2642                                null;
     2643                }
     2644        });
     2645}
     2646
     2647return Sizzle;
     2648
     2649})( window );
     2650
     2651
     2652
     2653jQuery.find = Sizzle;
     2654jQuery.expr = Sizzle.selectors;
     2655jQuery.expr[":"] = jQuery.expr.pseudos;
     2656jQuery.unique = Sizzle.uniqueSort;
     2657jQuery.text = Sizzle.getText;
     2658jQuery.isXMLDoc = Sizzle.isXML;
     2659jQuery.contains = Sizzle.contains;
     2660
     2661
     2662
     2663var rneedsContext = jQuery.expr.match.needsContext;
     2664
     2665var rsingleTag = (/^<(\w+)\s*\/?>(?:<\/\1>|)$/);
     2666
     2667
     2668
     2669var risSimple = /^.[^:#\[\.,]*$/;
     2670
     2671// Implement the identical functionality for filter and not
     2672function winnow( elements, qualifier, not ) {
     2673        if ( jQuery.isFunction( qualifier ) ) {
     2674                return jQuery.grep( elements, function( elem, i ) {
     2675                        /* jshint -W018 */
     2676                        return !!qualifier.call( elem, i, elem ) !== not;
     2677                });
     2678
     2679        }
     2680
     2681        if ( qualifier.nodeType ) {
     2682                return jQuery.grep( elements, function( elem ) {
     2683                        return ( elem === qualifier ) !== not;
     2684                });
     2685
     2686        }
     2687
     2688        if ( typeof qualifier === "string" ) {
     2689                if ( risSimple.test( qualifier ) ) {
     2690                        return jQuery.filter( qualifier, elements, not );
     2691                }
     2692
     2693                qualifier = jQuery.filter( qualifier, elements );
     2694        }
     2695
     2696        return jQuery.grep( elements, function( elem ) {
     2697                return ( jQuery.inArray( elem, qualifier ) >= 0 ) !== not;
     2698        });
     2699}
     2700
     2701jQuery.filter = function( expr, elems, not ) {
     2702        var elem = elems[ 0 ];
     2703
     2704        if ( not ) {
     2705                expr = ":not(" + expr + ")";
     2706        }
     2707
     2708        return elems.length === 1 && elem.nodeType === 1 ?
     2709                jQuery.find.matchesSelector( elem, expr ) ? [ elem ] : [] :
     2710                jQuery.find.matches( expr, jQuery.grep( elems, function( elem ) {
     2711                        return elem.nodeType === 1;
     2712                }));
     2713};
     2714
     2715jQuery.fn.extend({
     2716        find: function( selector ) {
     2717                var i,
     2718                        ret = [],
     2719                        self = this,
     2720                        len = self.length;
     2721
     2722                if ( typeof selector !== "string" ) {
     2723                        return this.pushStack( jQuery( selector ).filter(function() {
     2724                                for ( i = 0; i < len; i++ ) {
     2725                                        if ( jQuery.contains( self[ i ], this ) ) {
     2726                                                return true;
     2727                                        }
     2728                                }
     2729                        }) );
     2730                }
     2731
     2732                for ( i = 0; i < len; i++ ) {
     2733                        jQuery.find( selector, self[ i ], ret );
     2734                }
     2735
     2736                // Needed because $( selector, context ) becomes $( context ).find( selector )
     2737                ret = this.pushStack( len > 1 ? jQuery.unique( ret ) : ret );
     2738                ret.selector = this.selector ? this.selector + " " + selector : selector;
     2739                return ret;
     2740        },
     2741        filter: function( selector ) {
     2742                return this.pushStack( winnow(this, selector || [], false) );
     2743        },
     2744        not: function( selector ) {
     2745                return this.pushStack( winnow(this, selector || [], true) );
     2746        },
     2747        is: function( selector ) {
     2748                return !!winnow(
     2749                        this,
     2750
     2751                        // If this is a positional/relative selector, check membership in the returned set
     2752                        // so $("p:first").is("p:last") won't return true for a doc with two "p".
     2753                        typeof selector === "string" && rneedsContext.test( selector ) ?
     2754                                jQuery( selector ) :
     2755                                selector || [],
     2756                        false
     2757                ).length;
     2758        }
     2759});
     2760
     2761
     2762// Initialize a jQuery object
     2763
     2764
     2765// A central reference to the root jQuery(document)
     2766var rootjQuery,
     2767
     2768        // Use the correct document accordingly with window argument (sandbox)
     2769        document = window.document,
     2770
     2771        // A simple way to check for HTML strings
     2772        // Prioritize #id over <tag> to avoid XSS via location.hash (#9521)
     2773        // Strict HTML recognition (#11290: must start with <)
     2774        rquickExpr = /^(?:\s*(<[\w\W]+>)[^>]*|#([\w-]*))$/,
     2775
     2776        init = jQuery.fn.init = function( selector, context ) {
     2777                var match, elem;
     2778
     2779                // HANDLE: $(""), $(null), $(undefined), $(false)
    972780                if ( !selector ) {
    982781                        return this;
    992782                }
    1002783
    101                 // Handle $(DOMElement)
    102                 if ( selector.nodeType ) {
    103                         this.context = this[0] = selector;
    104                         this.length = 1;
    105                         return this;
    106                 }
    107 
    108                 // The body element only exists once, optimize finding it
    109                 if ( selector === "body" && !context && document.body ) {
    110                         this.context = document;
    111                         this[0] = document.body;
    112                         this.selector = selector;
    113                         this.length = 1;
    114                         return this;
    115                 }
    116 
    1172784                // Handle HTML strings
    1182785                if ( typeof selector === "string" ) {
    119                         // Are we dealing with HTML string or an ID?
    1202786                        if ( selector.charAt(0) === "<" && selector.charAt( selector.length - 1 ) === ">" && selector.length >= 3 ) {
    1212787                                // Assume that strings that start and end with <> are HTML and skip the regex check
     
    1232789
    1242790                        } else {
    125                                 match = quickExpr.exec( selector );
    126                         }
    127 
    128                         // Verify a match, and that no context was specified for #id
     2791                                match = rquickExpr.exec( selector );
     2792                        }
     2793
     2794                        // Match html or make sure no context is specified for #id
    1292795                        if ( match && (match[1] || !context) ) {
    1302796
     
    1322798                                if ( match[1] ) {
    1332799                                        context = context instanceof jQuery ? context[0] : context;
    134                                         doc = (context ? context.ownerDocument || context : document);
    135 
    136                                         // If a single string is passed in and it's a single tag
    137                                         // just do a createElement and skip the rest
    138                                         ret = rsingleTag.exec( selector );
    139 
    140                                         if ( ret ) {
    141                                                 if ( jQuery.isPlainObject( context ) ) {
    142                                                         selector = [ document.createElement( ret[1] ) ];
    143                                                         jQuery.fn.attr.call( selector, context, true );
    144 
    145                                                 } else {
    146                                                         selector = [ doc.createElement( ret[1] ) ];
     2800
     2801                                        // scripts is true for back-compat
     2802                                        // Intentionally let the error be thrown if parseHTML is not present
     2803                                        jQuery.merge( this, jQuery.parseHTML(
     2804                                                match[1],
     2805                                                context && context.nodeType ? context.ownerDocument || context : document,
     2806                                                true
     2807                                        ) );
     2808
     2809                                        // HANDLE: $(html, props)
     2810                                        if ( rsingleTag.test( match[1] ) && jQuery.isPlainObject( context ) ) {
     2811                                                for ( match in context ) {
     2812                                                        // Properties of context are called as methods if possible
     2813                                                        if ( jQuery.isFunction( this[ match ] ) ) {
     2814                                                                this[ match ]( context[ match ] );
     2815
     2816                                                        // ...and otherwise set as attributes
     2817                                                        } else {
     2818                                                                this.attr( match, context[ match ] );
     2819                                                        }
    1472820                                                }
    148 
    149                                         } else {
    150                                                 ret = jQuery.buildFragment( [ match[1] ], [ doc ] );
    151                                                 selector = (ret.cacheable ? jQuery.clone(ret.fragment) : ret.fragment).childNodes;
    1522821                                        }
    1532822
    154                                         return jQuery.merge( this, selector );
    155 
    156                                 // HANDLE: $("#id")
     2823                                        return this;
     2824
     2825                                // HANDLE: $(#id)
    1572826                                } else {
    1582827                                        elem = document.getElementById( match[2] );
     
    1792848                        // HANDLE: $(expr, $(...))
    1802849                        } else if ( !context || context.jquery ) {
    181                                 return (context || rootjQuery).find( selector );
     2850                                return ( context || rootjQuery ).find( selector );
    1822851
    1832852                        // HANDLE: $(expr, context)
     
    1872856                        }
    1882857
     2858                // HANDLE: $(DOMElement)
     2859                } else if ( selector.nodeType ) {
     2860                        this.context = this[0] = selector;
     2861                        this.length = 1;
     2862                        return this;
     2863
    1892864                // HANDLE: $(function)
    1902865                // Shortcut for document ready
    1912866                } else if ( jQuery.isFunction( selector ) ) {
    192                         return rootjQuery.ready( selector );
    193                 }
    194 
    195                 if (selector.selector !== undefined) {
     2867                        return typeof rootjQuery.ready !== "undefined" ?
     2868                                rootjQuery.ready( selector ) :
     2869                                // Execute immediately if ready is not present
     2870                                selector( jQuery );
     2871                }
     2872
     2873                if ( selector.selector !== undefined ) {
    1962874                        this.selector = selector.selector;
    1972875                        this.context = selector.context;
     
    1992877
    2002878                return jQuery.makeArray( selector, this );
    201         },
    202 
    203         // Start with an empty selector
    204         selector: "",
    205 
    206         // The current version of jQuery being used
    207         jquery: "1.6",
    208 
    209         // The default length of a jQuery object is 0
    210         length: 0,
    211 
    212         // The number of elements contained in the matched element set
    213         size: function() {
    214                 return this.length;
    215         },
    216 
    217         toArray: function() {
    218                 return slice.call( this, 0 );
    219         },
    220 
    221         // Get the Nth element in the matched element set OR
    222         // Get the whole matched element set as a clean array
    223         get: function( num ) {
    224                 return num == null ?
    225 
    226                         // Return a 'clean' array
    227                         this.toArray() :
    228 
    229                         // Return just the object
    230                         ( num < 0 ? this[ this.length + num ] : this[ num ] );
    231         },
    232 
    233         // Take an array of elements and push it onto the stack
    234         // (returning the new matched element set)
    235         pushStack: function( elems, name, selector ) {
    236                 // Build a new jQuery matched element set
    237                 var ret = this.constructor();
    238 
    239                 if ( jQuery.isArray( elems ) ) {
    240                         push.apply( ret, elems );
    241 
    242                 } else {
    243                         jQuery.merge( ret, elems );
    244                 }
    245 
    246                 // Add the old object onto the stack (as a reference)
    247                 ret.prevObject = this;
    248 
    249                 ret.context = this.context;
    250 
    251                 if ( name === "find" ) {
    252                         ret.selector = this.selector + (this.selector ? " " : "") + selector;
    253                 } else if ( name ) {
    254                         ret.selector = this.selector + "." + name + "(" + selector + ")";
    255                 }
    256 
    257                 // Return the newly-formed element set
    258                 return ret;
    259         },
    260 
    261         // Execute a callback for every element in the matched set.
    262         // (You can seed the arguments with an array of args, but this is
    263         // only used internally.)
    264         each: function( callback, args ) {
    265                 return jQuery.each( this, callback, args );
    266         },
    267 
    268         ready: function( fn ) {
    269                 // Attach the listeners
    270                 jQuery.bindReady();
    271 
    272                 // Add the callback
    273                 readyList.done( fn );
    274 
    275                 return this;
    276         },
    277 
    278         eq: function( i ) {
    279                 return i === -1 ?
    280                         this.slice( i ) :
    281                         this.slice( i, +i + 1 );
    282         },
    283 
    284         first: function() {
    285                 return this.eq( 0 );
    286         },
    287 
    288         last: function() {
    289                 return this.eq( -1 );
    290         },
    291 
    292         slice: function() {
    293                 return this.pushStack( slice.apply( this, arguments ),
    294                         "slice", slice.call(arguments).join(",") );
    295         },
    296 
    297         map: function( callback ) {
    298                 return this.pushStack( jQuery.map(this, function( elem, i ) {
    299                         return callback.call( elem, i, elem );
    300                 }));
    301         },
    302 
    303         end: function() {
    304                 return this.prevObject || this.constructor(null);
    305         },
    306 
    307         // For internal use only.
    308         // Behaves like an Array's method, not like a jQuery method.
    309         push: push,
    310         sort: [].sort,
    311         splice: [].splice
    312 };
     2879        };
    3132880
    3142881// Give the init function the jQuery prototype for later instantiation
    315 jQuery.fn.init.prototype = jQuery.fn;
    316 
    317 jQuery.extend = jQuery.fn.extend = function() {
    318         var options, name, src, copy, copyIsArray, clone,
    319                 target = arguments[0] || {},
    320                 i = 1,
    321                 length = arguments.length,
    322                 deep = false;
    323 
    324         // Handle a deep copy situation
    325         if ( typeof target === "boolean" ) {
    326                 deep = target;
    327                 target = arguments[1] || {};
    328                 // skip the boolean and the target
    329                 i = 2;
    330         }
    331 
    332         // Handle case when target is a string or something (possible in deep copy)
    333         if ( typeof target !== "object" && !jQuery.isFunction(target) ) {
    334                 target = {};
    335         }
    336 
    337         // extend jQuery itself if only one argument is passed
    338         if ( length === i ) {
    339                 target = this;
    340                 --i;
    341         }
    342 
    343         for ( ; i < length; i++ ) {
    344                 // Only deal with non-null/undefined values
    345                 if ( (options = arguments[ i ]) != null ) {
    346                         // Extend the base object
    347                         for ( name in options ) {
    348                                 src = target[ name ];
    349                                 copy = options[ name ];
    350 
    351                                 // Prevent never-ending loop
    352                                 if ( target === copy ) {
    353                                         continue;
    354                                 }
    355 
    356                                 // Recurse if we're merging plain objects or arrays
    357                                 if ( deep && copy && ( jQuery.isPlainObject(copy) || (copyIsArray = jQuery.isArray(copy)) ) ) {
    358                                         if ( copyIsArray ) {
    359                                                 copyIsArray = false;
    360                                                 clone = src && jQuery.isArray(src) ? src : [];
    361 
    362                                         } else {
    363                                                 clone = src && jQuery.isPlainObject(src) ? src : {};
    364                                         }
    365 
    366                                         // Never move original objects, clone them
    367                                         target[ name ] = jQuery.extend( deep, clone, copy );
    368 
    369                                 // Don't bring in undefined values
    370                                 } else if ( copy !== undefined ) {
    371                                         target[ name ] = copy;
    372                                 }
    373                         }
    374                 }
    375         }
    376 
    377         // Return the modified object
    378         return target;
    379 };
    380 
    381 jQuery.extend({
    382         noConflict: function( deep ) {
    383                 if ( window.$ === jQuery ) {
    384                         window.$ = _$;
    385                 }
    386 
    387                 if ( deep && window.jQuery === jQuery ) {
    388                         window.jQuery = _jQuery;
    389                 }
    390 
    391                 return jQuery;
    392         },
    393 
    394         // Is the DOM ready to be used? Set to true once it occurs.
    395         isReady: false,
    396 
    397         // A counter to track how many items to wait for before
    398         // the ready event fires. See #6781
    399         readyWait: 1,
    400 
    401         // Hold (or release) the ready event
    402         holdReady: function( hold ) {
    403                 if ( hold ) {
    404                         jQuery.readyWait++;
    405                 } else {
    406                         jQuery.ready( true );
    407                 }
    408         },
    409 
    410         // Handle when the DOM is ready
    411         ready: function( wait ) {
    412                 // Either a released hold or an DOMready/load event and not yet ready
    413                 if ( (wait === true && !--jQuery.readyWait) || (wait !== true && !jQuery.isReady) ) {
    414                         // Make sure body exists, at least, in case IE gets a little overzealous (ticket #5443).
    415                         if ( !document.body ) {
    416                                 return setTimeout( jQuery.ready, 1 );
    417                         }
    418 
    419                         // Remember that the DOM is ready
    420                         jQuery.isReady = true;
    421 
    422                         // If a normal DOM Ready event fired, decrement, and wait if need be
    423                         if ( wait !== true && --jQuery.readyWait > 0 ) {
    424                                 return;
    425                         }
    426 
    427                         // If there are functions bound, to execute
    428                         readyList.resolveWith( document, [ jQuery ] );
    429 
    430                         // Trigger any bound ready events
    431                         if ( jQuery.fn.trigger ) {
    432                                 jQuery( document ).trigger( "ready" ).unbind( "ready" );
    433                         }
    434                 }
    435         },
    436 
    437         bindReady: function() {
    438                 if ( readyList ) {
    439                         return;
    440                 }
    441 
    442                 readyList = jQuery._Deferred();
    443 
    444                 // Catch cases where $(document).ready() is called after the
    445                 // browser event has already occurred.
    446                 if ( document.readyState === "complete" ) {
    447                         // Handle it asynchronously to allow scripts the opportunity to delay ready
    448                         return setTimeout( jQuery.ready, 1 );
    449                 }
    450 
    451                 // Mozilla, Opera and webkit nightlies currently support this event
    452                 if ( document.addEventListener ) {
    453                         // Use the handy event callback
    454                         document.addEventListener( "DOMContentLoaded", DOMContentLoaded, false );
    455 
    456                         // A fallback to window.onload, that will always work
    457                         window.addEventListener( "load", jQuery.ready, false );
    458 
    459                 // If IE event model is used
    460                 } else if ( document.attachEvent ) {
    461                         // ensure firing before onload,
    462                         // maybe late but safe also for iframes
    463                         document.attachEvent( "onreadystatechange", DOMContentLoaded );
    464 
    465                         // A fallback to window.onload, that will always work
    466                         window.attachEvent( "onload", jQuery.ready );
    467 
    468                         // If IE and not a frame
    469                         // continually check to see if the document is ready
    470                         var toplevel = false;
    471 
    472                         try {
    473                                 toplevel = window.frameElement == null;
    474                         } catch(e) {}
    475 
    476                         if ( document.documentElement.doScroll && toplevel ) {
    477                                 doScrollCheck();
    478                         }
    479                 }
    480         },
    481 
    482         // See test/unit/core.js for details concerning isFunction.
    483         // Since version 1.3, DOM methods and functions like alert
    484         // aren't supported. They return false on IE (#2968).
    485         isFunction: function( obj ) {
    486                 return jQuery.type(obj) === "function";
    487         },
    488 
    489         isArray: Array.isArray || function( obj ) {
    490                 return jQuery.type(obj) === "array";
    491         },
    492 
    493         // A crude way of determining if an object is a window
    494         isWindow: function( obj ) {
    495                 return obj && typeof obj === "object" && "setInterval" in obj;
    496         },
    497 
    498         isNaN: function( obj ) {
    499                 return obj == null || !rdigit.test( obj ) || isNaN( obj );
    500         },
    501 
    502         type: function( obj ) {
    503                 return obj == null ?
    504                         String( obj ) :
    505                         class2type[ toString.call(obj) ] || "object";
    506         },
    507 
    508         isPlainObject: function( obj ) {
    509                 // Must be an Object.
    510                 // Because of IE, we also have to check the presence of the constructor property.
    511                 // Make sure that DOM nodes and window objects don't pass through, as well
    512                 if ( !obj || jQuery.type(obj) !== "object" || obj.nodeType || jQuery.isWindow( obj ) ) {
    513                         return false;
    514                 }
    515 
    516                 // Not own constructor property must be Object
    517                 if ( obj.constructor &&
    518                         !hasOwn.call(obj, "constructor") &&
    519                         !hasOwn.call(obj.constructor.prototype, "isPrototypeOf") ) {
    520                         return false;
    521                 }
    522 
    523                 // Own properties are enumerated firstly, so to speed up,
    524                 // if last one is own, then all properties are own.
    525 
    526                 var key;
    527                 for ( key in obj ) {}
    528 
    529                 return key === undefined || hasOwn.call( obj, key );
    530         },
    531 
    532         isEmptyObject: function( obj ) {
    533                 for ( var name in obj ) {
    534                         return false;
    535                 }
    536                 return true;
    537         },
    538 
    539         error: function( msg ) {
    540                 throw msg;
    541         },
    542 
    543         parseJSON: function( data ) {
    544                 if ( typeof data !== "string" || !data ) {
    545                         return null;
    546                 }
    547 
    548                 // Make sure leading/trailing whitespace is removed (IE can't handle it)
    549                 data = jQuery.trim( data );
    550 
    551                 // Attempt to parse using the native JSON parser first
    552                 if ( window.JSON && window.JSON.parse ) {
    553                         return window.JSON.parse( data );
    554                 }
    555 
    556                 // Make sure the incoming data is actual JSON
    557                 // Logic borrowed from http://json.org/json2.js
    558                 if ( rvalidchars.test( data.replace( rvalidescape, "@" )
    559                         .replace( rvalidtokens, "]" )
    560                         .replace( rvalidbraces, "")) ) {
    561 
    562                         return (new Function( "return " + data ))();
    563 
    564                 }
    565                 jQuery.error( "Invalid JSON: " + data );
    566         },
    567 
    568         // Cross-browser xml parsing
    569         // (xml & tmp used internally)
    570         parseXML: function( data , xml , tmp ) {
    571 
    572                 if ( window.DOMParser ) { // Standard
    573                         tmp = new DOMParser();
    574                         xml = tmp.parseFromString( data , "text/xml" );
    575                 } else { // IE
    576                         xml = new ActiveXObject( "Microsoft.XMLDOM" );
    577                         xml.async = "false";
    578                         xml.loadXML( data );
    579                 }
    580 
    581                 tmp = xml.documentElement;
    582 
    583                 if ( ! tmp || ! tmp.nodeName || tmp.nodeName === "parsererror" ) {
    584                         jQuery.error( "Invalid XML: " + data );
    585                 }
    586 
    587                 return xml;
    588         },
    589 
    590         noop: function() {},
    591 
    592         // Evaluates a script in a global context
    593         // Workarounds based on findings by Jim Driscoll
    594         // http://weblogs.java.net/blog/driscoll/archive/2009/09/08/eval-javascript-global-context
    595         globalEval: function( data ) {
    596                 if ( data && rnotwhite.test( data ) ) {
    597