15

I want to make an additional click handler (client page, cant modify his js/html) and it should work like this in my script:

1) event.stopPropagation (pause client click propagation)
2) my function (do my function, when everything is done do next)
3) event.startPropagation (continue standard client action)

Right now, the first and second work. The third is the problem.
I know event.startPropagation doesn't exist, but I want something like that. Any hints?

taylorc93
  • 3,676
  • 2
  • 20
  • 34
Piotr Wu
  • 1,362
  • 3
  • 14
  • 31

3 Answers3

10

You can re-trigger the same event object on the parent node, f.ex (jQuery). You will need to copy the event object first and pass it into the trigger in order to capture the same event properties in the bubble (f.ex e.pageX):

var copy = $.extend(true, {}, e);
setTimeout(function() {
    $(copy.target.parentNode).trigger(copy);
},500);
e.stopPropagation();

Demo: http://jsfiddle.net/GKkth/

EDIT

Based on your comment, I think you are looking for something like:

$.fn.bindFirst = function(type, handler) {
    return this.each(function() {
        var elm = this;
        var evs = $._data(this).events;
        if ( type in evs ) {
            var handlers = evs[type].map(function(ev) {
                return ev.handler;
            });
            $(elm).unbind(type).on(type, function(e) {
                handler.call(elm, e, function() {
                    handlers.forEach(function(fn) {
                        fn.call(elm);
                    });
                });
            });
        }
    });
};

This prototype allows you to bind a "premium handler" that holds a next function that will execute all previous handlers to the same element when you want to. Use it like:

$('button').click(function() {
    console.log('first');
}).click(function() {
    console.log('second');
}).bindFirst('click', function(e, next) {
    console.log('do something first');
    setTimeout(next, 1000); // holds the other handlers for 1sec
});

DEMO: http://jsfiddle.net/BGuU3/1/

David Hellsing
  • 106,495
  • 44
  • 176
  • 212
  • Ok, I tried this in many ways with no good result. Maybe I do something wrong. For example: //client side, his own click handler $('p').click(function(e) { document.location = 'http://www.onet.pl'; }); //my script $('p').click(function(e) { e.stopPropagation(); e.preventDefault(); $.get( ...., ...., function(){ //if ok, then do something like startPropagation } ) }); – Piotr Wu Jul 17 '13 at 14:20
  • 2
    @PiotrWójcik sounds like you are looking for `stopImmediatePropagation()` since the handler is attached to the same element: http://api.jquery.com/event.stopImmediatePropagation/. Just remember that it won’t stop handlers previously bound from being executed. Or maybe you just need to find the handlers that are already bound, save them and execute them later in your own trigger. – David Hellsing Jul 17 '13 at 20:14
  • 2
    @PiotrWójcik I edited my answer with a possible solution, is that what you need? – David Hellsing Jul 17 '13 at 20:39
  • nice answer! this is perfect for what I want - it's a shame that it's apparently reliant on JQuery's internal structure i.e. `$._data(this)` - which might change between versions. But really good - just upvoted it - BTW, David, if you have a version that doesn't rely on what I think it's an internal call - i.e. `$._data(this)` please let us know :) – João Antunes Jul 11 '19 at 12:56
  • Alrighty @DavidHellsing - again - lovely answer - I do have a 'bone' to pick with it - which is - I would change the line `fn.call(elm);` to `fn.call(elm,e);` - to preserve the access of the other handlers to the original event :) It would be great if you could edit the code above ;) – João Antunes Jul 11 '19 at 13:04
2

Don't stop propagation in the first place.

Test if my function does what you want it to do, and then decide if you are going to stop propagation or not.

Quentin
  • 914,110
  • 126
  • 1,211
  • 1,335
  • 1
    When I click to anchor, my function (GET to DB) hasn't time to execute. I think its necessary to stopPropagation on start – Piotr Wu Jul 17 '13 at 09:16
  • You should consider the possible user experience harm there: The user clicks on something and nothing happens until a database call completes. Worst-case, that could be a long time of looking unresponsive. – ehdv Jul 17 '13 at 20:40
  • 3
    This is a bad answer because stopping propagation is often necessary when you have several events bubbling on the same element. It is the entire reason the method exists. – kjdion84 Aug 18 '17 at 15:35
0

Add and remove the click handler if you want to enable/disable the click event respectively. Because event.stopPropagation() will stop the events from propagating up the dom tree.

Update:

If you are using jQuery, use .trigger() function.

http://api.jquery.com/trigger/

Dinesh
  • 350
  • 2
  • 12