How to write scalable jQuery functions

Early in my career as a web developer, one of my colleagues showed me a great way to use jQuery functions. It was a game changer for a newbie like me. Before that, I was just writing things in the hope that everything would somehow work out, and I didn't even consider what could happen if circumstances were different from what I was prepared for.
Before we start, I want to make sure we are on the same page. I assume that jQuery is available in your environment and that you have already created a file with your javascript content.
// main.js (function($){ })(jQuery);
First, we wrap the code like this to make sure that $ is treated as jQuery inside this closure.
// main.js (function($){ $.fn.toggleMenu = function() { } })(jQuery);
Then we create an empty function inside. The $.fn allows you to extend jQuery with your own functions.
// main.js (function($){ $.fn.toggleClass = function() { var $el; var init = function() { } } })(jQuery);
We declare $el on which we will later initiate our function. init is a place where we will take care of all the functionality we want to implement.
// main.js (function($){ $.fn.toggleClass = function() { var $el; var init = function() { } if (this.length > 0) { if (this.length > 1) { this.each(function() { $(this).toggleMenu(); }); } else { $el = this; init(); } } } })(jQuery);
And here comes the most important part of our work. if (this.length > 0) checks if the function has been called at least once. If (this.length > 1) checks if the function has been called more than once. Let's look at the else case first. We call our this as $el and call the init function where all the magic happens. But what if the toggleMenu function is called two, three or even four times? For each call, our function falls into else, creating many independent instances.
// main.js (function($){ $.fn.toggleClass = function() { var $el; var init = function() { $button = $el.find('button'); $button.on('click', function(e) { e.preventDefault(); $el.toggleClass('toggled'); }) } if (this.length > 0) { if (this.length > 1) { this.each(function() { $(this).toggleMenu(); }); } else { $el = this; init(); } } } })(jQuery);
We have created a very simple function that toggles the class when the button is clicked. Now all we need to do is call it when our document is ready.
// main.js (function($){ $(document).on('ready', function() { $(#element).toggleClass(); }); $.fn.toggleClass = function() { var $el; var init = function() { $button = $el.find('button'); $button.on('click', function(e) { e.preventDefault(); $el.toggleClass('toggled'); }) } if (this.length > 0) { if (this.length > 1) { this.each(function() { $(this).toggleMenu(); }); } else { $el = this; init(); } } } })(jQuery);
Voila! As you can see, creating a function in this way makes it really transparent and keeps your javascript file tidy. With this solution, you can call the function as many times as you like, and each call will be completely independent.
Hopefully the concept has been presented in a simple way. It will probably take me a while to implement comments on my website, so if anyone has any questions - I'll be happy to answer them. You can find me at hello@michalkotowski.pl.