Reputation: 2288
I've recently completed something in jQuery after having to change it and I kind of feel dirty. But let me explain.
My first attempt was simple, on page load I looped through and created all the bindings such as below I have attached below. This allows the bindings to happen at one time.
var flyouts = $('.comment[data-flyout]');
$.each(flyouts,function(){
var textarea = $(this).find('textarea');
var flyout = $(this).find('.write-comment__flyouts');
var addFile= $(this).find('[data-flyout=btn-file]');
textarea.click(function(){
flyout.addClass('open');
});
addFile.click(function(){
flyout.addClass('open').removeClass('open-link').toggleClass('open-files');
});
});
Because of the project I've had to switch over to using jQuery's .on() function because content is dynamic. The problem there is that I can't create all the bindings at one time and instead, whenever there is a 'click' or a 'focus' have to navigate the DOM from that point up to a parent object and back down. Since I can't figure out a way to create the bindings at one point. Below is the same functionality as above.
var wrapper = $('.flyout-holder');
var textarea = 'textarea';
var flyout = '.write-comment__flyouts';
var addFile = '[data-flyout=btn-file]';
var parent = '.write-comment[data-flyout]';
wrapper.on('click',textarea,(function(){
$(this).closest(parent).find(flyout).addClass('open');
});
wrapper.on('click',addFile,function(){
$(this).closest(parent).find(flyout).addClass('open').removeClass('open-link').toggleClass('open-files');
});
So I now have to go find the related object that I want to do something to every single time there's an event. Versus hooking it all up in the beginning. Is there a better way to do this when working with jQuery's .on() function?
Upvotes: 2
Views: 63
Reputation: 195982
What you do is that correct way to do it, since the DOM does not exist at the moment you run your code, and so the handlers have to figure it out at runtime.
If your issue is with the traversing of the DOM you could store references to the final elements in the current element..
Perhaps something like this (although i doubt it is an improvement..)
var wrapper = $('.flyout-holder');
var flyout = '.write-comment__flyouts';
var parent = '.write-comment[data-flyout]';
wrapper.on('click','textarea',(function(){
var self = $(this),
myFlyout = self.data('flyout') || self.data('flyout',self.closest(parent).find(flyout)).data('flyout');
myFlyout.addClass('open');
});
wrapper.on('click','[data-flyout=btn-file]',function(){
var self = $(this),
myFlyout = self.data('flyout') || self.data('flyout',self.closest(parent).find(flyout)).data('flyout');
myFlyout.addClass('open').removeClass('open-link').toggleClass('open-files');
});
First time an element is clicked, it will store at its data
under the key flyout
a reference to its relative flyout element. The following times it will use this cached version instead of searching for it through DOM traversing.
But it is really trivial to do that kind of DOM traversing, so this optimization really is of no importance..
Upvotes: 1