(function (w) {
var ver = '1.0';
var doc = document;
//var simple = /^(?:#|\.)?([\w-_]+)/;
var r1 = /^(a|body|canvas|button|div|form|frame|frameset|h1|h2|h3|h4|h5|h6|iframe|img|input|li|object|p|span|table|th|tr|td|textarea|ul|video|script|\*)$/i; //\w 任意一个字母或数字或下划线,也就是 A~Z,a~z,0~9,_ 中任意一个
var r2 = /[^\w]+/; //特殊字符 .#~().... //\w 任意一个字母或数字或下划线,也就是 A~Z,a~z,0~9,_ 中任意一个
function Q(query, context) {
context = (context || doc); //设定上下文
if (typeof (query) == 'object') {
return filter2(context, query); //暂未在上下文context中筛选
}
if (!r2.test(query) && !r1.test(query)) { //没有特殊符号 且非关键字 (兼容以前旧的写法)
return filter2(context, doc.getElementById(query));
}
//调用原生选择器
if (context.querySelector && false) { //querySelector //querySelectorAll
alert('原生选择器');
return context.querySelector(query);
} else {
alert('自定义选择器');
var ret = handle(query, context);
if (!ret) {
return null;
}
if (IsArray(ret) || isCollection(ret)) {
return (ret.length > 0) ? ret[0] : null; //如是数组,返回第一个对象
} else {
return ret;
}
}
}
//自定义选择器
function handle(query, context) {
var parts = query.replace(/\s+/g, " ").split(" "); //分组: \s 包括空格、制表符、换页符等空白字符的其中任意一个 \+相当于{1,}
var part = parts.pop(); //筛选出最后一个 pop() 方法将删除数组的最后一个元素,把数组长度减 1,并且返回它删除的元素的值。如果数组已经为空,则 pop() 不改变数组,并返回 undefined 值。
var s = Factory.create(part); //创建选择器对象
if (!s) { return null; } //如果创建选择器失败返回null
var ret = s.find(context);
//如有对象,从上下文context中查找 包含字符part的对象,[返回可能是对象,也可能是对象数组]
if (parts[0] && ret) { //有对象且还要待筛选项
var ret2 = [];
if (!IsArray(ret) && !isCollection(ret)) { ret = [ret]; } //单个对象
for (var i = 0; i < ret.length; i++) {
if (filter(parts.slice(0), ret[i], ret[i], context)) { ret2.push(ret[i]); } //有匹配,加入返回列表
}
if (ret2.length > 0) { return ret2; } else { return null; }
} else {
return ret;
}
}
function filter(parts, node, ret, context) { //从上下文中逐级筛选
var part = parts.pop(); //筛选出最后一个
var s = Factory.create(part); //创建选择器对象
if (!s) { return null; } //如果创建失败,返回null
var selector = s.find(context); //查询对象
if (!selector) { return null; } //未找到对象返回null
if (!IsArray(selector) && !isCollection(selector)) { selector = [selector]; } //初始化容器对象数组
for (var i = 0; i < selector.length; i++) { //只要有匹配的就直接返回
if (contains(selector[i], node)) {
if (parts[0]) {
if (filter(parts.slice(0), selector[i], ret, context)) {
return ret;
}
} else {
return ret;
}
}
}
return null; //未找到返回null
}
function filter2(p, node) {
if (node) {
var parent = node.parentNode;
while (parent) {
if (parent == p) {
return node;
}
parent = parent.parentNode;
}
}
return null;
}
//a包含b
function contains(a, b) {
if (b) {
while ((b = b.parentNode)) {
if (b === a) {
return true;
}
}
}
return false;
};
// contains = hasCompare || rnative.test(docElem.contains) ?
// function (a, b) {
// var adown = a.nodeType === 9 ? a.documentElement : a,
// bup = b && b.parentNode;
// return a === bup || !!(bup && bup.nodeType === 1 && (
// adown.contains ?
// adown.contains(bup) :
// a.compareDocumentPosition && a.compareDocumentPosition(bup) & 16
// ));
// } :
// function (a, b) {
// if (b) {
// while ((b = b.parentNode)) {
// if (b === a) {
// return true;
// }
// }
// }
// return false;
// };
//根据查询选择符创建相应选择器对象
var Factory = {
create: function (query) {
if (IDSelector.test(query)) {
return new IDSelector(query);
} else if (TagSelector.test(query)) {
return new TagSelector(query);
} else if (ClassSelector.test(query)) {
return new ClassSelector(query);
}
return null;
}
};
//ID选择器
function IDSelector(id) {
this.id = id.substring(1);
}
IDSelector.prototype = {
find: function (context) {
var ret = doc.getElementById(this.id);
return (contains(context, ret) ? ret : null);
},
match: function (element) {
return element.id == this.id;
}
};
IDSelector.test = function (selector) {
var regex = /^#([\w\-]+)$/;
return regex.test(selector);
};
//元素选择器
function TagSelector(tagName) {
this.tagName = tagName.toUpperCase();
}
TagSelector.prototype = {
find: function (context) {
return context.getElementsByTagName(this.tagName);
},
match: function (element) {
return this.tagName == element.tagName.toUpperCase() || this.tagName === "*";
}
};
TagSelector.test = function (selector) {
var regex = /^([\w\*\-]+)$/;
return regex.test(selector);
};
//类选择器 如div.c1.c2 #Id.c1.c2
function ClassSelector(className) {
this.tagName = (className.replace(/^(#?[\w\-]+)?((\.[\w\-]+)+)$/, '$1') || '*');
this.className = ('|' + className.replace(/^(#?[\w\-]+)?((\.[\w\-]+)+)$/, '$2').replace(/\./g, '|.|') + '|').split('.').slice(1);
}
ClassSelector.prototype = {
find: function (context) {
var s = Factory.create(this.tagName);
if (!s) { return null; } //创建失败返回null
var elements = s.find(context);
if (!elements) { return null; } //未找到对象返回null
var ret = []; //创建返回对象
if (!IsArray(elements) && !isCollection(elements)) { elements = [elements]; } //初始对象数组
for (var i = 0; i < elements.length; i++) {
if (this.match(elements[i])) {
ret.push(elements[i]);
}
}
if (ret.length < 1) { return null } else { return ret; }
},
match: function (element) {
if (!element.className) { return false; }
var className = this.className;
var cname = ('|' + element.className.replace(/[ ]+/g, '|') + '|').replace(/\|+/g, '|');
for (var i = 0; i < className.length; i++) {
if (cname.indexOf(className[i]) < 0) { //只要有不匹配的就返回false
return false;
}
}
return true;
}
};
ClassSelector.test = function (selector) {
var regex = /^(#?[\w\-]+)?((\.[\w\-]+)+)$/; //div.c1.c2 #Id.c1.c2
return regex.test(selector);
};
//TODO:属性选择器
function AttributeSelector(attr) {
this.find = function (context) {
};
this.match = function (element) {
};
}
AttributeSelector.test = function (selector) {
var regex = /\[([\w\-_]+)(?:=([\w\-_]+))?\]/;
return regex.test(selector);
};
//是否数组
function IsArray(o) {
return Object.prototype.toString.call(o) === '[object Array]';
}
function isCollection(o) {
if (o && o.length && !o.nodeType) {
return true;
} else {
return false;
}
//return o.toString() == '[object HTMLCollection]';
}
w.$ || (w.$ = Q);
})(window)
var ver = '1.0';
var doc = document;
//var simple = /^(?:#|\.)?([\w-_]+)/;
var r1 = /^(a|body|canvas|button|div|form|frame|frameset|h1|h2|h3|h4|h5|h6|iframe|img|input|li|object|p|span|table|th|tr|td|textarea|ul|video|script|\*)$/i; //\w 任意一个字母或数字或下划线,也就是 A~Z,a~z,0~9,_ 中任意一个
var r2 = /[^\w]+/; //特殊字符 .#~().... //\w 任意一个字母或数字或下划线,也就是 A~Z,a~z,0~9,_ 中任意一个
function Q(query, context) {
context = (context || doc); //设定上下文
if (typeof (query) == 'object') {
return filter2(context, query); //暂未在上下文context中筛选
}
if (!r2.test(query) && !r1.test(query)) { //没有特殊符号 且非关键字 (兼容以前旧的写法)
return filter2(context, doc.getElementById(query));
}
//调用原生选择器
if (context.querySelector && false) { //querySelector //querySelectorAll
alert('原生选择器');
return context.querySelector(query);
} else {
alert('自定义选择器');
var ret = handle(query, context);
if (!ret) {
return null;
}
if (IsArray(ret) || isCollection(ret)) {
return (ret.length > 0) ? ret[0] : null; //如是数组,返回第一个对象
} else {
return ret;
}
}
}
//自定义选择器
function handle(query, context) {
var parts = query.replace(/\s+/g, " ").split(" "); //分组: \s 包括空格、制表符、换页符等空白字符的其中任意一个 \+相当于{1,}
var part = parts.pop(); //筛选出最后一个 pop() 方法将删除数组的最后一个元素,把数组长度减 1,并且返回它删除的元素的值。如果数组已经为空,则 pop() 不改变数组,并返回 undefined 值。
var s = Factory.create(part); //创建选择器对象
if (!s) { return null; } //如果创建选择器失败返回null
var ret = s.find(context);
//如有对象,从上下文context中查找 包含字符part的对象,[返回可能是对象,也可能是对象数组]
if (parts[0] && ret) { //有对象且还要待筛选项
var ret2 = [];
if (!IsArray(ret) && !isCollection(ret)) { ret = [ret]; } //单个对象
for (var i = 0; i < ret.length; i++) {
if (filter(parts.slice(0), ret[i], ret[i], context)) { ret2.push(ret[i]); } //有匹配,加入返回列表
}
if (ret2.length > 0) { return ret2; } else { return null; }
} else {
return ret;
}
}
function filter(parts, node, ret, context) { //从上下文中逐级筛选
var part = parts.pop(); //筛选出最后一个
var s = Factory.create(part); //创建选择器对象
if (!s) { return null; } //如果创建失败,返回null
var selector = s.find(context); //查询对象
if (!selector) { return null; } //未找到对象返回null
if (!IsArray(selector) && !isCollection(selector)) { selector = [selector]; } //初始化容器对象数组
for (var i = 0; i < selector.length; i++) { //只要有匹配的就直接返回
if (contains(selector[i], node)) {
if (parts[0]) {
if (filter(parts.slice(0), selector[i], ret, context)) {
return ret;
}
} else {
return ret;
}
}
}
return null; //未找到返回null
}
function filter2(p, node) {
if (node) {
var parent = node.parentNode;
while (parent) {
if (parent == p) {
return node;
}
parent = parent.parentNode;
}
}
return null;
}
//a包含b
function contains(a, b) {
if (b) {
while ((b = b.parentNode)) {
if (b === a) {
return true;
}
}
}
return false;
};
// contains = hasCompare || rnative.test(docElem.contains) ?
// function (a, b) {
// var adown = a.nodeType === 9 ? a.documentElement : a,
// bup = b && b.parentNode;
// return a === bup || !!(bup && bup.nodeType === 1 && (
// adown.contains ?
// adown.contains(bup) :
// a.compareDocumentPosition && a.compareDocumentPosition(bup) & 16
// ));
// } :
// function (a, b) {
// if (b) {
// while ((b = b.parentNode)) {
// if (b === a) {
// return true;
// }
// }
// }
// return false;
// };
//根据查询选择符创建相应选择器对象
var Factory = {
create: function (query) {
if (IDSelector.test(query)) {
return new IDSelector(query);
} else if (TagSelector.test(query)) {
return new TagSelector(query);
} else if (ClassSelector.test(query)) {
return new ClassSelector(query);
}
return null;
}
};
//ID选择器
function IDSelector(id) {
this.id = id.substring(1);
}
IDSelector.prototype = {
find: function (context) {
var ret = doc.getElementById(this.id);
return (contains(context, ret) ? ret : null);
},
match: function (element) {
return element.id == this.id;
}
};
IDSelector.test = function (selector) {
var regex = /^#([\w\-]+)$/;
return regex.test(selector);
};
//元素选择器
function TagSelector(tagName) {
this.tagName = tagName.toUpperCase();
}
TagSelector.prototype = {
find: function (context) {
return context.getElementsByTagName(this.tagName);
},
match: function (element) {
return this.tagName == element.tagName.toUpperCase() || this.tagName === "*";
}
};
TagSelector.test = function (selector) {
var regex = /^([\w\*\-]+)$/;
return regex.test(selector);
};
//类选择器 如div.c1.c2 #Id.c1.c2
function ClassSelector(className) {
this.tagName = (className.replace(/^(#?[\w\-]+)?((\.[\w\-]+)+)$/, '$1') || '*');
this.className = ('|' + className.replace(/^(#?[\w\-]+)?((\.[\w\-]+)+)$/, '$2').replace(/\./g, '|.|') + '|').split('.').slice(1);
}
ClassSelector.prototype = {
find: function (context) {
var s = Factory.create(this.tagName);
if (!s) { return null; } //创建失败返回null
var elements = s.find(context);
if (!elements) { return null; } //未找到对象返回null
var ret = []; //创建返回对象
if (!IsArray(elements) && !isCollection(elements)) { elements = [elements]; } //初始对象数组
for (var i = 0; i < elements.length; i++) {
if (this.match(elements[i])) {
ret.push(elements[i]);
}
}
if (ret.length < 1) { return null } else { return ret; }
},
match: function (element) {
if (!element.className) { return false; }
var className = this.className;
var cname = ('|' + element.className.replace(/[ ]+/g, '|') + '|').replace(/\|+/g, '|');
for (var i = 0; i < className.length; i++) {
if (cname.indexOf(className[i]) < 0) { //只要有不匹配的就返回false
return false;
}
}
return true;
}
};
ClassSelector.test = function (selector) {
var regex = /^(#?[\w\-]+)?((\.[\w\-]+)+)$/; //div.c1.c2 #Id.c1.c2
return regex.test(selector);
};
//TODO:属性选择器
function AttributeSelector(attr) {
this.find = function (context) {
};
this.match = function (element) {
};
}
AttributeSelector.test = function (selector) {
var regex = /\[([\w\-_]+)(?:=([\w\-_]+))?\]/;
return regex.test(selector);
};
//是否数组
function IsArray(o) {
return Object.prototype.toString.call(o) === '[object Array]';
}
function isCollection(o) {
if (o && o.length && !o.nodeType) {
return true;
} else {
return false;
}
//return o.toString() == '[object HTMLCollection]';
}
w.$ || (w.$ = Q);
})(window)