Question

I've searched a little bit around SO and haven't found any questions/answers that are helping me. The problem is my jQuery function calls are getting much too large to maintain. I'm wondering if I should be refactoring a lot more or if there is a better way to do all of these calls. You'll see as I make one call, the anonymous functions that are arguments for the function end up being very large and make the readability of the code terrible. I could in theory break all these up into their own functions but I don't know if that's a best practice or not. Here is an example of some of the jQuery so far:

$('#dialog').html('A TON OF HTML TO BUILD A FORM').dialog('option', 'buttons', { 'Save': function(){$.post('/use/add/', $('#use_form').serialize(), function(data){ ......There were 4 more lines of this but I'm saving you so you don't rip your eyeballs out hopefully you get the idea.....dialog('option','title','New Use').dialog('open');

As you can see since so many of the functions I'm calling take functions as arguments, when I create anonymous functions I end up with a huge mess (there were about 3 more anonymous function declarations in this code)

Should I simply make a bunch of functions and call those to make it more readable. The only reason I'd be against this is because I'd have a bunch of functions declared that are only used once.

Thanks in advance for the help!

Was it helpful?

Solution

Define the functions in the correct scope and it's not a big deal.

var generateHTML = function() {
  ...
};
var somethingElse = function() {
  ...
};

... some more ...

$('#dialog').html( generateHTML() )...etc

There's not much else you can do except reorganize your code in general (say, using an object oriented style) to encapsulate code so it isn't so messy.

OTHER TIPS

The only reason I'd be against this is because I'd have a bunch of functions declared that are only used once.

Using anonymous functions as you are currently doing is really no different to declaring correctly scoped named functions, except that they are inline and make it slightly more difficult to debug in many JavaScript debuggers as the function name is not displayed.

If there are any patterns to your anonymous functions across pages, I would attempt to refactor named functions out that provide a common base to the functionality needed.

I'd be inclined to avoid having large strings of html within jQuery method calls or embedded inside JavaScript <script> tags and keep these in a separate location that can be easily queried to retrieve the relevant content - this could be text files, etc.

An obvious way to maintain maintainability is to use some sort of formatting.

I understand your dislike of naming singly used functions, but it's easy to contain the names. The javascript idiom to imitate a scope is to wrap the code in question in an anonymous function that's called immediately:

(function () {
  var f = function (x) ...
  var g = function (y, z) ...
  // operations involving f and g
}()); // called immediately

I prefer another form, which makes the fact that the code is executed right away more visible:

new function () { // called immediately
  var f = function (x) ...
  var g = function (y, z) ...
  // operations involving f and g
};

there's another way to create names with this:

new function (i, j, k) {
  // functions f and g
  f(i, g(j, k));
}(3, 4, 5);

Formatting, formatting, formatting! With proper use of whitespace your code CAN look readable:

$('#dialog').
    html('A TON OF HTML TO BUILD A FORM').
    dialog('option',
        'buttons', {
            'Save': function(){
                var callback = function(data){
                    // There were 4 more lines of this
                    // but I'm saving you so you don't
                    // rip your eyeballs out hopefully
                    // you get the idea
                }
                $.post(
                    '/use/add/',
                    $('#use_form').serialize(),
                    callback
                )
             }
         }).
    dialog('option',
        'title',
        'New Use').
    dialog('open');

This is just how I would personally format it. There are other ways but I'd strongly suggest leaving opening braces/brackets and coutinuing commas/dots/+ at the end of the line because javascript has a tendency to automatically add a ';' at the end of a line if it thinks the line is a complete well-formed statement.

The important thing is not what specific formatting rule you adopt. The important thing is to be consistent about it. In some ways Python was right: it's sometimes good to force people to indent their code (but I hate being forced by Python).

I'd try to decompose the code into plugins as much as possible and in fact design the code around this principle. Not sure how well that idea fits your needs.

It's easy to get into the never ending chaining problem in jQuery. Function chaining is good if used moderately, or it takes forever to read and understand code that was written like 5 minutes ago. In that sense, formatting your code as slebetman suggested would be helpful. In addition scoping your functions as suggested by just somebody or thenduks will also be of great help.

If you were to walk an extra mile in your refactoring efforts, I would suggest you consider some sort of architectural patterns such as MVC or MVP to organize your code. A List Apart has a nice article on implementing MVC with Javascript. If there is a separation of view and models, it easily gives way to using custom events and plenty of other additions that are easily reusable. It also forces thinking in terms of the domain model rather than DOM objects (tables, rows, divs) or events (click, keyup), etc. Thinking in terms of the domain model and associated events such as onPostRollback, onPostCreate or onCommentAdded that might be applicable on SO for instance. jQuery recently added support for binding custom events and these are some good articles (first, second) explaining how tos.

In general, its difficult to reuse views, but models change very little across projects and is one area where we can achieve maximum reusability.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top