前文提要,jQuery用init方法创建的,它是jQuery.fn.init的实例而非jQuery的实例,后期会用jQuery.fn.init.
01.
//另一个复杂的方法
02.
css:
function
( key, value ) {
03.
// ignore negative width and height values
04.
if
( (key ==
'width'
|| key ==
'height'
) && parseFloat(value) < 0 )
05.
value = undefined;
06.
return
this
.attr( key, value,
"curCSS"
);
07.
},
08.
//与css与attr一样,既能读亦能写
09.
text:
function
( text ) {
10.
if
(
typeof
text !==
"object"
&& text !=
null
)
11.
return
this
.empty().append( (
this
[0] &&
this
[0].ownerDocument || document).createTextNode( text ) );
12.
13.
var
ret =
""
;
14.
15.
jQuery.each( text ||
this
,
function
(){
16.
jQuery.each(
this
.childNodes,
function
(){
17.
if
(
this
.nodeType != 8 )
18.
ret +=
this
.nodeType != 1 ?
19.
this
.nodeValue :
20.
jQuery.fn.text( [
this
] );
21.
});
22.
});
23.
24.
return
ret;
25.
},
26.
27.
//把匹配的元素作出了为一个整体用参数里的标签(如果传入的是元素也会转换为标签)包起来,
28.
//$("p").wrapAll('<div></div>') => <div><p>******</p><p>******</p><p>******</p></div>
29.
//这东西应该叫wrapOutter更好
30.
wrapAll:
function
( html ) {
31.
if
(
this
[0] ) {
32.
// The elements to wrap the target around
33.
var
wrap = jQuery( html,
this
[0].ownerDocument ).clone();
34.
35.
if
(
this
[0].parentNode )
36.
wrap.insertBefore(
this
[0] );
37.
38.
wrap.map(
function
(){
39.
var
elem =
this
;
40.
41.
while
( elem.firstChild )
42.
elem = elem.firstChild;
43.
44.
return
elem;
45.
}).append(
this
);
46.
}
47.
48.
return
this
;
49.
},
50.
//相当于把匹配的元素取得其innerHTML,然后用wrapAll方法包起来
51.
//$("p").wrapInner('<div></div>') => <p><div>******</div></p><p><div>******</div></p><p><div>******</div></p>
52.
wrapInner:
function
( html ) {
53.
return
this
.each(
function
(){
54.
jQuery(
this
).contents().wrapAll( html );
55.
});
56.
},
57.
//与上面相反,有点像outterHTML,内容外面加一层皮
58.
//$("p").wrap('<div></div>') => <div><p>******</p></div><div><p>******</p></div><div><p>******</p></div>
59.
wrap:
function
( html ) {
60.
return
this
.each(
function
(){
61.
jQuery(
this
).wrapAll( html );
62.
});
63.
},
接着下来分析append,prepend,before,after。内部实现非常复杂,先扼要类比一下已有的API吧。
1.
//append:向每个匹配的元素内部追加内容。
2.
//相当于
3.
//insertAdjacentHTML("beforeEnd",htmlstr)
4.
//insertAdjacentElement("beforeEnd",dom)
5.
//insertAdjacentElement("beforeEnd",jQueryEl)
6.
//并且具有处理复数个DOM对象的能力(内部用jQuery.each实现)
1.
//prepend:向每个匹配的元素内部前置内容。
2.
//相当于
3.
//insertAdjacentHTML("afterBegin",htmlstr)
4.
//insertAdjacentElement("afterBegin",dom)
5.
//insertAdjacentElement("afterBegin",jQueryEl)
6.
//并且具有处理复数个DOM对象的能力(内部用jQuery.each实现)
1.
//before:在每个匹配的元素之前插入内容。
2.
//相当于
3.
//insertAdjacentHTML("beforeBegin",htmlstr)
4.
//insertAdjacentElement("beforeBegin",dom)
5.
//insertAdjacentElement("beforeBegin",jQueryEl)
6.
//并且具有处理复数个DOM对象的能力(内部用jQuery.each实现)
1.
//after:在每个匹配的元素之后插入内容。。
2.
//相当于
3.
//insertAdjacentHTML("afterEnd",htmlstr)
4.
//insertAdjacentElement("afterEnd",dom)
5.
//insertAdjacentElement("afterEnd",jQueryEl)
6.
//并且具有处理复数个DOM对象的能力(内部用jQuery.each实现)
这些方法内部都调用一个叫domManip的方法,它的存在价值仅仅是为了兼容邪恶的火狐,因为火狐死活不支持IE的insertAdjacentXXX系列。
001.
//主要用于返回上次覆盖了DOM元素数组
002.
end:
function
() {
003.
return
this
.prevObject || jQuery( [] );
004.
},
005.
006.
// For internal use only.
007.
// Behaves like an Array's method, not like a jQuery method.
008.
push: [].push,
009.
sort: [].sort,
010.
splice: [].splice,
011.
//jQuery强大的CSS选择器
012.
find:
function
( selector ) {
013.
if
(
this
.length === 1 ) {
014.
var
ret =
this
.pushStack( [],
"find"
, selector );
015.
ret.length = 0;
016.
//分别为表达式,上下文,与之前获得的元素集合(它们将作为此次的搜索起点)
017.
jQuery.find( selector,
this
[0], ret );
018.
return
ret;
019.
}
else
{
020.
//每次都会重新洗牌,因此必须进行压栈操作
021.
return
this
.pushStack( jQuery.unique(jQuery.map(
this
,
function
(elem){
022.
return
jQuery.find( selector, elem );
023.
})),
"find"
, selector );
024.
}
025.
},
026.
//先复制DOM再复制其上的事件
027.
clone:
function
( events ) {
028.
// Do the clone
029.
var
ret =
this
.map(
function
(){
030.
if
( !jQuery.support.noCloneEvent && !jQuery.isXMLDoc(
this
) ) {
031.
// IE copies events bound via attachEvent when
032.
// using cloneNode. Calling detachEvent on the
033.
// clone will also remove the events from the orignal
034.
// In order to get around this, we use innerHTML.
035.
// Unfortunately, this means some modifications to
036.
// attributes in IE that are actually only stored
037.
// as properties will not be copied (such as the
038.
// the name attribute on an input).
039.
var
html =
this
.outerHTML;
040.
041.
if
( !html ) {
042.
var
div =
this
.ownerDocument.createElement(
"div"
);
043.
div.appendChild(
this
.cloneNode(
true
) );
044.
html = div.innerHTML;
045.
}
046.
//将字符串转换成jQuery对象
047.
return
jQuery.clean([html.replace(/ jQuery\d+=
"(?:\d+|null)"
/g,
""
).replace(/^\s*/,
""
)])[0];
048.
}
else
049.
return
this
.cloneNode(
true
);
050.
});
051.
//许多是后面的方法,到时再说
052.
// Copy the events from the original to the clone
053.
if
( events ===
true
) {
054.
var
orig =
this
.find(
"*"
).andSelf(), i = 0;
055.
056.
ret.find(
"*"
).andSelf().each(
function
(){
057.
if
(
this
.nodeName !== orig[i].nodeName )
058.
return
;
059.
060.
var
events = jQuery.data( orig[i],
"events"
);
061.
062.
for
(
var
type
in
events ) {
063.
for
(
var
handler
in
events[ type ] ) {
064.
jQuery.event.add(
this
, type, events[ type ][ handler ], events[ type ][ handler ].data );
065.
}
066.
}
067.
068.
i++;
069.
});
070.
}
071.
072.
// Return the cloned set
073.
return
ret;
074.
},
075.
//如果参数是函数则用jQuery.greg,否则用jQuery.multiFiler
076.
filter:
function
( selector ) {
077.
return
this
.pushStack(
078.
jQuery.isFunction( selector ) &&
079.
jQuery.grep(
this
,
function
(elem, i){
080.
return
selector.call( elem, i );
081.
}) ||
082.
083.
jQuery.multiFilter( selector, jQuery.grep(
this
,
function
(elem){
084.
return
elem.nodeType === 1;
085.
}) ),
"filter"
, selector );
086.
},
087.
//筛选最近的元素
088.
closest:
function
( selector ) {
089.
//判断是否用于方位的
090.
var
pos = jQuery.expr.match.POS.test( selector ) ? jQuery(selector) :
null
,
091.
closer = 0;
092.
//把得到元素用map进行进一步的筛选
093.
return
this
.map(
function
(){
094.
var
cur =
this
;
095.
while
( cur && cur.ownerDocument ) {
096.
if
( pos ? pos.index(cur) > -1 : jQuery(cur).is(selector) ) {
097.
jQuery.data(cur,
"closest"
, closer);
098.
return
cur;
099.
}
100.
cur = cur.parentNode;
101.
closer++;
102.
}
103.
});
104.
},
105.
//用于反选,内部调用filter
106.
not:
function
( selector ) {
107.
if
(
typeof
selector ===
"string"
)
108.
// test special case where just one selector is passed in
109.
if
( isSimple.test( selector ) )
//如果单一的类
110.
return
this
.pushStack( jQuery.multiFilter( selector,
this
,
true
),
"not"
, selector );
111.
else
112.
selector = jQuery.multiFilter( selector,
this
);
113.
//处理NodeList
114.
var
isArrayLike = selector.length && selector[selector.length - 1] !== undefined && !selector.nodeType;
115.
return
this
.filter(
function
() {
//再回调用filter
116.
return
isArrayLike ? jQuery.inArray(
this
, selector ) < 0 :
this
!= selector;
117.
});
118.
},
119.
//添加新元素,内部进行清零压栈等操作
120.
add:
function
( selector ) {
121.
return
this
.pushStack( jQuery.unique( jQuery.merge(
122.
this
.get(),
123.
typeof
selector ===
"string"
?
124.
jQuery( selector ) :
125.
jQuery.makeArray( selector )
126.
)));
127.
},
128.
//相当于javascript1.6 Array的some方法
129.
is:
function
( selector ) {
130.
return
!!selector && jQuery.multiFilter( selector,
this
).length > 0;
131.
},
132.
//怎么这方法那么笨重?!
133.
hasClass:
function
( selector ) {
134.
return
!!selector &&
this
.is(
"."
+ selector );
135.
},
136.
//基本上是用于获取元素value属性的值
137.
//对于下拉开框,则是其innerText
138.
//与css,attr一样,可读可写
139.
val:
function
( value ) {
140.
if
( value === undefined ) {
141.
var
elem =
this
[0];
142.
143.
if
( elem ) {
144.
if
( jQuery.nodeName( elem,
'option'
) )
145.
return
(elem.attributes.value || {}).specified ? elem.value : elem.text;
146.
147.
// We need to handle select boxes special
148.
if
( jQuery.nodeName( elem,
"select"
) ) {
149.
var
index = elem.selectedIndex,
150.
values = [],
151.
options = elem.options,
152.
one = elem.type ==
"select-one"
;
153.
154.
// Nothing was selected
155.
if
( index < 0 )
156.
return
null
;
157.
158.
// Loop through all the selected options
159.
for
(
var
i = one ? index : 0, max = one ? index + 1 : options.length; i < max; i++ ) {
160.
var
option = options[ i ];
161.
162.
if
( option.selected ) {
163.
// Get the specifc value for the option
164.
value = jQuery(option).val();
165.
166.
// We don't need an array for one selects
167.
if
( one )
168.
return
value;
169.
170.
// Multi-Selects return an array
171.
values.push( value );
172.
}
173.
}
174.
175.
return
values;
176.
}
177.
178.
// Everything else, we just grab the value
179.
return
(elem.value ||
""
).replace(/\r/g,
""
);
180.
181.
}
182.
183.
return
undefined;
184.
}
185.
186.
if
(
typeof
value ===
"number"
)
187.
value +=
''
;
188.
189.
return
this
.each(
function
(){
190.
if
(
this
.nodeType != 1 )
191.
return
;
192.
//处理radio的checkbox checked属性,用于返回true与false
193.
if
( jQuery.isArray(value) && /radio|checkbox/.test(
this
.type ) )
194.
this
.checked = (jQuery.inArray(
this
.value, value) >= 0 ||
195.
jQuery.inArray(
this
.name, value) >= 0);
196.
197.
else
if
( jQuery.nodeName(
this
,
"select"
) ) {
198.
var
values = jQuery.makeArray(value);
199.
200.
jQuery(
"option"
,
this
).each(
function
(){
201.
this
.selected = (jQuery.inArray(
this
.value, values ) >= 0 ||
202.
jQuery.inArray(
this
.text, values ) >= 0);
203.
});
204.
205.
if
( !values.length )
206.
this
.selectedIndex = -1;
207.
208.
}
else
209.
this
.value = value;
210.
});
211.
},
212.
//就是innerHTML
213.
html:
function
( value ) {
214.
return
value === undefined ?
215.
(
this
[0] ?
216.
this
[0].innerHTML.replace(/ jQuery\d+=
"(?:\d+|null)"
/g,
""
) :
217.
null
) :
218.
this
.empty().append( value );
219.
},
220.
//与replaceNode差不多
221.
replaceWith:
function
( value ) {
222.
return
this
.after( value ).remove();
223.
},
224.
//把等于此索引值的DOM对象从jQuery对象中取出
225.
eq:
function
( i ) {
226.
return
this
.slice( i, +i + 1 );
227.
},