Сделать (возможно, динамически загружаемый) элемент кликабельным с помощью JavaScript, но отдавать приоритет ссылкам, содержащимся в - PullRequest
1 голос
/ 14 октября 2011

Я добавляю пользовательский атрибут данных data-js-href к различным элементам HTML, и при нажатии эти элементы должны вести себя как ссылка.Если щелкнуть ссылку в таком элементе, ссылка должна иметь приоритет, а функциональность data-js-href следует игнорировать.Кроме того, решение также должно работать с элементами, которые динамически добавляются позднее.

До сих пор я придумал следующее решение.Он в основном проверяет, был ли выполнен щелчок по ссылке или какому-либо дочернему элементу ссылки (например, <a href='…'><img src='…' alt='…' /></a>).

// Make all elements with a `data-js-href` attribute clickable
$$('body').addEvent('click:relay([data-js-href])',
                    function(event, clicked) {
    var link = clicked.get('data-js-href');
    if (link && !event.target.match('a')) {
        var parents = event.target.getParents();
        for (var i = 0; i < parents.length && parents[i] != clicked; i++) {
            if (parents[i].match('a')) {
                return;
            }
        }
        document.location.href = link;
    }
});

Это работает, но кажется очень неуклюжим,и я думаю, что должно быть более элегантное решение.Я пробовал что-то вроде

$$('body').addEvent('click:relay([data-js-href] a)',
                    function(event, clicked) {
    event.stopPropagation();
}

, но безрезультатно.(Я засорял код некоторыми сообщениями console.log(), чтобы проверить поведение.) Любая идея приветствуется.

1 Ответ

2 голосов
/ 14 октября 2011

вы можете сделать это с 2 делегированными событиями - без обратного поиска, и это дешево, поскольку они будут использовать одно и то же событие.недостатком является то, что это одно и то же событие, поэтому оно будет запускаться для обоих, и его нельзя остановить с помощью методов события (уже всплыло, это одно событие, которое суммирует несколько обратных вызовов псевдо-событий и выполняет их по порядку - событие остановилосьно обратные вызовы продолжаются) Возможно, это несоответствие в событии mootools и реализации делегирования, но это тема другого вопроса.

Обходные пути на данный момент могут быть:

, чтобы два обработчика событий взаимодействовали друг с другом.Он будет масштабироваться и работать с любыми новыми добавленными els.

для добавления делегатов на 2 разных элемента.например.document.body и #mainWrap.

http://jsfiddle.net/dimitar/J59PD/4/

var showURL = function(howLong) {
    // debug.
    return function() {
        console.log(window.location.href);
    }.delay(howLong || 1000);
};

document.id(document.body).addEvents({
    "click:relay([data-js-href] a))": function(e) {
        // performance on lookup for repeat clicks.
        var parent = this.retrieve("parent");
        if (!parent) {
            parent = this.getParent("[data-js-href]");
            this.store("parent", parent);
        }
        // communicate it's a dummy event to parent delegator.
        parent.store("linkEvent", e);
        // let it bubble...
    },
    "click:relay([data-js-href])": function(e) {
        // show where we have gone.
        showURL(1500);
        if (this.retrieve("linkEvent")) {
            this.eliminate("linkEvent");
            return;
        }
        var prop = this.get("data-js-href");
        if (prop)
            window.location.href = prop;


    }
});

Обсуждали это также с Иболмо и Кито из команды mootools в IRC, когда моя первоначальная попытка не сработала и оба обратных вызова сработали, несмотря на event.stop: http://jsfiddle.net/dimitar/J59PD/

В результате на короткое время был открыт тикет по вопросам github для mootools: https://github.com/mootools/mootools-core/issues/2105, но затем он приступил к обсуждению того, что нужно делать с точки зрения библиотеки, инасколько жизнеспособно стремиться изменить то, как все работает, так что ...

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...