jquery选择器逻辑与?

发布于 2024-09-02 17:29:26 字数 1997 浏览 3 评论 0原文

在 jQuery 中,我尝试仅选择 a 和 b 的文本值为 64 的安装节点并相应地“测试”。如果不存在 64 和“测试”,我还想回退到 32。不过,我在下面的代码中看到的是,返回的是 32 安装而不是 64。

XML:


<thingses>
    <thing>
        <a>32</a> <-- note, a here is 32 and not 64 -->
        <other>...</other>
        <mount>sample 1</mount>
        <b>test</b>
    </thing>
    <thing>
        <a>64</a>
        <other>...</other>
        <mount>sample 2</mount>
        <b>test</b>
    </thing>
    <thing>
        <a>64</a>
        <other>...</other>
        <mount>sample 3</mount>
        <b>unrelated</b>
    </thing>
    <thing>
        <a>128</a>
        <other>...</other>
        <mount>sample 4</mount>
        <b>unrelated</b>
    </thing>
</thingses>

不幸的是,我无法控制 XML,因为它来自某个地方别的。

我现在正在做的是:


var ret_val = '';

$data.find('thingses thing').each(function(i, node) {
    var $node = $(node), found_node = $node.find('b:first:is(test), a:first:is(64)').end().find('mount:first').text();
    if(found_node) {
        ret_val = found_node;
        return;
    }

    found_node = $node.find('b:first:is(test), a:first:is(32)').end().find('mount:first').text();
    if(found_node) {
        ret_val = found_node;
        return;
    }

    ret_val = 'not found';
});

// expected result is "sample 2", but if sample 2's parent "thing" was missing, the result would be "sample 1"
alert(ret_val);

对于我正在使用的“:is”选择器:


    if(jQuery){
        jQuery.expr[":"].is = function(obj, index, meta, stack){
            return (obj.textContent || obj.innerText || $(obj).text() || "").toLowerCase() == meta[3].toLowerCase();
        };
    }

必须有比我正在做的更好的方法。我希望我可以用“AND”或其他东西替换“,”。 :)

任何帮助将不胜感激。谢谢!

In jQuery I'm trying to select only mount nodes where a and b's text values are 64 and "test" accordingly. I'd also like to fallback to 32 if no 64 and "test" exist. What I'm seeing with the code below though, is that the 32 mount is being returned instead of the 64.

The XML:


<thingses>
    <thing>
        <a>32</a> <-- note, a here is 32 and not 64 -->
        <other>...</other>
        <mount>sample 1</mount>
        <b>test</b>
    </thing>
    <thing>
        <a>64</a>
        <other>...</other>
        <mount>sample 2</mount>
        <b>test</b>
    </thing>
    <thing>
        <a>64</a>
        <other>...</other>
        <mount>sample 3</mount>
        <b>unrelated</b>
    </thing>
    <thing>
        <a>128</a>
        <other>...</other>
        <mount>sample 4</mount>
        <b>unrelated</b>
    </thing>
</thingses>

And unfortunately I don't have control over the XML as it comes from somewhere else.

What I'm doing now is:


var ret_val = '';

$data.find('thingses thing').each(function(i, node) {
    var $node = $(node), found_node = $node.find('b:first:is(test), a:first:is(64)').end().find('mount:first').text();
    if(found_node) {
        ret_val = found_node;
        return;
    }

    found_node = $node.find('b:first:is(test), a:first:is(32)').end().find('mount:first').text();
    if(found_node) {
        ret_val = found_node;
        return;
    }

    ret_val = 'not found';
});

// expected result is "sample 2", but if sample 2's parent "thing" was missing, the result would be "sample 1"
alert(ret_val);

For my ":is" selector I'm using:


    if(jQuery){
        jQuery.expr[":"].is = function(obj, index, meta, stack){
            return (obj.textContent || obj.innerText || $(obj).text() || "").toLowerCase() == meta[3].toLowerCase();
        };
    }

There has to be a better way than how I'm doing it. I wish I could replace the "," with "AND" or something. :)

Any help would be much appreciated. thanks!

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

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

发布评论

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

评论(3

甜`诱少女 2024-09-09 17:29:26

为什么在 find() 之后调用 end() ?我可能没有正确理解你的意图,但是 end() 带你回到 $node,以便后续的 find("mount:first") 只是返回它的第一个 mount 子项。

我这里错了吗?

编辑

此外,为什么要对所有事物执行.each?这样,您的ret_value实际上将获得符合最后事物mount值64-if-not-then-32 条件。

如果你想选择第一个 64/test thing,如果没有这样的东西,那么选择第一个 32/test,那为什么不你不直接写这个吗?

var ret_value = $data.find( "thingses > thing:has( a:is(64) ):has( b:is(test) ) > mount" ).text();
if ( !ret_value )
    ret_value = $data.find( "thingses > thing:has( a:is(32) ):has( b:is(test) ) > mount" ).text();

您可以封装这个长查询以使代码更具可读性:

function findByAandB( data, a, b ) {
    return data.find( "thingses > thing:has( a:is(" + a + ") ):has( b:is(" + b + ") ) > mount" ).text();
}

var ret_value = findByAandB( 64, "test" ) || findByAandB( 32, "test" );

我是否误解了您的需求?因为我有点困惑:-)

Why do you call end() after find()? I may not understand your intention correctly, but end() takes you back to $node, so that the subsequent find("mount:first") just returns you the first mount child of that.

Am I wrong here?

Edit

Besides, why do you do .each on all things? This way, your ret_value will actually get the mount value of the last thing that conforms to the 64-if-not-then-32 condition.

If you want to select the first 64/test thing, and if there no such thing, then the first 32/test, then why don't you just write this explicitly?

var ret_value = $data.find( "thingses > thing:has( a:is(64) ):has( b:is(test) ) > mount" ).text();
if ( !ret_value )
    ret_value = $data.find( "thingses > thing:has( a:is(32) ):has( b:is(test) ) > mount" ).text();

And you could encapsulate that long query to make the code more readable:

function findByAandB( data, a, b ) {
    return data.find( "thingses > thing:has( a:is(" + a + ") ):has( b:is(" + b + ") ) > mount" ).text();
}

var ret_value = findByAandB( 64, "test" ) || findByAandB( 32, "test" );

Do I misunderstand what you need? Because I'm a bit confused :-)

过去的过去 2024-09-09 17:29:26

这似乎对我有用:

var el = $('thingses thing')
    .has('b:contains("test")')
    .has('a:contains(64)');
if(!el.length) 
    el = $('thingses thing')
        .has('b:contains("test")')
        .has('a:contains(32)');
alert(el.find('mount:first').text());

This seems to work for me:

var el = $('thingses thing')
    .has('b:contains("test")')
    .has('a:contains(64)');
if(!el.length) 
    el = $('thingses thing')
        .has('b:contains("test")')
        .has('a:contains(32)');
alert(el.find('mount:first').text());
我要还你自由 2024-09-09 17:29:26

各种想法:

  • 使用同级选择器(jQuery 中的层次结构选择器 )
    b 可以在 a 之前或之后,否则您可以保留选择器的一半

    find('b:first:is(test) ~ a:first:is(64), a:first:is(64) ~ b:first:is(test)')

  • 找到一个然后返回并找到另一个。我想它可能很丑

    find('b:first:is(test)).parent().find('a:first:is(64)')

  • 自定义 jQuery 选择器 可以接受参数,以便您可以编写您的 :allAtOnce 选择器:)

Various ideas:

  • Using a sibling selector (Hierarchy selectors in jQuery)
    b could precede or follow a, otherwise you can keep half of the selector

    find('b:first:is(test) ~ a:first:is(64), a:first:is(64) ~ b:first:is(test)')

  • find one then go back and find the other one. I guess it may be ugly though

    find('b:first:is(test)).parent().find('a:first:is(64)')

  • custom jQuery selectors can take parameters so you can write your :allAtOnce selector :)

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