Модераторы: Sardar, Aliance
  

Поиск:

Ответ в темуСоздание новой темы Создание опроса
> jpath^2 - быстрее, выше, сильнее! 
:(
    Опции темы
cruelangel
Дата 17.11.2007, 20:55 (ссылка)   | (голосов:1) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 319
Регистрация: 12.9.2007

Репутация: 1
Всего: 8



Код
var isset= function( value ){
    return( typeof value !== 'undefined' )&&( value !== null );
}

var jpath= function( path ){ // version 2.0b1
    var nodes= [ this ];
    var collector= [];
    var paths= [];
    while( path ){
        var m= /^\s*(?:([\[\]])|(\/\/|[-.+^\/])([\w#$-]+|\*)?(?:\:([\w-]+))?)\s*(.*?)$/.exec( path );
        if( !m ) throw 'jpath error: broken expression "' + path + '"';
        var scope= m[1];
        var axis= m[2];
        var name= m[3];
        var klass= m[4];
        path= m[5];
        switch( scope ){
            case '[':
                paths.unshift( path );
                collector.unshift( [] );
            break;
            case ']':
                if( !paths ) throw 'jpath scope error';
                if( nodes.length ){
                    path= paths[0];
                    collector[0]= collector[0].concat( nodes );
                } else {
                    nodes= collector.shift();
                    paths.unshift();
                }
            break;
            default:
                var newNodes= [];
                switch( axis ){
                    case '+':
                    case '-':
                    case '^':
                        var prop= {
                            '^': 'parentNode',
                            '+': 'nextSibling',
                            '-': 'previousSibling'
                        }[ axis ];
                        if( name ){
                            name= name.toUpperCase();
                            var checkNode= ( name === '*' )
                                ? function( node ){ return node.nodeType === 1 }
                                : function( node ){ return node.nodeName === name }
                        } else var checkNode= function( ){ return true }
                        var checkClass= klass
                            ? function( node ){ return RegExp( '\\b' + klass + '\\b' ).test( node.className ) }
                            : function( ){ return true }
                        for( var i= 0; i < nodes.length; ++i ){
                            var node= nodes[i];
                            while( node= node[ prop ] )
                                if( checkNode( node ) && checkClass( node ) ){
                                    newNodes.push( node );
                                    break;
                                }
                        }
                    break;
                    case '/':
                        if( name ){
                            name= name.toUpperCase();
                            checkNode= ( name === '*' )
                                ? function( node ){ return node.nodeType === 1 }
                                : function( node ){ return node.nodeName === name }
                        } else var checkNode= function( ){ return true }
                        var checkClass= klass
                            ? function( node ){ return RegExp( '\\b' + klass + '\\b' ).test( node.className ) }
                            : function( ){ return true }
                        for( var i= 0; i < nodes.length; ++i ){
                            var childs= nodes[i].childNodes;
                            for( var j= 0; j < childs.length; ++j ){
                                var node= childs[ j ];
                                if( checkNode( node ) && checkClass( node ) ) newNodes.push( node );
                            }
                        }
                    break;
                    case '//':
                        for( var i= 0; i < nodes.length; ++i ){
                            var node= nodes[i];
                            var descs= node.getElementsByTagName( name || '*' );
                            if( !name ){
                                var proc= function( node ){
                                    var childs= node.childNodes;
                                    for( var j= 0; j < childs.length; ++j )
                                        newNodes.push( childs[j] );
                                }
                                proc( node );
                                for( var j= 0; j < descs.length; ++j ) proc( descs[j] );
                            } else if( klass ){
                                for( var j= 0; j < descs.length; ++j ){
                                    var node= descs[j];
                                    if( RegExp( '\\b' + klass + '\\b' ).test( node.className ) )
                                        newNodes.push( node );
                                }
                            } else {
                                for( var j= 0; j < descs.length; ++j )
                                    newNodes.push( descs[j] );
                            }
                        }
                    break;
                    case '.':
                        if( !name ){
                            var proc= function( node ){
                                for( var i in node ){
                                    var val= node[ i ];
                                    if( isset( val ) ) newNodes.push( val );
                                }
                            }
                        } else if( name === '*' ){
                            var proc= function( node ){
                                for( var i in node ){
                                    var val= node[ i ];
                                    if( val ) newNodes.push( val );
                                }
                            }
                        } else {
                            var proc= function( node ){
                                var val= node[ name ];
                                if( isset( val ) ) newNodes.push( val );
                            }
                        }
                        for( var i= 0; i < nodes.length; ++i ) proc( nodes[i] );
                    break;
                } // switch axis
                nodes= newNodes;
            break;
        } // switch scope
    } // while path
    return nodes;
} // jpath


теперь совершенно не совместимо ни с xpath, ни с css, ни даже с jpath^1 ^_^

новая версия ещё больше ориентирована на яваскрипт. от осей отказался, но остались так называемые "макросы".

основной оператор - точка. если после него указано имя, то он вернёт значение свойства с этим именем. если имя не указано, то он вернёт значения всех свойств. если указана звёздочка - вернёт все значения, которые "труъ" ;-).

alert( jpath.call( [ 1, 2, 3 ], ' .1 ' ) ); // вернёт [ 2 ]
alert( jpath.call( [ false, 1, 2, 3 ], ' .* ' ) ); // вернёт [ 1, 2, 3 ]
alert( jpath.call( [ [ 1, 1.5 ] , [ 2, 2.5 ], 3 ], ' . .1 ' ) ); // вернёт [ 1.5, 2.5 ]

получить следующий узел можно так:

alert( jpath.call( node, ' .nextSibling ' )[0] ); // вернёт node.nextSibling
alert( jpath.call( node, ' + ' )[0] ); // то же самое

другие макросы:

alert( jpath.call( node, ' - ' )[0] ); // вернёт node.previousSibling
alert( jpath.call( node, ' ^ ' )[0] ); // вернёт node.parentNode

если нужны не любые узлы, а только элементы, то нужно указать звёздочку в качестве имени:

alert( jpath.call( node, ' +* ' )[0] ); // вернёт следующий элемент

если нужно отфильтровать по имени:

alert( jpath.call( node, ' +tr ' )[0] ); // вернёт следующую строку таблицы

если нужно отфильтровать ещё и по классу:

alert( jpath.call( node, ' ^*:megacontainer ' )[0] ); // вернёт ближайшего предка с классом "megacontainer"
alert( jpath.call( node, ' +p:alert ' )[0] ); // вернёт следующий параграф с классом "alert"

слэши по прежнему возвращают коллекции детей или потомков:

alert( jpath.call( node, ' / ' ) ); // вернёт всех детей
alert( jpath.call( node, ' /* ' ) ); // вернёт все дочерние элементы
alert( jpath.call( node, ' /li:odd ' ) ); // вернёт все элементы списка с классом 'odd'

alert( jpath.call( node, ' // ' ) ); // вернёт всех потомков (медленная и как правило бессмысленная операция)
alert( jpath.call( node, ' //* ' ) ); // вернёт все элементы-потомки
alert( jpath.call( document, ' //a:j-hover ' ) ); // вернёт все ссылки с классом 'j-hover'

доступ к отдельному элементу коллекции осуществляется с помощью точки:

alert( jpath.call( node, ' / .0 ' ) [0] ); // вернёт node.firstChild

и наоборот, используя квадратные скобки можно организовывать коллекции:

alert( jpath.call( node, ' [^] ' ) ); // вернёт всех предков
alert( jpath.call( node, ' [+tr] ' ) ); // вернёт все следующие строки
alert( jpath.call( node, ' [ +tr +tr ] ' ) ); // вернёт каждую вторую строку после текущей

alert( jpath.call( node, ' [/*] ' ) ); // вернёт всех потомков
alert( jpath.call( node, ' //* ' ) ); // то же самое, но гораздо быстрее

квадратные скобочки можно вкладывать друг в друга.

возвращаемое значение, как и прежде - массив найденных значений (null и undefined не возвращаются)

если функцию jpath сделать методом объекта, то при её вызове он будет будет являться началом пути. соответственно по дефолту - jpath( 'путь' ) - стартоым объектом является объект window.

alert( jpath.call( node, '//*' ) ); // вернёт все  элементы - потомки node
node.jpath= jpath;
alert( node.jpath( '//*' ) ); // вернёт все  элементы - потомки node

есть мысли в какую сторону стоит развивать всё это дальше?  smile:

Это сообщение отредактировал(а) cruelangel - 18.11.2007, 13:20
PM MAIL   Вверх
JSman
Дата 7.6.2008, 12:58 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 279
Регистрация: 10.7.2006

Репутация: 1
Всего: 4



XPath не убьешь, по простой причине: у него высокое быстродействие. Поэтому как минимум советую написать, там где возможно, конвертер твоего запроса в запрос XPath.
PM ICQ   Вверх
  
Ответ в темуСоздание новой темы Создание опроса
Здесь публикуют скрипты, которые уже проверены в обсуждениях других тем (при этом полезно поставить ссылки на все смежные обсуждения) или переносятся кем-либо из модераторов по просьбе участников, если видно, что в результате обсуждения темы был написан полезный или интересный скрипт. Третий возможный вариант - участник форума публикует скрипт, заведомо известный как полезный и эффективный, для, возможно, небольшой доработки и обсуждения.
 
0 Пользователей читают эту тему (0 Гостей и 0 Скрытых Пользователей)
0 Пользователей:
« Предыдущая тема | JavaScript: Наши скрипты | Следующая тема »


 




[ Время генерации скрипта: 0.1175 ]   [ Использовано запросов: 22 ]   [ GZIP включён ]


Реклама на сайте     Информационное спонсорство

 
По вопросам размещения рекламы пишите на vladimir(sobaka)vingrad.ru
Отказ от ответственности     Powered by Invision Power Board(R) 1.3 © 2003  IPS, Inc.