Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Global vs. local event handler binding for jQuery widget [closed]

I try to create a custom widget with jquery with rich functionality, therefore I need custom handlers for many standard events such as dblclick, click, focus, blur etc.

I can apply one of two strategies:

  1. Use $(document).on('click', '.widget-name .element-class', handle_click);
    once globally where handle_click is the handler function

  2. Use $(widget-element).find('.element-class').on('click', handle_click)
    during the creation of each widget instance

  3. Bind to the enclosing element like this:

    $(this.element)._on('click', function(event){
    var $this = $(this);
    if($this.is('.element-class')){ handle_click(this, event);}
    else if($this.is(...)){...}
    ...
    });

Which approach is better design?
I know "it depends" in general, so let me add some constraints:

a. the widget will typically consist of ~100 DOM elements with different events handled specially.
b. the widget will typically not be destroyed and created again, only hid sometimes.
c. typically 1-3 instances of the widget will be loaded.
d. elements will be added dynamically upon user request but only <10 at the same time
e. drag-n-drop is enabled within the widget that may involve repositioning ~20s of DOM elements at the same time.
f. the widget itself is typically not draggable.

Is there a substantial performance (or substantial memory) penalty on approach 2 due to defining many separate event handlers? (Yes, that could depend on browser implementations I know.)

like image 318
Barney Szabolcs Avatar asked Nov 24 '22 18:11

Barney Szabolcs


1 Answers

Using the first form is an easy way to implement the event handler once, but it has extra overhead. The handler is actually invoked for every click on the document, jQuery then has to check whether the target matches the selector; with the second form, the browser only invokes the handler when you click on the specific elements that it's bound to.

The first form can also fail in a subtle way. If there are enclosing elements that have their own click handlers, and they use event.stopPropagation(), this will prevent the event from bubbling up to the document, so the .on() handler will never be invoked.

Regular application developers can mitigate both problems by binding the event to the most deeply nested elements that enclose the dynamic elements they want to delegate to. But a widget developer doesn't have as much knowledge of the context, so it may have to use the wide document scope as in your code. If you can implement the second form, adding the handlers as you add elements to the DOM, that's likely to be better.

One way you may be able to do this easily is by using jQuery's .clone() method. It takes an optional argument indicating whether handlers should be copied. So create a prototype element with the handler bound, then clone it and the new element will also have the handler.

like image 74
Barmar Avatar answered Feb 16 '23 00:02

Barmar