JQuery выбрать элементы между двумя элементами, которые не являются братьями и сестрами - PullRequest
2 голосов
/ 25 марта 2010

(я удалил атрибуты, но это немного автоматически сгенерированного 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>

Мне нужно применить подсветку с фоном ко всему тексту, который находится между двумя ближайшими (в коде HTML) img.p элементами при наведении первого из них. Я понятия не имею, как это сделать. Допустим, я наведите первый img.p - он должен выделить hello world и text. и ничего больше.

А теперь самое худшее - мне нужно, чтобы фоны исчезали при отпускании мыши.

Мне нужно, чтобы он работал с любым возможным HTML-беспорядком. Выше приведен только пример, и структура документов будет отличаться.

Подсказка: обработка всего html перед наведением привязки и добавлением некоторых интервалов и т. Д. В порядке, если только это не меняет внешний вид выходного документа.

Ответы [ 2 ]

5 голосов
/ 25 марта 2010

Можно обрабатывать весь HTML-код перед наведением курсора и размещением некоторых интервалов и т. Д.

Вам, безусловно, придется это сделать, поскольку вы не можете стилизовать текстовые узлы, только элементы.

Вот функция, которую вы можете использовать, чтобы сделать это из скрипта. (К сожалению, 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);
            }
        }
    }
}

А вот некоторые функции, которые вы можете использовать для выбора узлов между другими узлами. (Опять же, 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;
}

Возможное использование:

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');
    });
});
1 голос
/ 25 марта 2010

Это абсолютно неструктурированный фрагмент HTML, который вы всегда должны избегать. Тем не менее, вы добавляете некоторые данные в img, которые хотите отслеживать при наведении, например:

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

Теперь вы можете поймать из атрибута "data-friends-group" класс, общий для всех элементов, которые вам нужно выделить. Теперь все остальное просто.

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

Очевидно, класс .hightlighted будет классом с background-color: yellow;

...