简体   繁体   English

jQuery在不是兄弟姐妹的两个元素之间选择元素

[英]jquery select elements between two elements that are not siblings

(I've removed attributes, but it's a bit of auto-generated HTML.) (我删除了属性,但这是一些自动生成的HTML。)

<img class="p"/>
<div> hello world
    <p>
        <font><font size="2">text.<img class="p"/>
        some text
        </font></font>
    </p>
    <img class="p"/>
    <p> <font><font size="2">more text<img class="p"/>
        another piece of text
        </font></font>
    </p><img class="p"/> some text on the end
</div>

I need to apply some highlighting with backgrounds to all text that is between two closest (in the HTML code) img.p elements when hovering first of them. 悬停在两个最接近(在HTML代码中) img.p元素之间的所有文本时,我需要对它们进行背景突出显示。 I have no idea how to do that. 我不知道该怎么做。 Lets say I hover the first img.p - it should highlight hello world and text. 可以说我将鼠标悬停在第一个img.p ,它应该突出显示hello worldtext. and nothing else. 没别的。

And now the worst part - I need the backgrounds to disappear on mouseleave. 现在最糟糕的部分-我需要背景在mouseleave上消失。

I need it to work with any HTML mess possible. 我需要它来处理任何可能的HTML混乱。 The above is just an example and structure of the documents will differ. 以上仅是示例,文档的结构将有所不同。

Tip: Processing the whole html before binding hover and putting some spans etc. is OK as long as it doesn't change the looks of the output document. 提示:在绑定悬停并放置一些跨度等之前处理整个html是可以的,只要它不会改变输出文档的外观即可。

Processing the whole html before binding hover and putting some spans etc. is ok 在绑定悬停并放置一些跨度等之前处理整个html是可以的

You certainly would have to do that, as you can't style text nodes, only elements. 当然,您将不得不这样做,因为您无法设置文本节点的样式,而只能设置元素的样式。

Here's a function you could use to do it from script. 这是一个可以从脚本中使用的功能。 (Unfortunately jQuery isn't much use here as it doesn't like handling text nodes.) (不幸的是,jQuery在这里用处不大,因为它不喜欢处理文本节点。)

// Wrap Text nodes in a new element of given tagname, when their
// parents contain a mixture of text and element content. Ignore
// whitespace nodes.
//
function wrapMixedContentText(el, tag) {
    var elementcontent= false;
    for (var i= el.childNodes.length; i-->0;) {
        var child= el.childNodes[i];
        if (child.nodeType===1) {
            elementcontent= true;
            wrapMixedContentText(child, tag);
        }
    }
    if (elementcontent) {
        for (var i= el.childNodes.length; i-->0;) {
            var child= el.childNodes[i];
            if (child.nodeType===3 && !child.data.match('^\\s*$')) {
                var wrap= document.createElement(tag);
                el.replaceChild(wrap, child);
                wrap.appendChild(child);
            }
        }
    }
}

And here's some functions that you could use to select nodes between other nodes. 这是一些可用于在其他节点之间选择节点的功能。 (Again, jQuery doesn't currently have a function for this.) (再次,jQuery当前没有为此功能。)

// Get array of outermost elements that are, in document order,
// between the two argument nodes (exclusively).
//
function getElementsBetweenTree(start, end) {
    var ancestor= getCommonAncestor(start, end);

    var before= [];
    while (start.parentNode!==ancestor) {
        var el= start;
        while (el.nextSibling)
            before.push(el= el.nextSibling);
        start= start.parentNode;
    }

    var after= [];
    while (end.parentNode!==ancestor) {
        var el= end;
        while (el.previousSibling)
            after.push(el= el.previousSibling);
        end= end.parentNode;
    }
    after.reverse();

    while ((start= start.nextSibling)!==end)
        before.push(start);
    return before.concat(after);
}

// Get the innermost element that is an ancestor of two nodes.
//
function getCommonAncestor(a, b) {
    var parents= $(a).parents().andSelf();
    while (b) {
        var ix= parents.index(b);
        if (ix!==-1)
            return b;
        b= b.parentNode;
    }
    return null;
}

Possible usage: 可能的用法:

var outer= document.getElementById('myhighlightingimagesdiv');
wrapMixedContentText(outer, 'span');

var ps= $('#myhighlightingimagesdiv .p');
ps.each(function(pi) {
    // Go up to the next image in the list, or for the last image, up
    // to the end of the outer wrapper div. (There must be a node
    // after the div for this to work.)
    //
    var end= pi===ps.length-1? outer.nextSibling : ps[pi+1];

    var tweens= $(getElementsBetweenTree(this, end));
    $(this).hover(function() {
        tweens.addClass('highlight');
    }, function() {
        tweens.removeClass('highlight');
    });
});

That is a totally unstructured piece of HTML, which is something you should always avoid. 那是一段完全非结构化的HTML,您应该始终避免这种情况。 However, you add some data to the img you want to track for hovering, like this: 但是,您将一些数据添加到要跟踪以进行悬停的img上,如下所示:

[...]
<img src="#" class="master" data-friends-group="group1"/>
[...]
<span class="group1">text1</span>
[...]
<span class="group1">text2</span>
[...]

You can now catch from the the "data-friends-group" attribute the class in common to all the elements you need to highlight. 现在,您可以从"data-friends-group"属性中捕获与您需要突出显示的所有元素相同的类。 Now the rest is easy stuff. 现在剩下的就是简单的东西了。

$(document).ready(function() {
    $("img.master").each(function() {
        $friends = $("." + $(this).attr("data-friends-group"));
        $(this).hover(
            function(){
                $friends.addClass("highlighted");
            },
            function(){
                $friends.removeClass("highlighted");
            }
        );
    });
});

Obviously, the class .hightlighted will be the one with the background-color: yellow; 显然, .hightlighted类将是具有background-color: yellow;

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM