JQuery: найдите текст элемента списка, который содержит вложенный ul

У меня есть следующее:

<ul id="list">
<li>item1
    <ul>
        <li>sub1</li>
        <li>sub2</li>
    </ul>    
</li>
</ul>

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

$("#list li").click(function() {
    alert($(this).text());
});

возвращает item1sub1sub2, как ожидалось.

Я не могу понять, как получить только "item1", если щелкнуть элемент 1 li. Я пробовал следующее (между прочим) без везения:

$("#list li").click(function() {
    alert($(this).filter("ul").text());
});

Любые идеи?

ИЗМЕНИТЬ

Это фрагмент примера - это может быть несколько уровней. Я также не хочу обертывать текст элемента списка в промежутке или другой разметке.

Ответы

Ответ 1

Как насчет этого подхода? Выполните клонирование объекта, удалите дочерние клоны и найдите текстовое содержимое.

$("#list li").click(function () {
    alert($(this).clone().children().remove().end().text());
}

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

Ответ 2

Обычные DOM-методы позволяют получать текстовое содержимое только для одного элемента, а не для jquery:

$("#list li").click(function() {
    alert($(this)[0].firstChild.textContent)
});

firstChild в этом случае является textNode под элементом li

Ответ 3

вам тяжело, потому что text() делает то, что должен - возвращает текст этого и всех дочерних элементов. Самое простое - добавить еще один тег к каждому <li> и использовать этот тег. Например:

<ul id="list">
<li><span>item1</span>
    <ul>
        <li><span>sub1</span></li>
        <li><span>sub2</span></li>
    </</ul>    
</li>
</ul>

И у вас есть простой селектор:

$("#list li").click(function() {
   alert($(this).find("span").eq(0).text());
});

или, если возможно (в зависимости от вашего стиля), вы можете добавить событие в диапазон:

$("#list span").click(function() {
   alert($(this).text());
});

Если вы не можете добавить эти <span> (как вы говорите), вы можете использовать jQuery .contents() , чтобы добавить их для вас, аналогично тому, что было сделано здесь:

Скрыть B в <x> A < br/ > B </x>

Ответ 4

Это проверяет, есть ли у элемента списка какие-либо дочерние элементы, и если он отфильтровывает только текстовые узлы и объединяет результат (в этом случае он будет работать для текстовых элементов, где бы они не были помещены в ли). Если вы только хотите проверить элементы в начале, вы можете избежать цикла for и просто работать с этим. FirstChild

$("#list li").click(function(e) {
    if ($(this).children().length > 0) {
       var text = "";
       for (var i = 0; i < this.childNodes.length; i++) {
           var node = this.childNodes[i];
           if (node.nodeType === 3 && $.trim(node.nodeValue).length > 0) {
                text += $.trim(node.nodeValue);
           }
       }
       alert(text);
    }
    else {
       alert($(this).text());
    }
    e.stopPropagation();
});

Ответ 5

Таким образом, этот механизм вытаскивает html из дочернего элемента, заменяет новые строки ничем, а затем возвращает строку только до первого символа "<". Я также добавил event.stopPropagation, чтобы избежать нажатия на событие click bubbling до родителя.

<script type="text/javascript">
$("#list li").click(function(event) {
    var sourceHTML = $(this).html().replace(/\n/g,'').replace(/<.*/,'');
    alert(sourceHTML);
    event.stopPropagation();
});
</script>

Ответ 6

Я думаю, вам нужно использовать каждый метод. поэтому попробуйте выполнить script:

$(document).ready(function() {
        $('ul').each(function() {
            $(this).find('li').click(function() {
                var listItem = this;
                alert($(listItem).text());
            });
        })
    });

со следующей разметкой

<ul>
    <li>1</li>
    <li>2</li>
    <li>3</li>
    <li>4</li>
</ul>

Ответ 7

Другой способ добиться того же

$("#list li").click(function() {
    alert($(this).contents().not('ul,ol').text());
});