traversing.js源码

提供查询、过滤方法

traversing.js

// dir.js

define([
	"../../core"
],function(jQuery){

return 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;
};

});


// siblings.js

define(function(){

return function(n,elem){
	var matched=[];

	for ( ; n; n=n.nextSibling ){
		if ( n.nodeType===1 && n!==elem ){
			matched.push(n);
		}
	}

	return matched;
};

});

// traversing.js

define( [
	"./core",
	"./var/indexOf",
	// dir(elem,dir,until) dir为待获取元素的elem的位置关系,until选择器找到该元素时,查询终止
	"./traversing/var/dir",
	// siblings(n,elem) 遍历获取n的兄弟节点,排除elem
	"./traversing/var/siblings",
	// jQuery.expr.match.needsContext "+"、":odd"等需要查询的父节点
	"./traversing/var/rneedsContext",
	"./core/init",
	"./traversing/findFilter",
	"./selector"
],function(jQuery,indexOf,dir,siblings,rneedsContext){

var rparentsprev=/^(?:parents|prev(?:Until|All))/,

	// Methods guaranteed to produce a unique set when starting from a unique set
	guaranteedUnique={
		children:true,
		contents:true,
		next:true,
		prev:true
	};

jQuery.fn.extend({
	// 查找子节点
	has:function(target){
		var targets=jQuery(target,this),
			l=targets.length;

		return this.filter(function(){
			var i=0;
			for ( ; i<l; i++ ){
				if ( jQuery.contains(this,targets[i]) ){
					return true;
				}
			}
		});
	},
	// 向上获取所有匹配selectors的节点,selector不能使":odd"、":first"、"+"等带有层级关系
	// 在文档查询所有selectors,滤除不是当前元素父节点的元素
	closest:function(selectors,context){
		var cur,
			i=0,
			l=this.length,
			matched=[],
			targets=typeof selectors!=="string" && jQuery(selectors);

		if ( !rneedsContext.test(selectors) ){
			for ( ; i<l; i++ ){
				for ( cur=this[i]; cur && cur!==context; cur=cur.parentNode ){

					if ( cur.nodeType<11 && ( targets ?
						targets.index(cur)>-1 :
						cur.nodeType===1 && jQuery.find.matchesSelector(cur,selectors) 
						) ){

						matched.push(cur);
						break;
					}
				}
			}
		}

		return this.pushStack(matched.length>1 ? jQuery.uniqueSort(matched) : matched);
	},

	// 获取当前元素在传参选择器俘获元素中的index值,或传参元素在当前元素集合中的index值
	index:function(elem){

		// 没有参数传入,first获取当前元素的首项,判断它在父节点中的序号值
		if ( !elem ){
			return ( this[0] && this[0].parentNode ) ? this.first().prevAll().length : -1;
		}

		// 传参为elem,返回当前元素在$(elem)中的序号值,当前元素和$(elem)平辈
		if ( typeof elem==="string" ){
			return indexOf.call(jQuery(elem),this[0]);
		}

		// 若传入dom元素或jquery对象,判断它们在当前元素中的index序号
		return indexOf.call(this, elem.jquery ? elem[0] : elem);
	},

	// context下找到的selector元素添加到当前元素集合中返回
	add:function(selector,context){
		return this.pushStack(
			jQuery.uniqueSort(
				jQuery.merge(this.get(),jQuery(selector,context))
			)
		);
	},

	// 与end不同的是,addBack不只回到先前操作的元素集合,还包含滤除不匹配selector的元素
	addBack:function(selector){
		return this.add( selector==null ?
			this.prevObject : this.prevObject.filter(selector)
		);
	}
} );

function sibling( cur, dir ) {
	while ( ( cur = cur[ dir ] ) && cur.nodeType !== 1 ) {}
	return cur;
}

jQuery.each({
	// 父节点
	parent:function(elem){
		var parent=elem.parentNode;
		return parent && parent.nodeType!==11 ? parent : null;
	},
	// 祖先节点
	parents:function(elem){
		return dir(elem,"parentNode");
	},
	// 祖先节点,获取直到until级为止,until为选择器
	parentsUntil:function(elem,i,until){
		return dir(elem,"parentNode",until);
	},
	// 后一个节点
	next:function(elem){
		return sibling(elem,"nextSibling");
	},
	// 前一个节点
	prev:function(elem){
		return sibling(elem,"previousSibling");
	},
	// 后续兄弟节点
	nextAll:function(elem){
		return dir(elem,"nextSibling");
	},
	// 此前的兄弟节点
	prevAll:function(elem){
		return dir(elem,"previousSibling");
	},
	// 后续兄弟节点,到until为止
	nextUntil:function(elem,i,until){
		return dir(elem,"nextSibling",until);
	},
	// 之前的兄弟节点,到until为止
	prevUntil:function(elem,i,until){
		return dir(elem,"previousSibling",until);
	},
	// 兄弟节点
	siblings:function(elem){
		return siblings((elem.parentNode || {}).firstChild,elem);
	},
	// 直接子节点,须是元素节点
	children:function(elem){
		return siblings(elem.firstChild);
	},
	// 子节点,不一定是元素节点
	contents:function(elem){
		return elem.contentDocument || jQuery.merge([],elem.childNodes);
	}
},function(name,fn){
	jQuery.fn[name]=function(until,selector){
		// $ele.prev方法: 通过sibling函数使用原生语句获取当前元素之前的节点
		// $ele.siblings方法:通过siblings函数使用原生语句查找当前元素父节点下
		// 			首个子节点的nextSibling节点,即当前元素的兄弟节点
		// $ele.siblings方法			
		var matched=jQuery.map(this,fn,until);

		// 方法名中不带until,jQuery.fn[name]只需要单参数selector
		if ( name.slice(-5)!=="Until" ){
			selector=until;
		}

		// 过滤
		if ( selector && typeof selector==="string" ){
			matched = jQuery.filter(selector,matched);
		}

		if ( this.length>1 ){
			if ( !guaranteedUnique[name] ){
				jQuery.uniqueSort(matched);
			}

			if ( rparentsprev.test(name) ){
				matched.reverse();
			}
		}

		return this.pushStack(matched);
	};
} );

return jQuery;
});

findFilter.js

define([
	"../core",
	"../var/indexOf",
	"./var/rneedsContext",
	"../selector"
],function(jQuery,indexOf,rneedsContext){

var risSimple=/^.[^:#\[\.,]*$/;

function winnow(elements,qualifier,not){
	// qualifier为函数,$.grep方法执行函数过滤
	if ( jQuery.isFunction(qualifier) ){
		return jQuery.grep(elements,function(elem,i){
			return !!qualifier.call(elem,i,elem)!==not;
		});

	}

	// qualifier为节点,比较过滤
	if ( qualifier.nodeType ){
		return jQuery.grep(elements,function(elem){
			return (elem===qualifier)!==not;
		});

	}

	// qualifier为选择器,使用jQuery.filter找到元素内部符合qualifier的元素,再调用$.grep过滤
	if ( typeof qualifier==="string" ){
		if ( risSimple.test(qualifier) ){
			return jQuery.filter(qualifier,elements,not);
		}

		qualifier=jQuery.filter(qualifier,elements);
	}

	return jQuery.grep(elements,function(elem){
		return ( indexOf.call(qualifier,elem)>-1 )!==not && elem.nodeType===1;
	});
}

// 过滤
jQuery.filter=function(expr,elems,not){
	var elem=elems[0];

	if ( not ){
		expr=":not("+expr+")";
	}

	return elems.length===1 && elem.nodeType===1 ?
		jQuery.find.matchesSelector(elem,expr) ? [elem] : [] :
		jQuery.find.matches(expr,jQuery.grep(elems,function(elem){
			return elem.nodeType===1;
		}));
};

jQuery.fn.extend({
	// 当前元素中查询,不是选择器时,使用$.contains过滤;不然当前元素作为find方法的context
	find:function(selector){
		var i, ret,
			len=this.length,
			self=this;

		if ( typeof selector!=="string" ) {
			return this.pushStack(jQuery(selector).filter(function(){
				for ( i=0; i<len; i++ ){
					if ( jQuery.contains(self[i],this) ){
						return true;
					}
				}
			}));
		}

		ret=this.pushStack([]);

		for ( i=0; i<len; i++ ){
			jQuery.find(selector,self[i],ret);
		}

		return len>1 ? jQuery.uniqueSort(ret) : ret;
	},
	// 过滤
	filter:function(selector){
		return this.pushStack(winnow(this,selector || [],false));
	},
	not:function(selector){
		return this.pushStack(winnow(this,selector || [],true));
	},
	// 过滤找出当前元素中selector节点,以它的长度作为返回值
	is:function(selector){
		return !!winnow(
			this,
			typeof selector==="string" && rneedsContext.test(selector) ?
				jQuery(selector) :
				selector || [],
			false
		).length;
	}
});

});

相关推荐