Click hijacking in jQuery, part 2

Mike
@mikerfulcher on Twitter
6twenty on GitHub

Recently I wrote about a better method of hijacking click events in jQuery so that only unmodified left-click events will be captured. Unfortunately this method required using custom event binding functions rather than jQuery's native functions. To address this we can utilise jQuery's special events API, making our left-click plugin much more robust and easier to use.

Many developers who are familiar with jQuery will know all about binding to and triggering events. Adding custom events is stupidly simple:

  1. // bind to the custom event
  2. $('my-selector').bind('my-custom-event', function() { ... });
  3. // trigger the custom event
  4. $('my-selector').trigger('my-custom-event');

Unfortunately this has one significant drawback: you must manually trigger the event on the correct element(s). What if you don't know in advance what these elements will be? Luckily, jQuery has a not-so-well-documented API for building custom (or "special") events. The basic skeleton looks like this:

  1. $.event.special.myCustomEvent = {
  2. setup: function(data, namespaces) {
  3. // apply event handlers
  4. },
  5. teardown: function(namespaces) {
  6. // remove event handlers
  7. }
  8. }

There's much more to special events than this, so you may want to read more about the special events API here, an article which takes inspiration from two of Brandon Aaron's articles: special events and special event hooks.

Armed with this API, we can take it a step further and set up our custom left-click event. I've named my custom event click:left to maintain some semblance to the familiar click event:

  1. $.event.special['click:left'] = {
  2. setup: function(data, namespaces) {
  3. // as in the previous version, we simply add a standard "click" event binding
  4. $.event.add(this, 'click', $.event.special['click:left'].handler);
  5. },
  6. teardown: function(namespaces) {
  7. $.event.remove(this, 'click');
  8. },
  9. handler: function(event) {
  10. // as before, we'll check that the event is an unmodified left click before
  11. // triggering the event
  12. if (event.which <= 1 && !event.metaKey && !event.shiftKey && !event.altKey && !event.ctrlKey) {
  13. // because during the setup we attached a standard "click" event, we now
  14. // need to override the event type so that the correct event is recorded
  15. event.type = "click:left";
  16. $.event.handle.apply(this, arguments); // finally, we trigger the event
  17. }
  18. }
  19. }
  20. // now we can bind to our custom event using any of jQuery's native event binding functions
  21. $('my-selector a').on('click:left', function() { ... }); // jQuery 1.7+
  22. $('my-selector a').bind('click:left', function() { ... });
  23. $('my-selector').delegate('a', 'click:left', function() { ... });

And the final plugin (also available on Github):

  1. (function($){
  2. $.event.special['click:left'] = {
  3. setup: function() {
  4. $.event.add(this, 'click', $.event.special['click:left'].handler);
  5. },
  6. teardown: function() {
  7. $.event.remove(this, 'click');
  8. },
  9. handler: function(e) {
  10. if (e.which <= 1 && !e.metaKey && !e.shiftKey && !e.altKey && !e.ctrlKey) {
  11. e.type = "click:left";
  12. $.event.handle.apply(this, arguments);
  13. }
  14. }
  15. };
  16. })(jQuery);

Posted Nov 11th, 2011. Tagged javascript, jquery


blog comments powered by Disqus



© 2011 rawnet.com