@@ -6,6 +6,7 @@ var curCSS, iframe, iframeDoc,
6
6
// see here for display values: https://developer.mozilla.org/en-US/docs/CSS/display
7
7
rdisplayswap = / ^ ( n o n e | t a b l e (? ! - c [ e a ] ) .+ ) / ,
8
8
rmargin = / ^ m a r g i n / ,
9
+ // core_pnum = /[\-+]?(?:\d*\.|)\d+(?:[eE][\-+]?\d+|)/.source,
9
10
rnumsplit = new RegExp ( "^(" + core_pnum + ")(.*)$" , "i" ) ,
10
11
rnumnonpx = new RegExp ( "^(" + core_pnum + ")(?!px)[a-z%]+$" , "i" ) ,
11
12
rrelNum = new RegExp ( "^([-+])=(" + core_pnum + ")" , "i" ) ,
@@ -23,15 +24,18 @@ var curCSS, iframe, iframeDoc,
23
24
eventsToggle = jQuery . fn . toggle ;
24
25
25
26
// return a css property mapped to a potentially vendor prefixed property
27
+ // 获取css属性名
26
28
function vendorPropName ( style , name ) {
27
29
28
30
// shortcut for names that are not vendor prefixed
31
+ // 简单处理不带前缀的属性名
29
32
if ( name in style ) {
30
33
return name ;
31
34
}
32
35
33
36
// check for vendor prefixed names
34
- var capName = name . charAt ( 0 ) . toUpperCase ( ) + name . slice ( 1 ) ,
37
+ // 带前缀的属性名
38
+ var capName = name . charAt ( 0 ) . toUpperCase ( ) + name . slice ( 1 ) , // 第一个字母大写
35
39
origName = name ,
36
40
i = cssPrefixes . length ;
37
41
@@ -45,33 +49,43 @@ function vendorPropName( style, name ) {
45
49
return origName ;
46
50
}
47
51
52
+ // 判断节点是否隐藏
53
+ // 为什么用两个参数?
48
54
function isHidden ( elem , el ) {
49
55
elem = el || elem ;
56
+ // elem.ownerDocument 返回elem的根节点,即document
57
+ // 所以这里后半句为判断此elem是否包含在document中,若不包含,jQuery就认为它是隐藏的。
50
58
return jQuery . css ( elem , "display" ) === "none" || ! jQuery . contains ( elem . ownerDocument , elem ) ;
51
59
}
52
60
61
+ // 显示或隐藏节点
53
62
function showHide ( elements , show ) {
54
63
var elem , display ,
55
64
values = [ ] ,
56
65
index = 0 ,
57
66
length = elements . length ;
58
67
68
+ // 第一次遍历节点
59
69
for ( ; index < length ; index ++ ) {
60
70
elem = elements [ index ] ;
71
+ // 没有style属性
61
72
if ( ! elem . style ) {
62
73
continue ;
63
74
}
75
+ // 取出保存在缓存的olddisplay值
64
76
values [ index ] = jQuery . _data ( elem , "olddisplay" ) ;
65
77
if ( show ) {
66
78
// Reset the inline display of this element to learn if it is
67
79
// being hidden by cascaded rules or not
80
+ // 通过将display设置成空字符,来判断节点是否会显示
68
81
if ( ! values [ index ] && elem . style . display === "none" ) {
69
82
elem . style . display = "" ;
70
83
}
71
84
72
85
// Set elements which have been overridden with display: none
73
86
// in a stylesheet to whatever the default browser style is
74
87
// for such an element
88
+ // 如果display被设成了空字符,并且节点是隐藏的,则通过css_defaultDisplay把display默认值缓存起来
75
89
if ( elem . style . display === "" && isHidden ( elem ) ) {
76
90
values [ index ] = jQuery . _data ( elem , "olddisplay" , css_defaultDisplay ( elem . nodeName ) ) ;
77
91
}
@@ -86,12 +100,14 @@ function showHide( elements, show ) {
86
100
87
101
// Set the display of most of the elements in a second loop
88
102
// to avoid the constant reflow
103
+ // 第二次遍历节点时设置display,避免不断reflow
89
104
for ( index = 0 ; index < length ; index ++ ) {
90
105
elem = elements [ index ] ;
91
106
if ( ! elem . style ) {
92
107
continue ;
93
108
}
94
109
if ( ! show || elem . style . display === "none" || elem . style . display === "" ) {
110
+ // 如果要显示,则设置为缓存值或者空字符,否则设置为none
95
111
elem . style . display = show ? values [ index ] || "" : "none" ;
96
112
}
97
113
}
@@ -100,12 +116,23 @@ function showHide( elements, show ) {
100
116
}
101
117
102
118
jQuery . fn . extend ( {
119
+ // 对外提供的接口,读取/设置节点样式
120
+ // 方式1:$('header').css('height')
121
+ // 方式2:$('header').css('height', '20px')
122
+ // 方式3:$('header').css(attr, function(index,oldValue){})
123
+ // 方式4:$('header').css({'height':'10px', 'width':'20px'})
103
124
css : function ( name , value ) {
125
+ // jQuery.access是一个多功能内部方法,神一样的代码
126
+ // 此处需要比较需要关心的是 function( elem, name, value ) 这个匿名方法
127
+ // 在jQuery.access经过各种判断检测后,最终就是调用这个匿名方法,遍历this,进行样式读取、设置
128
+ // elem:设置/读取样式的节点
129
+ // name:样式名
130
+ // value:样式值
104
131
return jQuery . access ( this , function ( elem , name , value ) {
105
132
return value !== undefined ?
106
- jQuery . style ( elem , name , value ) :
107
- jQuery . css ( elem , name ) ;
108
- } , name , value , arguments . length > 1 ) ;
133
+ jQuery . style ( elem , name , value ) : // 设置样式,方式2、3、4的最终归宿
134
+ jQuery . css ( elem , name ) ; // 读取样式,方式1的最终归宿
135
+ } , name , value , arguments . length > 1 ) ; // arguments.length > 1 即 value !== undefined,jQuery.access中的参数为chainable,设置样式的时候实现链式调用。但实际上如果采用css({'height':'10px', 'width':'20px'})这种方式来设置,arguments.length == 1,jQuery.access内部对这种情况做了特殊处理,chainable继续为true
109
136
} ,
110
137
show : function ( ) {
111
138
return showHide ( this , true ) ;
@@ -166,24 +193,30 @@ jQuery.extend({
166
193
} ,
167
194
168
195
// Get and set the style property on a DOM Node
196
+ // 读取和设置DOM节点的style属性
169
197
style : function ( elem , name , value , extra ) {
170
198
// Don't set styles on text and comment nodes
199
+ // 过滤掉文本和注释节点以及没有style属性的节点
200
+ // nodeType = 3,文本;8,注释;
171
201
if ( ! elem || elem . nodeType === 3 || elem . nodeType === 8 || ! elem . style ) {
172
202
return ;
173
203
}
174
204
175
205
// Make sure that we're working with the right name
206
+ // 修正属性名
176
207
var ret , type , hooks ,
177
208
origName = jQuery . camelCase ( name ) ,
178
209
style = elem . style ;
179
210
211
+ //jQuery.cssProps中如果有则取出,否则通过vendorPropName方法来得到实际的css属性名,并缓存在jQuery.cssProps中
180
212
name = jQuery . cssProps [ origName ] || ( jQuery . cssProps [ origName ] = vendorPropName ( style , origName ) ) ;
181
213
182
214
// gets hook for the prefixed version
183
215
// followed by the unprefixed version
184
216
hooks = jQuery . cssHooks [ name ] || jQuery . cssHooks [ origName ] ;
185
217
186
218
// Check if we're setting a value
219
+ // 设置属性
187
220
if ( value !== undefined ) {
188
221
type = typeof value ;
189
222
@@ -224,6 +257,7 @@ jQuery.extend({
224
257
}
225
258
} ,
226
259
260
+ // 读取节点渲染后的样式值
227
261
css : function ( elem , name , numeric , extra ) {
228
262
var val , num , hooks ,
229
263
origName = jQuery . camelCase ( name ) ;
@@ -282,6 +316,12 @@ jQuery.extend({
282
316
283
317
// NOTE: To any future maintainer, we've window.getComputedStyle
284
318
// because jsdom on node.js will break without it.
319
+ // curCSS 为 jQuery.css 的核心方法,获取节点样式
320
+ // window.getComputedStyle类似于style,但有区别:
321
+ // 1、只读与可写
322
+ // 2、获取的对象范围
323
+ // 关于window.getComputedStyle,延伸阅读 http://www.zhangxinxu.com/wordpress/2012/05/getcomputedstyle-js-getpropertyvalue-currentstyle/
324
+ // IE6-8不支持
285
325
if ( window . getComputedStyle ) {
286
326
curCSS = function ( elem , name ) {
287
327
var ret , width , minWidth , maxWidth ,
@@ -291,6 +331,9 @@ if ( window.getComputedStyle ) {
291
331
if ( computed ) {
292
332
293
333
// getPropertyValue is only needed for .css('filter') in IE9, see #12537
334
+ // getPropertyValue方法可以获取CSS样式对象上的属性值(直接属性名称)
335
+ // 这里是针对12537bug的修复 http://bugs.jquery.com/ticket/12537
336
+ // bug现象是 element.css('filter') returns undefined in IE9
294
337
ret = computed . getPropertyValue ( name ) || computed [ name ] ;
295
338
296
339
if ( ret === "" && ! jQuery . contains ( elem . ownerDocument , elem ) ) {
@@ -301,6 +344,7 @@ if ( window.getComputedStyle ) {
301
344
// Chrome < 17 and Safari 5.0 uses "computed value" instead of "used value" for margin-right
302
345
// Safari 5.1.7 (at least) returns percentage for a larger set of values, but width seems to be reliably pixels
303
346
// this is against the CSSOM draft spec: http://dev.w3.org/csswg/cssom/#resolved-values
347
+ // 来自Dean Edwards的碉堡了的hack
304
348
if ( rnumnonpx . test ( ret ) && rmargin . test ( name ) ) {
305
349
width = style . width ;
306
350
minWidth = style . minWidth ;
@@ -318,13 +362,15 @@ if ( window.getComputedStyle ) {
318
362
return ret ;
319
363
} ;
320
364
} else if ( document . documentElement . currentStyle ) {
365
+ // currentStyle与getComputedStyle相似,只有IE支持
321
366
curCSS = function ( elem , name ) {
322
367
var left , rsLeft ,
323
368
ret = elem . currentStyle && elem . currentStyle [ name ] ,
324
369
style = elem . style ;
325
370
326
371
// Avoid setting ret to empty string here
327
372
// so we don't default to auto
373
+ // 如果currentStyle取不到,尝试用style来取
328
374
if ( ret == null && style && style [ name ] ) {
329
375
ret = style [ name ] ;
330
376
}
@@ -336,6 +382,8 @@ if ( window.getComputedStyle ) {
336
382
// but a number that has a weird ending, we need to convert it to pixels
337
383
// but not position css attributes, as those are proportional to the parent element instead
338
384
// and we can't measure the parent instead because it might trigger a "stacking dolls" problem
385
+ // 又是来自Dean Edwards的碉堡了的hack
386
+ // 不规则的像素数字需要额外处理
339
387
if ( rnumnonpx . test ( ret ) && ! rposition . test ( name ) ) {
340
388
341
389
// Remember the original values
@@ -360,6 +408,7 @@ if ( window.getComputedStyle ) {
360
408
} ;
361
409
}
362
410
411
+ // 设置正数
363
412
function setPositiveNumber ( elem , value , subtract ) {
364
413
var matches = rnumsplit . exec ( value ) ;
365
414
return matches ?
@@ -452,17 +501,21 @@ function getWidthOrHeight( elem, name, extra ) {
452
501
453
502
454
503
// Try to determine the default display value of an element
504
+ // 判断一个节点的display默认值
455
505
function css_defaultDisplay ( nodeName ) {
506
+ // 缓存中已有,直接return值
456
507
if ( elemdisplay [ nodeName ] ) {
457
508
return elemdisplay [ nodeName ] ;
458
509
}
459
510
511
+ // 向body中添加一个节点,取其display值
460
512
var elem = jQuery ( "<" + nodeName + ">" ) . appendTo ( document . body ) ,
461
513
display = elem . css ( "display" ) ;
462
514
elem . remove ( ) ;
463
515
464
516
// If the simple way fails,
465
517
// get element's real default display by attaching it to a temp iframe
518
+ // 如果上述方法无效,则创建一个临时的iframe,将节点append到此iframe中,再取其display值
466
519
if ( display === "none" || display === "" ) {
467
520
// Use the already-created iframe if possible
468
521
iframe = document . body . appendChild (
@@ -489,6 +542,7 @@ function css_defaultDisplay( nodeName ) {
489
542
}
490
543
491
544
// Store the correct default display
545
+ // 将值缓存起来
492
546
elemdisplay [ nodeName ] = display ;
493
547
494
548
return display ;
0 commit comments