jQuery.fn.css = function( name, value ) { if ( arguments.length === 2 && value === undefined ) { return this; } return jQuery.access( this, name, value, true, function( elem, name, value ) { return value !== undefined ?jQuery.style( elem, name, value ) : jQuery.css( elem, name ); }); };
jQuery处理样式,如果参数长度为2,而vlaue值undefined,则无需赋值直接返回。否则返回jQuery.access操作结果
access: function( elems, key, value, exec, fn, pass ) { var length = elems.length; if ( typeof key === "object" ) { for ( var k in key ) { jQuery.access( elems, k, key[k], exec, fn, value); } return elems; } if ( value !== undefined ) { exec = !pass && exec && jQuery.isFunction(value); for ( var i = 0; i < length; i++ ) { fn( elems[i], key, exec ? value.call( elems[i], i, fn( elems[i], key ) ) : value, pass ); } return elems; } return length ? fn( elems[0], key ) : undefined; }
内部公用方法access,首先会先通过判断key的类型是否为object,如果为真,则通过递归的方式把每个key[k]作为的属性分别进行操作。
if ( typeof key === "object" ) { for ( var k in key ) { jQuery.access( elems, k, key[k], exec, fn, value); } return elems; }
然后对单个节点进行操作,判断value!==underfined,true则通过传入的方法fn设置属性key[k]的值并返回对象集elems,false则返回属性的值
if ( value !== undefined ) { exec = !pass && exec && jQuery.isFunction(value); for ( var i = 0; i < length; i++ ) { fn( elems[i], key, exec ? value.call( elems[i], i, fn( elems[i], key ) ) : value, pass ); } return elems; }
return length ? fn( elems[0], key ) : undefined;
在这里,fn为:
function( elem, name, value ) {
return value !== undefined ?jQuery.style( elem, name, value ) :jQuery.css( elem, name );
}
通过判断传入的value来判断是否是设置节点elem样式name的值value:jQuery.style( elem, name, value )或者获取elem样式name的值:jQuery.css( elem, name ).
cssHooks: {//特别处理的属性 opacity: { get: function( elem, computed ) { if ( computed ) { var ret = curCSS( elem, "opacity", "opacity" ); return ret === "" ? "1" : ret; } else { return elem.style.opacity; } } } }, cssNumber: {// "zIndex": true, "fontWeight": true, "opacity": true, "zoom": true, "lineHeight": true, "widows": true, "orphans": true }, cssProps: {// "float": jQuery.support.cssFloat ? "cssFloat" : "styleFloat" }, style: function( elem, name, value, extra ) { if ( !elem || elem.nodeType === 3 || elem.nodeType === 8 || !elem.style ) { return; } var ret, type, origName = jQuery.camelCase( name ), style = elem.style, hooks = jQuery.cssHooks[ origName ]; name = jQuery.cssProps[ origName ] || origName; if ( value !== undefined ) { type = typeof value; if ( type === "number" && isNaN( value ) || value == null ) { return; } ative number strings (+= or -=) to relative numbers. #7345 if ( type === "string" && rrelNum.test( value ) ) { value = +value.replace( rrelNumFilter, "" ) + parseFloat( jQuery.css( elem, name ) ); } if ( type === "number" && !jQuery.cssNumber[ origName ] ) { value += "px"; } if ( !hooks || !("set" in hooks) || (value = hooks.set( elem, value )) !== undefined ) { try { style[ name ] = value; } catch(e) {} } } else { // 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; } return style[ name ]; } }, css: function( elem, name, extra ) { var ret, hooks; name = jQuery.camelCase( name ); hooks = jQuery.cssHooks[ name ]; name = jQuery.cssProps[ name ] || name;// if ( name === "cssFloat" ) { name = "float"; } if ( hooks && "get" in hooks && (ret = hooks.get( elem, true, extra )) !== undefined ) { return ret; } else if ( curCSS ) { return curCSS( elem, name ); } }, swap: function( elem, options, callback ) { var old = {}; for ( var name in options ) { old[ name ] = elem.style[ name ]; elem.style[ name ] = options[ name ]; } callback.call( elem ); for ( name in options ) { elem.style[ name ] = old[ name ]; } }, camelCase: function( string ) { return string.replace( rdashAlpha, fcamelCase ); }
cssHooks://特别处理的属性
cssNumber://排除下面的CSS属性添加PX
cssProps://浮动属性
camelCase://对有中线的样式名转换成驼峰写法,如:image-position:imagePosition
设置样式值
style: function( elem, name, value, extra ) { if ( !elem || elem.nodeType === 3 || elem.nodeType === 8 || !elem.style ) {//elem不存在,文本节点,注释节点,没有style则返回 return; } var ret, type, origName = jQuery.camelCase( name ), style = elem.style, hooks = jQuery.cssHooks[ origName ]; name = jQuery.cssProps[ origName ] || origName; if ( value !== undefined ) { type = typeof value; if ( type === "number" && isNaN( value ) || value == null ) {// return; } if ( type === "string" && rrelNum.test( value ) ) {//例如+=2123asd -=1231203排序叫撒旦过滤后对属性数值进行加减+2123 -1231203 value = +value.replace( rrelNumFilter, "" ) + parseFloat( jQuery.css( elem, name ) ); } if ( type === "number" && !jQuery.cssNumber[ origName ] ) {//对非规定的样式和不带单位的参数,默认加上单位“px” value += "px"; } if ( !hooks || !("set" in hooks) || (value = hooks.set( elem, value )) !== undefined ) {//对特殊样式,用hooks.set()方法进行设置 try { style[ name ] = value; } catch(e) {} } } else {// if ( hooks && "get" in hooks && (ret = hooks.get( elem, false, extra )) !== undefined ) { return ret; } return style[ name ];//直接通过style属性获取name样式的值 } }
获取样式值:
css: function( elem, name, extra ) { var ret, hooks; name = jQuery.camelCase( name );//样式名转换成驼峰写法 hooks = jQuery.cssHooks[ name ];//判断是否是特殊样式 name = jQuery.cssProps[ name ] || name;//是否是浮动样式以便后面转换 if ( name === "cssFloat" ) {//针对ie name = "float"; } if ( hooks && "get" in hooks && (ret = hooks.get( elem, true, extra )) !== undefined ) {//如果是特殊样式则通过hooks.get(elem,true,extra)处理并返回结果 return ret; } else if ( curCSS ) { return curCSS( elem, name );//否则通过curCSS返回执行的结果 } },
curCSS:
if ( document.defaultView && document.defaultView.getComputedStyle ) { getComputedStyle = function( elem, name ) { var ret, defaultView, computedStyle; name = name.replace( rupper, "-$1" ).toLowerCase(); if ( !(defaultView = elem.ownerDocument.defaultView) ) { return undefined; } if ( (computedStyle = defaultView.getComputedStyle( elem, null )) ) { ret = computedStyle.getPropertyValue( name ); if ( ret === "" && !jQuery.contains( elem.ownerDocument.documentElement, elem ) ) { ret = jQuery.style( elem, name ); } } return ret; }; } if ( document.documentElement.currentStyle ) { currentStyle = function( elem, name ) { var left, ret = elem.currentStyle && elem.currentStyle[ name ], rsLeft = elem.runtimeStyle && elem.runtimeStyle[ name ], style = elem.style; // 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 ( !rnumpx.test( ret ) && rnum.test( ret ) ) { // Remember the original values left = style.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 || 0); 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.css(elem,name)是通过curCSS计算最终样式