0

These days I find myself putting a lot of my code in the $(document).ready() which does not seem clean to me. For example, if I am creating something that will query my database via ajax and return it and append it to my list i would do something like this:

$(function(){
   //Initialize my DOM elements
   $MyList = $("#MyList"),
   $MyButton = $("#MyButton");

   //Add my Click event
   $MyButton.click(function(){
      $.ajax({
         type: 'POST',
         url: "/lists/getmylist",
         contentType: "application/json",
         success: function(results){
            //Parse my results and append them using my favorite templating helper
            var jsonResults = $.parseJSON(result);
            $MyList.mustache("my-template", jsonResults);
         }
      });
   })
});

Now I know this is a small example but it starts to get really big and messy when I have multiple click events, ajax requests etc. It all ends up going in my document ready. I know that I can possibly put all my ajax requests in an external javascript file to help make it cleaner, but is this architecture in general ok? just seems like its really messy. I have seen others use plugin architectures or init functions. I usually have this document ready at the bottom of all my pages and just throw in whatever is necessary to make my page work correctly. Is this a good way to structure my js?

anthonypliu
  • 12,179
  • 28
  • 92
  • 154
  • 1
    I can migrate this over to our Code Review beta site if you'd like. You might get better answers over there. @ reply me if you'd like that. – Kev Mar 16 '13 at 17:39

2 Answers2

4

I think the addition of some Model objects and general object oriented programming principals might go a long way here. If you break your your data fetching and storing out into model classes it should help a lot.

Here are some links that should get you started thinking about OO with Javascript.

Writing Object-Oriented JavaScript

Javascript Design Patterns

Javascript: prototypal inheritance Javascript: prototypal inheritance 2

Another thing that might help out would be to break the Javascript into multiple files. One for global scripts that might be included via a header that attaches to all your pages and a script for each of your pages that requires it.

Community
  • 1
  • 1
Gunnar Hoffman
  • 1,226
  • 1
  • 11
  • 11
1

Perhaps Backbone.js ( or one of the other frameworks ) could be part of the rescue you are looking for.

I found Backbone immensely helpful organising some inherited spaghetti. Your starting point might be to transition your massive document ready into a backbone view (or multiples of)

Organise your scripts by separating out the views, collections, models into individual files then bundle and minify them together into a single file so the browser only needs to make one request instead of many.

ASP.NET MVC4 can do the bundling for you, it also works similarly on MVC3

This is just a example of simple starting point, there are more advanced techniques (eg. AMD, require.js) to reduce the script size per page, but with caching and gzip I find that the single everything script bundle is fine for a lot of cases.

As for your example, here's a possible backbone implementation

Remember to namespace out your code...

var app = app || {};

$(function ($) {

// depending on your server setup you might be able to just override the url
// and get away with what you want. Otherwise you might look into overriding
// the save/fetch or sync methods of the collection
app.MyListCollection = Backbone.Collection.extend({
    url: '/lists/getmylist'

});


app.MyListView = Backbone.View.extend({

//bind the view to the existing element in the HTML.
    el: '#MyList',

    // your mustache template 
    template:$('#list-template').html(),

    // hook up your event handlers to page components
//(within the context of your el)
    events: {
        'click #MyButton': 'onMyButtonClick'
    },

    //called on object creation.
    initialize: function () {

//you could create a collection here or pass it into the init function
        this.collection = new app.MyListCollection();

        //when the collection is changes, call the render method
        this.listenTo(this.collection, 'reset', this.render);
    },
    // render is named by convention, but its where you would "redraw" your view and apply your template
    render: function () {

    this.$el.html(
        Mustache.render(
            this.template(this.collection.toJSON())));

        return this;
    },

    //your click handler
    onMyButtonClick: function(e){
        this.collection.fetch();
    }

});
});

use your doc ready to spin up whatever backbone functionality you need and use it bootstrap your javascript with any server side data that you may have.

$(function () {

// create an instance of your view
new app.MyListView();

//example bootstrap using razor
app.title = @Model.Title;
});
HaveThunk
  • 230
  • 1
  • 7