前言

我师父(http://www.cnblogs.com/aaronjs/)说应当阅读框架(jquery),所以老夫就准备开始看了

然后公司的师兄原来写了个dom选择器,感觉不错啊!!!原来自己从来没有想过能写这些,所以我们今天一起来试试吧

我写的这个很简单,就是最简单的那种了,但是公司师兄写的很好。。。。。。

简单dom选择器

先上个完整的代码吧,因为我已经写起了:

 <html xmlns="http://www.w3.org/1999/xhtml">
<head>
<title></title>
</head>
<body>
<div id="parent">
<div class="child1" id="c">
<div>
</div>
<input type="button" value="测试" class="child1.1" />
</div>
<div class="child1">
</div>
<div class="child2">
</div>
<div class="child2 child1">
<div class="child1.1">
<input class="l" value="三层测试" />
</div>
</div>
<input type="button" value="测试2" />
</div>
<script type="text/javascript"> (function () {
var queryFunc = {
'#': function (id) {
var arr = [];
arr.push(document.getElementById(id))
return arr;
},
'.': function (className) {
var els = document.getElementsByTagName('*');
var reg = new RegExp('(^|\\s)' + className + '(\\s|$)');
var arr = [];
for (var i = 0, len = els.length; i < len; i++) {
if (reg.test(els[i].className)) {
arr.push(els[i]);
}
}
return arr;
},
'tag': function (tag) {
return document.getElementsByTagName(tag);
}
}; var filterFunc = {
'#': function (el, id) {
return this.commomFunc(el, function (p) {
if (p.id == id) {
return true;
}
});
},
'.': function (el, className) {
var reg = new RegExp('(^|\\s)' + className + '(\\s|$)');
return this.commomFunc(el, function (p) {
if (reg.test(p.className)) {
return true;
}
});
},
'tag': function (el, tag) {
return this.commomFunc(el, function (p) {
if (p.tagName.toLowerCase() == tag) {
return true;
}
});
},
commomFunc: function (el, callback) {
var p = el;
var end = false;
while (!end) {
p = p.parentNode || p.parentElement || null;
if (!p) return false;
var b = callback && callback(p);
if (b) return b;
if (p.tagName == 'BODY') {
end = true;
}
}
return false;
}
}; var getKV = function (str) {
if (!str || typeof str != 'string') return null;
var k = str.substring(0, 1);
var v = str;
if (k == '.' || k == '#') {
v = str.substring(1, str.length);
} else {
k = 'tag';
}
return {
k: k,
v: v
};
} var query = function (str) {
var kv = getKV(str)
return (queryFunc[kv.k] && queryFunc[kv.k](kv.v));
};
var filter = function (el, str) {
var kv = getKV(str);
return (filterFunc[kv.k] && filterFunc[kv.k](el, kv.v));
};
var explodeSelector = function (str) {
if (!str) return [];
//第一步去掉多余的空格
str = str.replace(/\s+/g, ' ');
var arr = str.split(' ');
return arr;
};
//筛选元素是否具有该属性 var queryAll = function (str) {
var arrSelector = explodeSelector(str);
var len = arrSelector.length; //当前索引
var index = len - 2;
var curDom = null;
var curSelector = null; //第一轮筛选出来的元素
var els = query(arrSelector[len - 1]);
//只有一个选择器便直接返回了
if (len == 1) return els; while (index != -1) {
//获取当前的筛选选择器
curSelector = arrSelector[index];
var tmpArr = [];
for (var i = 0, len = els.length; i < len; i++) {
var tmpEl = els[i];
if (filter(tmpEl, curSelector))
tmpArr.push(tmpEl);
}
els = tmpArr;
index--;
}
return els;
};
window.queryAll = queryAll;
})(); var selector = [
'div',
'div input',
'#parent',
'#parent .child1',
'#parent .child2',
'.child1 .child1.1',
'#c .child1.1',
'#parent .child1 .child1.1 input'
]; for (var i in selector) {
console.log(selector[i] + '——' + queryAll(selector[i]));
var s = '';
} </script>
</body>
</html>
 <div id="parent">
<div class="child1" id="c">
<div>
</div>
<input type="button" value="测试" class="child1.1" />
</div>
<div class="child1">
</div>
<div class="child2">
</div>
<div class="child2 child1">
<div class="child1.1">
<input class="l" value="三层测试" />
</div>
</div>
<input type="button" value="测试2" />
</div>

简单的结果,然后我们来简单看看我丑陋的代码:

 (function () {
var queryFunc = {
'#': function (id) {
var arr = [];
arr.push(document.getElementById(id))
return arr;
},
'.': function (className) {
var els = document.getElementsByTagName('*');
var reg = new RegExp('(^|\\s)' + className + '(\\s|$)');
var arr = [];
for (var i = 0, len = els.length; i < len; i++) {
if (reg.test(els[i].className)) {
arr.push(els[i]);
}
}
return arr;
},
'tag': function (tag) {
return document.getElementsByTagName(tag);
}
}; var filterFunc = {
'#': function (el, id) {
return this.commomFunc(el, function (p) {
if (p.id == id) {
return true;
}
});
},
'.': function (el, className) {
var reg = new RegExp('(^|\\s)' + className + '(\\s|$)');
return this.commomFunc(el, function (p) {
if (reg.test(p.className)) {
return true;
}
});
},
'tag': function (el, tag) {
return this.commomFunc(el, function (p) {
if (p.tagName.toLowerCase() == tag) {
return true;
}
});
},
commomFunc: function (el, callback) {
var p = el;
var end = false;
while (!end) {
p = p.parentNode || p.parentElement || null;
if (!p) return false;
var b = callback && callback(p);
if (b) return b;
if (p.tagName == 'BODY') {
end = true;
}
}
return false;
}
}; var getKV = function (str) {
if (!str || typeof str != 'string') return null;
var k = str.substring(0, 1);
var v = str;
if (k == '.' || k == '#') {
v = str.substring(1, str.length);
} else {
k = 'tag';
}
return {
k: k,
v: v
};
} var query = function (str) {
var kv = getKV(str)
return (queryFunc[kv.k] && queryFunc[kv.k](kv.v));
};
var filter = function (el, str) {
var kv = getKV(str);
return (filterFunc[kv.k] && filterFunc[kv.k](el, kv.v));
};
var explodeSelector = function (str) {
if (!str) return [];
//第一步去掉多余的空格
str = str.replace(/\s+/g, ' ');
var arr = str.split(' ');
return arr;
};
//筛选元素是否具有该属性 var queryAll = function (str) {
var arrSelector = explodeSelector(str);
var len = arrSelector.length; //当前索引
var index = len - 2;
var curDom = null;
var curSelector = null; //第一轮筛选出来的元素
var els = query(arrSelector[len - 1]);
//只有一个选择器便直接返回了
if (len == 1) return els; while (index != -1) {
//获取当前的筛选选择器
curSelector = arrSelector[index];
var tmpArr = [];
for (var i = 0, len = els.length; i < len; i++) {
var tmpEl = els[i];
if (filter(tmpEl, curSelector))
tmpArr.push(tmpEl);
}
els = tmpArr;
index--;
}
return els;
};
window.queryAll = queryAll;
})();

基本思路

① 获取选择器字符串,并将之分解为一个数组

var explodeSelector = function (str) {
if (!str) return [];
//第一步去掉多余的空格
str = str.replace(/\s+/g, ' ');
var arr = str.split(' ');
return arr;
};

② 与CSS选择器一致,根据各种条件选取相关元素

 var queryFunc = {
'#': function (id) {
var arr = [];
arr.push(document.getElementById(id))
return arr;
},
'.': function (className) {
var els = document.getElementsByTagName('*');
var reg = new RegExp('(^|\\s)' + className + '(\\s|$)');
var arr = [];
for (var i = 0, len = els.length; i < len; i++) {
if (reg.test(els[i].className)) {
arr.push(els[i]);
}
}
return arr;
},
'tag': function (tag) {
return document.getElementsByTagName(tag);
}
};

③ 根据选择器与获得的dom数组,判断其父元素是否具有相关属性(id,className,tag),有便留下来,没有就不管他

过滤下来的就是我们要的元素:

 var filterFunc = {
'#': function (el, id) {
return this.commomFunc(el, function (p) {
if (p.id == id) {
return true;
}
});
},
'.': function (el, className) {
var reg = new RegExp('(^|\\s)' + className + '(\\s|$)');
return this.commomFunc(el, function (p) {
if (reg.test(p.className)) {
return true;
}
});
},
'tag': function (el, tag) {
return this.commomFunc(el, function (p) {
if (p.tagName.toLowerCase() == tag) {
return true;
}
});
},
commomFunc: function (el, callback) {
var p = el;
var end = false;
while (!end) {
p = p.parentNode || p.parentElement || null;
if (!p) return false;
var b = callback && callback(p);
if (b) return b;
if (p.tagName == 'BODY') {
end = true;
}
}
return false;
}
};
 var queryAll = function (str) {
var arrSelector = explodeSelector(str);
var len = arrSelector.length; //当前索引
var index = len - 2;
var curDom = null;
var curSelector = null; //第一轮筛选出来的元素
var els = query(arrSelector[len - 1]);
//只有一个选择器便直接返回了
if (len == 1) return els; while (index != -1) {
//获取当前的筛选选择器
curSelector = arrSelector[index];
var tmpArr = [];
for (var i = 0, len = els.length; i < len; i++) {
var tmpEl = els[i];
if (filter(tmpEl, curSelector))
tmpArr.push(tmpEl);
}
els = tmpArr;
index--;
}
return els;
};

④,然后,就没有然后了。。。。

不足与提高

这个代码明显就是玩具,三无产品:

① 无测试

② 无子选择器/兄弟选择器

③ 无性能

但是,以上东西暂时和我无关啦,因为学习嘛。。。。

最后附上师兄选择器代码:

 <!doctype html>
<html>
<head>
<title>aiQuery test</title>
<script type="text/javascript">
/**
* aiQuery
* @author ouxingzhi
*/
void function (window, document, undefined) {
var location = window.location,
Slice = [].slice,
RegTrim = /(?:^\s+|\s+$)/,
RegBlank = /\s+/,
RegOperate = /\s*(?:\s|>|\+|~(?!\=))\s*/i,
RegElement = /^([\w\-]+|\*)?(?:\#([\w\-]+))?(?:\.([\w\-]+))?(?:\[([\w-]+)(?:([~|\^|\$|\*|\|]?=)['"]?([\w-]+)['"]?)?\])?(?:\:([\w-]+(?:\([\w-]+\))?))?$/i;
function AIQuery(Selector, Content) {
Selector = Selector.replace(RegTrim, '');
Content = Content || document;
if (Content.querySelectorAll) {
return Slice.call(Content.querySelectorAll(Selector));
} else {
return querySelectorAll(Selector, Content)
}
}
function querySelectorAll(Selector, Content) {
var Groups = Selector.split(/\s*\,\s*/img),
Results = [];
for (var i = 0,
len = Groups.length; i < len; i++) {
Results = Results.concat(Find(Groups[i], Content))
}
return Results
}
function Find(Selector, Content) {
var Results = [],
atoms = Selector.split(RegOperate),
operates = Selector.match(RegOperate);
operates = operates || [];
for (var i = 0,
len = operates.length; i < len; i++) (operates[i] = /^\s+$/.test(operates[i]) ? ' ' : operates[i].replace(RegTrim, ''));
var Results = EachTo(' ', atoms.shift(), operates, atoms, Content);
return Results
}
function EachTo(op, at, operates, atoms, Content) {
var Results = [],
Median = [],
operate,
atom;
if (Content.constructor === Array || 'length' in Content) {
for (var i = 0,
len = Content.length; i < len; i++) {
Results = Results.concat(EachTo(op, at, operates.slice(0), atoms.slice(0), Content[i]))
}
} else if (Content.constructor === String) {
Content = Find(Content, document);
Results.concat(EachTo(op, at, operates.slice(0), atoms.slice(0), Content[i]))
} else {
Median = GetElementByAny(op, at, Content);
if (Median) {
if (operates && operates.length && atoms && atoms.length) {
Results = EachTo(operates.shift(), atoms.shift(), operates, atoms, Median)
} else {
Results = Median
}
}
}
return Results
}
function GetElementByAny(op, at, Content) {
if (typeof OperateFunction[op] !== 'undefined') {
return OperateFunction[op](at, Content)
}
}
var OperateFunction = {
' ': function (at, Content) {
var einfo = buildElementInfo(at),
preNodes = [];
if (!einfo) return [];
if (einfo.Id) {
preNodes = document.getElementById(einfo.Id);
preNodes = preNodes ? [preNodes] : []
} else if (einfo.ClassName && Content.getElementsByClassName) {
preNodes = Content.getElementsByClassName(einfo.ClassName);
preNodes = preNodes || []
} else if (einfo.TagName && Content.getElementsByTagName) {
preNodes = Content.getElementsByTagName(einfo.TagName);
preNodes = preNodes || []
} else {
preNodes = Content.getElementsByTagName('*');
preNodes = preNodes || []
};
return filterNode(einfo, preNodes)
},
'>': function (at, Content) {
var einfo = buildElementInfo(at);
preNodes = Content.childNodes || [];
if (!einfo) return [];
return filterNode(einfo, preNodes)
},
'+': function (at, Content) {
if (Content === document) return [];
var einfo = buildElementInfo(at);
if (!einfo) return [];
var results = [],
preNodes = (function () {
var nextNode = Content.nextSibling;
while (nextNode && nextNode.nodeType != 1) {
nextNode = nextNode.nextSibling
}
return nextNode
})();
preNodes = preNodes ? [preNodes] : [];
if (preNodes.length) {
results = filterNode(einfo, preNodes)
} else {
results = []
}
return results
},
'~': function (at, Content) {
if (Content === document) return [];
var einfo = buildElementInfo(at),
preNodes = [];
if (!einfo) return [];
var sibling = Content.parentNode ? Content.parentNode.childNodes : null;
if (sibling) {
for (var i = 0,
len = sibling.length; i < len; i++) if (Content !== sibling[i]) preNodes.push(sibling[i])
}
return filterNode(einfo, preNodes)
}
};
function buildElementInfo(at) {
var Einfo = RegElement.exec(at);
if (!Einfo) return;
return {
TagName: Einfo[1] || undefined,
Id: Einfo[2] || undefined,
ClassName: Einfo[3] || undefined,
AttrName: Einfo[4] || undefined,
AttrOper: Einfo[5] || undefined,
AttrVal: Einfo[6] || undefined,
FakeClass: Einfo[7] || undefined
}
}
function filterNode(Einfo, Nodes) {
var results = [], RegClassName,
isMatch;
if (Einfo.ClassName) RegClassName = new RegExp('\\b' + Einfo.ClassName + '\\b', 'i');
for (var i = 0,
len = Nodes.length; i < len; i++) {
isMatch = true;
if (Einfo.TagName !== undefined && Einfo.TagName.toUpperCase() !== Nodes[i].nodeName) isMatch = false;
if (Einfo.Id !== undefined && Einfo.Id !== Nodes[i].id) isMatch = false;
if (Einfo.ClassName !== undefined && !Nodes[i].className.match(RegClassName)) isMatch = false;
isMatch = isMatchAttribute(Einfo, Nodes[i], isMatch);
isMatch = isMatchFakeClass(Einfo, Nodes[i], isMatch);
if (isMatch) results.push(Nodes[i])
}
return results
}
function isMatchAttribute(Einfo, node, isMatch) {
if (Einfo.AttrName === undefined && Einfo.AttrOper === undefined && Einfo.AttrVal === undefined) { } else if (Einfo.AttrName !== undefined && Einfo.AttrOper === undefined && Einfo.AttrVal === undefined && node.getAttribute && node.getAttribute(Einfo.AttrName) !== null) {
isMatch = true
} else if (Einfo.AttrName !== undefined && Einfo.AttrOper !== undefined && Einfo.AttrVal !== undefined && node.getAttribute) {
switch (Einfo.AttrOper) {
case '=':
isMatch = node.getAttribute(Einfo.AttrName) === Einfo.AttrVal;
break;
case '~=':
isMatch = !!(node.getAttribute(Einfo.AttrName) && node.getAttribute(Einfo.AttrName).match(new RegExp('(?:^|\\s+)' + Einfo.AttrVal + '(?:$|\\s+)', 'i')));
break;
case '^=':
isMatch = !!(node.getAttribute(Einfo.AttrName) && node.getAttribute(Einfo.AttrName).match(new RegExp('^' + Einfo.AttrVal, 'i')));
break;
case '$=':
isMatch = !!(node.getAttribute(Einfo.AttrName) && node.getAttribute(Einfo.AttrName).match(new RegExp(Einfo.AttrVal + '$', 'i')));
break;
case '*=':
isMatch = !!(node.getAttribute(Einfo.AttrName) && node.getAttribute(Einfo.AttrName).match(new RegExp(Einfo.AttrVal, 'i')));
break;
case '|=':
isMatch = !!(node.getAttribute(Einfo.AttrName) && node.getAttribute(Einfo.AttrName).match(new RegExp('(?:^|\\-)' + Einfo.AttrVal + '(?:$|\\-)', 'i')));
break
}
}
return isMatch
}
function isMatchFakeClass(Einfo, node, isMatch) {
if (Einfo.FakeClass === undefined) { } else {
switch (Einfo.FakeClass) {
case 'empty':
isMatch = node.innerHTML.replace(RegTrim, '').length == 0;
break;
case 'checked':
if (node.nodeName.match(/(?:INPUT|TEXTAREA|BUTTON|SELECT|OPTION)/i)) isMatch = !!node.checked;
break;
case 'enabled':
if (node.nodeName.match(/(?:INPUT|TEXTAREA|BUTTON|SELECT|OPTION)/i)) isMatch = !!node.disabled;
break;
case 'disabled':
if (node.nodeName.match(/(?:INPUT|TEXTAREA|BUTTON|SELECT|OPTION)/i)) isMatch = !!node.disabled;
break;
case 'target':
var hash = location.hash.replace('#', '');
isMatch = hash === node.id || (node.name && hash === node.name);
break
}
}
return isMatch
}
window['aiQuery'] = AIQuery;
} (window, document);
</script>
</head>
<body>
<div class="aaa">
<div class="bbb">
<label>
用户名:</label>
<input type="text" id="username" />
</div>
<pre>
//使用方法
alert(aiQuery('.aaa .bbb [type=text]'));
alert(aiQuery('.aaa label + input'));
alert(aiQuery('#username'));
</pre>
</div>
<script type="text/javascript">
alert(aiQuery('.aaa .bbb [type=text]'));
alert(aiQuery('.aaa label + input'));
alert(aiQuery('#username'));
</script>
</body>
</html>

然后,就没有然后了。。。

小插曲-浮点数计算

今天项目重遇到一个问题,我和我的小伙伴都惊呆了:

你没有看错,33.1 * 3 就是那么多!!!

尼玛已证明这是一个js的bug,我可以这么说么???

解决方案,求回复(我会说我想骗点回复么???)

parseInt(33.1 * 3 * 100) / 100

都别说工资低了,我们来一起写简单的dom选择器吧!的更多相关文章

  1. 给“.Net工资低”争论一个了结吧!

    昨天我写了一篇<工资低的.Net程序员,活该你工资低>,底下的支持.争吵.骂娘的评论依旧像之前几篇园友的博客一样繁荣.公说公有理,婆说婆有理,这样争吵下去永远没有尽头.数据没有情绪,是公正 ...

  2. 工资低的.Net程序员,活该你工资低

    这两天博客园上关于“.Net工资低”的讨论挺多的,让我不禁想起一句话“拉不出屎来怪地球没引力”. 那些抱怨“做.Net工作三年了月薪才6千,我的同学做Java现在都一万二”的哥们,你问问自己“我会什么 ...

  3. 我也谈谈.NET程序员工资低

    我从2011年下半年预谋转型,2012春季正式转型到iOS,看了<经过本人 6 年.net 工作经验证明 .net 工资确实比 Java 低>这篇文章,一下子有很多感慨. 我不好意思算我干 ...

  4. java反射并不是什么高深技术,面向对象语言都有这个功能,而且功能也很简单,就是利用jvm动态加载时生成的class对象

    java反射并不是什么高深技术,面向对象语言都有这个功能. 面向对象语言都有这个功能,而且功能也很简单,就是利用jvm动态加载时生成的class对象,去获取类相关的信息 2.利用java反射可以调用类 ...

  5. 刚学习java时的笔记, 有点渣, 毕竟都是从低往高走

    一片很有意义的论文: 写给那些在技术路上奔跑的人们!!!!! http://blog.csdn.net/xqhrs232/article/details/24885971 乱码处理 1.get处理 解 ...

  6. 别人都在认真听课,而我埋头写Python为主播疯狂点点点点点赞!

    最近有次在钉钉看直播,发现这个直播非常之精彩,于是情不自禁地想要为主播大佬连刷一波赞: 但我发现,手动连击点赞速度十分不可观.气人的是,钉钉直播不能长按刷赞!这让我很恼怒.心中满怀的激动和兴奋以及对大 ...

  7. 【yii2】 yii框架如果控制器和方法都是多个单词组成应该怎样写请求链接

    最近的一个项目碰到这种问题,摸索出了解决办法,故此记录下 example 如果控制器为 ShopCollect 方法为 UserList solution 请求的链接应该为 doman.com/sho ...

  8. WIN 下的超动态菜单(一)

    WIN 下的超动态菜单(一)介绍 WIN 下的超动态菜单(二)用法 WIN 下的超动态菜单(三)代码 作者:黄山松,发表于博客园:http://www.cnblogs.com/tomview/     ...

  9. (3)打造简单OS-MBR引导区转移加载简单程序(突破512限制)

    在第一节<(1)汇编写入引导区,虚拟机启动步骤>中讲解到一个简单屏幕显示一川字符串,第二节讲到BIOS启动过程! 第一节中基本原理就是将那个汇编代码用nasm汇编器进行汇编成二进制,然后把 ...

随机推荐

  1. DIV+CSS 图文混排的图片居中办法

    不少人为了让 Div 图文混排的图片可以居中,给 IMG 套各式各样的 SPAN.DIV.LI 等等,以便于使用 text-align来进行居中. <div>图文混排 <br> ...

  2. 【Windows编程】系列第八篇:通用对话框

    上一篇我们学习了菜单的基本编程,本篇来了解一下通用对话框的使用.Windows系统之所以是目前最流行的桌面系统,也是因为Windows有一套标准化,统一友好的交互界面,比如菜单.工具栏.状态栏以及各个 ...

  3. HashMap实现原理及源码分析

    哈希表(hash table)也叫散列表,是一种非常重要的数据结构,应用场景及其丰富,许多缓存技术(比如memcached)的核心其实就是在内存中维护一张大的哈希表,而HashMap的实现原理也常常出 ...

  4. python 类属性与方法

    Python 类属性与方法 标签(空格分隔): Python Python的访问限制 Python支持面向对象,其对属性的权限控制通过属性名来实现,如果一个属性有双下划线开头(__),该属性就无法被外 ...

  5. OllyUni.dll

    OllyUni.dll 周银辉 好像很多人找不到OllyUni.dll ,下载在这里:http://www.phenoelit.org/win/index.html 注:在OllyDBG2.0中用不了 ...

  6. Java 8新特性终极指南

    目录结构 介绍 Java语言的新特性 2.1 Lambdas表达式与Functional接口 2.2 接口的默认与静态方法 2.3 方法引用 2.4 重复注解 2.5 更好的类型推测机制 2.6 扩展 ...

  7. LeetCode:Merge k Sorted Lists

    题目链接 Merge k sorted linked lists and return it as one sorted list. Analyze and describe its complexi ...

  8. bootstrap-markdown编辑器引入

    MarkdownAsset.php <?php namespace app\assets; use yii\web\AssetBundle; class MarkdownAsset extend ...

  9. python实现计算器

    计算器功能 实现优先级解析,加减乘除四则运算 自定义小数位精度 实现思想: 先找到最里层括号,根据乘除,加减优先级,调用写好的乘除.加减运算函数算出括号内总值,再将原括号式用所得值替换,此过程循环进行 ...

  10. 链队列java实现

    public class LinkHeap<T> { class Node<T> { T data; Node<T> next; Node(T data) { th ...