0

In my app I have jquery that is specific to each page, that is scripts that are used strictly on one page. Is there a way to set a scope that I can work within to avoid any id/class collisions or behaviour creeping from one page to another?

I could do this, for example by specifying the wrapper div for the specific page

$(function(){
  $('#thing_page input.finder').focus(function(){ ... })
});

but I would need to prepend all the event bindings with the name of the page wrapper, which is a bit annoying.

For those who don't know, rails compresses all the javascript files in to one, which I like. Otherwise I could just include each file on a specific page.

recursive_acronym
  • 2,981
  • 6
  • 40
  • 59
  • 1
    i started a discussion very similar to this previously. might be of help to you: http://stackoverflow.com/questions/7582176/managing-document-ready-events-on-a-large-scale-website – WickyNilliams Jan 11 '12 at 15:41

2 Answers2

1

You can wrap it all in a giant switch statements. Assuming thing_page is the id for the body, you could do this:

$(function() {
    switch (document.body.id) {
        case 'thing_page':
           // Do stuff for thing page
           $('input.finder').focus(function(){ ... });
           break;
        case 'other_page':
           // do stuff for other page
           break;
        case 'third_page':
           // Do stuff for third page
           break;
        // ...and so on and so forth...
    }
});

The syntax highlighting here is pretty bad. Take a look at it in jsfiddle: http://jsfiddle.net/dFuVz/


Alternatively, you might consider using an object to contain your functions (similar to @Andrew's approach):

var pageFunctions = {
    thing_page: function() {
        // Code for thing_page
        $('#thing_page input.finder').focus(function(){...});
    },
    other_page: function() {
        // Code for other_page
    },
    third_page: function() {
        // Code for third_page
    }
};

// Now call the correct function, according to the body ID
pageFunctions[ document.body.id ]();

Again, since the syntax highlighting here is so terrible, look at it here: http://jsfiddle.net/9L592/

Joseph Silber
  • 214,931
  • 59
  • 362
  • 292
  • Mr. Silber's approach is a perfectly valid one. At some point, you may want to investigate JavaScript AMD as a way of managing page-specific widgets and needs - it's where the industry is moving in general, and it's a very good way of loading only what's necessary. Here's an introduction: http://unscriptable.com/index.php/2011/09/22/amd-module-patterns-singleton/ – Nate Jan 11 '12 at 15:44
1

Because functions are first class in javascript, you can effectively wrap each page's entire functions and variables in an object, then make calls to that object:

var allPages = {
    thingPage : function() {
        $('#thing_page input.finder').focus(function(){...});
    },
    nothingPage : {
        index: 0,
        removePost : function() {
            $('#nothing_page .post').find('p').remove();
        }
    }
};

And then you would invoke the functions by calling allPages.thingPage() or access a variable with allPages.nothingPage.index.

Also, read the "Functions Declaration" part of Douglas Crockford's article on Javascript code convention. Specifically, "When a function is to be invoked immediately, the entire invocation expression should be wrapped in parens so that it is clear that the value being produced is the result of the function and not the function itself." That technique is similar to what I wrote above, but probably more along the lines of what you should do.

Andrew
  • 1,081
  • 1
  • 8
  • 19