Override (wrap) an existing jQuery click event with another in javascript - Stack Overflow

Say I have an existing button and attach a click to it via jQuery:var $button = $('#test').cl

Say I have an existing button and attach a click to it via jQuery:

var $button = $('#test').click(function () { console.log('original function') });

Now, say I want to override that click so that I can add some logic to the function before and after it. I have tried binding and wrapping using the functions below.

Function.prototype.bind = function () {
   var fn = this;
   var args = Array.prototype.slice.call(arguments);
   var object = args.shift();

   return function () {
       return fn.apply(object, args.concat(Array.prototype.slice.call(arguments)));
   }
}

function wrap(object, method, wrapper) {
   var fn = object[method];

   return object[method] = function() {
       return wrapper.apply(this, [fn.bind(this)].concat(
        Array.prototype.slice.call(arguments)));
   }
}

so I call wrap with the object that the method is a property of, the method and an anonymous function that I want to execute instead. I thought:

wrap($button 'click', function (click) {
     console.log('do stuff before original function');
     click();
     console.log('do stuff after original function');
 });

This only calls the original function. I have used this approach on a method of an object before with success. Something like: See this Plunker

Can anyone help me do this with my specific example please?

Thanks

Say I have an existing button and attach a click to it via jQuery:

var $button = $('#test').click(function () { console.log('original function') });

Now, say I want to override that click so that I can add some logic to the function before and after it. I have tried binding and wrapping using the functions below.

Function.prototype.bind = function () {
   var fn = this;
   var args = Array.prototype.slice.call(arguments);
   var object = args.shift();

   return function () {
       return fn.apply(object, args.concat(Array.prototype.slice.call(arguments)));
   }
}

function wrap(object, method, wrapper) {
   var fn = object[method];

   return object[method] = function() {
       return wrapper.apply(this, [fn.bind(this)].concat(
        Array.prototype.slice.call(arguments)));
   }
}

so I call wrap with the object that the method is a property of, the method and an anonymous function that I want to execute instead. I thought:

wrap($button 'click', function (click) {
     console.log('do stuff before original function');
     click();
     console.log('do stuff after original function');
 });

This only calls the original function. I have used this approach on a method of an object before with success. Something like: See this Plunker

Can anyone help me do this with my specific example please?

Thanks

Share Improve this question edited Jan 19, 2016 at 17:11 davy asked Jan 19, 2016 at 17:01 davydavy 4,58210 gold badges50 silver badges73 bronze badges 5
  • Can you not just unbind using .off() and then just pass in your new function? Such as $('whatever').off().click(newFunc)?... Hmmm, just re-read the question, not sure if my original ment is going to give you what you want? – ann0nC0d3r Commented Jan 19, 2016 at 17:12
  • @ann0nC0d3r that is trivializing the issue – charlietfl Commented Jan 19, 2016 at 17:13
  • 1 @charlietfl... you should read my whole ment ;) – ann0nC0d3r Commented Jan 19, 2016 at 17:14
  • @ann0nC0d3r, I really just want to know how (if I can) override like or similar to the approach. Thanks. – davy Commented Jan 19, 2016 at 17:16
  • assuming original event is added by jquery, event handlers are cached internally by jQuery. The cache is not documented in api and is subject to change but you may be able to figure out how to access the event handler there and over write – charlietfl Commented Jan 19, 2016 at 17:33
Add a ment  | 

2 Answers 2

Reset to default 4

You could create a jQuery function that gets the original event handler function from data, removes the click event, then adds a new event handler. This function would have two parameters (each functions) of before and after handlers.

$(function() {

    jQuery.fn.wrapClick = function(before, after) {
        // Get and store the original click handler.
        // TODO: add a conditional to check if click event exists.
        var _orgClick = $._data(this[0], 'events').click[0].handler,
            _self = this;

        // Remove click event from object.
        _self.off('click');

        // Add new click event with before and after functions.
        return _self.click(function() {
            before.call(_self);
            _orgClick.call(_self);
            after.call(_self);
        });
    };

    var $btn = $('.btn').click(function() {
        console.log('original click');
    });

    $btn.wrapClick(function() {
        console.log('before click');
    }, function() {
        console.log('after click');
    });

});

Here is a Codepen

After a long search I reached the same answer as @Corey, here is a similar way of doing it considering multiple events:

function wrap(object, method, wrapper) {
          
  var arr = []
  var events = $._data(object[0], 'events')
  
  if(events[method] && events[method].length > 0){ // add all functions to array
    events[method].forEach(function(obj){
      arr.push(obj.handler)
    })
  }
  
  
  
  if(arr.length){
      function processAll(){ // process all original functions in the right order
        arr.forEach(function(func){
          func.call(object)
        })
      }
  
      object.off(method).on(method, function(e){wrapper.call(object,processAll)}) //unregister previous events and call new method passing old methods
  }
   
    
}


$(function(){
  $('#test').click(function () { console.log('original function 1') });
  var $button = $('#test').click(function () { console.log('original function 2') });
  wrap($button, 'click', function (click,e) {
     console.log('do stuff before original functions');
     click()
     console.log('do stuff after original functions');
 });
})
<script src="https://ajax.googleapis./ajax/libs/jquery/2.1.0/jquery.min.js"></script>


<div id='test'>click me</div>

发布者:admin,转转请注明出处:http://www.yc00.com/questions/1745608313a4635800.html

相关推荐

发表回复

评论列表(0条)

  • 暂无评论

联系我们

400-800-8888

在线咨询: QQ交谈

邮件:admin@example.com

工作时间:周一至周五,9:30-18:30,节假日休息

关注微信