• jquery core 源码分析


    1. **  
    2.  * author:prk  
    3.  * date:2008-08-05  
    4.  * comment:analeyse the core of jquery1.2.6  
    5.  *     
    6.  */  
    7.   
    8. /*  
    9.  * jQuery  
    10.  *   
    11.  * @VERSION - New Wave Javascript  
    12.  *   
    13.  * Copyright (c) 2008 John Resig (jquery.com) Dual licensed under the MIT  
    14.  * (MIT-LICENSE.txt) and GPL (GPL-LICENSE.txt) licenses.  
    15.  *   
    16.  * $Date: 2008-07-24 01:00:32 +0800 (Thu, 24 Jul 2008) $ $Rev: 5793 $  
    17.  */  
    18.   
    19. // Map over jQuery in case of overwrite   
    20. var _jQuery = window.jQuery,   
    21. // Map over the $ in case of overwriteff   
    22. _$ = window.$;   
    23.   
    24. var jQuery = window.jQuery = window.$ = function(selector, context) {   
    25.     // The jQuery object is actually just the init constructor 'enhanced'   
    26.     return new jQuery.fn.init(selector, context);   
    27. };   
    28.   
    29. // A simple way to check for HTML strings or ID strings   
    30. // (both of which we optimize for)   
    31. var quickExpr = /^[^<]*(<(.|\s)+>)[^>]*$|^#([\w-]+)$/,   
    32.   
    33. // Is it a simple selector   
    34. isSimple = /^.[^:#\[\.]*$/,   
    35.   
    36. // Will speed up references to undefined, and allows munging its name.   
    37. undefined;   
    38.   
    39. jQuery.fn = jQuery.prototype = {   
    40.     init : function(selector, context) {   
    41.         selector = selector || document;// 确定selector存在   
    42.   
    43.         // 第一种情况 Handle $(DOMElement)单个Dom 元素,忽略上下文   
    44.         if (selector.nodeType) {   
    45.             this[0] = selector;   
    46.             this.length = 1;   
    47.             return this;   
    48.         }          
    49.         if (typeof selector == "string") {//selector为string   
    50.             // Are we dealing with HTML string or an ID?   
    51.             var match = quickExpr.exec(selector);   
    52.             // Verify a match, and that no context was specified for #id   
    53.             if (match && (match[1] || !context)) {   
    54.                 if (match[1])// 第二种情况处理$(html) -> $(array)   
    55.                     selector = jQuery.clean([match[1]], context);   
    56.                 else {// 第三种情况:HANDLE: $("#id")//处理$("#id")   
    57.                     var elem = document.getElementById(match[3]);   
    58.   
    59.                     // Make sure an element was located   
    60.                     if (elem) {   
    61.                         // Handle the case where IE and Opera return items   
    62.                         // by name instead of ID   
    63.                         if (elem.id != match[3])   
    64.                             return jQuery().find(selector);// 默认是document.find()   
    65.   
    66.                         // Otherwise, we inject the element directly into the   
    67.                         // jQuery object   
    68.                         return jQuery(elem);   
    69.                     }   
    70.                     selector = [];   
    71.                 }   
    72.             } else  
    73.                 // 第四种情况:处理$(expr, [context])==$(content).find(expr)   
    74.                 return jQuery(context).find(selector);   
    75.         } else if (jQuery.isFunction(selector))   
    76.             // 第五种情况:处理$(function)七Shortcut for document ready   
    77.             return jQuery(document)[jQuery.fn.ready ? "ready" : "load"](selector);   
    78.   
    79.         // 第六种情况:处理$(elements)   
    80.         return this.setArray(jQuery.makeArray(selector));   
    81.     },   
    82.   
    83.     // 当前的版本号   
    84.     jquery : "@VERSION",   
    85.   
    86.     // jquery对象中的元素的个数。jquery像数组。能通过$('p')[0]去取得Dom对象。   
    87.     size : function() {   
    88.         return this.length;   
    89.     },   
    90.     // jquery对象的元素的个数   
    91.     length : 0,   
    92.   
    93.     // 取到本jquery对象的第几个Dom元素,无参数,代表全部的Dom元素   
    94.     get : function(num) {   
    95.         return num == undefined ? jQuery.makeArray(this) : this[num];   
    96.     },   
    97.   
    98.     // 采用jQuery构建新对象,同时引用老对象。   
    99.     pushStack : function(elems) {   
    100.         var ret = jQuery(elems);// 构建新的jquery对象   
    101.         ret.prevObject = this;// 保存老的对象的引用   
    102.         return ret;   
    103.     },   
    104.   
    105.     // 把array-like对象的元素全部push当前jquery对象。   
    106.     setArray : function(elems) {   
    107.         this.length = 0;   
    108.         Array.prototype.push.apply(this, elems);   
    109.         return this;   
    110.     },   
    111.   
    112.     // 当前jquery对象中每个元素都执行callback(index,elem)函数   
    113.     each : function(callback, args) {// 返回this   
    114.         // 其调用了jQuery的静态方法。prototype中的mothodize是解决这类问题的好方法   
    115.         return jQuery.each(this, callback, args);   
    116.     },   
    117.   
    118.     // 找到elem在本jquery对象的位置(index)   
    119.     index : function(elem) {   
    120.         var ret = -1;   
    121.         return jQuery.inArray( // 如是jQuery对象就取第一个元素   
    122.                 elem && elem.jquery ? elem[0] : elem, this);   
    123.     },   
    124.   
    125.     // attr(properties)   
    126.     // 将“名/值”形式的对象设置为所有匹配元素的属性。   
    127.     // attr(name)   
    128.     // 取得第一个匹配元素的属性值。通过这个方法可以方便地从第一个匹配元素中获取一个属性的值。如果元素没有相应属性,则返回 undefined 。   
    129.     // attr(key,value)   
    130.     // 为所有匹配的元素设置一个属性值。$("img").attr("src","test.jpg");   
    131.     // attr(key,fn)   
    132.     // 为所有匹配的元素设置一个由这个函数计算的值做属性值。   
    133.     attr : function(name, value, type) {   
    134.         var options = name;// 支持"名/值"形式的对象和string   
    135.         if (name.constructor == String)   
    136.             if (value === undefined)   
    137.                 // 调用curCss,attr静态方法返回本对象第一个元素的name的属性值   
    138.                 return this[0] && jQuery[type || "attr"](this[0], name);   
    139.             else {// 设定属性值,把name String 转换成"名/值"对象,便于统一的处理   
    140.                 options = {};   
    141.                 options[name] = value;   
    142.             }   
    143.         return this.each(function(i) {// 为每个元素的指定的name属性设值   
    144.                     for (name in options)   
    145.                         // value=options[name],可以是Fn(index),this-->each elem   
    146.                         jQuery.attr(type ? this.style : this, name, jQuery   
    147.                                 .prop(this, options[name], type, i, name));   
    148.                 });   
    149.     },   
    150.   
    151.     // css(name)   
    152.     // 访问第一个匹配元素的样式属性。   
    153.     // css(name,value)   
    154.     // 在所有匹配的元素中,设置一个样式属性的值。数字将自动转化为像素值   
    155.     // css(properties)   
    156.     // 把一个“名/值对”对象设置为所有匹配元素的样式属性。这是一种在所有匹配的元素上设置大量样式属性的最佳方式。   
    157.     css : function(key, value) {   
    158.   
    159.         if ((key == 'width' || key == 'height') && parseFloat(value) < 0)   
    160.             value = undefined;// 忽略负数   
    161.         return this.attr(key, value, "curCSS");// 调用了curCSS方法   
    162.     },   
    163.   
    164.     // text()   
    165.     // 取得所有匹配元素的内容。结果是由所有匹配元素包含的文本内容组合起来的文本。这个方法对HTML和XML文档都有效。   
    166.     // text(val)   
    167.     // 设置所有匹配元素的文本内容.与 html() 类似, 但将编码 HTML (将 "<" 和 ">" 替换成相应的HTML实体).   
    168.     text : function(text) {   
    169.         if (typeof text != "object" && text != null)   
    170.             return this.empty()// 除去所有的子元素,加上创建的文本节点   
    171.                     .append((this[0] && this[0].ownerDocument || document)   
    172.                             .createTextNode(text));   
    173.   
    174.         var ret = "";   
    175.         jQuery.each(text || this, function() {// 所有匹配元素包含的文本内容组合起来   
    176.                     jQuery.each(this.childNodes, function() {   
    177.                         if (this.nodeType != 8)// 8:注释   
    178.                                 ret += (this.nodeType != 1// 元素的话,递归子元素   
    179.                                         ? this.nodeValue   
    180.                                         : jQuery.fn.text([this]));   
    181.                         });   
    182.                 });   
    183.   
    184.         return ret;   
    185.     },   
    186.   
    187.     // *****************************************************************************   
    188.     // 一组用于元素标签包裹操作的函数   
    189.   
    190.     // 将所有匹配的元素用单个元素包裹起来   
    191.     // 这个函数的原理是检查提供的第一个元素并在它的代码结构中找到最上层的祖先元素--这个祖先元素就是包装元素。   
    192.     // 这于 '.wrap()' 是不同的,'.wrap()'为每一个匹配的元素都包裹一次。   
    193.     wrapAll : function(html) {   
    194.         if (this[0])   
    195.             /*  
    196.              * <p>Hello</p><p>cruel</p><p>World</p>。-->  
    197.              * $("p").wrapAll("<div></div>");-->调用wrapAll的jQuery对象,称:A。有三个元素。  
    198.              * 第一步:复制生成一个jQuery对象,称:B。得到:<div></div>的元素。  
    199.              * 第二步:把B所有的元素都插在A[0]元素之前,得到<div></div><p>Hello</p><p>cruel</p><p>World</p>  
    200.              * 第三步:找到B对象中所有元素的最内面的节点,如<div> </div>。称:inner Node;  
    201.              * 第四步:向所有innerNode内部插入A对象的所有元素,得到<div><p>Hello</p><p>cruel</p><p>World</p></div>  
    202.              */  
    203.             jQuery(html, this[0].ownerDocument).clone().insertBefore(this[0])   
    204.                     .map(function() {// 找到当前元素的最下层的子节点   
    205.                         var elem = this;   
    206.                         while (elem.firstChild)   
    207.                             elem = elem.firstChild;   
    208.                         return elem;   
    209.                     }).append(this);// this指是调用wrapAll的jQuery对象。   
    210.   
    211.         return this;   
    212.     },   
    213.   
    214.     // 将每一个匹配的元素的子内容(包括文本节点)用一个HTML结构包裹起来   
    215.     wrapInner : function(html) {   
    216.         return this.each(function() {// 这里包裹的对象是每个元素的对象的contents()   
    217.                     jQuery(this).contents().wrapAll(html);   
    218.                 });   
    219.     },   
    220.   
    221.     // 对于当前的jquery对象的每个元素都执行wrapAll(html)   
    222.     wrap : function(html) {   
    223.         return this.each(function() {// 这里包裹的对象是每个元素的对象   
    224.                     jQuery(this).wrapAll(html);   
    225.                 });   
    226.     },   
    227.   
    228.     // ************************************************************************   
    229.   
    230.     // ******************************************************************   
    231.     // 该组方法主要是完成把元素插到什么地方,与Ext的DomHelp的功能相似。   
    232.     // 在一个元素之前,之后,元素的开始,结束位置   
    233.   
    234.     // 向每个匹配的元素内部追加内容。   
    235.     // 这个操作与对指定的元素执行appendChild方法,将它们添加到文档中的情况类似   
    236.     append : function() {   
    237.         return this.domManip(arguments, truefalse, function(elem) {   
    238.             if (this.nodeType == 1)   
    239.                 this.appendChild(elem);   
    240.         });   
    241.     },   
    242.     // 向每个匹配的元素内部前置内容。   
    243.     // 这是向所有匹配元素内部的开始处插入内容的最佳方式。   
    244.     prepend : function() {// elem =arguments的转化集合中的dom元素   
    245.         return this.domManip(arguments, truetrue, function(elem) {   
    246.             if (this.nodeType == 1)// this=jQuery对象的每个元素(对于tr之类会修正)   
    247.                     this.insertBefore(elem, this.firstChild);   
    248.             });   
    249.     },   
    250.   
    251.     // 在每个匹配的元素之前插入内容。   
    252.     before : function() {   
    253.         return this.domManip(arguments, falsefalse, function(elem) {   
    254.             this.parentNode.insertBefore(elem, this);// this=jQuery对象的每个元素   
    255.             });   
    256.     },   
    257.   
    258.     // 在每个匹配的元素之后插入内容   
    259.     after : function() {   
    260.         return this.domManip(arguments, falsetrue, function(elem) {   
    261.             this.parentNode.insertBefore(elem, this.nextSibling);   
    262.         });   
    263.     },   
    264.   
    265.     // ******************************************************************   
    266.   
    267.     // 回到最近的一个"破坏性"操作之前。即,将匹配的元素列表变为前一次的状态。   
    268.     end : function() {   
    269.         return this.prevObject || jQuery([]);   
    270.     },   
    271.   
    272.     // 搜索所有与指定表达式匹配的元素。这个函数是找出正在处理的元素的后代元素的好方法。   
    273.     // 所有搜索都依靠jQuery表达式来完成。这个表达式可以使用CSS1-3的选择器语法来写。   
    274.     find : function(selector) {   
    275.         var elems = jQuery.map(this, function(elem) {// 找到每个元素的满足的   
    276.                     return jQuery.find(selector, elem);   
    277.                 });   
    278.   
    279.         return this.pushStack(/[^+>] [^+>]/.test(selector) ? jQuery   
    280.                 .unique(elems) : elems);// 是不是返回不重复的元素?   
    281.     },   
    282.   
    283.     // clone当前对象,events表明是否clone事件   
    284.     clone : function(events) {   
    285.         // 对每个元素都进行加工(copy)后的集合重新构建jQuery对象   
    286.         var ret = this.map(function() {   
    287.             if (jQuery.browser.msie && !jQuery.isXMLDoc(this)) {   
    288.                 // IE 中cloneNode不能copy 通过attachEvent增加的事件   
    289.                 // 而innserHTML不能copy一些修改过的属性(仅作为属性储存)如input 的name   
    290.                 var clone = this.cloneNode(true), container = document   
    291.                         .createElement("div");   
    292.                 container.appendChild(clone);   
    293.                 return jQuery.clean([container.innerHTML])[0];   
    294.             } else  
    295.                 return this.cloneNode(true);   
    296.         });   
    297.   
    298.         // Need to set the expando to null on the cloned set if it exists   
    299.         // removeData doesn't work here, IE removes it from the original as well   
    300.         // this is primarily for IE but the data expando shouldn't be copied   
    301.         // over in any browser   
    302.         var clone = ret.find("*").andSelf().each(function() {   
    303.             if (this[expando] != undefined)   
    304.                 this[expando] = null;   
    305.         });   
    306.   
    307.         if (events === true)// clone所有事件   
    308.             this.find("*").andSelf().each(function(i) {   
    309.                 if (this.nodeType == 3)   
    310.                     return;   
    311.                 var events = jQuery.data(this"events");   
    312.   
    313.                 for (var type in events)   
    314.                     for (var handler in events[type])   
    315.                         jQuery.event.add(clone[i], type, events[type][handler],   
    316.                                 events[type][handler].data);   
    317.             });   
    318.   
    319.         return ret;   
    320.     },   
    321.   
    322.     // 筛选出与指定表达式匹配的元素集合。可以通过函数来筛选当前jQuery对象的   
    323.     // 元素,还有通过用逗号分隔多个表达式来筛选   
    324.     filter : function(selector) {// grep,multiFilter的综合   
    325.         return this.pushStack(jQuery.isFunction(selector)   
    326.                 && jQuery.grep(this, function(elem, i) {   
    327.                     return selector.call(elem, i);   
    328.                 }) || jQuery.multiFilter(selector, this));   
    329.     },   
    330.   
    331.     // 删除与指定表达式匹配的元素   
    332.     not : function(selector) {   
    333.         if (selector.constructor == String)// 采用jQuery表达式   
    334.             if (isSimple.test(selector))   
    335.                 return this.pushStack(jQuery.multiFilter(selector, thistrue));   
    336.             else  
    337.                 // 多表达式要过滤   
    338.                 selector = jQuery.multiFilter(selector, this);   
    339.   
    340.         var isArrayLike = selector.length// array-like的集合?   
    341.                 && selector[selector.length - 1] !== undefined   
    342.                 && !selector.nodeType;   
    343.         return this.filter(function() {// 过滤掉return false的元素   
    344.                     return isArrayLike ? jQuery.inArray(this, selector) < 0// this在selector中?   
    345.                             : this != selector;   
    346.                 });   
    347.     },   
    348.   
    349.     // 把与表达式匹配的元素添加到jQuery对象中。array(-like)的集合也可以追加进来   
    350.     add : function(selector) {   
    351.         return this.pushStack(jQuery.unique(jQuery.merge(this.get(),   
    352.                 typeof selector == 'string' ? jQuery(selector) : jQuery   
    353.                         .makeArray(selector))));   
    354.     },   
    355.   
    356.     // 用一个表达式来检查当前选择的元素集合,如果其中至少有一个元素符合这个给定的表达式就返回true。   
    357.     is : function(selector) {   
    358.         return !!selector && jQuery.multiFilter(selector, this).length > 0;   
    359.     },   
    360.   
    361.     // 检查当前的元素是否含有某个特定的类,如果有,则返回true   
    362.     hasClass : function(selector) {   
    363.         return this.is("." + selector);   
    364.     },   
    365.   
    366.     // 获得第一个匹配元素的当前值。   
    367.     // 在 jQuery 1.2 中,可以返回任意元素的值了。包括select。如果多选,将返回一个数组,其包含所选的值。   
    368.     // 设置每一个匹配元素的值。在 jQuery 1.2, 这也可以为select元件赋值   
    369.     val : function(value) {   
    370.         if (value == undefined) {   
    371.   
    372.             if (this.length) {   
    373.                 var elem = this[0];   
    374.   
    375.                 if (jQuery.nodeName(elem, 'option'))   
    376.                     return (elem.attributes.value || {}).specified   
    377.                             ? elem.value   
    378.                             : elem.text;   
    379.   
    380.                 // We need to handle select boxes special   
    381.                 if (jQuery.nodeName(elem, "select")) {   
    382.                     var index = elem.selectedIndex, values = [], options = elem.options, one = elem.type == "select-one";   
    383.   
    384.                     // Nothing was selected   
    385.                     if (index < 0)   
    386.                         return null;   
    387.   
    388.                     // Loop through all the selected options   
    389.                     for (var i = one ? index : 0, max = one   
    390.                             ? index + 1  
    391.                             : options.length;i < max; i++) {   
    392.                         var option = options[i];   
    393.   
    394.                         if (option.selected) {   
    395.                             // Get the specifc value for the option   
    396.                             value = jQuery(option).val();   
    397.   
    398.                             // We don't need an array for one selects   
    399.                             if (one)   
    400.                                 return value;   
    401.   
    402.                             // Multi-Selects return an array   
    403.                             values.push(value);   
    404.                         }   
    405.                     }   
    406.   
    407.                     return values;   
    408.   
    409.                     // Everything else, we just grab the value   
    410.                 } else  
    411.                     return (this[0].value || "").replace(/\r/g, "");   
    412.   
    413.             }   
    414.   
    415.             return undefined;   
    416.         }   
    417.   
    418.         if (value.constructor == Number)   
    419.             value += '';   
    420.   
    421.         return this  
    422.                 .each(function() {   
    423.                     if (this.nodeType != 1)   
    424.                         return;   
    425.   
    426.                     if (value.constructor == Array   
    427.                             && /radio|checkbox/.test(this.type))   
    428.                         this.checked = (jQuery.inArray(this.value, value) >= 0 || jQuery   
    429.                                 .inArray(this.name, value) >= 0);   
    430.   
    431.                     else if (jQuery.nodeName(this"select")) {   
    432.                         var values = jQuery.makeArray(value);   
    433.   
    434.                         jQuery("option"this)   
    435.                                 .each(function() {   
    436.                                     this.selected = (jQuery.inArray(this.value,   
    437.                                             values) >= 0 || jQuery.inArray(   
    438.                                             this.text, values) >= 0);   
    439.                                 });   
    440.   
    441.                         if (!values.length)   
    442.                             this.selectedIndex = -1;   
    443.   
    444.                     } else  
    445.                         this.value = value;   
    446.                 });   
    447.     },   
    448.   
    449.     // 设置每一个匹配元素的html内容。这个函数不能用于XML文档。但可以用于XHTML文档。   
    450.     // 取得第一个匹配的元素的html内容   
    451.     html : function(value) {   
    452.         return value == undefined ? (this[0] ? this[0].innerHTML : null) : this  
    453.                 .empty().append(value);// 去掉子节点,追加value   
    454.     },   
    455.   
    456.     // 将所有匹配的元素替换成指定的HTML或DOM元素。   
    457.     replaceWith : function(value) {   
    458.         return this.after(value).remove();// this.after(value),this没有变   
    459.     },   
    460.     // 获取第N个元素 。这个元素的位置是从0算起。   
    461.     eq : function(i) {   
    462.         return this.slice(i, +i + 1);   
    463.     },   
    464.   
    465.     // 代理数组的slice,同样的操作。   
    466.     slice : function() {   
    467.         return this.pushStack(Array.prototype.slice.apply(this, arguments));   
    468.     },   
    469.   
    470.     // 对于当前jquery对象中每个元素都进行callback(i,elem)的操作   
    471.     // 返回新生成的jquery对象。   
    472.     map : function(callback) {   
    473.         return this.pushStack(jQuery.map(this, function(elem, i) {   
    474.             return callback.call(elem, i, elem);   
    475.         }));   
    476.     },   
    477.   
    478.     // 把先前jQuery对象的所有元素加到当前的jQuery对象之中   
    479.     andSelf : function() {   
    480.         return this.add(this.prevObject);   
    481.     },   
    482.   
    483.     // data(name,value)   
    484.     // 在元素上存放数据,同时也返回value。   
    485.     // 如果jQuery集合指向多个元素,那将在所有元素上设置对应数据。   
    486.     // 这个函数不用建立一个新的expando,就能在一个元素上存放任何格式的数据,而不仅仅是字符串。   
    487.   
    488.     // data(name)   
    489.     // 返回元素上储存的相应名字的数据,可以用data(name, value)来设定。   
    490.     // 如果jQuery集合指向多个元素,那将只返回第一个元素的对应数据   
    491.     data : function(key, value) {   
    492.         var parts = key.split(".");   
    493.         parts[1] = parts[1] ? "." + parts[1] : "";   
    494.   
    495.         if (value === undefined) {// 取值   
    496.             // 这个特别的方法将会触发指定的事件类型上所有绑定的处理函数。但不会执行浏览器默认动作   
    497.             var data = this.triggerHandler("getData" + parts[1] + "!",   
    498.                     [parts[0]]);   
    499.   
    500.             if (data === undefined && this.length)   
    501.                 data = jQuery.data(this[0], key);   
    502.   
    503.             return data === undefined && parts[1] ? this.data(parts[0]) : data;   
    504.         } else { // 设值   
    505.             return this.trigger("setData" + parts[1] + "!", [parts[0], value])   
    506.                     .each(function() {   
    507.                         jQuery.data(this, key, value);   
    508.                     });   
    509.         }   
    510.     },   
    511.   
    512.     // 在元素上移除存放的数据   
    513.     // 与$(...).data(name, value)函数作用相反   
    514.     removeData : function(key) {   
    515.         return this.each(function() {   
    516.             jQuery.removeData(this, key);   
    517.         });   
    518.     },   
    519.   
    520.     // Dom manipulate操作的函数,对于每个jQuery对象中元素都运行   
    521.     // 由callback操作args转化成的Dom 元素集合的函数。   
    522.     domManip : function(args, table, reverse, callback) {   
    523.         var clone = this.length > 1, elems;   
    524.   
    525.         // 对当前的jquery对象中每个元素都进行操作   
    526.         return this.each(function() {   
    527.             if (!elems) {// 把args 转化为dom元素数组,追加的内容   
    528.                     elems = jQuery.clean(args, this.ownerDocument);   
    529.                     if (reverse)// 倒序   
    530.                         elems.reverse();   
    531.                 }   
    532.   
    533.                 var obj = this;   
    534.   
    535.                 // Ie Table不兼容,要进行特殊处理   
    536.                 if (table && jQuery.nodeName(this"table")// 当前元素是table?   
    537.                         && jQuery.nodeName(elems[0], "tr"))// 要追加是tr?   
    538.                     obj = this.getElementsByTagName("tbody")[0]// 没有tbody,创建追加   
    539.                             || this.appendChild(this.ownerDocument   
    540.                                     .createElement("tbody"));   
    541.   
    542.                 var scripts = jQuery([]);   
    543.   
    544.                 jQuery.each(elems, function() {   
    545.                     // 长度大于1,就采用clone。取第一个元素,否则就是本元素   
    546.                         var elem = clone ? jQuery(this).clone(true)[0] : this;   
    547.   
    548.                         // 执行所有 scripts 在所有的元素注入之后   
    549.                         if (jQuery.nodeName(elem, "script"))   
    550.                             scripts = scripts.add(elem);   
    551.                         else {   
    552.                             // 除去内部 scripts,同时保存起来, 为了之后的计算   
    553.                             if (elem.nodeType == 1)   
    554.                                 scripts = scripts.add(jQuery("script", elem)   
    555.                                         .remove());   
    556.   
    557.                             // 注册元素到document之中   
    558.                             callback.call(obj, elem);   
    559.                         }   
    560.                     });   
    561.   
    562.                 scripts.each(evalScript);   
    563.             });   
    564.     }   
    565. };   
    566.   
    567. // Give the init function the jQuery prototype for later instantiation   
    568. jQuery.fn.init.prototype = jQuery.fn;   
    569.   
    570. function evalScript(i, elem) {   
    571.     if (elem.src) {// <script src.. 通过ajax调用了   
    572.         jQuery.ajax( {   
    573.             url : elem.src,   
    574.             async : false,   
    575.             dataType : "script"  
    576.         });   
    577.     } else {// 对于本地的,通过globalEval运行   
    578.         jQuery   
    579.                 .globalEval(elem.text || elem.textContent || elem.innerHTML   
    580.                         || "");   
    581.     }   
    582.     if (elem.parentNode)// 除去   
    583.         elem.parentNode.removeChild(elem);   
    584. }   
    585.   
    586. function now() {   
    587.     return +new Date;   
    588. }   
    589.   
    590. jQuery.extend = jQuery.fn.extend = function() {   
    591.   
    592.     var target = arguments[0] || {}, // 第一个参数是目标   
    593.     i = 1, length = arguments.length, deep = false, options;   
    594.   
    595.     if (target.constructor == Boolean) {// 第一个参数是bool型的   
    596.         deep = target;// 深度copy   
    597.         target = arguments[1] || {};// target指向第二个参数   
    598.         i = 2;   
    599.     }   
    600.   
    601.     // target 是string 型的或?   
    602.     if (typeof target != "object" && typeof target != "function")   
    603.         target = {};   
    604.   
    605.     if (length == i) {// 只有一个参数?或deep copy 时,两个参数   
    606.         target = this;// 目标为this   
    607.         --i;   
    608.     }   
    609.   
    610.     for (;i < length; i++)   
    611.         if ((options = arguments[i]) != null)   
    612.   
    613.             for (var name in options) {   
    614.                 var src = target[name], copy = options[name];   
    615.                 if (target === copy)// 防止死循环   
    616.                     continue;   
    617.                 // 深度copy处理,最深为元素   
    618.                 if (deep && copy && typeof copy == "object" && !copy.nodeType)   
    619.                     target[name] = jQuery.extend(deep, src   
    620.                             || (copy.length != null ? [] : {}), copy);   
    621.                 else if (copy !== undefined)// 直接copy   
    622.                     target[name] = copy;   
    623.   
    624.             }   
    625.   
    626.     return target;   
    627. };   
    628.   
    629. var expando = "jQuery" + now(), uuid = 0, windowData = {},   
    630. // exclude the following css properties to add px   
    631. exclude = /z-?index|font-?weight|opacity|zoom|line-?height/i,   
    632. // cache defaultView   
    633. // defaultViewis generally a reference to the window object for the document   
    634. defaultView = document.defaultView || {};   
    635.   
    636. jQuery.extend( {   
    637.     noConflict : function(deep) {   
    638.         window.$ = _$;   
    639.   
    640.         if (deep)   
    641.             window.jQuery = _jQuery;   
    642.   
    643.         return jQuery;   
    644.     },   
    645.   
    646.     // See test/unit/core.js for details concerning this function.   
    647.         // Since 1.3 DOM methods and function like alert   
    648.         // aren't supported. They return false on IE (#2968).   
    649.         isFunction : function(fn) {   
    650.             return fn instanceof Function;   
    651.         },   
    652.   
    653.         // 判断是不是XMLDoc   
    654.         isXMLDoc : function(elem) {   
    655.             return elem.documentElement && !elem.body || elem.tagName   
    656.                     && elem.ownerDocument && !elem.ownerDocument.body;   
    657.         },   
    658.   
    659.         // Evalulates a script in a global context   
    660.         // 在全局的范围eval 代码,也就是在<head></head>中   
    661.         globalEval : function(data) {   
    662.             data = jQuery.trim(data);   
    663.   
    664.             if (data) {   
    665.                 // Inspired by code by Andrea Giammarchi   
    666.                 // http://webreflection.blogspot.com/2007/08/global-scope-evaluation-and-dom.html   
    667.                 var head = document.getElementsByTagName("head")[0]   
    668.                         || document.documentElement, script = document   
    669.                         .createElement("script");   
    670.   
    671.                 script.type = "text/javascript";   
    672.                 if (jQuery.browser.msie)   
    673.                     script.text = data;   
    674.                 else  
    675.                     script.appendChild(document.createTextNode(data));   
    676.   
    677.                 // Use insertBefore instead of appendChild to circumvent an IE6   
    678.                 // bug. This arises when a base node is used (#2709).   
    679.                 head.insertBefore(script, head.firstChild);   
    680.                 head.removeChild(script);   
    681.             }   
    682.         },   
    683.   
    684.         // 判断elem的nodeName是否存在   
    685.         nodeName : function(elem, name) {   
    686.             return elem.nodeName   
    687.                     && elem.nodeName.toUpperCase() == name.toUpperCase();   
    688.         },   
    689.   
    690.         cache : {},   
    691.   
    692.         data : function(elem, name, data) {   
    693.             elem = elem == window ? windowData : elem;   
    694.   
    695.             var id = elem[expando];   
    696.   
    697.             // Compute a unique ID for the element   
    698.             if (!id)   
    699.                 id = elem[expando] = ++uuid;   
    700.   
    701.             // Only generate the data cache if we're   
    702.             // trying to access or manipulate it   
    703.             if (name && !jQuery.cache[id])   
    704.                 jQuery.cache[id] = {};   
    705.   
    706.             // Prevent overriding the named cache with undefined values   
    707.             if (data !== undefined)   
    708.                 jQuery.cache[id][name] = data;   
    709.   
    710.             // Return the named cache data, or the ID for the element   
    711.             return name ? jQuery.cache[id][name] : id;   
    712.         },   
    713.   
    714.         removeData : function(elem, name) {   
    715.             elem = elem == window ? windowData : elem;   
    716.   
    717.             var id = elem[expando];   
    718.   
    719.             // If we want to remove a specific section of the element's data   
    720.             if (name) {   
    721.                 if (jQuery.cache[id]) {   
    722.                     // Remove the section of cache data   
    723.                     delete jQuery.cache[id][name];   
    724.   
    725.                     // If we've removed all the data, remove the element's cache   
    726.                     name = "";   
    727.   
    728.                     for (name in jQuery.cache[id])   
    729.                         break;   
    730.   
    731.                     if (!name)   
    732.                         jQuery.removeData(elem);   
    733.                 }   
    734.   
    735.                 // Otherwise, we want to remove all of the element's data   
    736.             } else {   
    737.                 // Clean up the element expando   
    738.                 try {   
    739.                     delete elem[expando];   
    740.                 } catch (e) {   
    741.                     // IE has trouble directly removing the expando   
    742.                     // but it's ok with using removeAttribute   
    743.                     if (elem.removeAttribute)   
    744.                         elem.removeAttribute(expando);   
    745.                 }   
    746.   
    747.                 // Completely remove the data cache   
    748.                 delete jQuery.cache[id];   
    749.             }   
    750.         },   
    751.   
    752.         // 对object中的每个对象都执行callback函数进行处理。args仅仅内部用   
    753.         each : function(object, callback, args) {   
    754.             var name, i = 0, length = object.length;   
    755.             // 和else的处理差不多,args的传参代替object的属性值   
    756.             if (args) {   
    757.                 if (length == undefined) {   
    758.                     for (name in object)   
    759.                         if (callback.apply(object[name], args) === false)   
    760.                             break;   
    761.                 } else  
    762.                     for (;i < length;)   
    763.                         if (callback.apply(object[i++], args) === false)   
    764.                             break;   
    765.   
    766.                 // A special, fast, case for the most common use of each   
    767.             } else {   
    768.                 // 不是array-like的object,对每个属性进行callback函数的调用   
    769.                 if (length == undefined) {   
    770.                     for (name in object)   
    771.                         if (callback.call(object[name], name, object[name]) === false)   
    772.                             break;   
    773.                 } else  
    774.                     // array-like object,采用数组的形式来处理   
    775.                     for (var value = object[0];i < length   
    776.                             && callback.call(value, i, value) !== false; value = object[++i]) {   
    777.                     }   
    778.             }   
    779.   
    780.             return object;   
    781.         },   
    782.   
    783.         // 根据指定元素(elem)的指定的name来修正value值,如加px,exec Fn.   
    784.         prop : function(elem, value, type, i, name) {   
    785.             if (jQuery.isFunction(value))// value=Fn   
    786.                 value = value.call(elem, i);// 得到Fn的返回value   
    787.             // 对于element的style中CSS属性,对需要加上单位的加上px单位   
    788.             return value && value.constructor == Number && type == "curCSS"  
    789.                     && !exclude.test(name) ? value + "px" : value;   
    790.         },   
    791.   
    792.         // 一组内部使用的Class操作函数   
    793.         className : {   
    794.             // 为元素增加classNameS   
    795.             add : function(elem, classNames) {// 多个className,空格分开   
    796.                 jQuery.each((classNames || "").split(/\s+/),   
    797.                         function(i, className) {   
    798.                             if (elem.nodeType == 1  
    799.                                     && !jQuery.className.has(elem.className,   
    800.                                             className))   
    801.                                 elem.className += (elem.className ? " " : "")   
    802.                                         + className;   
    803.                         });   
    804.             },   
    805.   
    806.             // 为元素除去classNames   
    807.             remove : function(elem, classNames) {   
    808.                 if (elem.nodeType == 1)// 元素   
    809.                     elem.className = classNames != undefined ? jQuery.grep(   
    810.                             elem.className.split(/\s+/), function(className) {// 过滤   
    811.                                 return !jQuery.className.has(classNames,   
    812.                                         className);   
    813.                             }).join(" ") : "";   
    814.             },   
    815.   
    816.             // 元素有没有className?   
    817.             has : function(elem, className) {   
    818.                 return jQuery.inArray(className, (elem.className || elem)   
    819.                         .toString().split(/\s+/)) > -1;   
    820.             }   
    821.         },   
    822.   
    823.         // 间隔改变elem的样式   
    824.         swap : function(elem, options, callback) {   
    825.             var old = {};   
    826.             for (var name in options) {// 替换elem.style中的属性   
    827.                 old[name] = elem.style[name];   
    828.                 elem.style[name] = options[name];   
    829.             }   
    830.             // 执行回调   
    831.             callback.call(elem);   
    832.   
    833.             // 重新换回原来的属性   
    834.             for (var name in options)   
    835.                 elem.style[name] = old[name];   
    836.         },   
    837.   
    838.         // 取得elem的name的属性值   
    839.         css : function(elem, name, force) {   
    840.             // 对元素的宽度高度修正   
    841.             if (name == "width" || name == "height") {   
    842.                 var val, props = {   
    843.                     position : "absolute",   
    844.                     visibility : "hidden",   
    845.                     display : "block"  
    846.                 }, which = (name == "width" ? ["Left""Right"] : ["Top",   
    847.                         "Bottom"]);   
    848.   
    849.                 function getWH() {// 求元素的实现高度,宽度   
    850.                     val = name == "width"  
    851.                             ? elem.offsetWidth   
    852.                             : elem.offsetHeight;   
    853.                     var padding = 0, border = 0;   
    854.                     jQuery.each(which, function() {   
    855.                         // paddinLeft,paddingRight   
    856.                             padding += parseFloat(jQuery.curCSS(elem, "padding"  
    857.                                     + thistrue))   
    858.                                     || 0;   
    859.                             // borderTopWidth,borderBottomWith   
    860.                             border += parseFloat(jQuery.curCSS(elem, "border"  
    861.                                     + this + "Width"true))   
    862.                                     || 0;   
    863.                         });   
    864.                     val -= Math.round(padding + border);   
    865.                 }   
    866.   
    867.                 if (jQuery(elem).is(":visible"))   
    868.                     getWH();   
    869.                 else  
    870.                     // 元素看不到的情况下,绝对定位,取高度或宽度   
    871.                     jQuery.swap(elem, props, getWH);   
    872.   
    873.                 return Math.max(0, val);   
    874.             }   
    875.   
    876.             return jQuery.curCSS(elem, name, force);   
    877.         },   
    878.   
    879.         curCSS : function(elem, name, force) {   
    880.             var ret, style = elem.style;   
    881.   
    882.             // elem的属性值被破坏   
    883.             function color(elem) {   
    884.                 if (!jQuery.browser.safari)   
    885.                     return false;   
    886.   
    887.                 // 从defaultView 取   
    888.                 var ret = defaultView.getComputedStyle(elem, null);   
    889.                 return !ret || ret.getPropertyValue("color") == "";   
    890.             }   
    891.   
    892.             // IE 中opacity 不兼容   
    893.             if (name == "opacity" && jQuery.browser.msie) {   
    894.                 ret = jQuery.attr(style, "opacity");   
    895.                 return ret == "" ? "1" : ret;// 1是100%的显示   
    896.             }   
    897.   
    898.             // Opera的display bug修正, 见 #2037   
    899.             if (jQuery.browser.opera && name == "display") {   
    900.                 var save = style.outline;   
    901.                 style.outline = "0 solid black";   
    902.                 style.outline = save;   
    903.             }   
    904.   
    905.             if (name.match(/float/i))// float是通过styleFloat取值的   
    906.                 name = styleFloat;   
    907.   
    908.             if (!force && style && style[name])   
    909.                 ret = style[name];// 取值   
    910.             else if (defaultView.getComputedStyle) {// 看看defaultView的CSS   
    911.   
    912.                 if (name.match(/float/i))   
    913.                     name = "float";   
    914.                 // 转换成lamb,如addMethod变成add-method   
    915.                 name = name.replace(/([A-Z])/g, "-$1").toLowerCase();   
    916.   
    917.                 var computedStyle = defaultView.getComputedStyle(elem, null);   
    918.   
    919.                 if (computedStyle && !color(elem))   
    920.                     ret = computedStyle.getPropertyValue(name);   
    921.                 else {// Safari没有正确地报道属性值,会提示none elements are involved   
    922.                     var swap = [], stack = [], a = elem, i = 0;   
    923.   
    924.                     // Locate all of the parent display: none elements   
    925.                     for (;a && color(a); a = a.parentNode)   
    926.                         stack.unshift(a);   
    927.   
    928.                     // Go through and make them visible, but in reverse   
    929.                     // (It would be better if we knew the exact display type   
    930.                     // that they had)   
    931.                     for (;i < stack.length; i++)   
    932.                         if (color(stack[i])) {   
    933.                             swap[i] = stack[i].style.display;   
    934.                             stack[i].style.display = "block";   
    935.                         }   
    936.   
    937.                     // Since we flip the display style, we have to handle that   
    938.                     // one special, otherwise get the value   
    939.                     ret = name == "display" && swap[stack.length - 1] != null  
    940.                             ? "none"  
    941.                             : (computedStyle && computedStyle   
    942.                                     .getPropertyValue(name))   
    943.                                     || "";   
    944.   
    945.                     // Finally, revert the display styles back   
    946.                     for (i = 0;i < swap.length; i++)   
    947.                         if (swap[i] != null)   
    948.                             stack[i].style.display = swap[i];   
    949.                 }   
    950.   
    951.                 // We should always get a number back from opacity   
    952.                 if (name == "opacity" && ret == "")   
    953.                     ret = "1";   
    954.   
    955.             } else if (elem.currentStyle) {// 元素的currentStyle   
    956.                 var camelCase = name.replace(/\-(\w)/g, function(all, letter) {   
    957.                     return letter.toUpperCase();   
    958.                 });   
    959.   
    960.                 ret = elem.currentStyle[name] || elem.currentStyle[camelCase];   
    961.   
    962.                 // From the awesome hack by Dean Edwards   
    963.                 // http://erik.eae.net/archives/2007/07/27/18.54.15/#comment-102291   
    964.   
    965.                 // If we're not dealing with a regular pixel number   
    966.                 // but a number that has a weird ending, we need to convert it   
    967.                 // to pixels   
    968.                 if (!/^\d+(px)?$/i.test(ret) && /^\d/.test(ret)) {   
    969.                     // Remember the original values   
    970.                     var left = style.left, rsLeft = elem.runtimeStyle.left;   
    971.   
    972.                     // Put in the new values to get a computed value out   
    973.                     elem.runtimeStyle.left = elem.currentStyle.left;   
    974.                     style.left = ret || 0;   
    975.                     ret = style.pixelLeft + "px";   
    976.   
    977.                     // Revert the changed values   
    978.                     style.left = left;   
    979.                     elem.runtimeStyle.left = rsLeft;   
    980.                 }   
    981.             }   
    982.   
    983.             return ret;   
    984.         },   
    985.   
    986.         // 把html转换成Dom元素,elems多个html string 的数组   
    987.         clean : function(elems, context) {   
    988.             var ret = [];   
    989.             context = context || document;   
    990.             // !context.createElement fails in IE with an error but returns   
    991.             // typeof 'object'   
    992.             if (typeof context.createElement == 'undefined')   
    993.                 // 处理context是jquery对象或数组的兼容。context可以是元素,或元素的集合,或空   
    994.                 context = context.ownerDocument || context[0]   
    995.                         && context[0].ownerDocument || document;   
    996.   
    997.             jQuery   
    998.                     .each(elems, function(i, elem) {   
    999.                         if (typeof elem == 'number')   
    1000.                             elem += '';// 把int 转换成string的最高效的方法   
    1001.   
    1002.                         if (!elem)   
    1003.                             return;// 为'',undefined,false等时返回   
    1004.   
    1005.                         // 转换html为Dom元素   
    1006.                         if (typeof elem == "string") {   
    1007.                             // Fix "XHTML"-style tags in all browsers   
    1008.                             // 对于其它的标签,修改成xml的格式   
    1009.                             elem = elem   
    1010.                                     .replace(   
    1011.                                             /(<(\w+)[^>]*?)\/>/g,// front=(<(\w+)[^>]*?)   
    1012.                                             function(all, front, tag) {   
    1013.                                                 return tag   
    1014.                                                         .match(/^(abbr|br|col|img|input|link|meta|param|hr|area|embed)$/i)   
    1015.                                                         ? all   
    1016.                                                         : front + "></" + tag   
    1017.                                                                 + ">";   
    1018.                                             });   
    1019.   
    1020.                             // 去空格,否则indexof可能会出不能正常工作   
    1021.                             var tags = jQuery.trim(elem).toLowerCase(), div = context   
    1022.                                     .createElement("div");   
    1023.                             // 有些标签必须是有一些约束的,比如<option>必须在<select></select>中间   
    1024.                             // 下面的代码在大部分是对<table>中子元素进行修正。数组中第一个元素为深度   
    1025.                             var wrap = !tags.indexOf("<opt")   
    1026.                                     && [1"<select multiple='multiple'>",   
    1027.                                             "</select>"]   
    1028.                                     || !tags.indexOf("<leg")   
    1029.                                     && [1"<fieldset>""</fieldset>"]   
    1030.                                     || tags   
    1031.                                             .match(/^<(thead|tbody|tfoot|colg|cap)/)   
    1032.                                     && [1"<table>""</table>"]   
    1033.                                     || !tags.indexOf("<tr")   
    1034.                                     && [2"<table><tbody>""</tbody></table>"]   
    1035.                                     || (!tags.indexOf("<td") || !tags   
    1036.                                             .indexOf("<th"))   
    1037.                                     && [3"<table><tbody><tr>",   
    1038.                                             "</tr></tbody></table>"]   
    1039.                                     || !tags.indexOf("<col")   
    1040.                                     && [2"<table><tbody></tbody><colgroup>",   
    1041.                                             "</colgroup></table>"]   
    1042.                                     ||   
    1043.   
    1044.                                     // IE can't serialize <link> and <script>   
    1045.                                     // tags normally   
    1046.                                     jQuery.browser.msie   
    1047.                                     && [1"div<div>""</div>"] ||   
    1048.   
    1049.                                     [0""""];   
    1050.   
    1051.                             // 包裹html之后,采用innerHTML转换成Dom   
    1052.                             div.innerHTML = wrap[1] + elem + wrap[2];   
    1053.   
    1054.                             while (wrap[0]--)   
    1055.                                 // 转到正确的深度,对于[1, "<table>",   
    1056.                                 // "</table>"],div=<table>   
    1057.                                 div = div.lastChild;   
    1058.   
    1059.                             // fragments去掉IE对<table>自动插入的<tbody>   
    1060.                             if (jQuery.browser.msie) {   
    1061.   
    1062.                                 // Tag字符是<table>, *may*有伪造的 <tbody>   
    1063.                                 var tbody = !tags.indexOf("<table")// <table开头   
    1064.                                         && tags.indexOf("<tbody") < 0// 但没有<tbody   
    1065.                                 ? div.firstChild// 生成的元素中可能会自动加的<tbody>   
    1066.                                         && div.firstChild.childNodes :   
    1067.   
    1068.                                 // String was a bare <thead> or <tfoot>   
    1069.                                         wrap[1] == "<table>"  
    1070.                                                 && tags.indexOf("<tbody") < 0// 没有出现<tbody   
    1071.                                         ? div.childNodes// 没有加<tbody>   
    1072.                                                 : [];   
    1073.                                 // 除去<tbody>   
    1074.                                 for (var j = tbody.length - 1;j >= 0; --j)   
    1075.                                     if (jQuery.nodeName(tbody[j], "tbody")   
    1076.                                             && !tbody[j].childNodes.length)   
    1077.                                         tbody[j].parentNode   
    1078.                                                 .removeChild(tbody[j]);   
    1079.   
    1080.                                 // IE completely kills leading whitespace when   
    1081.                                 // innerHTML is used   
    1082.                                 if (/^\s/.test(elem))   
    1083.                                     div.insertBefore(   
    1084.                                             context.createTextNode(elem   
    1085.                                                     .match(/^\s*/)[0]),   
    1086.                                             div.firstChild);   
    1087.   
    1088.                             }   
    1089.   
    1090.                             elem = jQuery.makeArray(div.childNodes);   
    1091.                         }   
    1092.   
    1093.                         if (elem.length === 0  
    1094.                                 && (!jQuery.nodeName(elem, "form") && !jQuery   
    1095.                                         .nodeName(elem, "select")))   
    1096.                             return;   
    1097.   
    1098.                         if (elem[0] == undefined   
    1099.                                 || jQuery.nodeName(elem, "form")   
    1100.                                 || elem.options)   
    1101.                             ret.push(elem);   
    1102.   
    1103.                         else  
    1104.                             // 对于elems是array-like的集合   
    1105.                             ret = jQuery.merge(ret, elem);   
    1106.   
    1107.                     });   
    1108.   
    1109.             return ret;   
    1110.         },   
    1111.   
    1112.         // 为给定的elem的name属性设定value值   
    1113.         // 或取elem的name属性值   
    1114.         attr : function(elem, name, value) {   
    1115.             // 文本,注释节点不处理   
    1116.             if (!elem || elem.nodeType == 3 || elem.nodeType == 8)   
    1117.                 return undefined;   
    1118.   
    1119.             var notxml = !jQuery.isXMLDoc(elem),   
    1120.             // 取值还是设值?   
    1121.             set = value !== undefined, msie = jQuery.browser.msie;   
    1122.   
    1123.             // 兼容的处理   
    1124.             name = notxml && jQuery.props[name] || name;   
    1125.   
    1126.             // Only do all the following if this is a node (faster for style)   
    1127.             // IE elem.getAttribute passes even for style   
    1128.             if (elem.tagName) {   
    1129.                 var special = /href|src|style/.test(name);// 要特殊处理   
    1130.   
    1131.                 // 对于safari的特殊处理   
    1132.                 if (name == "selected" && jQuery.browser.safari)   
    1133.                     elem.parentNode.selectedIndex;   
    1134.   
    1135.                 if (name in elem && notxml && !special) {// 通过DOM 0方式进入属性   
    1136.                     if (set) {// 改变属性   
    1137.                         // IE报错,type不能改变   
    1138.                         if (name == "type" && jQuery.nodeName(elem, "input")   
    1139.                                 && elem.parentNode)   
    1140.                             throw "type property can't be changed";   
    1141.   
    1142.                         elem[name] = value;   
    1143.                     }   
    1144.   
    1145.                     // 对于attr(form,name)取是form[name].value   
    1146.                     if (jQuery.nodeName(elem, "form")   
    1147.                             && elem.getAttributeNode(name))   
    1148.                         return elem.getAttributeNode(name).nodeValue;   
    1149.                     // 返回元素的属性值   
    1150.                     return elem[name];   
    1151.                 }   
    1152.                 // 对style进行属性的操作   
    1153.                 if (msie && notxml && name == "style")   
    1154.                     return jQuery.attr(elem.style, "cssText", value);   
    1155.   
    1156.                 if (set)   
    1157.                     // IE会报错 see #1070   
    1158.                     elem.setAttribute(name, "" + value);   
    1159.   
    1160.                 var attr = msie && notxml && special   
    1161.                 // Some attributes require a special call on IE   
    1162.                         ? elem.getAttribute(name, 2)   
    1163.                         : elem.getAttribute(name);   
    1164.                 // 不存在的属性返回null,改成undefined   
    1165.                 return attr === null ? undefined : attr;   
    1166.             }   
    1167.   
    1168.             // 当elem参数是elem.style时。。。   
    1169.   
    1170.             // IE 使用 filters for opacity   
    1171.             if (msie && name == "opacity") {   
    1172.                 if (set) {   
    1173.                     // IE opacity 要层的支持   
    1174.                     elem.zoom = 1;   
    1175.   
    1176.                     // 设 alpha filter 来设定 opacity   
    1177.                     elem.filter = (elem.filter || "").replace(/alpha\([^)]*\)/,   
    1178.                             "")   
    1179.                             + ((parseInt(value) + '' == "NaN"  
    1180.                                     ? ""  
    1181.                                     : "alpha(opacity=" + value * 100 + ")"));   
    1182.                 }   
    1183.   
    1184.                 return elem.filter && elem.filter.indexOf("opacity=") >= 0  
    1185.                         ? (parseFloat(elem.filter.match(/opacity=([^)]*)/)[1]) / 100)   
    1186.                                 + ''  
    1187.                         : "";   
    1188.             }   
    1189.             // lamb字的支持   
    1190.             name = name.replace(/-([a-z])/ig, function(all, letter) {   
    1191.                 return letter.toUpperCase();   
    1192.             });   
    1193.   
    1194.             if (set)   
    1195.                 elem[name] = value;   
    1196.   
    1197.             return elem[name];   
    1198.         },   
    1199.   
    1200.         // trim(text)   
    1201.         trim : function(text) {   
    1202.             return (text || "").replace(/^\s+|\s+$/g, "");   
    1203.         },   
    1204.   
    1205.         // 把参数array转换成数组。有可能是dom collection,arguments,jquery对象   
    1206.         makeArray : function(array) {   
    1207.             var ret = [];   
    1208.   
    1209.             if (array != null) {   
    1210.                 var i = array.length;   
    1211.                 // the window, strings and functions also have 'length'   
    1212.                 if (i == null || array.split || array.setInterval || array.call)   
    1213.                     ret[0] = array;   
    1214.                 else  
    1215.                     while (i)   
    1216.                         ret[--i] = array[i];   
    1217.             }   
    1218.   
    1219.             return ret;   
    1220.         },   
    1221.   
    1222.         // 判断elem元素在array中的位置(index)   
    1223.         inArray : function(elem, array) {   
    1224.             for (var i = 0, length = array.length;i < length; i++)   
    1225.                 // Use === because on IE, window == document   
    1226.                 if (array[i] === elem)   
    1227.                     return i;   
    1228.             return -1;   
    1229.         },   
    1230.   
    1231.         // 把second 元素追加到first的数组中。   
    1232.         merge : function(first, second) {   
    1233.             // We have to loop this way because IE & Opera overwrite the length   
    1234.             // expando of getElementsByTagName   
    1235.             var i = 0, elem, pos = first.length;   
    1236.             // Also, we need to make sure that the correct elements are being   
    1237.             // returned   
    1238.             // (IE returns comment nodes in a '*' query)   
    1239.             if (jQuery.browser.msie) {   
    1240.                 while (elem = second[i++])   
    1241.                     if (elem.nodeType != 8)   
    1242.                         first[pos++] = elem;   
    1243.   
    1244.             } else  
    1245.                 while (elem = second[i++])   
    1246.                     first[pos++] = elem;   
    1247.   
    1248.             return first;   
    1249.         },   
    1250.   
    1251.         // 判断数组中的元素是否有重复的元素,返回不重复的所有元素。如Ext.DomQuery中的nodup一样处理   
    1252.         unique : function(array) {   
    1253.             var ret = [], done = {};   
    1254.   
    1255.             try {   
    1256.   
    1257.                 for (var i = 0, length = array.length;i < length; i++) {   
    1258.                     var id = jQuery.data(array[i]);   
    1259.   
    1260.                     if (!done[id]) {   
    1261.                         done[id] = true;   
    1262.                         ret.push(array[i]);   
    1263.                     }   
    1264.                 }   
    1265.   
    1266.             } catch (e) {   
    1267.                 ret = array;   
    1268.             }   
    1269.   
    1270.             return ret;   
    1271.         },   
    1272.   
    1273.         // 过滤elems中满足callback处理的所有元素   
    1274.         grep : function(elems, callback, inv) {   
    1275.             var ret = [];   
    1276.   
    1277.             // Go through the array, only saving the items   
    1278.             // that pass the validator function   
    1279.             for (var i = 0, length = elems.length;i < length; i++)   
    1280.                 if (!inv != !callback(elems[i], i))   
    1281.                     ret.push(elems[i]);   
    1282.   
    1283.             return ret;   
    1284.         },   
    1285.   
    1286.         // 返回对elems每个元素都进行操作的callback函数的返回值的集合。   
    1287.         map : function(elems, callback) {   
    1288.             var ret = [];   
    1289.   
    1290.             // Go through the array, translating each of the items to their   
    1291.             // new value (or values).   
    1292.             for (var i = 0, length = elems.length;i < length; i++) {   
    1293.                 var value = callback(elems[i], i);   
    1294.   
    1295.                 if (value != null)   
    1296.                     ret[ret.length] = value;   
    1297.             }   
    1298.   
    1299.             return ret.concat.apply([], ret);   
    1300.         }   
    1301.     });   
    1302.   
    1303. var userAgent = navigator.userAgent.toLowerCase();   
    1304.   
    1305. // 计算出浏览器的相关信息   
    1306. jQuery.browser = {   
    1307.     version : (userAgent.match(/.+(?:rv|it|ra|ie)[\/: ]([\d.]+)/) || [0'0'])[1],   
    1308.     safari : /webkit/.test(userAgent),   
    1309.     opera : /opera/.test(userAgent),   
    1310.     msie : /msie/.test(userAgent) && !/opera/.test(userAgent),   
    1311.     mozilla : /mozilla/.test(userAgent)   
    1312.             && !/(compatible|webkit)/.test(userAgent)   
    1313. };   
    1314.   
    1315. var styleFloat = jQuery.browser.msie ? "styleFloat" : "cssFloat";   
    1316.   
    1317. jQuery.extend( {   
    1318.   
    1319.     // 支持不支持boxModel?IE不支持   
    1320.         boxModel : !jQuery.browser.msie || document.compatMode == "CSS1Compat",   
    1321.   
    1322.         props : {   
    1323.             "for" : "htmlFor",   
    1324.             "class" : "className",   
    1325.             "float" : styleFloat,   
    1326.             cssFloat : styleFloat,   
    1327.             styleFloat : styleFloat,   
    1328.             readonly : "readOnly",   
    1329.             maxlength : "maxLength",   
    1330.             cellspacing : "cellSpacing",   
    1331.             rowspan : "rowSpan"  
    1332.         }   
    1333.     });   
    1334.   
    1335. // 一组对元素的相关节点的操作,如父,子,兄节点等   
    1336. jQuery.each( {   
    1337.     parent : function(elem) {// 父亲节点   
    1338.             return elem.parentNode;   
    1339.         },   
    1340.         parents : function(elem) {// elem的所有parentNode   
    1341.             return jQuery.dir(elem, "parentNode");   
    1342.         },   
    1343.         next : function(elem) {// 元素的下一个兄弟   
    1344.             return jQuery.nth(elem, 2"nextSibling");   
    1345.         },   
    1346.         prev : function(elem) {// 前一个兄弟   
    1347.             return jQuery.nth(elem, 2"previousSibling");   
    1348.         },   
    1349.         nextAll : function(elem) {// 所有后继兄弟   
    1350.             return jQuery.dir(elem, "nextSibling");   
    1351.         },   
    1352.         prevAll : function(elem) {// 所有前继兄弟   
    1353.             return jQuery.dir(elem, "previousSibling");   
    1354.         },   
    1355.         siblings : function(elem) {// 所有兄弟   
    1356.             return jQuery.sibling(elem.parentNode.firstChild, elem);   
    1357.         },   
    1358.         children : function(elem) {// 所有孩子   
    1359.             return jQuery.sibling(elem.firstChild);   
    1360.         },   
    1361.         contents : function(elem) {// iframe?就是文档,或者所有子节点   
    1362.             return jQuery.nodeName(elem, "iframe") ? elem.contentDocument   
    1363.                     || elem.contentWindow.document : jQuery   
    1364.                     .makeArray(elem.childNodes);   
    1365.         }   
    1366.     }, function(name, fn) {// 注册到jQuery对象中去,可以调用同名方法   
    1367.             jQuery.fn[name] = function(selector) {   
    1368.                 var ret = jQuery.map(this, fn);// 每个元素都执行同名方法   
    1369.                 if (selector && typeof selector == "string")   
    1370.                     ret = jQuery.multiFilter(selector, ret);// 过滤元素集   
    1371.                 return this.pushStack(jQuery.unique(ret));// 构建jQuery对象   
    1372.             };   
    1373.         });   
    1374.   
    1375. // 为jQuery对象生成appendTo~replaceAll五个代理函数   
    1376. // 其功能是把当前的jquery对象的每个元素都插入到每个传入的参数(元素)的一个位置:   
    1377. // 之前,之后,开始,结束,overwrite   
    1378.   
    1379. jQuery.each( {   
    1380.     appendTo : "append",   
    1381.     prependTo : "prepend",   
    1382.     insertBefore : "before",   
    1383.     insertAfter : "after",   
    1384.     replaceAll : "replaceWith"  
    1385. }, function(name, original) {   
    1386.     jQuery.fn[name] = function() {   
    1387.         var args = arguments;// 每个参数和每个元素是对应起来的   
    1388.         // 对当前jQuery中每个元素都进行的操作   
    1389.         return this.each(function() {   
    1390.             for (var i = 0, length = args.length;i < length; i++)   
    1391.                 jQuery(args[i])[original](this);// 调用original代理工作   
    1392.             });   
    1393.     };   
    1394. });   
    1395.   
    1396. // 一组对元素attr,class等进行操作的函数   
    1397. jQuery.each( {   
    1398.     removeAttr : function(name) {// 除去元素的一个属性   
    1399.             jQuery.attr(this, name, "");   
    1400.             if (this.nodeType == 1)   
    1401.                 this.removeAttribute(name);   
    1402.         },   
    1403.   
    1404.         addClass : function(classNames) {// 为元素增加一些classNames   
    1405.             jQuery.className.add(this, classNames);   
    1406.         },   
    1407.   
    1408.         removeClass : function(classNames) {// 除去元素的一些classNames   
    1409.             jQuery.className.remove(this, classNames);   
    1410.         },   
    1411.   
    1412.         toggleClass : function(classNames) {// 开关该class,   
    1413.             jQuery.className[jQuery.className.has(this, classNames)   
    1414.                     ? "remove"  
    1415.                     : "add"](this, classNames);   
    1416.         },   
    1417.   
    1418.         remove : function(selector) {// 根据selector除去元素,防内存泄露   
    1419.             if (!selector || jQuery.filter(selector, [this]).r.length) {   
    1420.                 // Prevent memory leaks   
    1421.                 jQuery("*"this).add([this]).each(function() {   
    1422.                     jQuery.event.remove(this);   
    1423.                     jQuery.removeData(this);   
    1424.                 });   
    1425.                 if (this.parentNode)   
    1426.                     this.parentNode.removeChild(this);   
    1427.             }   
    1428.         },   
    1429.         empty : function() {// 清除元素的所有子节点   
    1430.             // 删除当前对象的每个元素的的所有子节点,防止内存泄漏   
    1431.             jQuery(">*"this).remove();   
    1432.             while (this.firstChild)   
    1433.                 // 删除余留的子节点   
    1434.                 this.removeChild(this.firstChild);   
    1435.         }   
    1436.     }, function(name, fn) {   
    1437.         jQuery.fn[name] = function() {   
    1438.             return this.each(fn, arguments);   
    1439.         };   
    1440.     });   
    1441.   
    1442. // 为jQuery对象注册height,width方法   
    1443. jQuery   
    1444.         .each(   
    1445.                 ["Height""Width"],   
    1446.                 function(i, name) {   
    1447.                     var type = name.toLowerCase();   
    1448.   
    1449.                     jQuery.fn[type] = function(size) {   
    1450.                         // window的宽度和高度   
    1451.                         return this[0] == window ? (// window的宽度和高度   
    1452.                                 jQuery.browser.opera   
    1453.                                         && document.body["client" + name]   
    1454.                                         || jQuery.browser.safari   
    1455.                                         && window["inner" + name]   
    1456.                                         || document.compatMode == "CSS1Compat"  
    1457.                                         && document.documentElement["client"  
    1458.                                                 + name] || document.body["client"  
    1459.                                         + name])   
    1460.                                 : this[0] == document ? (// document的宽度和高度   
    1461.                                         Math   
    1462.                                                 .max(   
    1463.                                                         Math   
    1464.                                                                 .max(   
    1465.                                                                         document.body["scroll"  
    1466.                                                                                 + name],   
    1467.                                                                         document.documentElement["scroll"  
    1468.                                                                                 + name]),   
    1469.                                                         Math   
    1470.                                                                 .max(   
    1471.                                                                         document.body["offset"  
    1472.                                                                                 + name],   
    1473.                                                                         document.documentElement["offset"  
    1474.                                                                                 + name])))   
    1475.                                         : (size == undefined ? (// 第一个元素的的宽度和高度   
    1476.                                                 this.length ? jQuery.css(   
    1477.                                                         this[0], type) : null)   
    1478.                                                 : (// 设定当前对象所有元素宽度和高度   
    1479.                                                 this  
    1480.                                                         .css(   
    1481.                                                                 type,   
    1482.                                                                 size.constructor == String   
    1483.                                                                         ? size   
    1484.                                                                         : size   
    1485.                                                                                 + "px")));   
    1486.                     };   
    1487.                 });   
    1488.   
    1489. // Helper function used by the dimensions and offset modules   
    1490. function num(elem, prop) {   
    1491.     return elem[0] && parseInt(jQuery.curCSS(elem[0], prop, true), 10) || 0;   
    1492. }  
  • 相关阅读:
    WordCloud 简介
    Volo.Abp.EntityFrameworkCore.MySQL 使用
    关于Git的那些事
    国内外各大免费搜索引擎、导航网址提交入口
    C#读取Excel的数据,并且以混合模式读取,防止数据类型变更
    如何提升程序员的非技术才能
    用户体验设计流程与文档编制指南
    【海量干货】89页PPT详解微信O2O行业解决方案
    AutoCompleteTextView 和 MultiAutoCompleteTextView 自动完成文本控件
    zookeeper简介
  • 原文地址:https://www.cnblogs.com/luluping/p/1347400.html
Copyright © 2020-2023  润新知