私の第5世代セレクタIcarus
59781 ワード
Icarusは私の現在のマッチング精度が最も高く(470ユニットのテストで精度を保証)、速度が最も速い(IE 67でjQueryを押して、他のブラウザはquerySelectorAllを使って上下を区別しない)セレクタで、CSS 3のすべての新しい擬似クラスを全面的にサポートして、jQueryが持っているカスタム擬似クラスをサポートして、XMLの検索をサポートして、XMLネーミングスペース付き要素の検索をサポートします(jQueryはネーミングスペースなし、間違いを報告しやすいのみをサポートします).
IcarusとjQuery 1.7 slickspeedでのスピード試合の結果(数値の最大代表が遅いほど):
Icarus
jQuery1.7
ひれい
IE7
443
657
1.5
IE6
975
1570
1.6
初期のjQueryと比較すると42は言うまでもなく、その2倍以上です.
Icarusの最大のハイライトはXMLの完璧なサポートです.そのため、xpathとgetElementsByTagNameを使用します.ネーミングスペースのサポートについては、「aaa\::bbb」を使用して検索してください.
以下は、IcarusがオリジナルのAPIを検索するために使用したものです. getElementById getElementsByTagName getElementsByTagNameNS getElementsByClassName evaluate (xpath) selectNodes (xpath) querySelectorAll
Icarusの符号量は930行(domに依存しない他のモジュール)、jQueryのSizzleは1500行である.
Icarus対CSS 3擬似クラスはW 3 Cの仕様で検索されます.例えば、not逆選択擬似クラスは、div:not(.a)のような単一の式のみをサポートし、div:not(.a.b)は使用できません.使用するには複数の逆選択が必要です.div:not(.a):not(.b).
IcarusはjQueryのカスタム擬似クラスをサポートしているが、位置擬似クラス(:first,:last,:even,:odd,:eq...)などの使用は提唱されていない.(last-child,:first-child,:nth-child(even)...)の代わりに、標準的なサブエレメントを使用して擬似クラスをフィルタリングすることができます.jQueryのカスタムフォーム擬似クラス(:text,:radio....)について、(input[type=text],input[type=radio]...)の代わりに属性セレクタを使用することもできます.とにかく、標準的でないものは長く生きられないので、覚えておいてほしい.
以下はIcarusのネーミングスペースのサポートプレゼンテーションです.例はinline SVGです.IE 9はサポートされていませんので、高バージョンの標準ブラウザで見てください.IE 10がSVGをサポートすると、SVGのアプリケーションが大幅に増加するため、ネーミングスペースのサポートが必要になります.
icarus svg by司徒正美
window.onload = function(){
alert(dom.query("svg\\:feOffset:first")[0].tagName)
}
x="128"y="128"width="256"height="256"
dx="128"dy="128"
result="displacement"
/>
id="textureLoader"
x="0"y="0"width="256"height="256"
xlink:href="texture.tinman.png"
/>
x="0"y="0"width="512"height="512"
result="texture"
/>
x="128"y="128"width="256"height="256"
in="texture" in2="displacement"
scale="255"
xChannelSelector="R"yChannelSelector="G"
/>
in2="displacement"
operator="in"
/>
x="0"y="0"width="256"height="256"
dx="-128"dy="-128"
/>
実行コード
後にjavascriptのセレクタは基本的にIE 678(IE 8のquerySelectoAllサポートの種類が少なすぎる)と互換性があるため、以降のセレクタは基本的にquerySelectorAllとevaluateとmatchesSelectorで書かれており、CSS 4もすぐに到来し、より多くの擬似クラスをもたらすため、jQueryのカスタム擬似クラスはほとんど存在しない必要がある.
関連リンク:
第1世代セレクタ
第2世代セレクタ
第3世代セレクタ
第4世代セレクタ
スピード?ゲーム
IcarusとjQuery 1.7 slickspeedでのスピード試合の結果(数値の最大代表が遅いほど):
Icarus
jQuery1.7
ひれい
IE7
443
657
1.5
IE6
975
1570
1.6
初期のjQueryと比較すると42は言うまでもなく、その2倍以上です.
Icarusの最大のハイライトはXMLの完璧なサポートです.そのため、xpathとgetElementsByTagNameを使用します.ネーミングスペースのサポートについては、「aaa\::bbb」を使用して検索してください.
以下は、IcarusがオリジナルのAPIを検索するために使用したものです.
Icarusの符号量は930行(domに依存しない他のモジュール)、jQueryのSizzleは1500行である.
Icarus対CSS 3擬似クラスはW 3 Cの仕様で検索されます.例えば、not逆選択擬似クラスは、div:not(.a)のような単一の式のみをサポートし、div:not(.a.b)は使用できません.使用するには複数の逆選択が必要です.div:not(.a):not(.b).
IcarusはjQueryのカスタム擬似クラスをサポートしているが、位置擬似クラス(:first,:last,:even,:odd,:eq...)などの使用は提唱されていない.(last-child,:first-child,:nth-child(even)...)の代わりに、標準的なサブエレメントを使用して擬似クラスをフィルタリングすることができます.jQueryのカスタムフォーム擬似クラス(:text,:radio....)について、(input[type=text],input[type=radio]...)の代わりに属性セレクタを使用することもできます.とにかく、標準的でないものは長く生きられないので、覚えておいてほしい.
//dom.query v5 Icarus
(function(global,DOC){
var dom = global[DOC.URL.replace(/(#.+|\W)/g,'')];
dom.define("query", function(){
dom.mix(dom,{
//http://www.cnblogs.com/rubylouvre/archive/2010/03/14/1685360.
isXML : function(el){
var doc = el.ownerDocument || el
return doc.createElement("p").nodeName !== doc.createElement("P").nodeName;
},
//
contains:function(a, b){
if(a.compareDocumentPosition){
return !!(a.compareDocumentPosition(b) & 16);
}else if(a.contains){
return a !== b && (a.contains ? a.contains(b) : true);
}
while ((b = b.parentNode))
if (a === b) return true;
return false;
},
// , , childNodes ,
// , , innerText textContent
getText : function() {
return function getText( nodes ) {
for ( var i = 0, ret = "",node; node = nodes[i++]; ) {
// CDATA
if ( node.nodeType === 3 || node.nodeType === 4 ) {
ret += node.nodeValue;
//
} else if ( node.nodeType !== 8 ) {
ret += getText( node.childNodes );
}
}
return ret;
}
}(),
unique :function(nodes){
if(nodes.length < 2){
return nodes;
}
var result = [], array = [], uniqResult = {}, node = nodes[0],index, ri = 0
// sourceIndex
//http://www.cnblogs.com/jkisjk/archive/2011/01/28/array_quickly_sortby.html
if(node.sourceIndex){//IE opera
for(var i = 0 , n = nodes.length; i< n; i++){
node = nodes[i];
index = node.sourceIndex+1e8;
if(!uniqResult[index]){
(array[ri++] = new String(index))._ = node;
uniqResult[index] = 1
}
}
array.sort();
while( ri )
result[--ri] = array[ri]._;
return result;
}else {
var sortOrder = node.compareDocumentPosition ? sortOrder1 : sortOrder2;
nodes.sort( sortOrder );
if (sortOrder.hasDuplicate ) {
for ( i = 1; i < nodes.length; i++ ) {
if ( nodes[i] === nodes[ i - 1 ] ) {
nodes.splice( i--, 1 );
}
}
}
sortOrder.hasDuplicate = false;
return nodes;
}
}
});
var reg_combinator = /^\s*([>+~,\s])\s*(\*|(?:[-\w*]|[^\x00-\xa0]|\\.)*)/
var trimLeft = /^\s+/;
var trimRight = /\s+$/;
var reg_quick = /^(^|[#.])((?:[-\w]|[^\x00-\xa0]|\\.)+)$/;
var reg_comma = /^\s*,\s*/;
var reg_sequence = /^([#\.:]|\[\s*)((?:[-\w]|[^\x00-\xa0]|\\.)+)/;
var reg_pseudo = /^\(\s*("([^"]*)"|'([^']*)'|[^\(\)]*(\([^\(\)]*\))?)\s*\)/;
var reg_attrib = /^\s*(?:(\S?=)\s*(?:(['"])(.*?)\2|(#?(?:[\w\u00c0-\uFFFF\-]|\\.)*)|)|)\s*\]/
var reg_attrval = /\\([0-9a-fA-F]{2,2})/g;
var reg_sensitive = /^(title|id|name|class|for|href|src)$/
var reg_backslash = /\\/g;
var reg_tag = /^((?:[-\w\*]|[^\x00-\xa0]|\\.)+)/;// getElementsByTagName CSS
if ( trimLeft.test( "\xA0" ) ) {
trimLeft = /^[\s\xA0]+/;
trimRight = /[\s\xA0]+$/;
}
var hash_operator = {
"=": 1,
"!=": 2,
"|=": 3,
"~=": 4,
"^=": 5,
"$=": 6,
"*=": 7
}
function sortOrder1( a, b ) {
if ( a === b ) {
sortOrder1.hasDuplicate = true;
return 0;
}
if ( !a.compareDocumentPosition || !b.compareDocumentPosition ) {
return a.compareDocumentPosition ? -1 : 1;
}
return a.compareDocumentPosition(b) & 4 ? -1 : 1;
};
function sortOrder2( a, b ) {// XML
if ( a === b ) {
sortOrder2.hasDuplicate = true;
return 0;
}
var al, bl,
ap = [],
bp = [],
aup = a.parentNode,
bup = b.parentNode,
cur = aup;
// , childNodes
if ( aup === bup ) {
return siblingCheck( a, b );
// If no parents were found then the nodes are disconnected
} else if ( !aup ) {
return -1;
} else if ( !bup ) {
return 1;
}
// Otherwise they're somewhere else in the tree so we need
// to build up a full list of the parentNodes for comparison
while ( cur ) {
ap.unshift( cur );
cur = cur.parentNode;
}
cur = bup;
while ( cur ) {
bp.unshift( cur );
cur = cur.parentNode;
}
al = ap.length;
bl = bp.length;
// Start walking down the tree looking for a discrepancy
for ( var i = 0; i < al && i < bl; i++ ) {
if ( ap[i] !== bp[i] ) {
return siblingCheck( ap[i], bp[i] );
}
}
// We ended someplace up the tree so do a sibling check
return i === al ?
siblingCheck( a, bp[i], -1 ) :
siblingCheck( ap[i], b, 1 );
};
function siblingCheck( a, b, ret ) {
if ( a === b ) {
return ret;
}
var cur = a.nextSibling;
while ( cur ) {
if ( cur === b ) {
return -1;
}
cur = cur.nextSibling;
}
return 1;
};
var slice = Array.prototype.slice;
function makeArray( nodes, result, flag_multi ) {
nodes = slice.call( nodes, 0 );
if ( result ) {
result.push.apply( result, nodes );
}else{
result = nodes;
}
return flag_multi ? dom.unique(result) : result;
};
//IE56789
try {
slice.call( dom.html.childNodes, 0 )[0].nodeType;
} catch( e ) {
function makeArray( nodes, result ,flag_multi) {
var ret = result || [], ri = ret.length;
for(var i = 0,el ; el = nodes[i++];){
ret[ri++] = el
}
return flag_multi ? dom.unique(ret) : ret;
}
}
function _toHex(x, y) {
return String.fromCharCode(parseInt(y, 16));
}
function parse_nth(expr) {
var orig = expr
expr = expr.replace(/^\+|\s*/g, '');//
var match = (expr === "even" && "2n" || expr === "odd" && "2n+1" || !/\D/.test(expr) && "0n+" + expr || expr).match(/(-?)(\d*)n([-+]?\d*)/);
return parse_nth[ orig ] = {
a: (match[1] + (match[2] || 1)) - 0,
b: match[3] - 0
};
}
function getElementsByTagName(tagName, els, flag_xml) {
var method = "getElementsByTagName", elems = [], uniqResult = {}, prefix
if(flag_xml && tagName.indexOf(":") > 0 && els.length && els[0].lookupNamespaceURI){
var arr = tagName.split(":");
prefix = arr[0];
tagName = arr[1];
method = "getElementsByTagNameNS";
prefix = els[0].lookupNamespaceURI(prefix);
}
switch (els.length) {
case 0:
return elems;
case 1:
// IE67 , name length input , all.length ,
var all = prefix ? els[0][method](prefix,tagName) : els[0][method](tagName);
for(var i = 0, ri = 0, el; el = all[i++];){
if(el.nodeType === 1){//
elems[ri++] = el
}
}
return elems;
default:
for(i = 0, ri = 0; el = els[i++];){
var nodes = prefix ? el[method](prefix,tagName) : el[method](tagName)
for (var j = 0, node; node = nodes[j++];) {
var uid = dom.getUid(node);
if (!uniqResult[uid]) {
uniqResult[uid] = elems[ri++] = node;
}
}
}
return elems;
}
}
//IE9 XML
var attrURL = dom.oneObject('action,cite,codebase,data,href,longdesc,lowsrc,src,usemap', 2);
var bools = dom["@bools"] = "autofocus,autoplay,async,checked,controls,declare,disabled,defer,defaultChecked,"+
"contentEditable,ismap,loop,multiple,noshade,open,noresize,readOnly,selected"
var boolOne = dom.oneObject(bools.toLowerCase() );
var getHTMLText = new Function("els","return els[0]."+ (dom.html.textContent ? "textContent" : "innerText") );
// BUG(fixGetAttribute,fixHasAttribute,fixById,fixByTag)
var fixGetAttribute,fixHasAttribute,fixById,fixByTag;
new function(){
var select = DOC.createElement("select");
var option = select.appendChild( DOC.createElement("option") );
option.setAttribute("selected","selected")
option.className ="x"
fixGetAttribute = option.getAttribute("class") != "x";
select.appendChild( DOC.createComment("") );
fixByTag = select.getElementsByTagName("*").length == 2
var all = DOC.getElementsByTagName("*"), node, nodeType, comments = [], i = 0, j = 0;
while ( (node = all[i++]) ) {
nodeType = node.nodeType;
nodeType === 1 ? dom.getUid(node) :
nodeType === 8 ? comments.push(node) : 0;
}
while ( (node = comments[j++]) ) {
node.parentNode.removeChild(node);
}
fixHasAttribute = select.hasAttribute ? !option.hasAttribute('selected') :true;
var form = DOC.createElement("div"),
id = "fixId" + (new Date()).getTime(),
root = dom.html;
form.innerHTML = "<a name='" + id + "'/>";
root.insertBefore( form, root.firstChild );
fixById = !!DOC.getElementById( id ) ;
root.removeChild(form )
};
//http://www.atmarkit.co.jp/fxml/tanpatsu/24bohem/01.html
//http://msdn.microsoft.com/zh-CN/library/ms256086.aspx
//https://developer.mozilla.org/cn/DOM/document.evaluate
//http://d.hatena.ne.jp/javascripter/20080425/1209094795
function getElementsByXPath(xpath,context,doc) {
var result = [];
try{
if(global.DOMParser){//IE9 DOMParser, doc.evaluate!global.DOMParser
var nodes = doc.evaluate(xpath, context, null, 7, null);
for (var i = 0, n = nodes.snapshotLength; i < n; i++){
result[i] = nodes.snapshotItem(i)
}
}else{
nodes = context.selectNodes(xpath);
for (i = 0, n = nodes.length; i < n; i++){
result[i] = nodes[i]
}
}
}catch(e){
return false;
}
return result;
};
/**
*
* @param {String} expr CSS
* @param {Node} context ( )
* @param {Array} result ( )
* @param {Array} lastResult ( )
* @param {Boolean}flag_xml XML ( )
* @param {Boolean}flag_multi ( )
* @param {Boolean}flag_dirty ( )
* @return {Array} result
*/
//http://webbugtrack.blogspot.com/
var Icarus = dom.query = function(expr, contexts, result, lastResult, flag_xml,flag_multi,flag_dirty){
result = result || [];
contexts = contexts || DOC;
var pushResult = makeArray;
if(!contexts.nodeType){//
contexts = pushResult(contexts);
if(!contexts.length)
return result
}else{
contexts = [contexts];
}
var rrelative = reg_combinator,//
rquick = reg_quick,
rBackslash = reg_backslash, rcomma = reg_comma,//
context = contexts[0],
doc = context.ownerDocument || context,
rtag = reg_tag,
flag_all, uniqResult, elems, nodes, tagName, last, ri, uid;
//
//
expr = expr.replace(trimLeft, "").replace(trimRight, "");
flag_xml = flag_xml !== void 0 ? flag_xml : dom.isXML(doc);
if (!flag_xml && doc.querySelectorAll2) {
var query = expr;
if(contexts.length > 2 || doc.documentMode == 8 && context.nodeType == 1 ){
if(contexts.length > 2 )
context = doc;
query = ".fix_icarus_sqa "+query;//IE8
for(var i = 0, node; node = contexts[i++];){
if(node.nodeType === 1){
node.className = "fix_icarus_sqa " + node.className;
}
}
}
if(doc.documentMode !== 8 || context.nodeName.toLowerCase() !== "object"){
try{
return pushResult( context.querySelectorAll(query), result, flag_multi);
}catch(e){
}finally{
if(query.indexOf(".fix_icarus_sqa") === 0 ){// ,
for(i = 0; node = contexts[i++];){
if(node.nodeType === 1){
node.className = node.className.replace("fix_icarus_sqa ","");
}
}
}
}
}
}
var match = expr.match(rquick);
if(match ){// , ID
var value = match[2].replace(rBackslash,""), key = match[1];
if ( key == "") {//tagName;
nodes = getElementsByTagName(value,contexts,flag_xml);
} else if ( key === "." && contexts.length === 1 ) {//className, 1
if(flag_xml){// XPATH , ,
nodes = getElementsByXPath("//*[@class='"+value+"']", context, doc);
}else if(context.getElementsByClassName){
nodes = context.getElementsByClassName( value );
}
}else if ( key === "#" && contexts.length === 1){//ID, 1
if( flag_xml){
nodes = getElementsByXPath("//*[@id='"+value+"']", context, doc);
// document , DOM , dom("<div id=\"A'B~C.D[E]\"><p>foo</p></div>").find("p")
}else if(context.nodeType == 9){
node = doc.getElementById(value);
//IE67 opera ,object ID NAME
//http://webbugtrack.blogspot.com/2007/08/bug-152-getelementbyid-returns.html
nodes = !node ? [] : !fixById ? [node] : node.getAttributeNode("id").nodeValue === value ? [node] : false;
}
}
if(nodes ){
return pushResult( nodes, result, flag_multi );
}
}
//
lastResult = contexts;
if(lastResult.length){
loop:
while (expr && last !== expr) {
flag_dirty = false;
elems = null;
uniqResult = {};
// ( )
if (match = expr.match(rrelative)) {
expr = RegExp.rightContext;
elems = [];
tagName = (flag_xml ? match[2] : match[2].toUpperCase()).replace(rBackslash,"") || "*";
i = 0;
ri = 0;
flag_all = tagName === "*";// tagName
switch (match[1]) {// ,
case " "://
if(expr.length || match[2]){//
elems = getElementsByTagName(tagName, lastResult, flag_xml);
}else{
elems = lastResult;
break loop
}
break;
case ">"://
while((node = lastResult[i++])){
for (node = node.firstChild; node; node = node.nextSibling){
if (node.nodeType === 1 && (flag_all || tagName === node.nodeName)){
elems[ri++] = node;
}
}
}
break;
case "+"://
while((node = lastResult[i++])){
while((node = node.nextSibling)){
if (node.nodeType === 1) {
if (flag_all || tagName === node.nodeName)
elems[ri++] = node;
break;
}
}
}
break;
case "~"://
while((node = lastResult[i++])){
while((node = node.nextSibling)){
if (node.nodeType === 1 && (flag_all || tagName === node.nodeName)) {
uid = dom.getUid(node);
if (uniqResult[uid]){
break;
}else {
uniqResult[uid] = elems[ri++] = node;
}
}
}
}
elems = dom.unique(elems);
break;
}
}else if(match = expr.match(rtag)){//
expr = RegExp.rightContext;
elems = getElementsByTagName(match[1].replace(rBackslash,""), lastResult, flag_xml);
}
if(expr){
var arr = Icarus.filter(expr, elems, lastResult, doc, flag_xml);
expr = arr[0];
elems = arr[1];
if (!elems) {
flag_dirty = true;
elems = getElementsByTagName("*", lastResult, flag_xml);
}
if (match = expr.match(rcomma)) {
expr = RegExp.rightContext;
pushResult(elems, result);
return Icarus(expr, contexts, result, [], flag_xml, true, flag_dirty);
}else{
lastResult = elems;
}
}
}
}
if (flag_multi) {
if (elems.length){
return pushResult(elems, result,flag_multi);
}
}else if (DOC !== doc || fixByTag && flag_dirty) {
for (result = [], ri = 0, i = 0; node = elems[i++]; )
if (node.nodeType === 1)
result[ri++] = node;
return result
}
return elems;
}
var onePosition = dom.oneObject("eq|gt|lt|first|last|even|odd".split("|"));
dom.mix(Icarus, {
//getAttribute
//http://reference.sitepoint.com/javascript/Element/getAttribute
getAttribute : !fixGetAttribute ?
function(elem, name) {
return elem.getAttribute(name) || '';
} :
function(elem, name, flag_xml) {
if(flag_xml)
return elem.getAttribute(name) || '';
name = name.toLowerCase();
//http://jsfox.cn/blog/javascript/get-right-href-attribute.html
if(attrURL[name]){// href , 、
return elem.getAttribute(name, 2) || ''
}
if(elem.tagName === "INPUT" && name == "type"){
return elem.getAttribute("type") || elem.type;//IE67 HTML5 input , input[type=search], el.type el.getAttributeNode 。
}
// , true , , getAttributeNode
var attr = boolOne[name] ? (elem.getAttribute(name) ? name : '') :
(elem = elem.getAttributeNode(name)) && elem.value || '';
return reg_sensitive.test(name)? attr :attr.toLowerCase();
},
hasAttribute : !fixHasAttribute ?
function(elem, name, flag_xml) {
return flag_xml ? !!elem.getAttribute(name) :elem.hasAttribute(name);
} :
function(elem, name) {
//http://help.dottoro.com/ljnqsrfe.php
name = name.toLowerCase();
// "", outerHTML
elem = elem.getAttributeNode(name);
return !!(elem && (elem.specified || elem.nodeValue));
},
filter : function(expr, elems, lastResult, doc, flag_xml, flag_get){
var rsequence = reg_sequence,
rattrib = reg_attrib ,
rpseudo = reg_pseudo,
rBackslash = reg_backslash,
rattrval = reg_attrval,
pushResult = makeArray,
toHex = _toHex,
_hash_op = hash_operator,
parseNth = parse_nth,
match ,key, tmp;
while ( match = expr.match(rsequence)) {//
expr = RegExp.rightContext;
key = ( match[2]|| "").replace(rBackslash,"");
if (!elems) {//
if (lastResult.length === 1 && lastResult[0] === doc){
switch (match[1]) {
case "#":
if (!flag_xml) {//FF chrome opera XML getElementById,
tmp = doc.getElementById(key);
if (!tmp) {
elems = [];
continue;
}
// name "id" form
if (fixById ? tmp.id === key : tmp.getAttributeNode("id").nodeValue === key) {
elems = [tmp];
continue;
}
}
break;
case ":":
switch (key) {
case "root":
elems = [doc.documentElement];
continue;
case "link":
elems = pushResult(doc.links || []);
continue;
}
break;
}
}
elems = getElementsByTagName("*", lastResult, flag_xml);//
}
// ,
var filter = 0, flag_not = false, args;
switch (match[1]) {
case "#"://ID
filter = ["id", "=", key];
break;
case "."://
filter = ["class", "~=", key];
break;
case ":"://
tmp = Icarus.pseudoAdapter[key];
if (match = expr.match(rpseudo)) {
expr = RegExp.rightContext;
if(!!~key.indexOf("nth")){
args = parseNth[match[1]] || parseNth(match[1]);
}else{
args = match[3] || match[2] || match[1]
}
}
if (tmp){
filter = tmp;
}else if (key === "not") {
flag_not = true;
if (args === "*"){//
elems = [];
}else if(reg_tag.test(args)){//
tmp = [];
match = flag_xml ? args : args.toUpperCase();
for (var i = 0, ri = 0, elem; elem = elems[i++];)
if (match !== elem.nodeName)
tmp[ri++] = elem;
elems = tmp;
}else{
var obj = Icarus.filter(args, elems, lastResult, doc, flag_xml, true) ;
filter = obj.filter;
args = obj.args;
}
}
else{
throw 'An invalid or illegal string was specified : "'+ key+'"!'
}
break
default:
filter = [key.toLowerCase()];
if (match = expr.match(rattrib)) {
expr = RegExp.rightContext;
if (match[1]) {
filter[1] = match[1];//op
filter[2] = match[3] || match[4];//
filter[2] = filter[2] ? filter[2].replace(rattrval, toHex).replace(rBackslash,"") : "";
}
}
break;
}
if(flag_get){
return {
filter:filter,
args:args
}
}
// ,
if (elems.length && filter) {
tmp = [];
i = 0;
ri = 0;
if (typeof filter === "function") {//
if(onePosition[key]){
// args void , exp
args = args === void 0 ? elems.length - 1 : ~~args;
for (; elem = elems[i];){
if(filter(i++, args) ^ flag_not)
tmp[ri++] = elem;
}
}else{
while((elem = elems[i++])){
if ((!!filter(elem, args)) ^ flag_not)
tmp[ri++] = elem;
}
}
}else if (typeof filter.exec === "function"){//
tmp = filter.exec({
not: flag_not,
xml: flag_xml
}, elems, args, doc);
} else {
var name = filter[0], op = _hash_op[filter[1]], val = filter[2]||"", flag, attr;
if (!flag_xml && name === "class" && op === 4) {//
val = " " + val + " ";
while((elem = elems[i++])){
var className = elem.className;
if (!!(className && (" " + className + " ").indexOf(val) > -1) ^ flag_not){
tmp[ri++] = elem;
}
}
} else {
if(!flag_xml && op && val && !reg_sensitive.test(name)){
val = val.toLowerCase();
}
if (op === 4){
val = " " + val + " ";
}
while((elem = elems[i++])){
if(!op){
flag = Icarus.hasAttribute(elem,name,flag_xml);//[title]
}else if(val === "" && op > 3){
flag = false
}else{
attr = Icarus.getAttribute(elem,name,flag_xml);
switch (op) {
case 1:// =
flag = attr === val;
break;
case 2://!= ,
flag = attr !== val;
break;
case 3://|= “-” , ,
flag = attr === val || attr.substr(0, val.length + 1) === val + "-";
break;
case 4://~= , 。
flag = attr && (" " + attr + " ").indexOf(val) >= 0;
break;
case 5://^=
flag = attr && attr.indexOf(val) === 0 ;
break;
case 6://$=
flag = attr &&attr.substr(attr.length - val.length) === val;
break;
case 7://*=
flag = attr && attr.indexOf(val) >= 0;
break;
}
}
if (flag ^ flag_not)
tmp[ri++] = elem;
}
}
}
elems = tmp;
}
}
return [expr, elems];
}
});
//=================== =====================
var filterPseudoHasExp = function(strchild,strsibling, type){
return {
exec:function(flags,lastResult,args){
var result = [], flag_not = flags.not,child = strchild, sibling = strsibling,
ofType = type, cache = {},lock = {},a = args.a, b = args.b, i = 0, ri = 0, el, found ,diff,count;
if(!ofType && a === 1 && b === 0 ){
return flag_not ? [] : lastResult;
}
var checkName = ofType ? "nodeName" : "nodeType";
for (; el = lastResult[i++];) {
var parent = el.parentNode;
var pid = dom.getUid(parent);
if (!lock[pid]){
count = lock[pid] = 1;
var checkValue = ofType ? el.nodeName : 1;
for(var node = parent[child];node;node = node[sibling]){
if(node[checkName] === checkValue){
pid = dom.getUid(node);
cache[pid] = count++;
}
}
}
diff = cache[dom.getUid(el)] - b;
found = a === 0 ? diff === 0 : (diff % a === 0 && diff / a >= 0 );
(found ^ flag_not) && (result[ri++] = el);
}
return result;
}
};
};
function filterPseudoNoExp(name, isLast, isOnly) {
var A = "var result = [], flag_not = flags.not, node, el, tagName, i = 0, ri = 0, found = 0; for (; node = el = lastResult[i++];found = 0) {"
var B = "{0} while (!found && (node=node.{1})) { (node.{2} === {3}) && ++found; }";
var C = " node = el;while (!found && (node = node.previousSibling)) { node.{2} === {3} && ++found; }";
var D = "!found ^ flag_not && (result[ri++] = el); } return result";
var start = isLast ? "nextSibling" : "previousSibling";
var fills = {
type: [" tagName = el.nodeName;", start, "nodeName", "tagName"],
child: ["", start, "nodeType", "1"]
}
[name];
var body = A+B+(isOnly ? C: "")+D;
var fn = new Function("flags","lastResult",body.replace(/{(\d)}/g, function ($, $1) {
return fills[$1];
}));
return {
exec:fn
}
}
function filterProp(str_prop, flag) {
return {
exec: function (flags, elems) {
var result = [], prop = str_prop, flag_not = flag ? flags.not : !flags.not;
for (var i = 0,ri = 0, elem; elem = elems[i++];)
if ( elem[prop] ^ flag_not)
result[ri++] = elem;//&& ( !flag || elem.type !== "hidden" )
return result;
}
};
};
Icarus.pseudoAdapter = {
root: function (el) {//
return el === (el.ownerDocument || el.document).documentElement;
},
target: {//
exec: function (flags, elems,_,doc) {
var result = [], flag_not = flags.not;
var win = doc.defaultView || doc.parentWindow;
var hash = win.location.hash.slice(1);
for (var i = 0,ri = 0, elem; elem = elems[i++];)
if (((elem.id || elem.name) === hash) ^ flag_not)
result[ri++] = elem;
return result;
}
},
"first-child" : filterPseudoNoExp("child", false, false),
"last-child" : filterPseudoNoExp("child", true, false),
"only-child" : filterPseudoNoExp("child", true, true),
"first-of-type" : filterPseudoNoExp("type", false, false),
"last-of-type" : filterPseudoNoExp("type", true, false),
"only-of-type" : filterPseudoNoExp("type", true, true),//name, isLast, isOnly
"nth-child" : filterPseudoHasExp("firstChild", "nextSibling", false),//
"nth-last-child" : filterPseudoHasExp("lastChild", "previousSibling", false),//
"nth-of-type" : filterPseudoHasExp("firstChild", "nextSibling", true),//
"nth-last-of-type": filterPseudoHasExp("lastChild", "previousSibling", true),//
empty: {//
exec: function (flags, elems) {
var result = [], flag_not = flags.not, check
for (var i = 0, ri = 0, elem; elem = elems[i++];) {
if(elem.nodeType == 1){
if (!elem.firstChild ^ flag_not)
result[ri++] = elem;
}
}
return result;
}
},
link: {//
exec: function (flags, elems) {
var links = (elems[0].ownerDocument || elems[0].document).links;
if (!links) return [];
var result = [],
checked = {},
flag_not = flags.not;
for (var i = 0, ri = 0,elem; elem = links[i++];)
checked[dom.getUid(elem) ] = 1;
for (i = 0; elem = elems[i++]; )
if (checked[dom.getUid(elem)] ^ flag_not)
result[ri++] = elem;
return result;
}
},
lang: {// CSS2
exec: function (flags, elems, arg) {
var result = [], reg = new RegExp("^" + arg, "i"), flag_not = flags.not;
for (var i = 0, ri = 0, elem; elem = elems[i++]; ){
var tmp = elem;
while (tmp && !tmp.getAttribute("lang"))
tmp = tmp.parentNode;
tmp = !!(tmp && reg.test(tmp.getAttribute("lang")));
if (tmp ^ flag_not)
result[ri++] = elem;
}
return result;
}
},
active: function(el){
return el === el.ownerDocument.activeElement;
},
focus:function(el){
return (el.type|| el.href) && el === el.ownerDocument.activeElement;
},
indeterminate : function(node){//
return node.indeterminate === true && node.type === "checkbox"
},
//http://www.w3.org/TR/css3-selectors/#UIstates
enabled: filterProp("disabled", false),//
disabled: filterProp("disabled", true),//
checked: filterProp("checked", true),//
contains: {
exec: function (flags, elems, arg) {
var res = [], elem = elems[0], fn = flags.xml ? dom.getText: getHTMLText,
flag_not = flags.not;
for (var i = 0, ri = 0, elem; elem = elems[i++]; ){
if ((!!~fn( [elem] ).indexOf(arg)) ^ flag_not)
res[ri++] = elem;
}
return res;
}
},
//
selected : function(el){
el.parentNode.selectedIndex;// safari bug
return el.selected === true;
},
header : function(el){
return /h\d/i.test( el.nodeName );
},
button : function(el){
return "button" === el.type || el.nodeName === "BUTTON";
},
input: function(el){
return /input|select|textarea|button/i.test(el.nodeName);
},
parent : function( el ) {
return !!el.firstChild;
},
has : function(el, expr){// expr
return !!dom.query(expr,[el]).length;
},
//
first: function(index){
return index === 0;
},
last: function(index, num){
return index === num;
},
even: function(index){
return index % 2 === 0;
},
odd: function(index){
return index % 2 === 1;
},
lt: function(index, num){
return index < num;
},
gt: function(index, num){
return index > num;
},
eq: function(index, num){
return index === num;
},
hidden : function( el ) {
return el.type === "hidden" || (!el.offsetWidth && !el.offsetHeight) || (el.currentStyle && el.currentStyle.display === "none") ;
}
}
Icarus.pseudoAdapter.visible = function(el){
return !Icarus.pseudoAdapter.hidden(el);
}
"text,radio,checkbox,file,password,submit,image,reset".replace(dom.rword, function(name){
Icarus.pseudoAdapter[name] = function(el){
return (el.getAttribute("type") || el.type) === name;// HTML5 BUG, el.type === name;
}
});
});
})(this,this.document);
//2011.10.25 dom.unique
//2011.10.26 name id , labed ,
//2011.10.30 , ‘input[name=brackets\\[5\\]\\[\\]]’
//2011.10.31 , hasAttribute , checked, selected, disabled
//2011.10.31 , switch
//2011.11.1 filterPseudoHasExp filterPseudoNoExp
//2011.11.2 FIX -of-type BUG
//2011.11.3 getAttribute hasAttribute API
//2011.11.4
//2011.11.5 getElementsByXpath XML
//2011.11.6 getElementsByTagName tagName
//2011.11.6 IE67 opera9 getElementById BUG
//2011.11.7 , IE678 , querySelectorAll
//2011.11.8 nth-child BUG, IE67 getAttribute input[type=search] , sortOrder
// swich...case , reg_sequence "[ " , , default
// $= , attr.indexOf(val) == attr.length - val.length, "PWD".indexOf("bar]") true
//2011.11.9 getText getElementById ID
//2011.11.10 exec match, parseNth
以下はIcarusのネーミングスペースのサポートプレゼンテーションです.例はinline SVGです.IE 9はサポートされていませんので、高バージョンの標準ブラウザで見てください.IE 10がSVGをサポートすると、SVGのアプリケーションが大幅に増加するため、ネーミングスペースのサポートが必要になります.
<html xmlns="http://www.w3.org/1999/xhtml" xmlns:svg="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<head>
<title>icarus svg by </title>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<script src="http://files.cnblogs.com/rubylouvre/icarus.js"></script>
<script>
window.onload = function(){
alert(dom.query("svg\\:feOffset:first")[0].tagName)
}
</script>
</head>
<body>
<svg:svg height="0">
<!-- Create the filter. Make sure it uses the sRGB colorspace or you're in for some nasty surprises. -->
<svg:filter color-interpolation-filters="sRGB" id="perspDisp" filterUnits="userSpaceOnUse" x="0%" y="0%" width="512" height="512" >
<!-- Move the video 128px to the bottom/right so that the displacement filter can reach 128px to the top/left without reaching beyond the image -->
<svg:feOffset
x="128" y="128" width="256" height="256"
dx="128" dy="128"
result="displacement"
/>
<!-- This actually loads our texture-->
<svg:feImage
id="textureLoader"
x="0" y="0" width="256" height="256"
xlink:href="texture.tinman.png"
/>
<!-- Tile the texture to fill the whole viewport so that the displacement filter can also reach 128px to the bottom/right without leaving the texture -->
<svg:feTile
x="0" y="0" width="512" height="512"
result="texture"
/>
<!-- Apply the displacement -->
<svg:feDisplacementMap
x="128" y="128" width="256" height="256"
in="texture" in2="displacement"
scale="255"
xChannelSelector="R" yChannelSelector="G"
/>
<!-- Apply the alpha of the displacement map to the final image, so that whatever is transparent in the map is also transparent in the final image -->
<svg:feComposite
in2="displacement"
operator="in"
/>
<!-- Move the image back to the top/left -->
<svg:feOffset
x="0" y="0" width="256" height="256"
dx="-128" dy="-128"
/>
</svg:filter>
</svg:svg>
</body>
</html>
window.onload = function(){
alert(dom.query("svg\\:feOffset:first")[0].tagName)
}
dx="128"dy="128"
result="displacement"
/>
x="0"y="0"width="256"height="256"
xlink:href="texture.tinman.png"
/>
result="texture"
/>
in="texture" in2="displacement"
scale="255"
xChannelSelector="R"yChannelSelector="G"
/>
operator="in"
/>
dx="-128"dy="-128"
/>
実行コード
後にjavascriptのセレクタは基本的にIE 678(IE 8のquerySelectoAllサポートの種類が少なすぎる)と互換性があるため、以降のセレクタは基本的にquerySelectorAllとevaluateとmatchesSelectorで書かれており、CSS 4もすぐに到来し、より多くの擬似クラスをもたらすため、jQueryのカスタム擬似クラスはほとんど存在しない必要がある.
関連リンク:
第1世代セレクタ
第2世代セレクタ
第3世代セレクタ
第4世代セレクタ
スピード?ゲーム