mk.loop(arr, fun):
loop : function(arr, fun){
if(!arr.length || typeof fun != "function") return;
for(var i=0; i<arr.length; i++)
if(fun(arr[i]))
break;
}
参数arr应该是一个具有length属性并能通过数字索引下标访问的集合
参数fun应该是一个function对象。当fun返回true(或者非null undefined 0)的时候,将会中断循环。
通过这个迭代函数,可以省去不停地写for的麻烦。此类的迭代函数,有的是写在Array类上,通过js的原型继承,来实现所有数组的迭代功能。
类似:
Array.prototype.each = function(fun){
if(typeof fun == "function")
for(var i=0; i<this.length; i++){
fun(this[i]);
}
}
但问题是,getElementsByTagName或者childNodes虽然返回的是一个集合,但不是一个Array,而且我们找不到它的原型,所以类似的集合无法继承到这个each,反而容易在编写代码中造成误解和错误。所以我没有采用这种迭代方式,而是用这个稍麻烦的工具来实现。而且,我不想“污染”原型。
mk.getSingleNodeInChildNodes(tag, parent, index)
getSingleNodeInChildNodes : function(tag, parent, index){
var _n = false;
if(typeof tag != "string") return _n;
var _parent = parent || document;
var _index = index || 0;
tag = tag.toLowerCase();
var _i = 0;
this.loop(_parent.childNodes, function(n){
if(n.nodeType == 1)
if(n.nodeName.toLowerCase() == tag){
_n = n;
if(_i++ >= _index)
return true;
}
});
return _n;
}
这个函数是通过遍历childNodes,来获取子元素中nodeName = tag的第index个元素。这只是个浅表的检索,因为通过getElementsByTagName获取的是包括嵌套在内全部的同名节点。
mk.getChildNodesOfType(typeNum, parent)
getChildNodesOfType : function(typeNum, parent){
var _cs = [];
if(typeof typeNum != "number") return _cs;
var _parent = parent || document;
this.loop(_parent.childNodes, function(n){
if(n.nodeType == typeNum)
_cs.push(n);
});
return _cs;
}
获取某节点childNodes中nodeType==typenum的所有节点。浅表检索。
mk.getSingleNodeByTagName(tagName, parent, index)
getSingleNodeByTagName : function(tagName, parent, index){
if(typeof tagName != "string") return false;
var _parent = parent || document;
var _index = typeof index == "number" || 0;
return _parent.getElementsByTagName(tagName)[_index];
}
这个貌似.net的xml中getSingleNode方法的东西,返回相同含义的节点。
mk.loopParentNode(self, parentTagName)
loopParentNode : function(self, parentTagName){
var n = false;
if(!self.parentNode || typeof parentTagName != "string") return n;
var p = self.parentNode;
parentTagName = parentTagName.toLowerCase();
while(!!p){
if(p.nodeName.toLowerCase() == parentTagName){
n = p;
break;
}
p = p.parentNode;
}
return n;
}
寻找一个节点的父节点,且父节点的nodeName==parentTagName
mk.getDeepAndPath(obj, tag, addChildToParent)
getDeepAndPath : function(obj, tag, addChildToParent){
var _path = [];
var _deep = 0;
var _obj = obj;
var _addChildToParent = !!addChildToParent;
if(!_obj.childEles && addChildToParent) _obj.childEles = [];
if(typeof tag == "string"){
tag = tag.toLowerCase();
while(_obj.parentNode){
_obj = _obj.parentNode;
if(_obj.nodeName.toLowerCase() == tag){
_deep++;
_path.push(_obj);
if(_addChildToParent)
_obj.childEles.push(obj);
}
}
} else {
while(_obj.parentNode){
_obj = _li.parentNode;
_deep++;
_path.push(_obj);
if(_addChildToParent)
_obj.childEles.push(obj);
}
}
return { path : _path.reverse(), deep : _deep };
}
寻找一个节点的所有父节点,且父节点的nodeName== tag,返回查找成功的树路径和深度。路径的length应该与深度相等。
如果参数tag不为一个字符串类型,则查找时对父节点的nodeName不进行筛选。
如果参数addChildToParent为true,则在父节点中添加childEles属性,存储曾向该节点查询过的子节点。
mk.dom
dom : { //get all elements of the page. only when nodeType == 1
nodes : [],
classNames : [],
init : function(n, addChildToParent){
var _n = n || document;
var _atp = !!addChildToParent;
if(!this.nodes.names) this.nodes.names = [];
for(var i=0; i<_n.childNodes.length; i++){
var node = _n.childNodes[i];
if(node.nodeType == 1){
this.nodes.push(node);
var nn = node.nodeName.toLowerCase();
if(!this.nodes[nn]){
this.nodes[nn] = [];
this.nodes.names.push(nn);
}
this.nodes[nn].push(node);
if(node.className){
if(!this.classNames[node.className]){
this.classNames.push(node.className);
this.classNames[node.className] = [];
}
this.classNames[node.className].push(node);
}
if(_atp){
if(p = node.parentNode){
if(!p.subNodes) p.subNodes = [];
p.subNodes.push(node);
}
}
this.init(node, _atp);
}
}
}
}
mk.dom 通过对指定节点内部节点的一次遍历,构建nodes对象和classNames对象,
并可以使用这两个对象,实现用class名或者节点名选取节点或节点的集合。
mk.dom.nodes : 返回所有节点集合
mk.dom.nodes[int i] : 返回索引为i的节点 遍历所有节点 深度优先
mk.dom.nodes[string tag] : 返回 NodeName = tag 的节点数组
mk.dom.nodes.names : 返回所有节点名称的索引数组
mk.dom.nodes[n].subNodes : 返回某一节点所有子节点数组 深度优先
mk.dom.nodes[n].subNodes[int i] : 返回某一节点中索引为i的子节点 遍历所有节点 深度优先
mk.dom.nodes[n].subNodes[string tag] : 返回某一节点中 NodeName = tag 的子节点数组
mk.dom.classNames : 返回页面中所有被节点引用过的className的索引数组
mk.dom.classNames[string className] : 返回class=className的节点数组
init(n, addChildToParent) : 初始化页面
n : 指定的节点 默认为document
addToParent : 是否将节点添加到父节点的subNodes中去。如要使节点具备subNodes属性,则该属性必须为true
下面是该类的完整代码。有些没有提及的函数是框架开发经常用到或者尚未完善的。
mk.js 2.9
if(!mk) var mk =
{
info : {
ver : [2, 9, 6, 3],
author : "MKing",
email : "winnie_mk@126.com"
}, xhr : {
}, magic : {
}, controls : {
}, b : {
/*@cc_on
isIE : true,
@*/
isFF : navigator.userAgent.search(/firefox/i) > -1 ? true : false,
isOpera : navigator.userAgent.search(/opera/i) > -1 && !this.isIE ? true : false
}, $ : function(obj){
return typeof obj == "string" ? document.getElementById(obj) : obj;
}, loop : function(arr, fun){
if(!arr.length || typeof fun != "function") return;
for(var i=0; i<arr.length; i++)
if(fun(arr[i]))
break;
}, getSingleNodeInChildNodes : function(tag, parent, index){
var _n = false;
if(typeof tag != "string") return _n;
var _parent = parent || document;
var _index = index || 0;
tag = tag.toLowerCase();
var _i = 0;
this.loop(_parent.childNodes, function(n){
if(n.nodeType == 1)
if(n.nodeName.toLowerCase() == tag){
_n = n;
if(_i++ >= _index)
return true;
}
});
return _n;
}, getChildNodesOfType : function(typeNum, parent){
var _cs = [];
if(typeof typeNum != "number") return _cs;
var _parent = parent || document;
this.loop(_parent.childNodes, function(n){
if(n.nodeType == typeNum)
_cs.push(n);
});
return _cs;
}, getSingleNodeByTagName : function(tagName, parent, index){
if(typeof tagName != "string") return false;
var _parent = parent || document;
var _index = typeof index == "number" || 0;
return _parent.getElementsByTagName(tagName)[_index];
}, getCurrentHeight : function(obj){
var height = false;
if(!obj) return height;
if(obj.currentStyle){
height = obj.currentStyle.height;
} else if(document.defaultView.getComputedStyle){
height = document.defaultView.getComputedStyle(obj, null).height;
}
return parseInt(height);
}, loopParentNode : function(self, parentTagName){
var n = false;
if(!self.parentNode || typeof parentTagName != "string") return n;
var p = self.parentNode;
parentTagName = parentTagName.toLowerCase();
while(!!p){
if(p.nodeName.toLowerCase() == parentTagName){
n = p;
break;
}
p = p.parentNode;
}
return n;
}, getDeepAndPath : function(obj, tag, addChildToParent){
var _path = [];
var _deep = 0;
var _obj = obj;
var _addChildToParent = !!addChildToParent;
if(!_obj.childEles && addChildToParent) _obj.childEles = [];
if(typeof tag == "string"){
tag = tag.toLowerCase();
while(_obj.parentNode){
_obj = _obj.parentNode;
if(_obj.nodeName.toLowerCase() == tag){
_deep++;
_path.push(_obj);
if(_addChildToParent)
_obj.childEles.push(obj);
}
}
} else {
while(_obj.parentNode){
_obj = _li.parentNode;
_deep++;
_path.push(_obj);
if(_addChildToParent)
_obj.childEles.push(obj);
}
}
return { path : _path.reverse(), deep : _deep };
}, dom : { //get all elements of the page. only when nodeType == 1
nodes : [],
classNames : [],
init : function(n, addChildToParent){
var _n = n || document;
var _atp = !!addChildToParent;
if(!this.nodes.names) this.nodes.names = [];
for(var i=0; i<_n.childNodes.length; i++){
var node = _n.childNodes[i];
if(node.nodeType == 1){
this.nodes.push(node);
var nn = node.nodeName.toLowerCase();
if(!this.nodes[nn]){
this.nodes[nn] = [];
this.nodes.names.push(nn);
}
this.nodes[nn].push(node);
if(node.className){
if(!this.classNames[node.className]){
this.classNames.push(node.className);
this.classNames[node.className] = [];
}
this.classNames[node.className].push(node);
}
if(_atp){
if(p = node.parentNode){
if(!p.subNodes) p.subNodes = [];
p.subNodes.push(node);
}
}
this.init(node, _atp);
}
}
}
}, splitStep : function(len, stepCount, minValue, type){
var steps = [];
switch(type){
default :
var step = parseInt(len / stepCount);
steps.push(minValue);
for(var i=0; i<=stepCount; i++){
var st = step * i;
if(st > minValue && st < len) steps.push(st);
}
steps.push(len);
return steps;
}
}, addEvent : function(obj, eventName, fun, bubble){
if(obj.addEventListener){
obj.addEventListener(eventName, fun, !!bubble);
} else if(obj.attachEvent){
obj.attachEvent("on" + eventName, fun);
} else {
obj["on" + eventName] = fun;
}
}, removeEvent : function(obj, eventName, fun, bubble){
if (obj.removeEventListener) {
obj.removeEventListener(eventName, fun, !!bubble);
} else if (obj.detachEvent) {
obj.detachEvent("on" + eventName, fun);
} else {
obj["on" + eventName] = null;
}
}