2 * Original code by ofk ( kQuery, ksk )
\r
3 * http://d.hatena.ne.jp/ofk/comment/20090106/1231258010
\r
4 * http://d.hatena.ne.jp/ofk/20090111/1231668170
\r
7 * http://standards.mitsue.co.jp/resources/w3c/TR/css3-selectors/#nth-child-pseudo
\r
11 X_Node_Selector__PSEUDO = {
\r
13 'nth-last-child' : 14,
\r
15 'nth-last-of-type' : 16,
\r
29 'last-of-type' : 12,
\r
30 'only-of-type' : 12,
\r
31 'first-of-type' : 13
\r
34 X_Node_Selector__COMBINATOR = {
\r
38 '+' : 3, // 兄弟セレクタ,共通の親を持つ、1番目要素が2番目要素の1つ前にある
\r
39 '~' : 4, // 一般兄弟セレクタ,共通の親を持つ、1番目要素が2番目要素の前 (直前でなくともよい) にある
\r
41 '@' : 6 // XML 用の拡張、属性ノードを辿る http://www.marguerite.jp/Nihongo/WWW/RefDOM/_Attr_interface.html
\r
43 X_Node_Selector__SELECTOR = {
\r
55 X_Node_Selector__OPERATORS = { '==' : 1, '!=': 2, '~=': 3, '^=': 4, '$=': 5, '*=': 6, '|=': 7 }, // '':0 は属性が存在するならtrue
\r
56 // TODO { a : 1, A : 2, _ : 3,,, }
\r
57 X_Node_Selector__ALPHABET = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ_-0123456789\\',
\r
58 X_Node_Selector__NUMBER = '+-0123456789';
\r
61 * セレクタ文字列の解析、但し一挙に行わず、ひと塊づつ
\r
62 * 結合子 + 単体セレクタ( タグ,*,#,.,[],: )
\r
63 * ' ' 子孫セレクタ, '>' 直下,'+','~' の場合、tagName|* を返す
\r
64 * return [ 今回のパースで解析した終端位置, [ selector, ... ] ] error: return pointer
\r
66 function X_Node_Selector__parse( query, last ){
\r
67 var COMBINATOR = X_Node_Selector__COMBINATOR,
\r
68 SELECTOR = X_Node_Selector__SELECTOR,
\r
69 OPERATORS = X_Node_Selector__OPERATORS,
\r
70 ALPHABET = X_Node_Selector__ALPHABET,
\r
71 NUMBER = X_Node_Selector__NUMBER,
\r
78 chr, chrCode, nameChr, name1st,
\r
79 tmp, escape, quot, start,
\r
80 name, key, value, operator, a, b, not;
\r
84 chr = query.charAt( ++i );
\r
85 chrCode = ALPHABET.indexOf( chr ); // TODO この関数無くす!
\r
86 nameChr = chrCode !== -1;
\r
87 name1st = nameChr && chrCode < 52;
\r
90 name1st ? // tagName
\r
91 ( ( selector = 1 ) && ( phase = 0x2 ) && ( start = i ) ) :
\r
92 !not && ( tmp = COMBINATOR[ chr ] ) ? (
\r
93 ( 1 < tmp && 1 < combinator ) ?
\r
95 ( phase = tmp === 5 ? 0xe : 0x0 ) & ( ( 1 < tmp || combinator < 1 ) && ( combinator = tmp ) ) & ( tmp === 5 && ++i ) ) : // ' ' でない結合子の上書きはエラー
\r
96 ( tmp = SELECTOR[ chr ] ) ? // [
\r
97 ( selector = tmp ) && ( phase = selector === 5 ? 0x4 : 0x1 ) : // 7:[, 0<:
\r
99 ( ( selector = 1 ) && ( name = chr ) && ( phase = 0xe ) && ++i ) :
\r
100 chr !== ' ' && ( phase = 0xf );
\r
101 //console.log( '0x0: ' + name1st + ' ' + chrCode + ' ' + chr + ' ' + phase + ' tmp:' + tmp + ' comb:' + combinator );
\r
105 ( ( start = i ) && ( phase = 0x2 ) ) :
\r
106 chr !== ' ' && ( phase = 0xf );
\r
109 !nameChr && !( escape && ( selector === 2 || selector === 3 ) && ( chr === ':' || chr === '.' ) ) ? // id or class の場合 : . を直前にエスケープした場合に限り使える
\r
110 ( name = query.substring( start, i ) ) && ( phase = selector === 4 && name !== 'not' && chr === '(' ? ( name !== 'lang' && name !== 'contains' ? 0x8 : 0xb ) : 0xe ) :
\r
111 SELECTOR[ chr ] < 4 && ( phase = 0xe );
\r
117 case 0x4 : // start attr filter
\r
119 ( ( phase = 0x5 ) && ( start = i ) ) :
\r
123 case 0x5 : // attr filter key
\r
125 ( ( operator = 1 ) && ( phase = 0x6 ) && ( key || ( key = query.substring( start, i ) ) ) && ( start = i + 1 ) ) :
\r
127 ( !( operator = 0 ) && ( phase = 0xe ) && ( key || ( key = query.substring( start, i ) ) ) && ++i ) :
\r
129 ( key || ( key = query.substring( start, i ) ) ) :
\r
130 ( operator = OPERATORS[ query.substr( i, 2 ) ] ) ?
\r
131 ( ( phase = 0x6 ) && ( key || ( key = query.substring( start, i ) ) ) && ( start = ++i ) ) :
\r
132 !nameChr && ( phase = 0xf );
\r
133 //console.log( name1st + ' ' + chrCode + chr + phase );
\r
136 ( chr === '"' || chr === "'" ) && !escape && !quot ?
\r
137 ( quot = chr ) && ( start = i + 1 ) && ( phase = 0x7 ) :
\r
138 chr !== ' ' && ( start = i ) && ( phase = 0x7 );
\r
141 case 0x7 : // attr filter value
\r
143 !escape && !value && ( value = query.substring( start, i ) ) :
\r
145 ( ( value || ( value = query.substring( start, i ) ) ) && ( phase = 0xe ) && ++i ) :
\r
146 chr === ' ' && !quot && !value && ( value = query.substring( start, i ) );
\r
147 //( chr === '"' || chr === "'" ) && !quot && ( quot = chr ) && ( start = i + 1 );
\r
150 case 0x8 : // 4, 2n, even, odd, -n+4,
\r
151 NUMBER.indexOf( chr ) !== -1 ?
\r
152 ( start = i ) && ( phase = 0x9 ) :
\r
154 ( phase = 0xa ) && ( a = 1 ) && ( start = i + 1 ) :
\r
155 query.substr( i, 4 ) === 'even' ?
\r
156 ( ( a = 2 ) && !( b = 0 ) && ( i += 3 ) ) :
\r
157 query.substr( i, 3 ) === 'odd' ?
\r
158 ( ( a = 2 ) && ( b = 1 ) && ( i += 2 ) ) :
\r
159 chr === ')' && ( phase = a ? 0xe : 0xf ) && ++i;
\r
160 //console.log( '0x8: ' + name1st + ' ' + chrCode + ' ' + chr + ' ' + phase + ' ' + name );
\r
163 tmp = query.substring( start, i );
\r
165 ( phase = 0xa ) && ( start = i + 1 ) && ( a = tmp === '+' ? 1 : tmp === '-' ? -1 : parseFloat( tmp ) ) :
\r
166 chr === ')' && ( phase = 0xe ) && ++i && ( b = parseFloat( tmp ) ) && ( a = 0 );
\r
167 //console.log( '0x9: ' + name1st + ' ' + chrCode + ' ' + chr + ' ' + phase );
\r
170 chr === ')' && ( phase = 0xe ) && ++i && ( b = parseFloat( query.substring( start, i ) ) || 0 );
\r
171 //console.log( '0xa: ' + start + ' ' + i );
\r
175 ( chr === '"' || chr === "'" ) && !escape && !quot &&
\r
176 ( quot = chr ) && ( start = i + 1 ) && ( phase = 0xc );
\r
179 chr === quot && !escape && ( value = query.substring( start, i ) ) && ( phase = 0xd );
\r
182 chr === ')' && ( phase = 0xe ) && ++i;
\r
187 if( phase === 0xf ) return i;
\r
189 //alert( chr + ' ' + phase + ' ' + selector + ' ' + name + ' ' + name1st )
\r
190 if( phase === 0xe ){
\r
191 if( selector === 4 ){// :not
\r
192 if( name === 'not' ){
\r
203 if( name === 'lang' || name === 'contains' ){
\r
204 result = [ not ? 0 : combinator, selector, name, value ];
\r
207 if( a !== a || b !== b ) return i;
\r
208 result = [ not ? 0 : combinator, SELECTOR[ name ] || selector, name, a, b ];
\r
216 [ not ? 0 : combinator, selector, key, operator, value ] :
\r
217 [ not ? 0 : combinator, selector, name.split( '\\' ).join( '' ) ];
\r
222 escape = chr === '\\' && !escape;
\r
224 //if( phase !== 0xe ) return i;
\r
225 if( not && ( tmp = query.substr( i ).indexOf( ')' ) ) === -1 ) return i;
\r
226 return not ? [ i + tmp + 1, [ combinator, 6, result ] ] : [ i, result ];
\r
230 * selector を使って Node, NodeList を取得する
\r
231 * @alias X.Doc.find
\r
233 * @param {string} セレクター文字列
\r
234 * @return {Node|NodeList}
\r
236 X[ 'Doc' ][ 'find' ] = X_shortcutFunction =
\r
239 * selector を使って Node, NodeList を取得する
\r
240 * @alias NodeList.prototype.find
\r
242 * @param {string} セレクター文字列
\r
243 * @return {Node|NodeList}
\r
245 X_NodeList.prototype[ 'find' ] = X_Node_find;
\r
248 * selector を使って Node, NodeList を取得する
\r
249 * @alias Node.prototype.find
\r
251 * @param {string} セレクター文字列
\r
252 * @return {Node|NodeList}
\r
254 function X_Node_find( queryString ){
\r
255 var HTML = X_Node_html,
\r
256 scope = this.constructor === X_NodeList && this.length ? this : [ this.constructor === Node || this[ 'instanceOf' ] && this[ 'instanceOf' ]( Node ) ? this : X_Node_body ],
\r
257 parents = scope, // 探索元の親要素 XNodeList の場合あり
\r
258 // TODO { title : true,,, }
\r
259 noLower = 'title id name class for action archive background cite classid codebase data href longdesc profile src usemap',// + X_Dom_DTD_ATTR_VAL_IS_URI.join( ' ' ),
\r
260 ARY_PUSH = Array.prototype.push,
\r
262 root = X_Node_getRoot( scope[ 0 ] ),
\r
263 isXML = !!X_Node_isXmlDocument( root ),
\r
264 isMulti = 1 < scope.length,// 要素をマージする必要がある
\r
267 isAll, isNot, hasRoot,
\r
270 merge, // 要素がコメントノードで汚染されている場合使う
\r
271 parent, children, j, m,
\r
272 combinator, selector, name, tagName,
\r
273 uid, tmp, xnode, filter, key, op, val, toLower, useName,
\r
274 links, className, attr, flag;
\r
277 if( X_ViewPort_readyState < X_EVENT_XDOM_READY ){
\r
278 alert( 'not ready! use X.ViewPort.listenOnce( X_EVENT_XDOM_READY, callback )' );
\r
284 if( !X_Type_isString( queryString ) ) return ret;
\r
289 for( ; queryString.length; ){
\r
290 //console.log( 'queryString[' + queryString + ']' );
\r
294 parsed = X_Node_Selector__parse( queryString );
\r
296 if( X_Type_isNumber( parsed ) ){
\r
301 queryString = queryString.substr( parsed[ 0 ] );
\r
302 parsed = parsed[ 1 ];
\r
304 //console.log( 'X_Node_Selector__parse ' + parsed );
\r
306 if( parsed === 5 ){
\r
309 xnodes && xnodes.length && ARY_PUSH.apply( ret, xnodes );
\r
317 combinator = parsed[ 0 ];
\r
318 selector = parsed[ 1 ];
\r
319 name = parsed[ 2 ];
\r
320 tagName = selector === 1 ? ( isXML ? name : name.toUpperCase() ) : '*';
\r
321 isAll = tagName === '*';
\r
324 if( !xnodes.length ){
\r
328 if( combinator !== 0 ){
\r
331 //console.log( 'cobinator !== 0 ' + parents.length + ' : ' + xnodes.length );
\r
336 l = parents.length;
\r
338 isMulti = isMulti || 1 < l;
\r
340 //console.log( 'combinator ' + combinator );
\r
342 switch( combinator ){
\r
345 for( ; i < l; ++i ){
\r
346 parent = parents[ i ];
\r
347 if( ( children = parent[ '_xnodes' ] ) && ( m = children.length ) ){
\r
348 for( j = 0; j < m; ++j ){
\r
349 xnode = children[ j ];
\r
350 if( xnode[ '_tag' ] && ( isAll || tagName === xnode[ '_tag' ] ) ) xnodes[ ++n ] = xnode;
\r
357 for( ; i < l; ++i ){
\r
359 xnode = parents[ i ];
\r
360 j = xnode[ 'getOrder' ]() + 1;
\r
361 parent = xnode.parent;
\r
362 if( parent && ( children = parent[ '_xnodes' ] ) && ( m = children.length ) ){
\r
363 for( ; j < m; ++j ){
\r
364 xnode = children[ j ];
\r
365 if( xnode[ '_tag' ] ){
\r
366 if( isAll || tagName === xnode[ '_tag' ] ){
\r
367 xnodes[ ++n ] = xnode;
\r
374 for( xnode = parents[ i ][ 'next' ](); xnode; xnode = xnode[ 'next' ]() ){
\r
375 if( xnode[ '_tag' ] ){
\r
376 if( isAll || tagName === xnode[ '_tag' ] ) xnodes[ ++n ] = xnode;
\r
385 for( ; i < l; ++i ){
\r
386 for( xnode = parents[ i ][ 'next' ](); xnode; xnode = xnode[ 'next' ]() ){
\r
387 if( xnode[ '_tag' ] && ( isAll || tagName === xnode[ '_tag' ] ) ){
\r
388 uid = xnode[ '_uid' ];
\r
389 if( merge[ uid ] ){
\r
392 merge[ uid ] = true;
\r
393 xnodes[ ++n ] = xnode;
\r
400 // case 6 : 属性ノードは実装しない
\r
403 if( combinator === 1 || ( isStart && selector < 7 ) ){
\r
405 if( tagName === 'HTML' ){
\r
406 xnodes[ 0 ] = X_Node_html;
\r
409 if( tagName === 'HEAD' ){
\r
410 xnodes[ 0 ] = X_Node_head;
\r
413 if( tagName === 'BODY' ){
\r
414 xnodes[ 0 ] = X_Node_body;
\r
419 //console.log( l + ' > ' + xnodes.length + ' tag:' + tagName );
\r
421 X_Node_Selector__fetchElements( xnodes, parents, isAll ? '' : tagName, merge );
\r
422 //console.log( l + ' >> ' + xnodes.length + ' tag:' + tagName );
\r
428 //alert( 'pre-selector:' + ( xnodes && xnodes.length ) )
\r
430 switch( selector ){
\r
433 filter = [ 'id', 1, name ]; break;
\r
436 filter = [ 'class', 3 /*'~='*/, name ]; break;
\r
439 if( !( filter = X_Node_Selector__filter[ name ] ) ){
\r
445 filter = [ name, parsed[ 3 ], parsed[ 4 ] ]; break;
\r
449 parsed = parsed[ 2 ];
\r
450 name = parsed[ 2 ];
\r
451 switch( parsed[ 1 ] ) {
\r
453 filter = [ 'tag', 1, isXML ? name : name.toUpperCase() ]; break;
\r
456 filter = [ 'id', 1, name ]; break;
\r
459 filter = [ 'class', 3, name ]; break;
\r
462 if( !( filter = X_Node_Selector__filter[ name ] ) ){
\r
468 filter = [ name, parsed[ 3 ], parsed[ 4 ] ]; break;
\r
473 xnodes = scope; break;
\r
477 xnodes = [ HTML ]; break;
\r
480 if( links = document.links ){
\r
481 for( xnodes = [], i = links.length; i; ){
\r
482 xnodes[ --i ] = Node( links[ i ] );
\r
485 // area[href],a[href]
\r
489 if( filter && xnodes.length ){
\r
498 parsed[ 3 ], parsed[ 4 ]
\r
502 if( X_Type_isFunction( filter ) ){
\r
504 for( i = 0, n = -1; xnode = xnodes[ i ]; ++i ){
\r
505 if( ( !!filter( xnode ) ) ^ isNot ) tmp[ ++n ] = xnode;
\r
515 key = X_Node_Attr_renameForTag[ key ] || key;
\r
518 if( !isXML && key === 'class' && op === 3 ){
\r
520 for( i = 0, n = -1; xnode = xnodes[ i ]; ++i ){
\r
521 className = xnode[ '_className' ];
\r
522 if( !!( className && ( _ + className + _ ).indexOf( val ) > -1 ) ^ isNot ) tmp[ ++n ] = xnode;
\r
527 // flag_call = ($.browser.safari && key === 'selected');
\r
528 // getAttributeを使わない
\r
529 useName = X_UA[ 'IE' ] && key !== 'href' && key !== 'src';
\r
530 toLower = !!val && !isXML && noLower.indexOf( key ) === -1; //!noLower.test(key);
\r
531 if( toLower ) val = val.toLowerCase();
\r
532 if( op === 3 ) val = _ + val + _;
\r
534 for( i = 0, n = -1, l = xnodes.length; i < l; ++i ){
\r
535 xnode = xnodes[ i ];
\r
537 key === 'tag' ? xnode[ '_tag' ] :
\r
538 key === 'id' ? xnode[ '_id' ] :
\r
539 key === 'class' ? xnode[ '_className' ] :
\r
540 xnode[ '_attrs' ] && xnode[ '_attrs' ][ key ];
\r
542 // funcAttr( elem, key ) :
\r
544 // elem[ X_Node_Attr_renameForDOM[ key ] || key ] :
\r
545 // elem.getAttribute( key, 2 );
\r
546 flag = !!attr;// && ( !useName || attr !== '' );
\r
548 if( toLower ) attr = attr.toLowerCase();
\r
552 flag = attr === val;
\r
555 flag = attr !== val;
\r
558 flag = ( _ + attr + _ ).indexOf( val ) !== -1;
\r
561 flag = attr.indexOf( val ) === 0;
\r
564 flag = attr.lastIndexOf( val ) + val.length === attr.length;
\r
567 flag = attr.indexOf( val ) !== -1;
\r
570 flag = attr === val || attr.substring( 0, val.length + 1 ) === val + '-';
\r
574 if( !!flag ^ isNot ) tmp[ ++n ] = xnode;
\r
584 //console.log( '//end :' + ( xnodes && xnodes.length ) );
\r
586 //console.log( 'multi:' + ( xnodes && xnodes.length ) );
\r
588 // tree 順に並び替え、同一要素の排除
\r
590 xnodes && xnodes.length && ARY_PUSH.apply( ret, xnodes );
\r
592 if( l < 2 ) return ret[ 0 ] || X_Node_none;
\r
596 for( i = 0, n = -1; i < l; ++i ){
\r
597 //alert( 'multi:' + i )
\r
599 if( !merge[ uid = xnode[ '_uid' ] ] ){
\r
600 merge[ uid ] = true;
\r
601 xnodes[ ++n ] = xnode;
\r
604 xnodes = X_Node_Selector__sortElementOrder( [], xnodes, hasRoot ? [ HTML ] : HTML[ '_xnodes' ] );
\r
607 return xnodes.length === 1 ? xnodes[ 0 ] : new X_NodeList( xnodes );
\r
610 function X_Node_Selector__sortElementOrder( newList, list, xnodes ){
\r
611 var l = xnodes.length,
\r
615 for( ; i < l; ++i ){
\r
616 child = xnodes[ i ];
\r
617 if( !child[ '_tag' ] ) continue;
\r
619 j = list.indexOf( child );
\r
621 newList[ newList.length ] = child;
\r
622 if( list.length === 2 ){
\r
623 newList[ newList.length ] = list[ j === 0 ? 1 : 0 ];
\r
626 list.splice( j, 1 );
\r
629 if( ( _xnodes = child[ '_xnodes' ] ) && X_Node_Selector__sortElementOrder( newList, list, _xnodes ) ){
\r
635 function X_Node_Selector__fetchElements( list, xnodes, tag, merge ){
\r
636 var l = xnodes.length,
\r
638 child, uid, _tag, _xnodes;
\r
640 for( ; i < l; ++i ){ // for( ; child = xnodes[ ++i ]; )
\r
641 child = xnodes[ i ];
\r
642 uid = child[ '_uid' ];
\r
643 _tag = child[ '_tag' ];
\r
644 if( !merge[ uid ] && _tag ){
\r
645 merge[ uid ] = true;
\r
646 ( !tag || tag === _tag ) && ( list[ list.length ] = child );
\r
647 if( ( _xnodes = child[ '_xnodes' ] ) && ( 1 < _xnodes.length || ( _xnodes[ 0 ] && _xnodes[ 0 ][ '_tag' ] ) ) ){
\r
648 X_Node_Selector__fetchElements( list, _xnodes, tag, merge );
\r
654 function X_Node_Selector__fetchElements( list, parent, tag, merge ){
\r
656 var xnodes = parent[ '_xnodes' ],
\r
662 memories = [ memory ],
\r
666 while( memories.length ){
\r
667 memory = memories.pop();
\r
668 xnodes = memory.xnodes;
\r
671 for( ; i < l; ++i ){
\r
672 xnode = xnodes[ i ];
\r
673 uid = xnode[ '_uid' ];
\r
674 if( !merge[ uid ] && xnode[ '_tag' ] ){
\r
675 if( !tag || xnode[ '_tag' ] === tag ) list[ list.length ] = xnode;
\r
677 if( _xnodes = xnode[ '_xnodes' ] ){
\r
678 if( 1 < _xnodes.length || ( _xnodes[ 0 ] && _xnodes[ 0 ][ '_tag' ] ) ){
\r
681 memory.xnodes = xnodes;
\r
682 memories[ memories.length ] = memory;
\r
683 memories[ memories.length ] = {
\r
685 l : _xnodes.length,
\r
688 merge[ uid ] = true;
\r
693 merge[ uid ] = true;
\r
698 function X_Node_Selector__funcSelectorChild( type, flag_all, flags, xnodes ){
\r
700 flag_not = flags.not,
\r
701 i = 0, n = -1, xnode, node,
\r
703 for( ; xnode = xnodes[ i ]; ++i ){
\r
704 tagName = flag_all || xnode[ '_tag' ];
\r
706 if( /* tmp === null && */ type <= 0 ){
\r
707 for( node = xnode[ 'prev' ](); node; node = node[ 'prev' ]() ){
\r
708 if( node[ '_tag' ] && ( flag_all || tagName === node[ '_tag' ] ) ){
\r
714 if( tmp === null && 0 <= type ){
\r
715 for( node = xnode[ 'next' ](); node; node = node[ 'next' ]() ){
\r
716 if( node[ '_tag' ] && ( flag_all || tagName === node[ '_tag' ] ) ){
\r
722 if( tmp === null ) tmp = true;
\r
723 if( tmp ^ flag_not ) res[ ++n ] = xnode;
\r
727 function X_Node_Selector__funcSelectorNth( pointer, sibling, flag_all, flags, xnodes, a, b ){
\r
730 flag_not = flags.not,
\r
731 i = 0, n = -1, uid,
\r
732 c, xnode, tmp, node, tagName;
\r
733 for( ; xnode = xnodes[ i ]; ++i ){
\r
734 uid = xnode[ '_uid' ];
\r
735 tmp = checked[ uid ];
\r
736 if( tmp === void 0 ){
\r
737 for( c = 0, node = xnode.parent[ pointer ](), tagName = flag_all || xnode[ '_tag' ]; node; node = node[ sibling ]() ){
\r
738 if( node[ '_tag' ] && ( flag_all || tagName === node[ '_tag' ] ) ){
\r
740 checked[ node[ '_uid' ] ] = a === 0 ? c === b : (c - b) % a === 0 && (c - b) / a >= 0;
\r
743 tmp = checked[ uid ];
\r
745 if( tmp ^ flag_not ) res[ ++n ] = xnode;
\r
749 function X_Node_Selector__funcSelectorProp( prop, flag, flags, xnodes ){
\r
751 flag_not = flag ? flags.not : !flags.not,
\r
752 i = 0, n = -1, xnode;
\r
753 for( ; xnode = xnodes[ i ]; ++i ){
\r
754 if( xnode[ '_attrs' ] && xnode[ '_attrs' ][ prop ] ^ flag_not ) res[ ++n ] = xnode;
\r
759 var X_Node_Selector__filter = {
\r
760 'root' : function(){
\r
761 return X_Node_html;
\r
764 m : function( flags, xnodes ){
\r
766 hash = location.hash.slice( 1 ),
\r
767 flag_not = flags.not,
\r
768 i = 0, n = -1, xnode;
\r
769 for ( ; xnode = xnodes[ i ]; ++i ){
\r
770 if( ( ( xnode[ '_id' ] || xnode[ '_attrs' ] && xnode[ '_attrs' ][ 'name' ] ) === hash ) ^ flag_not ) res[ ++n ] = xnode;
\r
776 m : function( flags, xnodes ){ return X_Node_Selector__funcSelectorChild( -1, true, flags, xnodes ); }
\r
779 m : function( flags, xnodes ){ return X_Node_Selector__funcSelectorChild( 1, true, flags, xnodes ); }
\r
782 m : function( flags, xnodes ){ return X_Node_Selector__funcSelectorChild( 0, true, flags, xnodes ); }
\r
784 'first-of-type' : {
\r
785 m : function( flags, xnodes ){ return X_Node_Selector__funcSelectorChild( -1, false, flags, xnodes ); }
\r
788 m : function( flags, xnodes ){ return X_Node_Selector__funcSelectorChild( 1, false, flags, xnodes ); }
\r
791 m : function( flags, xnodes ){ return X_Node_Selector__funcSelectorChild( 0, false, flags, xnodes ); }
\r
794 m : function( flags, xnodes, a, b ){ return X_Node_Selector__funcSelectorNth( 'firstChild', 'next', true, flags, xnodes, a, b ); }
\r
796 'nth-last-child' : {
\r
797 m : function( flags, xnodes, a, b ){ return X_Node_Selector__funcSelectorNth( 'lastChild', 'prev', true, flags, xnodes, a, b ); }
\r
800 m : function( flags, xnodes, a, b ){ return X_Node_Selector__funcSelectorNth( 'firstChild', 'next', false, flags, xnodes, a, b ); }
\r
802 'nth-last-of-type' : {
\r
803 m : function( flags, xnodes, a, b ){ return X_Node_Selector__funcSelectorNth( 'lastChild', 'prev', false, flags, xnodes, a, b ); }
\r
806 m : function( flags, xnodes ){
\r
808 flag_not = flags.not,
\r
809 i = 0, n = -1, xnode, tmp, node;
\r
810 for( ; xnode = xnodes[i]; ++i ){
\r
812 for( node = xnode[ 'firstChild' ](); node; node = node[ 'next' ]() ){
\r
813 if( node[ '_tag' ] || node[ '_text' ] ){
\r
818 if( tmp ^ flag_not ) res[ ++n ] = xnode;
\r
824 m : function( flags, xnodes ){
\r
825 var links = document.links,
\r
827 checked, flag_not, i, link, xnode, n;
\r
828 if( !links ) return res;
\r
830 flag_not = flags.not;
\r
831 for( i = 0; link = links[ i ]; ++i ){
\r
832 checked[ ( Node( link ) )[ '_uid' ] ] = true;
\r
834 for( i = 0, n = -1; xnode = xnodes[ i ]; ++i ){
\r
835 if( checked[ xnode[ '_uid' ] ] ^ flag_not ) res[ ++n ] = xnode;
\r
841 m : function( flags, xnodes, arg ){
\r
843 //reg = new RegExp('^' + arg, 'i'),
\r
844 flag_not = flags.not,
\r
845 i = 0, n = -1, xnode, tmp, lang;
\r
846 arg = arg.toLowerCase();
\r
847 for( ; tmp = xnode = xnodes[ i ]; ++i ){
\r
848 while( tmp && !( lang = tmp[ '_attrs' ] && tmp[ '_attrs' ][ 'lang' ] ) ){
\r
851 //tmp = !!(tmp && reg.test(tmp.getAttribute('lang')));
\r
852 if( ( !!lang && lang.toLowerCase().indexOf( arg ) === 0 ) ^ flag_not ) res[ ++n ] = xnode;
\r
858 m : function( flags, xnodes ){ return X_Node_Selector__funcSelectorProp( 'disabled', false, flags, xnodes ); }
\r
861 m : function( flags, xnodes ){ return X_Node_Selector__funcSelectorProp( 'disabled', true, flags, xnodes ); }
\r
864 m : function( flags, xnodes ){ return X_Node_Selector__funcSelectorProp( 'checked', true, flags, xnodes ); }
\r
867 m : function( flags, xnodes, arg ){
\r
869 flag_not = flags.not,
\r
870 i = 0, n = -1, xnode;
\r
871 for( ; xnode = xnodes[ i ]; ++i ){
\r
872 if ( ( -1 < ( xnode[ 'text' ]() ).indexOf( arg ) ) ^ flag_not ) res[ ++n ] = xnode;
\r