Search code examples
javascriptjqueryoopmodular-design

Modularize/Objectify JQuery


I have a number of different "control elements" on my application: dropdowns, tabs, menus, etc. On same pages, there are many of the same control. When writing JavaScript to handle the different events associated with each of these controls, I'm trying to make my code as DRY as possible. One of the challenges is modularizing my JQuery code so that events that occur within a specific control only effect that control.

Take this initial code for example, all it does is open a dropdown menu when it is clicked. I'm used to writing just a ton of different anonymous functions triggered by different events so this type of JQuery is really new to me.

var dropdown = {
  init: function() {
    $(".dropdown").click(".dropdown", dropdown.openDropdown);
  },  
  openDropdown: function() {
    $(this).children(".dropdown-menu").show();
    $(this).addClass("open");
  }
}

$(document).ready(dropdown.init);

My question is, within this dropdown variable, I want to be able to save/track different pieces of the dropdown control currently being acted upon. For example, I might want to write:

var menu = $(this).children(".dropdown-menu");

somewhere in this chunk so that I could refer back to this menu while calling different functions. I just cannot figure out syntactically how to do this. Any help/guidance is welcomed! Thanks.


Solution

  • Something I like about coffeescript is how it allows you to easily create classes. Classes in coffee are just a simplified way of generating "modules" using javascript's prototypal inheritance. More on that here: http://coffeescript.org/#classes

    But how YOU could implement more modular jQuery code is by doing something like this:

    http://jsfiddle.net/x858q/2/

    var DropDown = (function(){
        // constructor
        function DropDown(el){
            this.el = $(el);
            this.link = this.el.find("a");
            this.menu = this.el.find(".dropdown-menu");
            this.bindClick();
        }
    
        // method binding click event listener
        DropDown.prototype.bindClick = function(){
            var _this = this;
            this.link.click(function(e){
                _this.openDropDown();
                e.preventDefault();
            });
        };
    
        // click event handler
        DropDown.prototype.openDropDown = function(){
            this.menu.show();
            this.link.addClass("open");
        };
    
        return DropDown;
    })();
    
    $(function(){
        // init each .dropdown element as a new DropDown
        $(".dropdown").each(function(){
           new DropDown(this); 
        });
    });