Alex
Alex

Reputation: 77329

Central Management of Javascript

How do you manage Javascript content on a larger website? I'm especially struggling with various $(document).ready()'s and the fact that I need to juggle all those id ($('#id')) strings. I thought of combining the necessary $(document).ready() with each "module" that uses them but this results in visible speed degradation as I don't have my javascript at the bottom of each page anymore.

What is a good way to manage Javascript of a fairly large site efficiently and keep it easy to maintain?

Upvotes: 2

Views: 195

Answers (4)

yonkeltron
yonkeltron

Reputation: 643

If you are looking for a good resource on writing good and clean JS, you might want to look at Douglas Crockford's book JavaScript: The Good Parts as it contains many useful resources including tips on how to structure code well.

When I write apps which have a lot of JS, I typically create a single object (so as not to clutter the global namespace) and then divide it into sub objects which contain various bits of application data and behavior. A small example:

var PandaApp = {};
PandaApp.setup = {};
PandaApp.setup.init = function init() {
  // do something neat
};
PandaApp.utils = {};
PandaApp.utils.showMessage = function showMessage(msg) {
  // do some jQuery goodness or something
};

That way I have exactly one global object with all of my data in it and everything is neatly-namespaced in a manner of my choosing.

Upvotes: 0

Chris Moschini
Chris Moschini

Reputation: 37967

Look at how libraries like Dojo and ExtJS manage this for ideas. They use functions like require() to fetch scripts they depend on dynamically, and to ensure those common libraries aren't loaded twice. They define events to handle load dependencies, so that for example your large list of .ready() statements can be refactored in some places to instead be one important library initializing, then firing off one or more events to indicate certain things are ready, which other libraries use as their cue to initialize.

One thing I like to do once multiple coders are coding against the same codebase is to use the HTML/DOM as a mutual contract, and have code tie into it with selectors, as opposed to allowing inline events.

For example, if you write a calendar control that has an onclick on the img tag that has to show the calendar, you're making it very difficult for 2 other libraries to come along and key off of the "a calendar control is about to pop up" event. On the other hand, if the library looks for items with CSS className "calendarPick" and attaches an event to them, then you leave open other libraries to do what they will with the same DOM you're sharing, with little or no coordination between coders (writing code that demands coder coordination tends to slow coding down and increase the chances something will break).

If that same Calendar library offers some events to key off of it helps other coders get their work done, since if the event is already there they'll likely write it cleanly; if it's not they're more likely to hack it and make the code base less flexible in the process.

If you offer singleton methods, for example Calendar.getCalendars(), you'll help make working together easier as well because it prevents people from writing their own version of these methods, locking an implementation in to a specific set of class names, DOM order, or even more fragile circumstances so that everyone's version of this continues to work.

Upvotes: 1

andres descalzo
andres descalzo

Reputation: 14967

this is something that occurred to me at this time, I hope you can help. be responsible for an orderly call methods of each module, and all are called in one event ready. what level is in case you need to call any module before another

// Call the initial organizer of each modules
var modules = (function(){

    var level_0 = new Array();
    var level_1 = new Array();
    var level_2 = new Array();

    return {
        add: function(method, level){
            var returned = true;
            try{
                switch(level){
                    case 0:
                        level_0.push(method);
                        break;
                    case 1:
                        level_1.push(method);
                        break;
                    case 2:
                        level_2.push(method);
                        break;
                };
            }catch(ex){returned=false;}
            return returned;
        },
        callAll: function(){
            var returned   = true;
            var returned_0 = true;
            var returned_1 = true;
            var returned_2 = true;
            try{
                returned_0 = this.call(0);
                returned_1 = this.call(1);
                returned_2 = this.call(2);
            }catch(ex){returned=false;}
            return ((returned && returned_0 && returned_1 && returned_2) || false);
        },
        call: function(level){
            var returned = true;
            var level_call = null;
            try{
                switch(level){
                    case 0:
                        level_call = level_0;
                        break;
                    case 1:
                        level_call = level_1;
                        break;
                    case 2:
                        level_call = level_2;
                        break;
                };

                if (level_call!=null)
                    for(xcall in level_call)
                        level_call[xcall].call();

            }catch(ex){returned=false;}
            return returned;
        }
    };
})();

//in each file JS with ini method in module
modules.add(function(){alert("method file/module A in level 1 a");}, 1);
modules.add(function(){alert("method file/module B in level 1 b");}, 1);
modules.add(function(){alert("method file/module C in level 0 a");}, 0);
modules.add(function(){alert("method file/module D in level 0 b");}, 0);
modules.add(function(){alert("method file/module E in level 2 a");}, 2);
modules.add(function(){alert("method file/module F in level 2 b");}, 2);
modules.add(function(){alert("method file/module G in level 2 c");}, 2);
modules.add(function(){alert("method file/module H in level 0 c");}, 0);


// single call to the event ready
$(function(){
    //call all
    modules.callAll();

    // OR

    //call in other order 
    modules.call(0);
    modules.call(2);
    modules.call(1);
});

Upvotes: 0

Jonas B
Jonas B

Reputation: 2391

I dont know what your environment looks like. But I guess spliting the script into different segments. All code that is specific for a particular page or function should go into it's on javascript file.

Next is good naming conventions and standards.

Last but most important, document everything. When a page changes you should be able to look in your documentation what scripts it may effect. In the same way the documentation should be able to tell you what script does what in what pages.

I know this is not a direct answer to your question, but it will make maintaining easier in the long run. Especially if you are many people working on the same project.

When it comes to maintainable code, naming conventions again is very important. Both in the html and javascript part. Also javascript variables and functions should reflect the html code as much as possible. For example, if you have a form id = "banana" dont name the variable holding it "apple".

Upvotes: 0

Related Questions