如何制作 jQuery 的“过滤器”函数对于 SVG 节点是否正常工作?

发布于 2024-12-07 15:29:58 字数 2963 浏览 0 评论 0原文

假设我有以下 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 && set[0] && Sizzle.isXML( set[0] );

    while ( expr && set.length ) {
        for ( var type in Expr.filter ) {
            if ( (match = Expr.leftMatch[ type ].exec( expr )) != null && 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 && found != null ) {
                                if ( pass ) {
                                    anyFound = true;

                                } else {
                                    curLoop[i] = false;
                                }

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

                if ( found !== undefined ) {
                    if ( !inplace ) {
                        curLoop = result;
                    }

                    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;
};

Say I have the following SVG and jQuery:

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

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

The filter function doesn't work with SVG, probably because jQuery was designed for DOM manipulation, not namespaced SVG.

But how can I adapt jQuery's filter function to accept SVG correctly?

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

    while ( expr && set.length ) {
        for ( var type in Expr.filter ) {
            if ( (match = Expr.leftMatch[ type ].exec( expr )) != null && 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 && found != null ) {
                                if ( pass ) {
                                    anyFound = true;

                                } else {
                                    curLoop[i] = false;
                                }

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

                if ( found !== undefined ) {
                    if ( !inplace ) {
                        curLoop = result;
                    }

                    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;
};

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

陌上芳菲 2024-12-14 15:29:58

我认为您不需要更改 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
});

希望有帮助。干杯!

I don't think you need to alter the jQuery source, you can use other traversal methods that are compatible with XML.

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

to keep the current element as well:

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

or:

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

hope that helps. cheers!

一影成城 2024-12-14 15:29:58

SVG 节点在 jQuery 选择器中工作良好。问题是 $('#test').filter('text') 意味着“给我所有 ID 为 test 且也是文本节点的节点”。

正如 keegan 所指出的,您正在寻找 find() 函数,而不是 filter() 函数。

SVG nodes work fine in jQuery selectors. The problem is that $('#test').filter('text') means "give me all nodes with id test that are also text nodes."

As keegan indicated, you're looking for the find() function, not the filter() function.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文