欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

jQuery.clean使用方法及思路分析

 更新時(shí)間:2013年01月07日 10:13:29   作者:  
jQuery.clean源碼分析包括:jQuery.clean使用方法、思路分析及源碼注釋分析感興趣的朋友可以參考下

一、jQuery.clean使用方法
jQuery.clean( elems, context, fragment, scripts );
二、思路分析
1、處理參數(shù)context,確保其為文檔根節(jié)點(diǎn)document
2、處理參數(shù)elems數(shù)組(循環(huán)遍歷數(shù)組)
  2.1、elem為數(shù)字,轉(zhuǎn)換為字符串
  2.2、elem為非法值,跳出本次循環(huán)
  2.3、elem為字符串
  2.4、字符串不存在實(shí)體編號(hào)或html標(biāo)簽,則創(chuàng)建文本節(jié)點(diǎn)
  2.5、字符串為實(shí)體編號(hào)或html標(biāo)簽

復(fù)制代碼 代碼如下:

創(chuàng)建一個(gè)div元素并插入到文檔碎片中
 處理xhtml風(fēng)格標(biāo)簽
 將elem包裹起來,并將包裹后的字符串作為div的innerHTML
 如果包裹深度大于1,只留下第一層包裹元素
 清除在ie6,7中空table標(biāo)簽自動(dòng)加入的tbody
 將在ie9以下瀏覽器中剔除的開頭空白字符串作為div元素的第一個(gè)文本子節(jié)點(diǎn)
 將elem重新賦值為div的子節(jié)點(diǎn)集合(nodeList對(duì)象),
 移除本次循環(huán)中文檔碎片中的div,保持下一次循環(huán)中干凈的div元素    

2.3、如果elem為文本節(jié)點(diǎn),則直接添加到要返回的ret數(shù)組中,否則將elem(nodeList對(duì)象)中的節(jié)點(diǎn)合并到數(shù)組
  2.4、修復(fù)在ie6、7中type為radio,checkbox類型的節(jié)點(diǎn)的選中狀態(tài)(checked)失效的bug
3、處理參數(shù)fragment
  3.1、將ret中各節(jié)點(diǎn)添加到文檔碎片fragment中
  3.2、提取節(jié)點(diǎn)中的script子節(jié)點(diǎn),并將其添加到ret數(shù)組中,添加的script位置為其原父元素位置后面
4、返回ret數(shù)組
三、源碼注釋分析
1、函數(shù)中用到的變量及函數(shù)
復(fù)制代碼 代碼如下:

var nodeNames = "abbr|article|aside|audio|bdi|canvas|data|datalist|details|figcaption|figure|footer|" +
         "header|hgroup|mark|meter|nav|output|progress|section|summary|time|video",
     wrapMap = {
         option: [ 1, "<select multiple='multiple'>", "</select>" ],
         legend: [ 1, "<fieldset>", "</fieldset>" ],
         thead: [ 1, "<table>", "</table>" ],
         tr: [ 2, "<table><tbody>", "</tbody></table>" ],
         td: [ 3, "<table><tbody><tr>", "</tr></tbody></table>" ],
         col: [ 2, "<table><tbody></tbody><colgroup>", "</colgroup></table>" ],
         area: [ 1, "<map>", "</map>" ],
         _default: [ 0, "", "" ]
     },
     rxhtmlTag = /<(?!area|br|col|embed|hr|img|input|link|meta|param)(([\w:]+)[^>]*)\/>/gi,
     rtagName = /<([\w:]+)/,
     rtbody = /<tbody/i,
     rhtml = /<|&#?\w+;/,
     rleadingWhitespace = /^\s+/,
     rcheckableType = /^(?:checkbox|radio)$/,
     rscriptType = /\/(java|ecma)script/i;
 // 設(shè)置復(fù)選框checkbox或單選框radio表單元素的默認(rèn)選中狀態(tài)
 function fixDefaultChecked( elem ) {
     if ( rcheckableType.test( elem.type ) ) {
         elem.defaultChecked = elem.checked;
     }
 }
 // 創(chuàng)建一個(gè)安全的文檔碎片
 function createSafeFragment( document ) {
     var list = nodeNames.split( "|" ),
     safeFrag = document.createDocumentFragment(); // ie6,7,8瀏覽器把safeFrage作為HTMLDocument類型
     // 針對(duì)ie9以下瀏覽器
     if ( safeFrag.createElement ) {
         while ( list.length ) {
             safeFrag.createElement(
                 list.pop()
             );
         }
     }
     return safeFrag;
 }
 // 模擬ES5中Array的新功能
 // 該函數(shù)API:http://www.css88.com/jqapi-1.8/#p=jQuery.grep
 jQuery.extend({
     grep: function( elems, callback, inv ) {
         var retVal,
             ret = [],
             i = 0,
             length = elems.length;
         inv = !!inv;
         // Go through the array, only saving the items
         // that pass the validator function
         for ( ; i < length; i++ ) {
             retVal = !!callback( elems[ i ], i );
             if ( inv !== retVal ) {
                 ret.push( elems[ i ] );
             }
         }
         return ret;
     }             
 });

2、源碼分析
復(fù)制代碼 代碼如下:

jQuery.extend({
     clean: function( elems, context, fragment, scripts ) {
         // 聲明變量
         var i, j, elem, tag, wrap, depth, div, hasBody, tbody, len, handleScript, jsTags,
             safe = context === document && safeFragment,
             ret = [];
         // 確保變量context為文檔根節(jié)點(diǎn)document
         if ( !context || typeof context.createDocumentFragment === "undefined" ) {
             context = document;
         }
         // Use the already-created safe fragment if context permits
         for ( i = 0; (elem = elems[i]) != null; i++ ) {
             // 如果elem為數(shù)字,則將其轉(zhuǎn)換為字符串
             if ( typeof elem === "number" ) {
                 elem += "";
             }
             // 如果elem為undefined,跳出本次循環(huán)
             if ( !elem ) {
                 continue;
             }
             // Convert html string into DOM nodes
             // 轉(zhuǎn)換數(shù)組項(xiàng)(字符串)為DOM節(jié)點(diǎn)
             if ( typeof elem === "string" ) {
                 // 如果不存在html實(shí)體編號(hào)或標(biāo)簽,則創(chuàng)建文本節(jié)點(diǎn)
                 if ( !rhtml.test( elem ) ) {
                     elem = context.createTextNode( elem );
                 }
                 // 處理是html標(biāo)簽字符串的數(shù)組項(xiàng)
                 else {
                     // Ensure a safe container in which to render the html
                     // safe為#document-fragment類型,在ie9以下瀏覽器中,safe為HTMLDocument類型節(jié)點(diǎn),且nodeNames數(shù)組為空
                     safe = safe || createSafeFragment( context );
                     // 創(chuàng)建一個(gè)div元素并將其插入到文檔碎片中
                     div = context.createElement("div");
                     safe.appendChild( div );
                     // Fix "XHTML"-style tags in all browsers
                     // 除了area,br,col,embed,hr,img,input,link,meta,param這些標(biāo)簽外,
                     // 將開始標(biāo)簽?zāi)┪布尤胄备艿臉?biāo)簽轉(zhuǎn)換為開始和結(jié)束標(biāo)簽
                     elem = elem.replace(rxhtmlTag, "<$1></$2>");
                     // Go to html and back, then peel off extra wrappers
                     // 獲取左邊第一個(gè)標(biāo)簽元素
                     tag = ( rtagName.exec( elem ) || ["", ""] )[1].toLowerCase();
                     // 獲取最外層元素的包裹元素,并將元素包裹在其中
                     wrap = wrapMap[ tag ] || wrapMap._default;
                     depth = wrap[0];
                     div.innerHTML = wrap[1] + elem + wrap[2];
                     // Move to the right depth
                     // 如果元素的包裹深度大于1,div重新賦值為元素最近的包裹元素(即:包含第一層包裹元素)
                     while ( depth-- ) {
                         div = div.lastChild;
                     }
                     // Remove IE's autoinserted <tbody> from table fragments
                     // 在IE6,7中,清除字符串中空table標(biāo)簽中自動(dòng)加入的tbody標(biāo)簽(手動(dòng)加入的除外)
                     if ( !jQuery.support.tbody ) {
                         // String was a <table>, *may* have spurious(偽造的) <tbody>
                         // 判斷字符串中是否擁有空tbody標(biāo)簽
                         hasBody = rtbody.test(elem);
                         // 如果最外層標(biāo)簽為table且table中沒有手動(dòng)加入tbody
                         // 變量tbody為div.firstChild.childNodes(自動(dòng)加入的tbody標(biāo)簽集合)
                         tbody = tag === "table" && !hasBody ?
                             div.firstChild && div.firstChild.childNodes :
                             // String was a bare <thead> or <tfoot>
                             // 如果字符串中僅有一個(gè)空thead或tfoot標(biāo)簽
                             // 變量tbody為div.childNodes(字符串中的thead和tfoot標(biāo)簽集合)
                             wrap[1] === "<table>" && !hasBody ?
                                 div.childNodes :
                                 [];
                         for ( j = tbody.length - 1; j >= 0 ; --j ) {
                             // 排除thead或tfoot標(biāo)簽
                             if ( jQuery.nodeName( tbody[ j ], "tbody" ) && !tbody[ j ].childNodes.length ) {
                                 // 清除空table標(biāo)簽中自動(dòng)加入的tbody
                                 tbody[ j ].parentNode.removeChild( tbody[ j ] );
                             }
                         }
                     }
                     // IE completely kills leading whitespace when innerHTML is used
                     // 在ie9以下瀏覽器中,字符串以空白字符串開頭,將空白字符串作為div元素的第一個(gè)文本子節(jié)點(diǎn)
                     if ( !jQuery.support.leadingWhitespace && rleadingWhitespace.test( elem ) ) {
                         div.insertBefore( context.createTextNode( rleadingWhitespace.exec(elem)[0] ), div.firstChild );
                     }
                     // 獲取已經(jīng)處理完畢的div子節(jié)點(diǎn)集合(nodeList對(duì)象)
                     elem = div.childNodes;
                     // Take out of fragment container (we need a fresh div each time)
                     // 在下一次循環(huán)處理字符串?dāng)?shù)組項(xiàng)前,清除處理創(chuàng)建過的div元素
                     div.parentNode.removeChild( div );
                 }
             }
             // 如果elem為DOM節(jié)點(diǎn)(文本節(jié)點(diǎn))
             if ( elem.nodeType ) {
                 ret.push( elem );
             }
             // 將nodeList對(duì)象中節(jié)點(diǎn)合并到返回的數(shù)組中
             else {
                 jQuery.merge( ret, elem );
             }
         }
         // Fix #11356: Clear elements from safeFragment
         if ( div ) {
             elem = div = safe = null;
         }
         // Reset defaultChecked for any radios and checkboxes
         // about to be appended to the DOM in IE 6/7 (#8060)
         // 在ie6,7中,擁有checked屬性的單選按鈕,復(fù)選框在插入到其他標(biāo)簽后,選中狀態(tài)會(huì)失效(下面代碼修復(fù)該bug)
         if ( !jQuery.support.appendChecked ) {
             for ( i = 0; (elem = ret[i]) != null; i++ ) {
                 if ( jQuery.nodeName( elem, "input" ) ) {
                     fixDefaultChecked( elem );
                 } else if ( typeof elem.getElementsByTagName !== "undefined" ) {
                     jQuery.grep( elem.getElementsByTagName("input"), fixDefaultChecked );
                 }
             }
         }
         // Append elements to a provided document fragment
         // 將ret數(shù)組中的各DOM節(jié)點(diǎn)插入到提供的文檔碎片中
         // 提取dom節(jié)點(diǎn)中的script節(jié)點(diǎn),并添加到ret數(shù)組中,位置為其原父元素索引位置后
         if ( fragment ) {
             // Special handling of each script element
             handleScript = function( elem ) {
                 // Check if we consider it executable
                 // 如果elem元素不存在type屬性或者type值為javascript或者為ecmascript
                 if ( !elem.type || rscriptType.test( elem.type ) ) {
                     // Detach the script and store it in the scripts array (if provided) or the fragment
                     // Return truthy to indicate that it has been handled
                     return scripts ?
                         scripts.push( elem.parentNode ? elem.parentNode.removeChild( elem ) : elem ) :
                         fragment.appendChild( elem );
                 }
             };
             for ( i = 0; (elem = ret[i]) != null; i++ ) {
                 // Check if we're done after handling an executable script
                 if ( !( jQuery.nodeName( elem, "script" ) && handleScript( elem ) ) ) {
                     // Append to fragment and handle embedded scripts
                     // 將elem元素添加到文檔碎片中并處理嵌入的腳本(script標(biāo)簽元素)
                     fragment.appendChild( elem );
                     if ( typeof elem.getElementsByTagName !== "undefined" ) {
                         // handleScript alters the DOM, so use jQuery.merge to ensure snapshot iteration
                         jsTags = jQuery.grep( jQuery.merge( [], elem.getElementsByTagName("script") ), handleScript );
                         // Splice the scripts into ret after their former ancestor and advance our index beyond them
                         // 將script標(biāo)簽添加到數(shù)組,位置為其原父元素索引位置后
                         ret.splice.apply( ret, [i + 1, 0].concat( jsTags ) );
                         i += jsTags.length;
                     }
                 }
             }
         }
         return ret;
     }
 });

相關(guān)文章

最新評(píng)論