Bezdepbonusu7Программирование: статьи и ответы

Вопрос

Лучший способ найти ближайший атрибут href?

Автор вопроса: FinnОтветов: 5

Почему я не думаю, что это дубликат.

Хм, я думаю, что это немного отличается от того, что я спрашиваю. Я не хочу добавлять прослушиватель ко всем тегам A, а скорее вычесть атрибут href, если он есть, для цели события клика.

Я пытаюсь "Ajaxify" весь свой сайт, чтобы, когда пользователь щелкает ЛЮБУЮ ссылку, содержащуюся на странице, скрипт отправлял атрибут "url" или HREF (выбранного элемента) в функцию Ajax, которая, в свою очередь, отображает запрошенный контент (как указано по нажатой ссылке).

Мне нужно найти атрибут HREF выбранного элемента, если элемент является ссылкой. Проблема здесь заключается в том, что многие элементы могут содержаться в теге A (из-за того, как я их структурировал), и e.target.href не обязательно всегда возвращает атрибут HREF.

Вот что у меня есть до сих пор:

function ajaxifyLinks(e) {
    var target = e.target;
    e.preventDefault();
    while(!target.href) {
        target = target.parentNode;
    }
    if(target.href) {
        ajaxLoad(target.href);
    }
}
document.body.addEventListener('click', ajaxifyLinks);

А вот примеры разных "кликабельных" ссылок, которые у меня есть:

<!-- Link -->
<a href="/cats">
   cats
</a>

<!-- Link -->
<a href="/hello">
   <span>
      <span> hi </span>
   </span>
</a>

<!-- Link -->
<a href="/bye">
   <span>
      bye
   </span>
</a>

Как видите, именно поэтому e.target.href не всегда возвращает атрибут HREF, потому что вы на самом деле щелкаете по "связанному" элементу span, однако браузер направляет вас по ссылке. Почему это происходит? И есть ли способ извлечь выгоду из такого поведения? (Например, извлечение местоположения, куда ведет вас браузер, даже если вы не нажимаете на тег A).

Мне не нравится мое решение, потому что цикл while просто продолжает искать дерево DOM, иногда без необходимости (когда e.target не является ссылкой или содержится в ссылке).

Спасибо.

  • Извините, но действительно неясно, что вы пытаетесь реализовать. Пожалуйста, опишите фактическую проблему, которую вы пытаетесь решить (какое поведение вы пытаетесь добавить на свой сайт), а не то, что вы пытаетесь решить. Пожалуйста, избегайте проблемы XY, когда вы описываете проблемы с вашим решением, не описывая фактические конечная цель. jfriend00 18.03.2015
  • Вы можете прослушивать события click для большинства элементов HTML. PM 77-1 18.03.2015
  • Хорошо, я отредактировал вопрос. Теперь стало яснее? (Для щедрых комментариев см. отредактированный вопрос выше, спасибо). Finn 18.03.2015
  • Тривиально просто с jQuery ~ $(document).on('click', 'a[href]', function() { var href = $(this).attr('href'); }) Phil 18.03.2015
  • Я понимаю это, но я действительно не хочу использовать jQuery в этом проекте. В любом случае, где я могу найти, как это реализует jQuery? Finn 18.03.2015
  • возможный дубликат Как выбрать все теги ‹a› и зарегистрировать событие onclick? Nishit Maheta 18.03.2015

javascriptajaxfindhref

Ответы

Ответ 1 · рейтинг 1 · Miguel Mota

Если щелкнутый элемент не имеет href, он ищет у своих родителей элемент, у которого есть href. Ванильное JS-решение.

function findUpTag(el, attr) {
    while (el.parentNode) {
        el = el.parentNode;
        if (el[attr]) {
            return el;
        }
    }
    return null;
}

document.body.onclick = function (event) {
    event.preventDefault();

    var href = event.target.href;

    if (!href) {
        var closest = findUpTag(event.target, 'href');
        if (closest) {
            href = closest.href;
        }
    }

    document.getElementById('output').innerHTML = 'element clicked: ' + event.target.nodeName + '<br>closest href: ' + href;
};
a,
output {
    display: block;
}
<!-- Link -->
<a href="/cats">
   cats
</a>

<!-- Link -->
<a href="/hello">
   <span>
      <span> hi </span>
   </span>
</a>

<!-- Link -->
<a href="/bye">
   <span>
      bye
   </span>
</a>

<output id="output"></output>

Ответ 2 · RaymondM

Используйте .parent(), ссылка: http://api.jquery.com/parent/

например, вы можете сделать

var hrefElem = $(target).parent('*[href]');
var link = hrefElem.attr('href');

Ответ 3 · Julio Marchi

Новый ответ:

<!-- Link -->
<a href="/cats">
   cats
</a>

<!-- Link -->
<a href="/hello">
   <span style="pointer-events: none;">
      <span style="pointer-events: none;"> hi </span>
   </span>
</a>

<!-- Link -->
<a href="/bye">
   <span style="pointer-events: none;">
      bye
   </span>
</a>

Ответ 4 · Ja͢ck

Просто прикрепите обработчик кликов к каждой ссылке на странице:

function ajaxify(e)
{
    e.preventDefault();
    ajaxLoad(this.href);
}

[].forEach.call(document.getElementsByTagName('a'), function(el) {
    el.addEventListener('click', ajaxify.bind(el));
});

Ответ 5 · cmbuckley

Взгляните на Что такое всплытие и захват событий?, чтобы понять, как события распространяются через ДОМ.

Техника захвата якорных ссылок и их загрузки через Ajax называется Hijax. Поскольку вы заменяете контент на странице, вы не можете просто настроить одно событие для обработки всех ссылок, и вы, вероятно, не хотите повторно связывать каждую загрузку страницы, поэтому подход, который вы используете, хорош, и называется делегированием событий.

В последней статье описана именно ваша проблема (прямо в самом конце), а также описано решение, похожее на ваше, что действительно лучше всего сделать в данном сценарии. Однако вы можете рассмотреть возможность использования микробиблиотеки для упрощения делегирования некоторых событий; например, gator.js.

Перевод вопроса и ответов сообщества Stack Overflow, лицензия CC BY-SA. Оригинал на Stack Overflow.

Похожие материалы