views:

798

answers:

5

I'm currently building a single page AJAX application. It's a large "sign-up form" that's been built as a multi-step wizard with multiple branches and different verbiage based on what choices the user makes. At the end of the form is an editable review page. Once the user submits the form, it sends a rather large email to us, and a small email to them. It's sort of like a very boring choose your own adventure book.

Feature creep has pushed the size of this app beyond the abilities of the current architecture, and it's too slow to work in any slower computers (not good for a web app), especially those using Internet Explorer. It currently has 64 individual steps, 5400 DOM elements and the .aspx file alone weighs in at 300kb (4206 LOC). Loading the app takes anywhere from 1.5 seconds on a fast machine running FireFox 3, to 20 seconds on a slower machine running IE7. Moving between steps takes about the same amount of time.

So let's recap the features:

  • Multi-Step, multi-path wizard style form (64 steps)
  • Current step is shown in a fashion similar to this: http://codylindley.com/CSS/325/css-step-menu
  • Multiple validated fields
  • Changing verbiage based on user choices
  • Final, editable review page

I'm using jQuery 1.3.2 and the following plugins:

  • jQuery Form Wizard Plugin
  • jQuery clueTip plugin
  • jQuery sexycombo
  • jQuery meioMask plugin

As well as some custom script for loading the verbiage from an XML file, running the review page and some aesthetic accoutrements.

I don't have this posted anywhere public, but I'm mostly looking for some tips on how to approach this sort of project and make it light weight and extensible. If anyone has any ideas as far as tools, tutorials or technologies, that's what I'm looking for. I'm a pretty novice programmer (I'm mostly a CSS/xHTML/Design guy), so speak gently. I just need a good plan of attack to make this app faster. Any ideas?

+4  A: 

One way would be to break apart the steps into multiple pages / requests. To do this you would have to store the state of the previous pages somewhere. You could use a database to do this or some other method.

Another way would be to dynamically load the parts you need via AJAX. This won't help with the 54000 DOM elements though, but it would help with the initial page load.


Based on the question comments a quick way to "solve" this problem is to make a C# class that mirrors all the fields in your question. Something like this:

public class MySurvey
{
  public string FirsName { get; set; }
  public string LastName { get; set; }
  // and so on...
}

Then you would store this in the session (too keep it easy... I know it's not the "best" way) like this

public MySurvey Survey 
{
  get 
  { 
    var survey = Session["MySurvey"] as MySurvey;
    if (survey == null)
    {
      survey = new MySurvey();
      Session["MySurvey"] = survey;
    }
    return survey;
  }
}

This way you'll always have a non-null Survey object you can work with.

The next step would be to break that big form into smaller pages, let's say: step1.aspx, step2.aspx, step3.aspx etc. All these pages would inherit from a common base page that would include the property above. After this all you'd need to do is send the request from step1.aspx back and save it to Survey, similar to what you're doing now but for each small piece. When done redirect (Response.Redirect("~/stepX.aspx")) to the next page. The info from the previous page would be saved in the session object. If they close the browser page they won't be able to get back though.

Rather than saving it to the session you could save it in a database or in a cookie, but you're limited to 4K for cookies so it may not fit.

pbz
I'd prefer to go the AJAX route and load each part as needed. I'm just not sure what the best way to go about this is, as each page would also need to know which chunk of verbiage to get depending on what path a user chooses.
Patrick Alan
You would need to handle all that via some custom JavaScript. If the user chose path X then load Y and so on. From a usability perspective, if this is a huge form, I would recommend saving as many steps as possible. There's nothing worse than spending 20 minutes filling out a form and then not being able to submit it because the net went down or the browser crashed, etc. Any reason why you prefer the AJAX route?
pbz
So if I did something like, var verbiage = "verbiage radio button selected" and then each time I loaded a step, loaded 'verbiage' for that step? Could I save the information in a cookie? would that be a good idea? I prefer AJAX because I'm more comfortable writing with jQuery than I am with anything else.
Patrick Alan
You can save those things in an xml file or temporary table in db.
Sharique
+1  A: 

I agree with PBZ, saving the individual steps would be ideal. You can, however, do this with AJAX. If you did, though, it'd require some stuff that sounds like it might be outside of your skillset of mostly front-end development, you'd need to probably create a new database row and tie it to the user's session ID, and every time they click to the next step have it update that row. Possibly even tie it to their IP address so if the whole thing blows up they can come back and hit "remember me?" for your application to retrieve it.

As far as optimizing the existing structure, jQuery is fairly heavy when it comes to optimization, and adding a lot of jQuery modules doesn't help that. I'm not saying it's bad, because it saves you a lot of time, but there are some instances where you are using a module for one of its many functionalities, and you can replace that entire module with a few lines of jQuery enabled javascript.

As far as minimizing the individual DOM elements, the step above I mentioned could help slim that down, because you're probably loading a lot of extensible functions for those modules that you may or may not need.

On the back end, I'd have to see the source to see how to tell you to optimize it, but it sounds like there's a lot of redundancy in individual steps, some of that can probably be trimmed down into functions that include a little recursion, or at the least delegate some of the tasks to one another.

I wish I could help more but without digging through your source I can only suggest basic strategies. Best of luck, though!

NateDSaint
A: 

Agree, break up the steps. 5400 elements is too many.

There are a few options if you need to keep it on one page.

  • AJAX requests to get back either raw HTML, or an array of objects to parse into HTML or DOM
  • Frames or Iframes
  • JavaScript to set innerHTML or manipulate the DOM based on the current step. Note with this option IE7 and especially IE6 will have memory leaks. Google IE6 JavaScript memory leaks for more info.
  • Use document.write to include only the .js file(s) needed for the current step.

HTH.

Axl
A: 

Sounds like mostly a JQuery optimization problem.

First suggestion would be switch as many selects into ID selectors as you can. I've had speedups of over 200-300x by being able to move to id attribute selection only.

Second suggestion is more of a plan of attack. Since IE is your main problem area, I suggest using the IE8 debugger. You just need to hit f12 in IE8... Tabs 3 and 4 are script and profiler respectively.

Once you've done as much of #1 as you think you can, to get a starting point, just go to profiler, hit start profiling, do some slow action on the webpage, and then stop profiling. You will see your longest method calls, and just work your way through it.

For finer testing/dev, go to the script tab. Breakpoints locals etc are there for analysis. You can dev/test changes via the immediate window... i.e. put a break point where you want to change a function, trigger the function, execute your javascript instead of the defined javascript in the immediate window.

When you think you have something figured out, profile your changes to make sure they are really improvements. Just start the profiler, run the old code, stop it and note your benchmark. Then re-start the profiler and use the immediate window to execute your altered function.

That's about it. If that flow can't take you far enough, as mentioned above, JQuery itself (and hence its plugins) are not terribly performant, and replacing with standard javascript will speed everything up. If your plugins benchmark slow, look at replacing them with other plugins.

A: 

If anything about current interaction design can be called “glamorous,” it’s creating Web applications. After all, when was the last time you heard someone rave about the interaction design of a product that wasn’t on the Web? (Okay, besides the iPod.) All the cool, innovative new projects are online.

grüner tee