jQuery.extend({
// 返回elem延DOM树某个方向访问的所有节点,直到遇到until条件
dir: function( elem, dir, until ) {
var matched = [],
truncate = until !== undefined;
while ( (elem = elem[ dir ]) && elem.nodeType !== 9 ) {
if ( elem.nodeType === 1 ) {
if ( truncate && jQuery( elem ).is( until ) ) {
break;
}
matched.push( elem );
}
}
return matched;
},
//返回n的兄弟节点(把n,elem设为相同元素时,不返回本身)
sibling: function( n, elem ) {
var matched = [];
for ( ; n; n = n.nextSibling ) {
if ( n.nodeType === 1 && n !== elem ) {
matched.push( n );
}
}
return matched;
}
});
jQuery.fn.extend({
has: function( target ) {
// 以当前jquery对象为上下文查找target
var targets = jQuery( target, this ),
l = targets.length;
// 过滤掉当前JQuery不包含target后代的元素
return this.filter(function() {
var i = 0;
for ( ; i < l; i++ ) {
if ( jQuery.contains( this, targets[i] ) ) {
return true;
}
}
});
},
// 返回包含符合selector元素的最近的JQuery对象
// 返回的可能是其包含自己或其父类的JQuery对象,其长度为0或1
closest: function( selectors, context ) {
var cur,
i = 0,
l = this.length,
matched = [],
pos = rneedsContext.test( selectors ) || typeof selectors !== "string" ?
jQuery( selectors, context || this.context ) :
0;
for ( ; i < l; i++ ) {
// 从本身开始,然后沿父类继续
for ( cur = this[i]; cur && cur !== context; cur = cur.parentNode ) {
// Always skip document fragments
// 如果pos是以$(selectors,context)查找出的JQuery对象
if ( cur.nodeType < 11 && (pos ?
// pos中是否可查找到cur元素
pos.index(cur) > -1 :
// 否则查看cur是否满足selectors选择表达式
// Don't pass non-elements to Sizzle
cur.nodeType === 1 &&
jQuery.find.matchesSelector(cur, selectors)) ) {
matched.push( cur );
break;
}
}
}
return this.pushStack( matched.length > 1 ? jQuery.unique( matched ) : matched );
},
// Determine the position of an element within
// the matched set of elements
index: function( elem ) {
// No argument, return index in parent
// 没有传入参数返回在同辈元素中的位置
if ( !elem ) {
return ( this[ 0 ] && this[ 0 ].parentNode ) ? this.first().prevAll().length : -1;
}
// index in selector
// 参数是选择器
if ( typeof elem === "string" ) {
// 返回本JQuery对象第一个元素在匹配所有此选择器的JQuery对象的位置
return indexOf.call( jQuery( elem ), this[ 0 ] );
}
// Locate the position of the desired element
// 返回参数元素在此JQuery对象的位置
return indexOf.call( this,
// If it receives a jQuery object, the first element is used
elem.jquery ? elem[ 0 ] : elem
);
},
// 在当前JQuery对象中添加额外元素
add: function( selector, context ) {
return this.pushStack(
jQuery.unique(
jQuery.merge( this.get(), jQuery( selector, context ) )
)
);
},
// 将调用链上前一个JQuery中的元素添加到当前JQuery对象中
// selector参数用于过滤前一个JQuery对象
addBack: function( selector ) {
return this.add( selector == null ?
this.prevObject : this.prevObject.filter(selector)
);
}
});
// 沿DOM树某个方向获取下一个DOM元素
function sibling( cur, dir ) {
// 一直遇到DOM元素再停下
while ( (cur = cur[dir]) && cur.nodeType !== 1 ) {}
return cur;
}
// 绑定快捷遍历JQuery对象方法
jQuery.each({
parent: function( elem ) {
var parent = elem.parentNode;
return parent && parent.nodeType !== 11 ? parent : null;
},
parents: function( elem ) {
return jQuery.dir( elem, "parentNode" );
},
parentsUntil: function( elem, i, until ) {
return jQuery.dir( elem, "parentNode", until );
},
next: function( elem ) {
return sibling( elem, "nextSibling" );
},
prev: function( elem ) {
return sibling( elem, "previousSibling" );
},
nextAll: function( elem ) {
return jQuery.dir( elem, "nextSibling" );
},
prevAll: function( elem ) {
return jQuery.dir( elem, "previousSibling" );
},
nextUntil: function( elem, i, until ) {
return jQuery.dir( elem, "nextSibling", until );
},
prevUntil: function( elem, i, until ) {
return jQuery.dir( elem, "previousSibling", until );
},
siblings: function( elem ) {
return jQuery.sibling( ( elem.parentNode || {} ).firstChild, elem );
},
children: function( elem ) {
return jQuery.sibling( elem.firstChild );
},
// frame里的所有子元素
contents: function( elem ) {
return elem.contentDocument || jQuery.merge( [], elem.childNodes );
}
}, function( name, fn ) {
// 在JQuery的原型对象上绑定快捷遍历函数
jQuery.fn[ name ] = function( until, selector ) {
// this指调用此方法的JQuery对象
// 根据不同遍历的fn,将this中的元素映射成其遍历后的元素
var matched = jQuery.map( this, fn, until );
// 如果方法不是没有终止条件(Until)
// 修正selector为第一个参数
if ( name.slice( -5 ) !== "Until" ) {
selector = until;
}
if ( selector && typeof selector === "string" ) {
// 过滤matched中不符合selecotr的元素
matched = jQuery.filter( selector, matched );
}
// this中如果有多个元素,那么遍历后的matched可能存在重复
if ( this.length > 1 ) {
// Remove duplicates
if ( !guaranteedUnique[ name ] ) {
jQuery.unique( matched );
}
// Reverse order for parents* and prev-derivatives
// parent或pare的遍历matched应该反转,使matched顺序更符合逻辑
if ( rparentsprev.test( name ) ) {
matched.reverse();
}
}
// 返回以matched为元素的新的JQuery对象
return this.pushStack( matched );
};
});
JQuery日记 6.3 JQuery遍历模块,布布扣,bubuko.com
JQuery日记 6.3 JQuery遍历模块