使(可能是动态加载的)元素可通过 JavaScript 单击,但优先考虑其中包含的链接

发布于 2024-12-09 20:42:12 字数 1105 浏览 0 评论 0原文

我正在向各种 HTML 元素添加自定义数据属性 data-js-href,这些元素在单击时的行为应该就像链接一样。如果单击此类元素中的链接,则该链接应优先,并且 data-js-href 功能应被忽略。此外,该解决方案还需要处理稍后动态添加的元素。

到目前为止,我已经提出了以下解决方案。它基本上检查是否在链接或链接的任何子元素上执行了单击(例如 ...)。

// 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() 消息来验证行为。)欢迎任何想法。

I am adding a custom data attribute data-js-href to various HTML elements, and these elements should behave just like a link when clicked. If a link within such an element is clicked, the link should take precedence and the data-js-href functionality should be ignored, though. Furthermore, the solution also needs to work with elements that are dynamically added at a later time.

So far, I have come up with the following solution. It basically checks if the click was performed on a link, or any child element of a link (think <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;
    }
});

It works, but it feels very clumsy, and I think that there has to be a more elegant solution. I tried something along the lines of

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

but to no avail. (I littered the code with some console.log() messages to verify the behavior.) Any idea is welcome.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

蓝咒 2024-12-16 20:42:12

您可以使用 2 个委托事件来完成此操作 - 无需反向查找,而且成本低廉,因为它们将共享相同的事件。缺点是,它是同一个事件,因此它会触发两个事件,并且无法通过事件方法停止它(已经冒泡,它是一个单个事件,堆叠多个伪事件回调并按顺序执行它们 - 事件已停止但回调仍在继续)这可能是 mootools 事件与委托实现的不一致,但这是另一个问题的主题。

目前的解决方法是:

让 2 个事件处理程序通过彼此进行通信。它将扩展并与添加的任何新元素一起工作。

将委托人添加到 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;


    }
});

与 Ibolmo 和 Keeto 讨论了这个问题来自 IRC 上的 mootools 团队,以及当我最初的尝试失败并且尽管 event.stop 仍然触发两个回调时:http://jsfiddle.net/dimitar/J59PD/

结果,在mootools github 问题:https://github.com/mootools/mootools-core/issues/2105 但它随后讨论了从库的角度来看什么是正确的事情以及它的可行性是追求改变事物运作的方式,以便......

you can do this with 2 delegated events - no reverse lookups and it's cheap as they will share the same event. the downside is, it is the same event so it will fire for both and there's no stopping it via the event methods (already bubbled, it's a single event that stacks up multiple pseudo event callbacks and executes them in order--the event has stopped but the callbacks continue) That's perhaps an inconsistency in mootools event vs delegation implementation but it's a subject of another issue.

Workarounds for now can be:

to have the 2 event handlers communicate through each other. It will scale and work with any new els added.

to add the delegators on 2 different elements. eg. document.body and #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;


    }
});

Discussed this with Ibolmo and Keeto from the mootools team on IRC as well when my initial attempt failed to work and both callbacks fired despite the event.stop: http://jsfiddle.net/dimitar/J59PD/

As a result, there was briefly a ticket open on the mootools github issues: https://github.com/mootools/mootools-core/issues/2105 but it then went into a discussion of what the right thing to do from the library standpoint is and how viable it is to pursue changing the way things work so...

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文