Как заставить функцию ‘filter’ jQuery корректно работать для узлов SVG?

#jquery #filter #svg #sizzle

#jquery #Фильтр #svg #шипение

Вопрос:

Допустим, у меня есть следующие SVG и jQuery:

 <g id="test">
    <rect>
    <text>demo</text>
</g>

$('#test').filter('text').each(function(){
    // do something
});
  

Функция фильтра не работает с SVG, вероятно, потому, что jQuery был разработан для манипулирования DOM, а не SVG с пространством имен.

Но как я могу адаптировать функцию фильтра jQuery для правильного приема SVG?

 Sizzle.filter = function( expr, set, inplace, not ) {
    var match, anyFound,
        old = expr,
        result = [],
        curLoop = set,
        isXMLFilter = set amp;amp; set[0] amp;amp; Sizzle.isXML( set[0] );

    while ( expr amp;amp; set.length ) {
        for ( var type in Expr.filter ) {
            if ( (match = Expr.leftMatch[ type ].exec( expr )) != null amp;amp; match[2] ) {
                var found, item,
                    filter = Expr.filter[ type ],
                    left = match[1];

                anyFound = false;

                match.splice(1,1);

                if ( left.substr( left.length - 1 ) === "\" ) {
                    continue;
                }

                if ( curLoop === result ) {
                    result = [];
                }

                if ( Expr.preFilter[ type ] ) {
                    match = Expr.preFilter[ type ]( match, curLoop, inplace, result, not, isXMLFilter );

                    if ( !match ) {
                        anyFound = found = true;

                    } else if ( match === true ) {
                        continue;
                    }
                }

                if ( match ) {
                    for ( var i = 0; (item = curLoop[i]) != null; i   ) {
                        if ( item ) {
                            found = filter( item, match, i, curLoop );
                            var pass = not ^ !!found;

                            if ( inplace amp;amp; found != null ) {
                                if ( pass ) {
                                    anyFound = true;

                                } else {
                                    curLoop[i] = false;
                                }

                            } else if ( pass ) {
                                result.push( item );
                                anyFound = true;
                            }
                        }
                    }
                }

                if ( found !== undefined ) {
                    if ( !inplace ) {
                        curLoop = resu<
                    }

                    expr = expr.replace( Expr.match[ type ], "" );

                    if ( !anyFound ) {
                        return [];
                    }

                    break;
                }
            }
        }

        // Improper expression
        if ( expr === old ) {
            if ( anyFound == null ) {
                Sizzle.error( expr );

            } else {
                break;
            }
        }

        old = expr;
    }

    return curLoop;
};
  

Комментарии:

1. Кстати, проблема может быть где-то еще в ядре jQuery, но временами она настолько запутана.

Ответ №1:

Я не думаю, что вам нужно изменять исходный код jQuery, вы можете использовать другие методы обхода, совместимые с XML.

 // This works
$("#test").find("text").each(function() {
    // do something
});
  

чтобы сохранить текущий элемент, а также:

 var svg = $("#test");
svg.find( "text" ).add( svg ).each(function() {
    // do something
});
  

или:

 var svg = $("#test");
svg.find( "text" ).andSelf().each(function() {
    // do something
});
  

надеюсь, это поможет. приветствия!

Комментарии:

1. Функция ‘find’ не включает текущий элемент, только его потомки. Мне нужно включить текущий элемент, а также потомки.

2. ах, в этом случае вы можете использовать либо andSelf(), либо add(). отредактировано выше.

Ответ №2:

SVG-узлы отлично работают в селекторах jQuery. Проблема в том, что $(‘#test’).filter(‘text’) означает «дайте мне все узлы с id test, которые также являются текстовыми узлами».

Как указал Киган, вы ищете функцию find(), а не функцию filter() .

Комментарии:

1. Спасибо вам обоим. Это очень помогло.