jQuery源碼-CSS樣式相關部分


jquery版本:1.7.2

根據實際需要,對CSS部分無關代碼進行適當刪除,如有疑問,可參見jquery源碼:http://code.jquery.com/jquery-1.7.2.js

因實際工作中暫時沒有用到jquery,故對jquery了解很粗淺,文章可能有錯漏之處,敬請見諒並指出

本文參考借鑒了nuysoft 的jquery源碼分析系列,挺不錯的系列文章,推薦下:

http://www.cnblogs.com/nuysoft/archive/2011/11/14/2248023.html

 


 

jquery里節點樣式讀取以及設置都是通過.css()這個方法來實現的,本章通過以下三個部分簡單探究下jquery里這部分代碼的實現

  1. 方法使用
  2. 源碼概覽
  3. 源碼解析

一、方法使用

常見的有四種用法,包括一種讀取樣式三種設置樣式:(詳細可參見:http://api.jquery.com/css/

(1)讀取樣式:

.css(propertyName)  //用法1

 (2)設置演示:

.css(propertyName, value)  //用法2

.css(propertyName, function(index, oldValue))  //用法3

.css(map)  //用法4

首先看下面幾個例子:

<div id="header"></div>
<ul id="list">
    <li></li> <li></li> <li></li>
</ul>
$('#header').css('height');  //讀取樣式值
$('#header').css('height', '10px');  //設置樣式值
$('#header').css({height:'20px', 'width':'20px'});  //通過map方式設置多個屬性
$('#list li').css('height', function(index, oldValue){ //通過傳入function來設置樣式,常用於集合操作
                                //index:為對應集合元素的索引,從0開始;而oldValue:元素原先樣式
    return index*10+'px';  //返回值:節點最終設置的樣式值
});

二、源碼概覽

主要代碼:

  • jQuery.fn.css  //對外接口,樣式讀取、設置都通過它完成
  • jQuery.access  //jQuery.fn.css內部調用的,完成樣式的讀取、設置
  • jQuery.css  //讀取節點樣式(實際渲染后)
  • jQuery.style  //讀取節點樣式(內聯樣式)、設置節點樣式
  • curCSS  //瀏覽器內置獲取節點樣式方法,為(1)支持標准的瀏覽器:getComputedStyle (2)IE系列:currentStyle

其他相關:

  • jQuery.cssHooks  //鈎子函數,某些樣式,如'height'、'width'等用到
  • jQuery.support  //瀏覽器對某些特性的支持,詳情見下文
  • jQuery.swap  //節點隱藏等情況下,height、width等獲取值不准,此時需利用此方法來獲得准確值,詳情見下文
  • jQuery.cssProps  //某些屬性,在瀏覽器里有各自的別名,如float:IE里為styleFloat,遵守標准的瀏覽器里為cssFoat,詳情見下文
  • jQuery.cssNumber  //某些屬性,如z-index,為數值類型,不需要單位,詳情見下文

相關正則:

    詳情見下文

三、源碼解析

主要代碼:

  • jQuery.fn.css  //對外接口,樣式讀取、設置都通過它完成
/**
 * @description 真正對外提供的接口,包括 讀取/設置 dom節點樣式 
 * @param 
 * @example 方式1:$('#header').css('height') ==> jQuery.css
 *          方式2:$('#header').css('height', '20px'),采用這種方式設置,只會對第一個元素進行樣式設置 ==> jQuery.style
            方式3:$('ul#list li.item').css(attr, function(index,oldValue){}),最終在內部轉換成 jQuery.style(attr, newValue)的形式 ==> jQuery.style
            方式4:$('#header').css({'height':'10px', 'width':'20px'}),最終在內部轉換成$(node).style(attr, value)形式 ==> jQuery.style
 */
jQuery.fn.css = function( name, value ) {
    //此處需要比較需要關心的是 function( elem, name, value ) 這個匿名方法
    //在jQuery.access經過各種判斷檢測后,最終就是調用這個匿名方法,遍歷this,進行樣式讀取、設置
    //elem:設置/讀取樣式的節點
    //name:樣式名
    //value:樣式值
    return jQuery.access( this, function( elem, name, value ) {
        return value !== undefined ?
            jQuery.style( elem, name, value ) :    //設置樣式,方式2、3、4的最終歸宿,jQuery.style源碼解析見下文
            jQuery.css( elem, name );    //讀取樣式,方法1的最終歸宿,jQuery.css源碼解析見下文
    }, name, value, arguments.length > 1 );    //arguments.length > 1,即value!=undefined,為設置樣式
                                            //此處判斷目的為:如設置樣式,最后需返回elem,以實現鏈式調用,如$(node).css('height','10px').css('width','20px')
                                            //當采用$(node).css(map)方式設置,arguments.length == 1,按照此處邏輯判斷,為讀取樣式
                                            //jQuery.access對這種情況進行了特殊處理,同樣返回elem,個人覺得這里寫法有點詭異
    
    //jQuery.access 定義如下,源碼解析見下文;此處只是方便參照把定義拷貝了過來,源碼里是沒有下面這一句的
    //jQuery.access = function( elems, fn, key, value, chainable, emptyGet, pass ){}
    //在css樣式設置這塊,emptyGet、pass兩個參數沒用到,請直接忽視,
};
  • jQuery.access  //jQuery.fn.css內部調用的,完成樣式的讀取、設置

備注:此方法在多處用到,此處只分析CSS相關部分,里面有部分參數、邏輯還有待了解

/**
 * @description 多功能函數,來自地獄的代碼
 *              多處用到,包括 jQuery.fn.css, jQuery.fn.attr, jQuery.fn.prop,此處只分析CSS相關部分
 * @param {DOMObject} elems 讀取/設置 樣式的dom元素
 * @param {Function} fn 讀取/設置 樣式對應的方法(1)讀取:jQuery.css(elem) (2)設置jQuery.style(elem,key,value)
 * @param {String} key 讀取/設置 樣式對應的屬性,如.css('height'),則key === 'height'
 * @param {Boolean} chainable 是否需要返回jQuery對象實現鏈式調用
 * @emptyGet CSS樣式部分貌似木有用到,暫忽略
 * @pass CSS樣式部分貌似木有用到,暫忽略
*/
jQuery.access = function( elems, fn, key, value, chainable, emptyGet, pass ) {
    var exec,
        bulk = key == null,    //key==null,表示key為null或者undefined
        i = 0,    //多么糟糕的變量啊!!又做index索引,又做對象的鍵值
        length = elems.length;

    // Sets many values
    if ( key && typeof key === "object" ) {    //設置樣式,對應jQuery.fn.css 方式4,如:$('#header').css({'height':'10px', 'width':'20px'})
        //通過遍歷哈希表方式,逐個設置節點樣式
        //此時key形式為:{'height':'10px', 'width':'20px'},key這變量名相當有迷惑性
        for ( i in key ) {
            jQuery.access( elems, fn, i, key[i], 1, emptyGet, value );    //逐個設置樣式,此處value==undefined
        }
        chainable = 1;    //chainable = 1 ,表示此處設置樣式

    // Sets one value
    } else if ( value !== undefined ) {    //設置樣式,如方式3:$('ul#list li.item').css('height', function(index,node){})
                                                    //方式2:$('#header').css('height', '20px')
        // Optionally, function values get executed if exec is true
        exec = pass === undefined && jQuery.isFunction( value );    //exec == true,則表示采用.css( property, function(index, oldValue) )方式設置樣式

        if ( bulk ) {    //@todo:目前還沒想到神馬情況下會走到這個分支里,有可能CSS樣式設置里不會出現,待進一步考察
            // Bulk operations only iterate when executing function values
            if ( exec ) {
                exec = fn;
                fn = function( elem, key, value ) {
                    return exec.call( jQuery( elem ), value );
                };

            // Otherwise they run against the entire set
            } else {
                fn.call( elems, value );
                fn = null;
            }
        }

        if ( fn ) {    
            for (; i < length; i++ ) {    //遍歷集合里的元素
                //value.call( elems[i], i, fn( elems[i], key ) )返回節點設置之前的的樣式
                //value ==> function(index, oldValue),i對應index, fn( elems[i], key )對應oldValue, fn為 jQuery.css
                //exec值參見上文
                fn( elems[i], key, exec ? value.call( elems[i], i, fn( elems[i], key ) ) : value, pass );
            }
        }

        chainable = 1;
    }
    
    return chainable ?    //chainable == 1,表示設置樣式,返回設置樣式的元素,實現鏈式調用
        // 設置樣式,返回元素
        elems :

        // 獲取樣式
        bulk ?    //bulk值參見上文
            fn.call( elems ) :    
            length ? fn( elems[0], key ) : emptyGet;    //此時fn對應 jQuery.css
                                                        //當elems為集合元素時,返回集合里第一個元素key對應的樣式值
                                 //此處的返回值為access的返回值,也即.css(propertyName)的返回值
}
  • jQuery.css  //讀取節點樣式(實際渲染后)
    /**
     * @description 讀取 dom 實際渲染的樣式值
     * @param {DOMObject} elem 獲取樣式的dom節點
     * @param {String} name 樣式名
     * @param extra 
    */
    css: function( elem, name, extra ) {
        var ret, hooks;

        // Make sure that we're working with the right name
        name = jQuery.camelCase( name );    //轉成駝峰形式,如margin-left --> marginLeft
        hooks = jQuery.cssHooks[ name ];    //某些特定的屬性有對應的get、set方法,如'height'、'width'、'opacity'等
        name = jQuery.cssProps[ name ] || name;    //對某些特殊屬性,如float進行修正

        // cssFloat needs a special treatment
        if ( name === "cssFloat" ) {    //兼容標准的瀏覽器如chrome,用$(node).css('float')或$(node).css('cssFloat')
            name = "float";
        }

        // If a hook was provided get the computed value from there
        //如果有對應的hook對象,且該對象有get方法,則調用hooks[name].get 來獲取樣式值
        if ( hooks && "get" in hooks && (ret = hooks.get( elem, true, extra )) !== undefined ) {
            return ret;
        // Otherwise, if a way to get the computed value exists, use that
        } else if ( curCSS ) {    //否則,通過curCSS方法來獲取實際渲染后的樣式值,curCSS定義見curCSS部分說明
            return curCSS( elem, name );
        }
    },
  • jQuery.style  //讀取節點樣式(內聯樣式)、設置節點樣式
    // Get and set the style property on a DOM Node
    /**
     * @description 讀取/設置 dom 節點樣式
     * @param {DOMObject} elem dom節點
     * @param {String} name 屬性值
     * @param {String|Number} value 樣式值
     * @note 當獲取樣式值時,返回的是內聯樣式值,而非瀏覽器實際渲染后的值
    */
    style: function( elem, name, value, extra ) {
        // Don't set styles on text and comment nodes
        //elem.nodeType ==> 3:文本,8:注釋,此處過濾文本、注釋節點
        //elem為document,則document.style == undefined,過濾無法設置屬性的節點
        if ( !elem || elem.nodeType === 3 || elem.nodeType === 8 || !elem.style ) {
            return;
        }

        // Make sure that we're working with the right name
        var ret, type, origName = jQuery.camelCase( name ),    //返回駝峰命名形式的屬性名
            style = elem.style, hooks = jQuery.cssHooks[ origName ];

        name = jQuery.cssProps[ origName ] || origName;    //float返回cssFloat或styleFloat(目前就只對這個屬性進行特殊處理)

        // Check if we're setting a value
        if ( value !== undefined ) {
            type = typeof value;

            // convert relative number strings (+= or -=) to relative numbers. #7345
            //采用相對值進行設置,如$(node).css('height','+=10px')
            //ret = rrelNum.exec( value ),如采用相對值進行設置,則:
            //ret[1]:+/-
            //ret[2]:相對值的大小
            if ( type === "string" && (ret = rrelNum.exec( value )) ) {
                value = ( +( ret[1] + 1) * +ret[2] ) + parseFloat( jQuery.css( elem, name ) );    //將相對值與原來的屬性值進行運算,獲得實際設置的值
                // Fixes bug #9237
                type = "number";
            }

            // Make sure that NaN and null values aren't set. See: #7116
            //如果設置的值為 null 或者 NaN,則不設置,直接返回
            if ( value == null || type === "number" && isNaN( value ) ) {
                return;
            }

            // If a number was passed in, add 'px' to the (except for certain CSS properties)
            //如果傳進來的值是number類型,如.css('height',10),則給10加上單位px
            if ( type === "number" && !jQuery.cssNumber[ origName ] ) {
                value += "px";
            }

            // If a hook was provided, use that value, otherwise just set the specified value
            //如果該屬性存在對應鈎子對象,且該對象有set方法,則調用剛set方法設置樣式值
            if ( !hooks || !("set" in hooks) || (value = hooks.set( elem, value )) !== undefined ) {
                // Wrapped to prevent IE from throwing errors when 'invalid' values are provided
                // Fixes bug #5509
                try {
                    style[ name ] = value;
                } catch(e) {}
            }

        } else {
            //如果value沒有提供,jQuery.css返回內聯樣式值
            // If a hook was provided get the non-computed value from there
            if ( hooks && "get" in hooks && (ret = hooks.get( elem, false, extra )) !== undefined ) {
                return ret;
            }
            // Otherwise just get the value from the style object
            return style[ name ];
        }
    },
  • curCSS  //瀏覽器內置獲取節點樣式方法,為(1)遵守支持標准的瀏覽器:getComputedStyle (2)IE系列:currentStyle
//處理遵守W3C標准的瀏覽器
//在瀏覽器里,document.defaultView返回與document相關的window對象,如果不存在,則返回null
//IE9以下版本的IE系列不支持defaultView
//其實可以直接window.getComputedStyle,除了一種情況,見:https://developer.mozilla.org/en-US/docs/DOM/window.getComputedStyle
//getComputedStyle() gives the final used values of all the CSS properties of an element.
//比如樣式表里設置font-size:12px,內聯樣式設置font-size:20px,返回的是20px
if ( document.defaultView && document.defaultView.getComputedStyle ) {    //兼容標准的瀏覽器
    getComputedStyle = function( elem, name ) {
        var ret, defaultView, computedStyle, width,
            style = elem.style;
        name = name.replace( rupper, "-$1" ).toLowerCase();    //將屬性名轉換成margin-left這種帶連字符的形式
                                                            //rupper定義:rupper = /([A-Z]|^ms)/g
        if ( (defaultView = elem.ownerDocument.defaultView) &&
                (computedStyle = defaultView.getComputedStyle( elem, null )) ) {    //ownerDocument 可返回某元素的根元素,定義見:https://developer.mozilla.org/en-US/docs/DOM/Node.ownerDocument
                                                                                    //getComputedStyle,返回計算后的樣式值,定義見:https://developer.mozilla.org/en-US/docs/DOM/window.getComputedStyle
                                                                                    //關於getComputedStyle與computed value、used value的關系:https://developer.mozilla.org/en-US/docs/CSS/computed_value
            ret = computedStyle.getPropertyValue( name );    //
            if ( ret === "" && !jQuery.contains( elem.ownerDocument.documentElement, elem ) ) {    //這句的作用??
                ret = jQuery.style( elem, name );
            }
            //document.documentElement返回文檔的的根節點,比如html文檔的<html>元素
        }

        // A tribute to the "awesome hack by Dean Edwards"
        // WebKit uses "computed value (percentage if specified)" instead of "used value" for margins
        // which is against the CSSOM draft spec: http://dev.w3.org/csswg/cssom/#resolved-values
        //jQuery.support.pixelMargin:是否支持margin返回的結果是px為單位(webkit里面,如果設置了百分值,則返回百分值)??
        //經chrome測試,jQuery.support.pixelMargin === true
        if ( !jQuery.support.pixelMargin && computedStyle && rmargin.test( name ) && rnumnonpx.test( ret ) ) {
            width = style.width;
            style.width = ret;
            ret = computedStyle.width;
            style.width = width;
        }

        return ret;
    };
}

//IE瀏覽器,此處留坑待填
if ( document.documentElement.currentStyle ) {    //currentStyle:IE瀏覽器特有的屬性
    currentStyle = function( elem, name ) {
        var left, rsLeft, uncomputed,
            ret = elem.currentStyle && elem.currentStyle[ name ],
            style = elem.style;

        // Avoid setting ret to empty string here
        // so we don't default to auto
        if ( ret == null && style && (uncomputed = style[ name ]) ) {
            ret = uncomputed;
        }

        // From the awesome hack by Dean Edwards
        // http://erik.eae.net/archives/2007/07/27/18.54.15/#comment-102291

        // If we're not dealing with a regular pixel number
        // but a number that has a weird ending, we need to convert it to pixels
        if ( rnumnonpx.test( ret ) ) {    //rnumnonpx定義:rnumnonpx = /^-?(?:\d*\.)?\d+(?!px)[^\d\s]+$/i

            // Remember the original values
            left = style.left;
            rsLeft = elem.runtimeStyle && elem.runtimeStyle.left;

            // Put in the new values to get a computed value out
            if ( rsLeft ) {
                elem.runtimeStyle.left = elem.currentStyle.left;
            }
            style.left = name === "fontSize" ? "1em" : ret;
            ret = style.pixelLeft + "px";

            // Revert the changed values
            style.left = left;
            if ( rsLeft ) {
                elem.runtimeStyle.left = rsLeft;
            }
        }

        return ret === "" ? "auto" : ret;
    };
}

curCSS = getComputedStyle || currentStyle;

其他相關:

  • jQuery.cssHooks  //鈎子函數,某些樣式,如'height'、'width'等用到
jQuery.extend({
    // Add in style property hooks for overriding the default
    // behavior of getting and setting a style property
    //鈎子方法,對一些特殊的屬性,需要有特殊的樣式讀取(get)、設置(set)方法
    cssHooks: {
        //@cssHooks1:透明度
        opacity: {
            get: function( elem, computed ) {
                if ( computed ) {
                    // We should always get a number back from opacity
                    var ret = curCSS( elem, "opacity" );
                    return ret === "" ? "1" : ret;

                } else {
                    return elem.style.opacity;
                }
            }
        }
    }
});

//@cssHooks3:透明度
if ( !jQuery.support.opacity ) {    //如果不支持style.opacity,關於support下文有講到,暫時從字面上理解即可
    jQuery.cssHooks.opacity = {
        get: function( elem, computed ) {
            // IE uses filters for opacity
            return ropacity.test( (computed && elem.currentStyle ? elem.currentStyle.filter : elem.style.filter) || "" ) ?    //IE:是否存在filter:alpha(opacity=30)的樣式設置
                ( parseFloat( RegExp.$1 ) / 100 ) + "" :    //存在:將opacity轉換成小數點形式(與遵守標准的瀏覽器保持一致)
                computed ? "1" : "";    //不存在:未設置opacity,視為全部透明,即1
        },

        set: function( elem, value ) {
            var style = elem.style,
                currentStyle = elem.currentStyle,
                opacity = jQuery.isNumeric( value ) ? "alpha(opacity=" + value * 100 + ")" : "",    //為IE、非IE保持一致,需要乘以100
                filter = currentStyle && currentStyle.filter || style.filter || "";

            // IE has trouble with opacity if it does not have layout
            // Force it by setting the zoom level
            style.zoom = 1;    //此處為解決IE bug,表示還不知道有這么個bug存在於人世間,重構的兄弟們辛苦了

            // if setting opacity to 1, and no other filters exist - attempt to remove filter attribute #6652
            if ( value >= 1 && jQuery.trim( filter.replace( ralpha, "" ) ) === "" ) {

                // Setting style.filter to null, "" & " " still leave "filter:" in the cssText
                // if "filter:" is present at all, clearType is disabled, we want to avoid this
                // style.removeAttribute is IE Only, but so apparently is this code path...
                style.removeAttribute( "filter" );

                // if there there is no filter style applied in a css rule, we are done
                if ( currentStyle && !currentStyle.filter ) {
                    return;
                }
            }

            // otherwise, set new filter values
            style.filter = ralpha.test( filter ) ?
                filter.replace( ralpha, opacity ) :
                filter + " " + opacity;
        }
    };
}

//@cssHooks4:marginRight(右外邊距)
//據說是為了處理神bug存在的,就不傷害自己腦細胞了,了解下即可
jQuery(function() {
    // This hook cannot be added until DOM ready because the support test
    // for it is not run until after DOM ready
    if ( !jQuery.support.reliableMarginRight ) {
        jQuery.cssHooks.marginRight = {
            get: function( elem, computed ) {
                // WebKit Bug 13343 - getComputedStyle returns wrong value for margin-right
                // Work around by temporarily setting element display to inline-block
                return jQuery.swap( elem, { "display": "inline-block" }, function() {
                    if ( computed ) {
                        return curCSS( elem, "margin-right" );
                    } else {
                        return elem.style.marginRight;
                    }
                });
            }
        };
    }
});

// These hooks are used by animate to expand properties
//@cssHooks5:待填坑
jQuery.each({
    margin: "",
    padding: "",
    border: "Width"
}, function( prefix, suffix ) {

    jQuery.cssHooks[ prefix + suffix ] = {
        expand: function( value ) {
            var i,

                // assumes a single number if not a string
                parts = typeof value === "string" ? value.split(" ") : [ value ],
                expanded = {};

            for ( i = 0; i < 4; i++ ) {
                expanded[ prefix + cssExpand[ i ] + suffix ] =
                    parts[ i ] || parts[ i - 2 ] || parts[ 0 ];
            }

            return expanded;
        }
    };
});

//@cssHooks2用到
function getWidthOrHeight( elem, name, extra ) {

    // Start with offset property
    var val = name === "width" ? elem.offsetWidth : elem.offsetHeight,
        i = name === "width" ? 1 : 0,
        len = 4;

    if ( val > 0 ) {    //此處作用,減去paddingTopWidth、paddingBottomWidth、borderTopWidth、borderBottomWidth,要不要這么隱晦啊啊!!!
        if ( extra !== "border" ) {
            for ( ; i < len; i += 2 ) {
                if ( !extra ) {
                    val -= parseFloat( jQuery.css( elem, "padding" + cssExpand[ i ] ) ) || 0;
                }
                if ( extra === "margin" ) {
                    val += parseFloat( jQuery.css( elem, extra + cssExpand[ i ] ) ) || 0;
                } else {
                    val -= parseFloat( jQuery.css( elem, "border" + cssExpand[ i ] + "Width" ) ) || 0;
                }
            }
        }

        return val + "px";
    }

    // Fall back to computed then uncomputed css if necessary
    val = curCSS( elem, name );
    if ( val < 0 || val == null ) {    //會有小於0的情況嗎???
        val = elem.style[ name ];
    }

    // Computed unit is not pixels. Stop here and return.
    if ( rnumnonpx.test(val) ) {    //val單位非px
        return val;
    }

    // Normalize "", auto, and prepare for extra
    val = parseFloat( val ) || 0;

    // Add padding, border, margin
    //目測:在getClentHeight、getClientWidth等處可以用到
    if ( extra ) {
        for ( ; i < len; i += 2 ) {
            val += parseFloat( jQuery.css( elem, "padding" + cssExpand[ i ] ) ) || 0;
            if ( extra !== "padding" ) {
                val += parseFloat( jQuery.css( elem, "border" + cssExpand[ i ] + "Width" ) ) || 0;
            }
            if ( extra === "margin" ) {
                val += parseFloat( jQuery.css( elem, extra + cssExpand[ i ]) ) || 0;
            }
        }
    }

    return val + "px";
}
  • jQuery.support  //瀏覽器對某些特性的支持,詳情見下文
//各種測試是否支持某些屬性
//僅將CSS相關部分挑出來,完整的support方法包注釋200++行,有興趣可以看下源碼
jQuery.support = (function(){
    var marginDiv,
        div = document.createElement( "div" );
    div.innerHTML = "   <link/><table></table><a href='/a' style='top:1px;float:left;opacity:.55;'>a</a><input type='checkbox'/>";    
    
    var a = div.getElementsByTagName( "a" )[ 0 ];
    
    var support = {
        // Make sure that element opacity exists
        // (IE uses filter instead)
        // Use a regex to work around a WebKit issue. See #5145
        opacity: /^0.55/.test( a.style.opacity ),    //是否支持opacity==>IE6/7/8采用filter來實現(半)透明效果,
        
        // Verify style float existence
        // (IE uses styleFloat instead of cssFloat)
        cssFloat: !!a.style.cssFloat,    //(1)IE:node.style.styleFloat(2)chrome等:node.style.cssFloat
        
        reliableMarginRight: true,        //解決webkit的bug:getComputedStyle返回錯誤的margin-right值
                                        //解決方案:暫時將節點的display屬性設為inline-block
        pixelMargin: true,    //是否支持margin返回的結果是px為單位(webkit里面,如果設置了百分值,則返回百分值),測試了下chrome下是ok的    
    };
    
    // Check if div with explicit width and no margin-right incorrectly
    // gets computed margin-right based on width of container. For more
    // info see bug #3333
    // Fails in WebKit before Feb 2011 nightlies
    // WebKit Bug 13343 - getComputedStyle returns wrong value for margin-right
    if ( window.getComputedStyle ) {    //jQuery.support.reliableMarginRight
        div.innerHTML = "";
        marginDiv = document.createElement( "div" );
        marginDiv.style.width = "0";
        marginDiv.style.marginRight = "0";
        div.style.width = "2px";
        div.appendChild( marginDiv );
        support.reliableMarginRight =
            ( parseInt( ( window.getComputedStyle( marginDiv, null ) || { marginRight: 0 } ).marginRight, 10 ) || 0 ) === 0;
    }
    
    if ( window.getComputedStyle ) {    //jQuery.support.pixelMargin
        div.style.marginTop = "1%";
        support.pixelMargin = ( window.getComputedStyle( div, null ) || { marginTop: 0 } ).marginTop !== "1%";
    }    
    
    return support;
})();
  • jQuery.swap  //節點隱藏等情況下,height、width等獲取值不准,此時需利用此方法來獲得准確值
jQuery.extend({
	// A method for quickly swapping in/out CSS properties to get correct calculations
	//將offsetHeight、offsetWidth為0的元素快速修改樣式,獲得需要的值后,再改回去
	//options:{display:'block',position:'absolute',visibility:'hidden'}
	/**
	 * @description 將offsetHeight、offsetWidth為0(可能因display=none等原因導致)的元素快速修改樣式,獲得瀏覽器實際渲染的值后,再改回去
	 * @param {DOMObject} elem dom節點
	 * @param {Object} options {display:'block',position:'absolute',visibility:'hidden'}
	 * @param {Function} callback 回調方法,如獲取修改后的dom節點的寬、高等
	*/
	swap: function( elem, options, callback ) {
		var old = {},
			ret, name;

		// Remember the old values, and insert the new ones
		for ( name in options ) {	//先將dom元素設置為display=block;position=absolute;visibility=hidden;
			old[ name ] = elem.style[ name ];
			elem.style[ name ] = options[ name ];
		}

		ret = callback.call( elem );

		// Revert the old values
		for ( name in options ) {	//將改變的display、position、visibiliby設置回去
			elem.style[ name ] = old[ name ];
		}

		return ret;
	}
});
  • jQuery.cssProps  //某些屬性,在瀏覽器里有各自的別名,如float:IE里為styleFloat,遵守標准的瀏覽器里為cssFoat
jQuery.extend({
    // Add in properties whose names you wish to fix before
    // setting or getting the value
    //此處的屬性名需要特殊處理,如float,在IE里為node.style.styleFloat,支持標准的瀏覽器里為node.style.cssFloat
    cssProps: {
        // normalize float css property
        "float": jQuery.support.cssFloat ? "cssFloat" : "styleFloat"
    }
});
  • jQuery.cssNumber  //某些屬性,如z-index,為數值類型,不需要單位
jQuery.extend({
    // Exclude the following css properties to add px
    //排除一下css屬性,無需加px,此處有些疑問,如lineHeight,需再研究下。
    cssNumber: {
        "fillOpacity": true,
        "fontWeight": true,
        "lineHeight": true,
        "opacity": true,
        "orphans": true,
        "widows": true,
        "zIndex": true,
        "zoom": true
    }
});

相關正則等:

var ralpha = /alpha\([^)]*\)/i,    //匹配如:alpha(opacity=20)
    ropacity = /opacity=([^)]*)/,    //匹配如:filter:alpha(opacity=20)等形式
    // fixed for IE9, see #8346
    rupper = /([A-Z]|^ms)/g,    //此處暫不明,但覺厲,需再探究下
    rnum = /^[\-+]?(?:\d*\.)?\d+$/i,    //匹配數字(包括浮點),如(+/-)1、(+/-)0.1、(+/-).1、(+/-)1.1
    rnumnonpx = /^-?(?:\d*\.)?\d+(?!px)[^\d\s]+$/i,    //非px值,如'10em'、'10%'等
    rrelNum = /^([\-+])=([\-+.\de]+)/,    //設置屬性支持相對寫法,如$('#header').css('height', '+=10px')等。。
    rmargin = /^margin/,    //屬性是否為margin開頭的,如margin-left、margin-top等

    cssShow = { position: "absolute", visibility: "hidden", display: "block" },    //對於offsetHeight或offsetWidth為0的元素

    // order is important!
    cssExpand = [ "Top", "Right", "Bottom", "Left" ],    //計算寬、高用到

    curCSS,    //最終只是把getComputedStyle或currentStyle方法其中之一賦給curCss

    getComputedStyle,    //遵守標准的瀏覽器獲取css樣式的方法
    currentStyle;    //IE瀏覽器獲取css樣式的方法

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM