简体   繁体   中英

Add event listener to child whose parent has event disabled

Weird one here. Earlier I was messing around with preventing the default touchmove behavior in an iOS webapp I'm building. It's easy enough to add the event listener and prevent propogation, but I need to add the default behavior back to one of it's children. As I understand it though, because the parent is disabled the child will never register the event.

So I need a solution.

Essentially, there's a lot of swiping going on, so the default body-scrolling behavior needs to be knocked out. The page sliding around while swiping is infuriating. Naturally, I have to add the event listener to the outside container. Can't avoid it.

How can I add back the default, browser controlled behavior to one of the children? I don't want to fake it with my own physics and all.

Thanks for your help.

HTML:

<div id="mainPanel"> <!-- add event listener and preventDefault(); -->
    <div id="nonScrollingPanel></div>
    <div id="scrollingPanel></div> <!-- add event listener and re-enable default -->
</div>

JavaScript:

$bod.on('touchmove', '#mainPanel', function(event){

    event.preventDefault();
});

$('#mainPanel').on('touchmove', '#scrollingPanel', function(){

    return true;
});

Simply put, the simplest way is to check before the preventDefault() if it's not the child.

An example in plain JS:

HTML:

<div id="parent">
    parent
    <div id="child">
        child
    </div>
</div>​

JS:

var parent = document.getElementById('parent');

parent.addEventListener('click', function(e) {
    // Gets closest div
    var div = function closest(el) {
        if (el.tagName === 'DIV') {
            return el;
        }
        else {
            return closest(el.parentNode);
        }
    }(e.target);

    if (div.id !== 'child') {
        e.preventDefault();
    }
});

Jsfiddle example: http://jsfiddle.net/Ralt/yxxmx/

Following your example, it'd be something like:

$bod.on('touchmove', '#mainPanel', function(event){
    if ($(event.target).closest('div')[0].id !== 'scrollingPanel') {
        event.preventDefault();
    }
});

The reason why this doesn't work as you expect, is that jQuery runs all event handlers, unless you stop propagation in one of them. In your example, both event handlers will run.

Here's one solution, which I don't like because you might actually want the event to propagate for some other purpose.

$('#main-panel').on('touchmove', function(e) {
    e.preventDefault();
});

$('#scrolling-panel').on('touchmove', function(e) {
    e.stopPropagation();
});​

So here's what I would do, unless iOS has some special meta tag to disable page sliding:

$('#main-panel').on('touchmove', function(e) {
    if (!$('#scrolling-panel')[0].contains(e.target)) {
        e.preventDefault();
    }
});

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM