频 道 直 达 - 新闻 - 培训 - 软件 - 教程 - 前沿 - 组网 - 系统应用 - 安全 - 编程 - 存储 - 操作系统 - 数据库 - 服务器 - 专题 - 产品 - 案例库 - 读书 - 博客 - BBS
51CTO.COM_中国最大的网络技术网站
找资料:

3.16.6 实现代码及使用举例

作者: 夏天 出处:电子工业出版社博文视点  2008-04-16 12:38    砖    好    评论   进入论坛
阅读提示:《JavaScript高级应用与实践 》第3章重点讲了Object扩展和性能及Web应用之神兵利器,本节给大家介绍的是 实现代码及使用举例。
3.16.6  实现代码及使用举例
1.代码
JavaScript部分代码,请读者多看看其中的注释,这部分的代码将全部移到Jcore.js里,以便后面章节直接使用,请见下面的代码:
    // 我们为了让正则表达式工作得更快,因此笔者实现一个方便的
// 正则表达式编译方法,使得它更加简单易用
// 使得你不必再使用复杂、烦琐的compile方法
// 使用举例:var r /\s[a-z]\s/.cmp();
RegExp.reg = /(?:\/)([gmi]*$)/.compile("(?:\\/)([gmi]*$)", ""); 
RegExp.prototype.cmp = function()
{
var s = String(this).substr(1), m = RegExp.reg.exec(s);
return this.compile(s.substr(0, s.length - m[0].length), m[1] || "");
};
// 正则表达式集中管理和维护,
// 最主要的是进行预编译,使得运行更快
// 不过这里只集中那些在function中的,不是程序[js]装载时能编译的正则表达式
Object.jcoreRegs = [
/*00*/ /[^\x00-\xFF]/gm.cmp(),
/*01*/ /^[\da-z_\u4E00-\u9FA5]+[\da-z_\.-\u4E00-\u9FA5]*@[\da-z\u4E00- \u9FA5]+[\da-z\u4E00-\u9FA5_-]+(\.[\da-z\u4E00-\u9FA5_-]+)+$/i.cmp(),
/*02*/ /^[_a-z][_a-z0-9\.-]*@[_a-z0-9\.-]+(\.[_a-z0-9\.-]+)+$/i.cmp(),
/*03*/ /^(\d+)\.(\d+).(\d+).(\d+)$/.cmp(),
/*04*/ /^(?:\s*[,;\|]?\s*)(\d+)(?:\s*[-~]\s*)(\d+)(?:\s*)/.cmp(),
/*05*/ /^\s*\[?\s*\d+(\s*[,;\|&]\s*\d+)*\]?\s*/.cmp(),
/*06*/ /[\s\[\]]/g.cmp(),
/*07*/ /[,;\|&]/.cmp(),
/*08*/ /^(?:\s*)([><])(?:\s*)(\d+)(?:(?:\s*[;,\|&]\s*)([><])(?:\s*)(\d+))?/.cmp(),
/*09*/ /\s/gm.cmp(),
/*10*/ /(^['"])|(['"]$)/.cmp(),
/*11*/ /(\s*>\s*<\s*)|(^\s*<\s*)|(\s*>\s*$)/gm.cmp(),
/*12*/ /\s{2,}/gm.cmp(),
/*13*/ /(\s*>.<\s*)|(\s*[,;\|]\s*)/.cmp(),
/*14*/ /^[!!]/.cmp(),
/*15*/ /\d/g.cmp(),
/*16*/ /(^\s*)|(\s*$)/gm.cmp()
];
// 这段代码只在这里出现一次,然后就移进Jcore.js里
// 获取当前浏览器信息
var b = navigator.userAgent.toLowerCase();
// 浏览器
Object.browser = {
version: (b.match(/.+(?:rv|it|ra|ie)[\/: ]([\d.]+)/) || [])[1],
safari: /webkit/.test(b),
opera: /opera/.test(b),
msie: /msie/.test(b) && !/opera/.test(b),
mozilla: /mozilla/.test(b) && !/(compatible|webkit)/.test(b)
};
// 特殊的Float属性处理
Object.styleFloat = Object.browser.msie ? "styleFloat" : "cssFloat",
// 属性转换对照,你可以扩展它来支持更多的特别属性,如果
Object.props = {
"for": "htmlFor",
"class": "className",
"float": Object.styleFloat,
cssFloat: Object.styleFloat,
styleFloat: Object.styleFloat,
Float: Object.styleFloat,
innerHTML: "innerHTML",
value: "value",
readonly: "readOnly",
maxlength: "maxLength",
tagname:"tagName"
};
// 浏览器类型检测
// 操作符号转换
Object.opts = {
"="  : "=="
, "<>" : "!="
, "gt" : ">"
, "lt" : "<"
, "eq" : "=="
, "~=" : function(szParm, szAtt)
{
// 匹配属性szAtt,以空格分隔的其中一个等于,或者全等于szParm
szParm = szParm.toLowerCase, szAtt = szAtt.toLowerCase;
return szParm == szAtt || -1 < szAtt.split(/\s+/).indexOf(szParm);
}
, "^=" : function(szParm, szAtt)
{
// 匹配属性szAtt,以szParm开头的节点
return 0 == szAtt.toLowerCase().indexOf(szParm.toLowerCase());
}
, "$=" : function(szParm, szAtt)
{// 匹配属性szAtt,以szParm结尾的节点
szParm = szParm.toLowerCase, szAtt = szAtt.toLowerCase;
return (szAtt.length - szParm.length) == szAtt.lastIndexOf(szParm);
}
, "*=" : function(szParm, szAtt)
{
// 匹配属性szAtt,包含szParm的节点
return -1 < szAtt.toLowerCase().indexOf(szParm.toLowerCase());
}        
, "|=" : function(szParm, szAtt)
{
// 匹配属性szAtt以szParm + 【_-】连接符号开始的节点
szParm = szParm.toLowerCase, szAtt = szAtt.toLowerCase;
return 0 == szAtt.indexOf(szParm + "-") || 0 == szAtt.indexOf (szParm + "_");
}
};
// 谓词、伪模式定义
Object.mtps = {
// 查找frame和iframe对象
"frame":function(o)
{
var aRst = [];
// 设置不再对frame和iframe对象进行深度迭代
aRst.bNs = true;
// 考虑到性能问题,这些方法我们在迭代的时候都取消了深度迭代
// 因为默认我们已经取所有的HTML对象进行迭代了,因此没有必要加深度迭代的加了后,
// 反而导致有的对象迭代多次,而push不得不改为add,这时候性能就更受到影响了
// 因为add为了防止将重复的对象加进去,虽然做了最大的优化始终不如不用深度迭代
return o.each(function()
{
switch(this.nodeName)
{
case 'FRAME':
case 'IFRAME':
aRst.push(this);
break;
}
}), aRst;
},
// 筛选输入对象
"input":function(o)
{
var aRst = [];
// 考虑到性能问题,这些方法我们在迭代的时候都取消了深度迭代
// 因为默认我们已经取所有的HTML对象进行迭代了,因此没有必要加深度迭代的加了后,
// 反而导致有的对象迭代多次,而push不得不改为add,这时候性能就更受到影响了
// 因为add为了防止将重复的对象加进去,虽然做了最大的优化始终不如不用深度迭代
return o.each(function()
{
switch(this.nodeName)
{
case 'INPUT':
case 'SELECT':
case 'TEXTAREA':
case 'BUTTON':
aRst.push(this);
break;
}
}), aRst;
},
// 筛选文本输入对象
"text":function(o)
{
var aRst = [], rg = /^text$/i.cmp();
o.each(function()
{
if(rg.exec(this['type']))aRst.push(this);
});
delete rg;
return aRst;
// 实际上我们可以这样: return XPath.bind({obj:o}, "[type=text]")()
// 但是,往往有时候代码空间却能置换性能的空间,也就是说,多写些代码性能反而会更高
},
// 筛选密码输入对象
"password":function(o)
{
var aRst = [], rg = /^password$/i.cmp();
o.each(function()
{
if(rg.exec(this['type']))aRst.push(this);
});
delete rg;
return aRst;
// 实际上我们可以这样: return XPath.bind({obj:o}, "[type=password]")()
// 但是,往往有时候代码空间却能置换性能的空间,也就是说,多写些代码性能反而会更高
},
// 筛选radio单选输入对象
"radio":function(o)
{
var aRst = [], rg = /^radio$/i.cmp();
o.each(function()
{
if(rg.exec(this['type']))aRst.push(this);
});
delete rg;
return aRst;
// 实际上我们可以这样: return XPath.bind({obj:o}, "[type=radio]")()
// 但是,往往有时候代码空间却能置换性能的空间,也就是说,多写些代码性能反而会更高
},
// 筛选checkbox多选输入对象
"checkbox":function(o)
{
var aRst = [], rg = /^checkbox$/i.cmp();
o.each(function()
{
if(rg.exec(this['type']))aRst.push(this);
});
delete rg;
return aRst;
// 实际上我们可以这样: return XPath.bind({obj:o}, "[type=checkbox]")()
// 但是,往往有时候代码空间却能置换性能的空间,也就是说,多写些代码性能反而会更高
},
// 筛选提交按钮输入对象
"submit":function(o)
{
var aRst = [], rg = /^submit$/i.cmp();
o.each(function()
{
if(rg.exec(this['type']))aRst.push(this);
});
delete rg;
return aRst;
// 实际上我们可以这样: return XPath.bind({obj:o}, "[type=submit]")()
// 但是,往往有时候代码空间却能置换性能的空间,也就是说,多写些代码性能反而会更高
},
// 筛选图形按钮输入对象
"image":function(o)
{
var aRst = [], rg = /^image$/i.cmp();
o.each(function()
{
if(rg.exec(this['type']))aRst.push(this);
});
delete rg;
return aRst;
// 实际上我们可以这样: return XPath.bind({obj:o}, "[type=image]")()
// 但是,往往有时候代码空间却能置换性能的空间,也就是说,多写些代码性能反而会更高
},
// 筛选reset重置按钮输入对象
"reset":function(o)
{
var aRst = [], rg = /^reset$/i.cmp();
o.each(function()
{
if(rg.exec(this['type']))aRst.push(this);
});
delete rg;
return aRst;
// 实际上我们可以这样: return XPath.bind({obj:o}, "[type=reset]")()
// 但是,往往有时候代码空间却能置换性能的空间,也就是说,多写些代码性能反而会更高
},
// 筛选按钮输入对象
"button":function(o)
{
var aRst = [], rg = /^button^/i.cmp();
o.each(function()
{
if(rg.exec(this['type']))aRst.add(this);
});
delete rg;
return aRst;
// 实际上我们可以这样: XPath.bind({obj:o}, "[type=button]")();
// 但是,往往有时候代码空间却能置换性能的空间,也就是说,多写些代码性能反而会更高
},
// 筛选不可见输入对象
"hidden":function(o)
{
var aRst = [], rg = /^hidden$/i.cmp();
o.each(function()
{
if(rg.exec(this['type']))aRst.add(this);
});
delete rg;
return aRst;
// 实际上我们可以这样: XPath.bind({obj:o}, "[type=hidden]")();
// 但是,往往有时候代码空间却能置换性能的空间,也就是说,多写些代码性能反而会更高
},
// 从匹配的元素集中取第一个元素
"last":function(o)
{
return o.get(o.size() - 1) || null;
},
// 从匹配的元素集中取第一个元素
"first":function(o)
{
return o.get(0) || null;
},
// 从匹配的元素集中取序数为偶数的元素,包含第一个元素
"even":function(o)
{
var aRst = [], i = 0;
o.each(function()
{
if(0 == i % 2)aRst.add(this);
i++;
});
return aRst;
},
// 从匹配的元素集中取序数为偶数的元素,不包含第一个元素
"odd":function(o)
{
var aRst = [], i = 1;
o.each(function()
{
if(0 == i % 2)aRst.add(this);
i++;
});
return aRst;
},
// 选择包含有子元素的元素,或者,如果指定为parent(3)则表示选择元素的父节点的
// 父节点的父节点,也就是往上3级的节点
"parent":function(o, n)
{
var aRst = [];
if(n)
{
o.each(function()
{
var oTmp = this, i = 0;
for(;n > i; i++)
{
if(!oTmp.parentNode)break;
oTmp = oTmp.parentNode;
}
if(i == n)aRst.add(oTmp);
});
}
else
{
o.each(function()
{
if((this.hasChildNodes && this.hasChildNodes()) || (this.childNodes && this.childNodes.length))aRst.add(this);
});
}
return aRst;
},
// 选择checked属性为真的元素。
"checked":function(o)
{
var aRst = [];
o.each(function()
{
// !!将表达式结果转换为有效的Boolean对象
if(true == !!this.getAttribute('checked'))aRst.add(this);
});
return aRst;
},
// 选择enabled属性为真的元素
"enabled":function(o)
{
var aRst = [];
o.each(function()
{
// !!将表达式结果转换为有效的Boolean对象
if(true != !!this.getAttribute('disabled'))aRst.add(this);
});
return aRst;
},
// 选择disabled的元素
"disabled":function(o)
{
var aRst = [];
o.each(function()
{
if(true == !!this.getAttribute('disabled'))aRst.add(this);
});
return aRst;
},
// 没有子元素(包括text节点)的元素
"empty":function(o)
{
var aRst = [];
o.each(function()
{
if((this.hasChildNodes && !this.hasChildNodes()) || !this.childNodes)aRst.add(this);
});
return aRst;
},
// 排除not(s)里指定的s规则的集合
"not":function(o, s)
{
var a = XPath.bind({obj:o},s)();
var aRst = [];
if(0 < a.length)
o.each(function()
{
if(-1 == a.indexOf(this))aRst.add(this);
});
else return o;
return aRst;
},
// 用参数s中的XPath在当前集合中每个元素里执行,然后再返回最后的结果集合
// each node
"ecnd":function(o, s)
{
var a = [];
if(0 < o.length)
s && o.each(function()
{
[].push.apply(a, [this].J(s));
}, false);
return a;
},
// 功能更强大的获取方式,s可以是下面形式中的一种,注意,下面说的位置都是从零开始
// 3-7或4~8,表示获取第三个到第七个,第四个到第八个,他们都包含三和七,
// 四和八这个位置的对象,这样的也可以多对组合
// 3,6,8或者[3,6,8],表示你要下标为3、6、8的对象
// >6&<3,表示,获取下标大于6和小于3的对象,中间可以用"&,;|"来分隔
"get":function(o, s)
{
var aRst = [], i = 0, m = null, r;
              // 特别需要注意的是,下面的if判断的模式是要注意顺序的,
// 认为第二个if中的模式也能匹配第二个
// 处理 3-7或4~8这样的形式
// 这里看上去似乎是不正确的写法,正确的应该是null != (m = /^(?:\s*[,;\|]?\s*)(\d+)(?:\s*[-~]\s*)(\d+)(?:\s*)/.exec(s))
// 不过,我们大可以像下面这样简化它的
// 我们先给模式r变量赋予值,然后用逗号运算符号连接,使得m是最终的if判断的对象
if(r = Object.jcoreRegs[4],m = r.exec(s))
{
var bStart = false;
if(m[2] > m[1])
{
o.each(function()
{
if(i >= m[1] && i <= m[2])bStart = true,aRst.add(this);
// 加了标志是为了减少没必要的迭代
else if(bStart)throw {message:'调处each', jname:"J"};
i++;
});
}
s = s.replace(r, '');
while(m = r.exec(s))
{
bStart = false;
if(m[2] > m[1])
{
o.each(function()
{
if(i >= m[1] && i <= m[2])bStart = true,aRst.add(this);
// 加了标志是为了减少没必要的迭代
else if(bStart)throw {message:'调处each', jname:"J"};
i++;
});
}
s = s.replace(r, '');
if(0 == s.length)break;
}
}
// 处理3,6,8或者[3,6,8],表示你要下标为3、6、8的对象
else if(Object.jcoreRegs[5].exec(s))
{
s = s.replace(Object.jcoreRegs[6], '').split(Object.jcoreRegs[7]);
o.each(function()
{
if(-1 < s.indexOf(i))aRst.add(this);
i++;
});
}
// 处理这样的形式:>6&<3
else if(r = Object.jcoreRegs[8], m = r.exec(s))
{
var szStr = '';
for(i = 1; i < m.length - 1; i += 2)
{
if(1 < i)szStr += "||";
szStr += "(i" + m[i] + m[i + 1] + ")";
}
var oFun = new Function("i", "return " + szStr.replace(Object.jcoreRegs[9], ''));
i = 0;
o.each(function()
{
if(oFun(i))aRst.add(this);
i++;
});
delete oFun;
}
delete r;
delete m;
              return aRst;
},
// 返回序号大于s的
"gt":function(o, s)
{
return o.slice(parseInt(s));
},
// 返回序号小于s的
"lt":function(o, s)
{
return o.slice(0, parseInt(s));
},
// 选择所有指定属性含有指定文本的元素。
// 因此s的格式是: ['属性名', '要包含的值']
"attct":function(o, s)
{
// 这里我们将串行的Array对象转换到Array对象,当然用eval也是可以的
s = s.replace(/[\[\'\"\]\s]/g.cmp(), "").split(",");
var aRst = [], rg = new RegExp(s[1], "gi").cmp();
if(s[0] = s[0] || null)
o.each(function()
{
// Object.props[s[0]] || s[0]如果没找到转义的属性名就用原来的名字
if(rg.exec(this.getAttribute(Object.props[s[0]] || s[0]) || null))aRst.add(this);
});
              return aRst;
},
// 选择所有含有指定文本的元素,主要指text和innerText的内容
"contains":function(o, s)
{
var aRst = [], rg = new RegExp(s, "gmi").cmp();
o.each(function()
{
// 如果节点是注释对象,则有text,如果是非IE浏览器,则可能有innerText
if(rg.exec(this.innerText || this.value || this.text || this.textContent || ''))aRst.add(this);
});
delete s;
delete rg;
return aRst;
},
// 返回隐藏的对象
"hide":function(o)
{
var aRst = [];
o.each(function()
{
var oStyle = this.style || this.currentStyle || {};
var szHd = oStyle.display || oStyle.visibility || '';
if("hidden" == szHd || "none" == szHd)aRst.add(this);
});
return aRst;
},
// 返回可见的对象
"visible":function(o)
{
var aRst = [];
o.each(function()
{
var oStyle = this.style || this.currentStyle || {};
var szHd = oStyle.display || oStyle.visibility || '';
if("hidden" != szHd && "none" != szHd)aRst.add(this);
});
return aRst;
}
};
// 正则表达式集合,集中写在这里便于扩展
// 第一个元素是要执行的函数代码,方法的第一个参数a表示当前可迭代的对象,
// m是正则表达式执行后的结果
// 函数返回的结果将作为下一次的传入a,因此返回的结果必须是可迭代的对象
// 每个模式力求功能单一,这样便于维护
// 后面则是支持的多种正则表达式对象
// 注意,每个正则表达式会循环使用,因此请注意,每个必须从头开始匹配
// 一旦匹配到了这段匹配到的串就会从源中删除,进入下轮处理,所以每个匹配不能使用全局
// 另外,每个正则表达式会在while里进行处理,每次使用匹配到的位置为1的结果,
// 直到没有匹配才停止
// a默认就是当前的HTML Dom, 初始化是document.all
Object.RegExps = [
// 包括html前的<!-- ... -->注释和!DOCTYPE在内的匹配
// 匹配模式是:开头[*!!]中任一个
[function(a, m)
{
// 匹配:/*/
var aRst = [];
return a.each(function()
{
this['getElementsByTagName'] && aRst.add(_A(this.getElementsByTagName(m[1]) || this)) ||
this.childNodes && aRst.add(_A(this.childNodes));
}), aRst;
}, /^(?:\s*\/?\s*)([\*!!])(?:\s*\/?\s*)/.cmp()]
// 匹配: // , /descendent-or-self::node()/,等于document.documentElement,包含html在内的节点
, [function(a, m)
{
return _A(document.getElementsByTagName("*"), true);
}, /^(\s*\/\s*){2}/.cmp(), /^\s*\/\s*descendent\s*-\s*or\s*-\s*self\s*:\s*:\s*node\s*\(\s*\)\s*\/\s*/i.cmp()]
// 匹配: ":input"这种形式的谓词
, [function(a, m)
{
// 匹配到的临时结果
var aMyTmp = [], szParm = m[3] || "";
m[1] = Object.mtps[m[1].trim().toLowerCase()];
if(m[1])
{
aMyTmp = m[1](a, (szParm || '').replace(Object.jcoreRegs[10], ''));
delete m[1];
}
return aMyTmp;
}, /^(?:\s*:\s*)([\w-]+)(?:\s*\(\s*)('?|"?)(?:\s*)(.*)(?:\s*)\2(?:\s*\)\s*)(?:\s*\/?\s*)/i.cmp(), /^(?:\s*:\s*)([\w-]+)(?:\s*\/?\s*)/i.cmp()]
// 匹配select,button或#myDivId,button或<div><span>
, [function(a, m)
{
// 匹配到的临时结果
var aMyTmp = [], aM;
aM = m[1].trim().replace(Object.jcoreRegs[11], '').replace(Object.jcoreRegs[12], ' ').split(Object.jcoreRegs[13]);
delete m[1];
// 如果传进来的是个数组,则对它进行迭代
if(0 < aM.length)
{
aM.each(function()
{
var _this = this, rg = new RegExp("^(" + _this + ")$", "i").cmp();
// 对要获取的同级对象进行获取并合并结果
a.each(function(o, i)
{
!!rg.exec([ this.nodeName || '',
this.getAttribute && (this.getAttribute('id') || this.getAttribute('uniqueID')) || '',
this.className || ""].join("|")) && aMyTmp.add(this);
// 改变fnGetObjs的当前对象为_this,
//  Array的add方法兼容了HTML DOM的一些操作,请参加Array章节
aMyTmp.add(fnGetObjs.call(this, _this));
});
});
}
return aMyTmp;
}, /^(?:\s*\/?\s*#?)((?:\s*<?\s*[\w-]+\s*>?\s*[;,\|]?\s*)+)(?:\s*\/?\s*)/i.cmp()]
// 匹配:../,当前集合的父节点对象的集合
, [function(a, m)
{
var aMyTmp = [];
a.each(function()
{
aMyTmp.add(this.parentNode);
});
delete a;
return aMyTmp;
}, /^(\s*\/?\s*\.\s*\.\s*\/?\s*)/i.cmp()]
// 匹配:div.myClassName/
, [function(a, m)
{
m[1] = !!m[1] && m[1] || m[2] || "";
var aMyTmp = [];
// 如果传进来的是个数组,则对它进行迭代
if(0 < m[1].length)
{
var rg = new RegExp(m[1], "i").cmp();
a.each(function()
{
if(!!rg.exec((this.nodeName || ",") + "|" +
(this.id || this.uniqueID || ',') + "|" +
(this.className || ",")))
aMyTmp.add(this);
// 将执行结果合并到临时数组里
aMyTmp.add(fnGetObjs.call(this, m[1]));
});
if(0 < aMyTmp.length)a = aMyTmp;
}
// 对class属性进行过滤
var szPpt = Object.props["class"] || "className";
m[2] = m[2].toLowerCase();
delete aMyTmp, aMyTmp = [];
a.each(function()
{
// 这里过滤掉了文本节点
// if(3 != this.nodeType)
if(this.getAttribute && this.getAttribute(szPpt).toLowerCase() == m[2])aMyTmp.add(this);
});
return aMyTmp;
}, /^(?:\s*\/?\s*)([\w-]*)(?:\s*\.\s*)([\w-]*)(?:\s*\/?\s*)/i.cmp()]
// 匹配:[@class]或者[myvalue],匹配有指定属性但是却没有指定值对象或nodeName,或ID
, [function(a, m)
{
var aMyTmp = [], bNot = false, rg = Object.jcoreRegs[14];
// HTML 对象 nodeName、ID、属性名
m[1] = m[1].trimAll();
// 支持div[4]这样的形式
if(0 == m[1].replace(Object.jcoreRegs[15], "").length)
{
// 匹配到的临时结果
if(0 <= m[1] && m[1] <= a.length)
return [a[m[1]]];
return [];
}
     if(rg.exec(m[1]))
bNot = true, m[1] = m[1].replace(rg, "");
a.each(function()
{
// 将执行结果合并到临时数组里
aMyTmp.add(fnGetObjs.apply({obj:this}, [m[1]]));
});
// 如果不是选择属性模式就返回了
if(0 < aMyTmp.length)return aMyTmp;
// 再做初始化
delete aMyTmp, aMyTmp = [];
// 对象属性名,如果转义存在则转义,否则直接使用原来的名字
var szPpt = Object.props[m[1]] || m[1];
a.each(function()
{
// 不包含给定属性或者需要包含
// 这里过滤掉了文本节点 if(3 != this.nodeType)
if((!bNot && this.getAttribute(szPpt)) || (bNot && !this.getAttribute(szPpt)))aMyTmp.push(this);
});// 这里本来必须启用深度迭代,不过由于我们在外边已经准备好要迭代的元素,
// 为了防止深度递归调用而影响性能,我们取消了所有的深度迭代
// 释放内存是很好的习惯
delete szPpt;
return aMyTmp;
}, /^(?:\s*\/?\s*\[\s*@?\s*)(!?\s*[\w-]+)(?:\s*\]\s*\/?\s*)/i.cmp()]
// 匹配:[div @styleFloat='left']或者[@styleFloat!='left']
, [function(a, m)
{
var aMyTmp = [];
if(4 > m.length)return a;
// HTML 对象 nodeName
m[1] = m[1].trimAll();
// HTML 对象属性名
m[2] = m[2].trimAll();
// 如果没取到属性名,表示属性名已经落到对象名上
m[2] || (m[2] = m[1], m[1] = "");
// HTML 对象属性操作符号
m[3] = m[3].trimAll();
// 操作符号需要转义,如果没有定义相应的转义就直接使用
m[3] = Object.opts[m[3]] || m[3];
// HTML 对象属性操作的值
m[4] = m[4].toLowerCase();
// 如果只是[@styleFloat!='left']/span这样的形式,m[1]是可能为空的
// 如果传进来的是个数组,则对他进行迭代
if(0 < m[1].length)
{
a.each(function()
{
// 将执行结果合并到临时数组里
aMyTmp.add(fnGetObjs.apply({obj:this}, [m[1]]));
});
if(0 < aMyTmp.length)a = aMyTmp;
// aMyTmp2 = null;也可以,不过我们测试发现delete性能比直接赋予null更优秀
}
// "? (expression): (expression);"三目运算符号中的(expression)
// 可以随便给个字符,
// 表示给一个为定义的变量,等于用 undefined,或者用''一对引号也可以
// 对属性进行过滤,m[2] 属性名称, m[3] 是运算符号, m[4] 是属性值
delete aMyTmp, aMyTmp = [];
// 对象属性名,如果转义存在则转义,否则直接使用原来的名字
var szPpt = Object.props[m[2]] || m[2];
// 定义操作函数对象,注意new Function这样的形式的上下文是不同它的容器的,
// 这个匿名函数不一样
// 因为这里需要组装代码,所以我们必须用new Function这样的动态形式
var szCode = "return (s||'').toLowerCase()" + m[3] + "'" + m[4] + "'";
try
{
var oFunc = Function == m[3].constructor && m[3] || new Function("szParm", "s", szCode);
a.each(function()
{
// 这里过滤掉了文本节点 if(3 != this.nodeType)
if(oFunc(m[4], this.getAttribute(szPpt)))aMyTmp.push(this);
});
}catch(e){}
// 释放内存是很好的习惯
delete oFunc;
delete szPpt;
return aMyTmp;
}, /^(?:\s*\/?\s*\[\s*)([\w-]*)(?:\s*@?\s*)([\w-]*)(?:\s*)([=!<>\s\^~$\*\|]+)(?:\s*['"]?\s*)([\w-\(\)]+)(?:\s*["']?\s*\]\s*\/?\s*)/i.cmp()]
];
// 功能描述:将当前对象toString或者传入的第一个参数toString或转换为
//  html中能正确显示的文本,也就是把html代码转换为能在页面上正确显示的文本
// 返回信息:元素的个数
// 使用指南:[].size(); // 等于0
// 应用范围:各种Web客户端
Object.prototype.sanitizeHTML = function(s)
{
var d = document.createElement('div');
d.appendChild(document.createTextNode(s || this.toString()));
return d.innerHTML;
};
// 功能描述:将当前对象传递到callback回调函数里执行
// 使得XPath选择器更加方便地对临时结果进行处理,然后再进行其他
//  XPath选择器处理,这样就使得每个XPath选择不必都从所有对象中进行检索
// 从而提高了性能,它区别于every的是,它将整个对象作为一个参数传递给回调函数
// 而不像every,它接收的是对象的单个元素。every是第4章的内容
// 返回信息:返回当前的对象
// 使用指南:[12,33.98, 887].getAll(function(){}).each(function(){});
// 应用范围:各种Web客户端和服务器端
Object.prototype.getAll = function(callback)
{
callback && callback.apply(this, [this]);
return this;
};
// Xpath选择器的设计
var XPath = Object.prototype.XPath = function(s1)
{
// if(0 == arguments.length)return new XPath(this.toString());
// 正则表达式
var s = (s1 || this.toString() || "").trim(), a, m, x, i, oT;
if(0 == s.length)return [];
// 结果数组a, 模式匹配结果m, this.obj是为了支持指定开始选择的接点对象
var atmp = [];
// 如果节点太多,建议使用更详细的xpath选择器,而不应该依赖智能的选择,
// 因为越智能也就越消耗性能
// 因此这里当节点大于300就把根作为默认开始节点
a = this.length && this ||
_A( this.obj ||
(atmp = (this.win || window).document.getElementsByTagName("*"),
300 < atmp.length ? (this.win || window).document.documentElement : atmp)
);

// 定义一个标签,表示我们将在多重循环的最里面停止我们最外面的循环
var nF = Object.RegExps.length % 8, n1, oN = nF, j, oMyRg, oFn;
// 注意,JavaScript也支持Labeled 语句,不过在firefox中不支持,
// 因此真正的示例中我们没有这样做
ExitAllDo:
do
{
 i = 0;
 n1 = nF, j = 0;
 // 执行 取8余数的零头的循环
 do
{
  // 初始化
  if(j >= Object.RegExps.length)j = 0;
   x = 1;
   // 如果当前是多个组合:text,select这样的形式,则认为需要合并结果
   // 每个匹配允许有多个正则表达式的匹配
   do
   {
     oMyRg = Object.RegExps[j];
     oFn = oMyRg[0];
     if( null != (m = oMyRg[x].exec(s)))
        {
        i++;
        // 模式方法执行返回的结果
        oT = new oFn(a, m);
        // 下一轮的结果从它开始选择
        switch(oT.constructor)
        {
          case Array:
             a = oT;
             break;
          default: (a = []).push(oT);
        }
        s = s.replace(oMyRg[x], "");
        delete oT;
        break;
     }
     if(0 == s.length || 0 == a.length)break ExitAllDo;
   }while(++x < oMyRg.length)
}while(j++,0 < n1--);

 n1 = (Object.RegExps.length - oN) / 8;
 // 八分法开始
 do
{
  // 初始化: 1
  if(j >= Object.RegExps.length) j = 0;
   x = 1;
   // 如果当前是多个组合:text,select这样的形式,则认为需要合并结果
   // 每个匹配允许有多个正则表达式的匹配
   do
   {
     oMyRg = Object.RegExps[j];
     if(null != (m = oMyRg[x].exec(s)))
        {
        i++;
        // 模式方法执行返回的结果
        oT = new Object.RegExps[j][0](a, m);
        // 下一轮的结果从它开始选择
        switch(oT.constructor)
        {
          case Array:
             a = oT;
             break;
          default: (a = []).push(oT);
        }
        s = s.replace(oMyRg[x], "");
        delete oT;
        break;
     }
     if(0 == s.length || 0 == a.length)break ExitAllDo;
   }while(++x < oMyRg.length)
   j++;
  
   // 初始化: 2
   if(j >= Object.RegExps.length) j = 0;
   x = 1;
   // 如果当前是多个组合:text,select这样的形式,则认为需要合并结果
   // 每个匹配允许有多个正则表达式的匹配
   do
   {
     oMyRg = Object.RegExps[j];
     if( null != (m = oMyRg[x].exec(s)))
        {
        i++;
        // 模式方法执行返回的结果
        oT = new Object.RegExps[j][0](a, m);
        // 下一轮的结果从它开始选择
        switch(oT.constructor)
        {
          case Array:
             a = oT;
             break;
          default: (a = []).push(oT);
        }
        s = s.replace(oMyRg[x], "");
        delete oT;
        break;
     }
     if(0 == s.length || 0 == a.length)break ExitAllDo;
   }while(++x < oMyRg.length)
   j++;
  
   // 初始化: 3
   if(j >= Object.RegExps.length) j = 0;
   x = 1;
   // 如果当前是多个组合:text,select这样的形式,则认为需要合并结果
   // 每个匹配允许有多个正则表达式的匹配
   do
   {
     oMyRg = Object.RegExps[j];
     if( null != (m = oMyRg[x].exec(s)))
        {
        i++;
        // 模式方法执行返回的结果
        oT = new Object.RegExps[j][0](a, m);
        // 下一轮的结果从它开始选择
        switch(oT.constructor)
        {
          case Array:
             a = oT;
             break;
          default: (a = []).push(oT);
        }
        s = s.replace(oMyRg[x], "");
        delete oT;
        break;
     }
     if(0 == s.length || 0 == a.length)break ExitAllDo;
   }while(++x < oMyRg.length)
   j++;
  
   // 初始化: 4
   if(j >= Object.RegExps.length) j = 0;
   x = 1;
   // 如果当前是多个组合:text,select这样的形式,则认为需要合并结果
   // 每个匹配允许有多个正则表达式的匹配
   do
   {
     oMyRg = Object.RegExps[j];
     if( null != (m = oMyRg[x].exec(s)))
        {
        i++;
        // 模式方法执行返回的结果
        oT = new Object.RegExps[j][0](a, m);
        // 下一轮的结果从它开始选择
        switch(oT.constructor)
        {
          case Array:
             a = oT;
             break;
          default: (a = []).push(oT);
        }
        s = s.replace(oMyRg[x], "");
        delete oT;
        break;
     }
     if(0 == s.length || 0 == a.length)break ExitAllDo;
   }while(++x < oMyRg.length)
   j++;
  
   // 初始化: 5
   if(j >= Object.RegExps.length) j = 0;
   x = 1;
   // 如果当前是多个组合:text,select这样的形式,则认为需要合并结果
   // 每个匹配允许有多个正则表达式的匹配
   do
   {
     oMyRg = Object.RegExps[j];
     if( null != (m = oMyRg[x].exec(s)))
        {
        i++;
        // 模式方法执行返回的结果
        oT = new Object.RegExps[j][0](a, m);
        // 下一轮的结果从它开始选择
        switch(oT.constructor)
        {
          case Array:
             a = oT;
             break;
          default: (a = []).push(oT);
        }
        s = s.replace(oMyRg[x], "");
        delete oT;
        break;
     }
     if(0 == s.length || 0 == a.length)break ExitAllDo;
   }while(++x < oMyRg.length)
   j++;
  
   // 初始化: 6
   if(j >= Object.RegExps.length) j = 0;
   x = 1;
   // 如果当前是多个组合:text,select这样的形式,则认为需要合并结果
   // 每个匹配允许有多个正则表达式的匹配
   do
   {
     oMyRg = Object.RegExps[j];
     if( null != (m = oMyRg[x].exec(s)))
        {
        i++;
        // 模式方法执行返回的结果
        oT = new Object.RegExps[j][0](a, m);
        // 下一轮的结果从它开始选择
        switch(oT.constructor)
        {
          case Array:
             a = oT;
             break;
          default: (a = []).push(oT);
        }
        s = s.replace(oMyRg[x], "");
        delete oT;
        break;
     }
     if(0 == s.length || 0 == a.length)break ExitAllDo;
   }while(++x < oMyRg.length)
   j++;
  
   // 初始化: 7
   if(j >= Object.RegExps.length) j = 0;
   x = 1;
   // 如果当前是多个组合:text,select这样的形式,则认为需要合并结果
   // 每个匹配允许有多个正则表达式的匹配
   do
   {
     oMyRg = Object.RegExps[j];
     if( null != (m = oMyRg[x].exec(s)))
       {
        i++;
        // 模式方法执行返回的结果
        oT = new Object.RegExps[j][0](a, m);
        // 下一轮的结果从它开始选择
        switch(oT.constructor)
        {
          case Array:
             a = oT;
             break;
          default: (a = []).push(oT);
        }
        s = s.replace(oMyRg[x], "");
        delete oT;
        break;
     }
     if(0 == s.length || 0 == a.length)break ExitAllDo;
   }while(++x < oMyRg.length)
   j++;
  
   // 初始化: 8
   if(j >= Object.RegExps.length) j = 0;
   x = 1;
   // 如果当前是多个组合:text,select这样的形式,则认为需要合并结果
   // 每个匹配允许有多个正则表达式的匹配
   do
   {
     oMyRg = Object.RegExps[j];
     if( null != (m = oMyRg[x].exec(s)))
        {
        i++;
        // 模式方法执行返回的结果
        oT = new Object.RegExps[j][0](a, m);
        // 下一轮的结果从它开始选择
        switch(oT.constructor)
        {
          case Array:
             a = oT;
             break;
          default: (a = []).push(oT);
        }
        s = s.replace(oMyRg[x], "");
        delete oT;
        break;
     }
     if(0 == s.length || 0 == a.length)break ExitAllDo;
   }while(++x < oMyRg.length)
   j++;
}while(0 < n1--);
// 如果匹配完成,或者整个模式都没有任何匹配就退出
 // 防止死循环是设计中应该常常考虑的
if(0 == s.length || 0 == i || 0 == a.length)break;
}while(s.length > 0)
return a;
};
测试的iframe文件“ifrm.jsp”的内容:
<body>
<button class="myTestGood" name="myTest" id="myTest">测试绑定事件1</button> <br><br>
<button name="myTest1" id="myTest1" >绑定前面按钮的onmouseover1</button><br>
<button name="myTest1" class="myTestGood">卸载onmouseover前面按钮的onmouseover1</button><br>
</body>
2.测试用例
    <%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%><html>
<head><meta http-equiv=content-type content="text/html; charset=utf-8">
<title>测试”打造“完美中的完美“的HTML DOM 对象XPath对象选择器”</title>
</head>
<body>
<div id="myTestDiv">
<input type=text name=testtext>
<input type=text name=text2>
<input type=radio name=dfgdsgdg value=3242424 checked='true'>
<select><option>test Option</select>
<textarea>textarea value</textarea>
<button class="myTestGood" name="myTest" id="myTest" onclick="kkkkkkk()">测试绑定事件</button><br><br>
<button name="myTest1" id="myTest1" onclick="fnAddEvent(J('myTest')[0], 'onmouseover', fnTestOnmouseover)">绑定前面按钮的onmouseover</button><br>
<button name="myTest1" class="myTestGood" onclick="fnDelEvent(J('myTest')[0], 'onmouseover',fnTestOnmouseover)">卸载onmouseover前面按钮的onmouseover</button><br>
这里不难可以看出,我们可以多次点这个按钮,多次绑定相同的函数,<br>
而这个事件也会同时多次响应,这完全符合我们的要求
<iframe src="ifrm.jsp" style="width:100%;height:150px"></iframe>
</div>
<button onclick="fnMyTest()">点这里开始测试</button>
<script type="text/javascript" language="JavaScript" src="/jcore/resource/javascript/Jcore.js"></script>
<script type="text/javascript" language="JavaScript">
<!--
function kkkkkkk()
{
var oIpt = J("//:input");
var oText = oIpt.XPath(":text");
alert(oText[0].outerHTML)
alert([oIpt.length, oText.length].join("\n"))
}
function fnTestOnmouseover()
{
alert("good");
}
"//textarea".XPath()[0].value = "我的测sdf试"; // .each(function(){this.value = "我的测试"});
// 统一给筛选出来的对象加事件响应
// 更好的是,你的函数里的this,也就是上下文,我已经帮你设置为触发事件的对象了
// 这对你来说是非常好的哦,同时还支持链式的调用
"#myTestDiv/*/:input:get('1, 7,8;9')".XPath().click(function()
{
alert(this.outerHTML);
}).mouseover(function()
{
this.style.color = "red";
}).mouseout(function()
{
this.style.color = "";
});
J("input[@type=radio][@checked]").each(function()
{
alert(this.outerHTML)
});
// 测试函数
function fnMyTest()
{
// 这里我们定义了一个临时的数组,每个元素是我们定义的一个文本传
// 每个都是一个典型的选择器测试
[
// 匹配所有button对象的上一级父对象的集合
"bUtToN:parent(1)",

// 选择id为myTestDiv下的所有元素中,name等于myTest1
// 的元素集合中,有class属性的对象集合
"#myTestDiv/*/[name='myTest1']/[@class]",

// 选择id为myTestDiv下的所有元素中,tagName为input的集合里,
// type属性等于text的对象的集合
"#myTestDiv/*/:text",

// 选择id为myTestDiv下的所有元素中,tagName为button,input,
// textarea,select的所有对象的集合
"#myTestDiv/*/button,input,textarea,select",

// 选择当前页面[不包含iframe]中所有button集合里,
// name等于myTest1的对象中有class属性的对象集合
"button/[name='myTest1']/[@class]",

// 功能同上,不过要包含iframe和frame里的对象
"//button/[name='myTest1']/[@class]",

// 功能同上面的:"#myTestDiv/button,input,textarea,select"
// "#myTestDiv/*/:input",

// 选择id为myTestDiv下所有的输入对象[button,input,textarea,
// select]中没有class属性的对象集合,包含iframe和frame里的对象
"#myTestDiv/*/:input/[!class]",

// 松散匹配所有button对象中class等于myTestGood的对象集合中,名字等于myTest的集合
"bUtToN.myTestGood/[ @ name = \" myTest \" ]",     

// 选择id为myTestDiv下所有的输入对象[button,input,textarea,
// select]中排除开not里模式匹配的集合,特别注意的是
// 这里的not里等于所有不是button的的对象,因此在加他前面的排除
// 就等于选择所有的button对象了,当然这里也支持iframe和frame的
"#myTestDiv/*/:input:not( '[tagName!=button]' )",

// 选择id为myTestDiv下所有的输入对象[button,input,textarea,
// select]中可见的对象
"#myTestDiv/*/:input:visible",

// 选择id为myTestDiv下所有的输入对象[button,input,textarea,
// select]中文本里包含了'事件'的对象集合
"#myTestDiv/*/:input:contains('事件')",

// 选择id为myTestDiv下所有的输入对象[button,input,textarea,
// select]中文本里不包含了'事件'的对象集合
"#myTestDiv/*/:input:not(:contains('事件'))",

// 选择id为myTestDiv下所有的输入对象[button,input,textarea,
// select]中属性class里包含了'Good'的对象集合
"#myTestDiv/*/:input:attct(['class','Good'])",

// 选择id为myTestDiv下所有的输入对象[button,input,textarea,
// select]集合数组里,下标为2到3的对象集合
"#myTestDiv/*/:input:get(' 2 - 3 ')",

// 选择id为myTestDiv下所有的输入对象[button,input,textarea,
// select]集合数组里,下标为1,7,8,9的对象集合
"#myTestDiv/*/:input:get('1, 7,8;9')",

// 选择id为myTestDiv下所有的输入对象[button,input,textarea,
// select]集合数组里,下标大于0小于100的集合里属性value包含了'测试'的所有对象的集合
"#myTestDiv/*/:input:get(' > 0 ,  < 100 '):attct(['value','测试'])",

// 选择id为myTestDiv下所有的输入对象[button,input,textarea,
// select]集合数组里,下标大于7小于1的分段集合
"#myTestDiv/*/:input:get(' > 7 ,  < 1 ')",

// 支持button[3]这样的形式
"//div/*/button[1]"
].each(function()
{
   alert("开始:" + this);
   this.XPath().each(function()
{
 var oStyle = this.style || {}, szCur = this.currentStyle.cssText;
 oStyle.border = "1px solid red";
     alert(this.outerHTML);
     oStyle.cssText = szCur;
});
});
}
-->
</script>
</body>
</html>
【责任编辑:夏书 TEL:(010)68476606】

回书目   上一节   下一节
专题
C和指针
思科全球CEO钱伯斯第七次访华
应试捷径—典型考题解析与考点贯通( 系统分析师考试)
软件安全:使安全成为软件开发必需的部分
Linux系统管理技术手册(中文第二版)
我也说两句

匿名发表

(如果看不清请点击图片进行更换)


中 国 最 大 的 网 络 技 术 网 站 ·
技 术 成 就 梦 想
订阅技术快讯
电子杂志下载
名称:SQL Server数据库管理精品黄皮书
简介:书中文章经过精挑细选,便于用户能根据自己的实际工作和学习,快速在本书寻找到相关资料。内容涵盖了SQL Server的安装与升级、语句查询、数据备份和恢复、自动化任务、数据同步、数据字典、安全和预防、性能和优化、集群等各方面应用信息,以及DBA管理人员在数据库管理工作中
名称:2007路由技术大全
简介:《2007路由技术大全》由51CTO.com网站特别策划制作,该书包括路由器技术、路由器产品、路由器配置、安全设置、路由器故障处理、路由器密码恢复,以及广大网友在实践使用中的心得经验和技巧文章,内容注重实用性,适用于初学者入门,也适合多年从业者提高,是一本实践和理论完
名称:网络安全精品应用黄皮书
简介:《2007精品网络安全黄皮书》包括了9个大类24个小类, 800余篇文章,内容包含了熊猫烧香病毒、DDOS攻击、ARP病等热点问题的介绍及解决方案。从病毒查杀、防范、系统、数据等各方面的安全设置到黑客技术的了解、防范,涉及到了安全应用的全部领域, 由浅至深内容全面。
思科全球CEO钱伯斯第七次访华
思科全球CEO钱伯斯第七次访华
北漂技术人90天求职纪实
北漂技术人90天求职纪实
2007年互联网大会
2007年互联网大会
· 2007年互联网大会
· 龙芯要做中国的“奔腾”
· IPv6协议--拓展网络无..
· 国际文档格式标准开战
· 微软出价446亿美元收购..
· 贝恩资本携手华为22亿..
· Linux——从菜鸟到高手
· SOA 面向服务架构
· 2008年4月全国计算机等..
· 微软Forefront企业安全..
· 华为员工自杀频频拷问..
· 技术人求职简历完备手册
· 勇闯IT培训黑色围城
· 隐私保护技术探讨
· Windows Server 2008专..
· NAC安全访问控制
ARP攻击防范与解决方案
ARP攻击防范与解决方案
iSCSI应用与发展
iSCSI应用与发展
SQL Server 2008/2005全解
SQL Server 2008/2005全解
· SQL Server 2008/2005..
· SOA 面向服务架构
· SQL Server 2008/2005..
· iSCSI应用与发展
· RAID——磁盘阵列基础
· 中间件应用技术专题
· SQL Server入门到精通
· 病毒查杀专题
· 国际文档格式标准开战
· 路由器设置与口令恢复
· Linux防火墙
· 打造安全服务器
· SOA 面向服务架构
· PHP开发应用手册
· ADSL应用面面俱到
· 入侵防护系统(IPS)初探
ARP攻击防范与解决方案
ARP攻击防范与解决方案
SQL Server 2008/2005全解
SQL Server 2008/2005全解
iSCSI应用与发展
iSCSI应用与发展
· iSCSI应用与发展
· 中间件应用技术专题
· SQL Server入门到精通
· SQL Server 2008/2005..
· SOA 面向服务架构
· iSCSI应用与发展
· RAID——磁盘阵列基础
· 病毒查杀专题
· 路由器设置与口令恢复
· SOA 面向服务架构
· 了解统一威胁管理(UTM)..
· ADSL应用面面俱到
· ADSL应用面面俱到
· 反垃圾邮件技术应用
· PHP开发应用手册
· 中间件应用技术专题