Запретить ссылку по умолчанию, если родитель hasClass()

Упрощенный HTML:

<ul>
    <li class="no-link"><a>Should not be clickable</a>
        <ul>
            <li><a>Should be clickable</a></li>
            <li><a>Should be clickable</a></li>
        </ul>
    </li>
</ul>

Javascript:

jQuery(document).ready(function( $ ) {

    $('a').parent().click(function(e) {
        if($(this).hasClass('no-link')){
            e.preventDefault();
        }
    });
})

Прекрасно работает со ссылкой, которая не должна быть кликабельной, но также влияет на два потомка тегов a. Почему? Я думал, что parent() прошел только один шаг в DOM.

Я добавляю класс программно через WordPress (как вариант в панели управления «Внешний вид»> «Меню»), поэтому нацеливание на тег a напрямую через класс на самом деле не вариант.


person Chris J. Zähller    schedule 11.08.2016    source источник


Ответы (3)


Что вы хотите, так это фактически захватить щелчок по элементу a, а затем проверить родительский класс внутри него.

Просто измените свой код на:

$('a').click(function(e) {
     if($(this).parent().hasClass('no-link')){
         e.preventDefault();
     }
});
person SparK    schedule 11.08.2016
comment
Ах. Я знал, что это что-то простое и очевидное, но просто не видел этого. Спасибо! - person Chris J. Zähller; 12.08.2016

"Я думал, что parent() прошел только один шаг в DOM."

Оно делает. Но вы прикрепляете свой обработчик кликов к родителю, и события щелчка всплывают от элемента, по которому щелкнули, через их родителя, родителя родителя и т. Д., И могут быть отменены в любом месте этой цепочки. Таким образом, ваш код отменяет все клики для всех якорей в этом родительском элементе.

Попробуйте это вместо этого:

$('a').click(function(e) {
   if($(this).parent().hasClass('no-link')){
     e.preventDefault();
   }
});

То есть обрабатывать событие щелчка на уровне привязки, проверяя родителя выбранного элемента.

person nnnnnn    schedule 11.08.2016

Лучшее простое решение - просто остановить распространение:

jQuery(document).ready(function( $ ) {
    $('a').parent().click(function(e) {
        e.stopPropagation(); // Preventing from event bubbling and capturing
        if($(this).hasClass('no-link')){
            e.preventDefault();
        }
    });
})
person jacqbus    schedule 12.08.2016
comment
Нет, это не очень хорошее решение. stopPropagation нарушает поток событий, а также является поводом для неприятностей, если вы хотите добавить какие-либо прослушиватели событий к любому из предков, и это действительно сложно отладить, если вы забудете, что добавили stopPropagation - person strah; 12.08.2016
comment
@strah Я использовал stopPropagation только для этого конкретного случая, но вы имеете право - если этот код будет расширен, stopPropagation может вызвать проблемы. - person jacqbus; 12.08.2016