Archive for the ‘javascript’ Category

Our Back Button Story

May 9, 2007

Ah, the back button. That thing users want and don’t understand why it isn’t so simple anymore. Our project has a user story for the back button. It described a specific set of scenarios and what the users expectations were for when the back button was clicked. Suprisingly enough, it was easily one of the biggest stories for us in terms of difficulty and time to implement. I just wanted to talk through our path to making this story work. The back button is a fun, difficult challenge to be sure ;)
For the impatient, I’ll lay it out for you right up front. Put simply, the approach we were able to take to tackle the back button was as follows:

  • Have a client-side model that represents the state of the app (the user’s search criteria in our case)
  • Serialize that model (JSON) and post it to an iframe in response to user actions (actually, ours had a 300ms dirty-check interval that would post to the iframe).
  • Have the content that is loaded in the iframe notify (call a function) on the parent window passing it the result and the model used to get that result (basically just echo back the serialized model alongside the results).

And the longer-winded walk-through:

The site is for a real estate company. It allows users to find listings based on the typical (and some custom) criteria they specify via some widgets on the page. As they make their selections, the results are ajax-erifically loaded for them in the results area. They can page through the results and click on a listing to see further detail. The detail page is a full page load with a restful url.

From what I’ve described so far, the back button should behave as follows:

  • If the user is viewing page 3 of the results, then goes to page 4, the back button should take them back to page 3 of the results.
  • If the user is on a detail page, the back button should take them back to the results (and it should be on the correct page if the user was paging).

Sounds simple enough right? In Web1.0, this is no big deal. The user changes search criteria and clicks ’submit’, server answers with the results and pre-populates the page with the users’ criteria. One full-page load later, the page has everything it needs wired right into its very source code. User adds more criteria, clicks submit and voila, another page load and another full page that has all the data it needs. Click the back button and that first page returns…still wired up with the results AND the criteria for that page…as though the last page load never even happened.

Web2.0(-ish, there really isn’t a social aspect to this app, but its more lively that the typical sites) we want to stay on the same page…just load the results portion. This makes the user experience more fluid as the page reloads tend to be more jarring. It should also be more performant as there is less to render (fewer database queries) and ultimately less data to transfer.

The first task to handle is actually getting some results via ajax, and this is fairly simple. The user makes their selections and an ajax call is made to get the matching results. The results are then plopped into a div on the page when they return. The server code is pretty straight forward, simpler than 1.0 even, because it just has to answer the specific question and render only the results. No need to re-populate the user’s criteria. Now, how to handle the back button?

As described, the back button will do what it was designed to do: take the user to the previously viewed page. When the user is searching in our app, they are only ever on one page, so nothing they are doing is added to the browser history. The actions that they expect to be able to be ‘backed out’ of are not. For the back button to EVER work, we needed to have our ajax code add to the browser history.

One approach (described http://dojotoolkit.org/node/100) is to simply add to the fragment identifier portion part of the url (everything after the #). The browser treats these as links to elements within the current document and will attempt to scroll to the element whose id matches the hash value. So it will add to the history, but it won’t reload the page. In our case, we’d do this for every criteria change or pagination change (switch from results page 3 to results page 4).

At this point our app would be adding to the ‘history’ and the back button would be changing the url…but the results won’t be changing just yet because we don’t have anything to respond to/reset the results when the back button was clicked. Essentially, we need to store some state (the users criteria and the results) with the value we put on the url, so that when the back button is clicked, that state can be restored. That is exactly what the dojo undo and the RSH and others do for us…but we have to have clean urls so adding #’s to the current url won’t do.

The other approach is pretty old-school. Load the results via a hidden iframe. As the user changes criteria we modify the src of an iframe to get the results instead of via an XmlHttpRequest. The iframe src changes are added to the browser’s history as well. We’d need a way to know when the iframe was ready with the results so that the page could pick them up and display them. We knew that some ajax frameworks would degrade to using an iframe approach when a proper XHR is not available…but the simplest thing we could get to work at the time was to have an onload in the result content that the iframe loaded that would tell the parent window what the results were by calling a javascript function on the parent. Basically the results would announce themselves to the containing window. (In hind-site our final approach may be more re-usable if we switch to monitoring the readystate of the iframe via and onreadystatechanged handler).

So at this point, we have results loading in the iframe, then the iframe telling the parent that results were loaded and the parent placing the results on the page. When the back button is clicked, the iframe loads the previous page of results (because iframe src changes are added to the browser history) and the iframe again tells the parent that results were loaded and the parent displays those results. And we still have our pretty urls ;)
However…we don’t have the correct criteria. The iframe only loads the results. So if the user changes the criteria a few times, then clicks the back button, the results will ‘go back’ but the criteria will not change, so they still appear to be the last criteria used. Not only that, but if we load a detail page (those are full page loads) and hit the back button, the correct results page will load, but there will be NO criteria present (because the criteria change on the page dynamically and hence are not part of the source that is restored by the back button…and the iframe that IS restored only has the results). If only the criteria were part of the results…

That’s pretty much what we did. We decided that we needed to have the results page also pass along the search criteria. When loaded, the results AND the criteria used to get those results would be passed along to the parent. Then the parent would render the results and restore the criteria.

The real key in simplifying the back button problem was to organize our javascript into true objects and have a model that could be used to represent the state of the page. That model could be passed around via the iframe and restored with ease in response to the back button. The road to refactoring the javascript to get to this point is another interesting topic for another day.

Thinking out loud, it would be interesting to revisit the RSH and dojo approaches and see if there could be a hybrid to what we needed to do here (or maybe they could already support what we need and we just didn’t see it ;)). I’m thinking like an api that would make an XHR call, then when the results come back, adds a # to the src of an iframe, then puts the result text as well as the model into an input in the iframe. There would be a readystatechanged listener on the iframe that would attempt to restore the state of the parent page from the ‘results’ and model stored in the iframe.

Sorry, no code for this one…just our story.

Binding to Views

March 26, 2007

I’ve landed on something of a simplified View object that can be used for javascript widgetry. The notion really is that the views are just some template
html string that gets plopped onto a page and bound to a model and a controller. This implementation takes that pretty literally. The View expects a model, controller, peer element (where it should ‘paint’ its template), Template, and Binders. Subclasses should just pass the right thing to the View constructor. The TaskView became quite simple when it switched to using the base View:

var TaskView = function(_task, _viewPort){
	View.call(this, {
             model:_task,
             controller:this,
             peer:_viewPort,
             template:TaskView.Template,
             binders:TaskView.Binders
        });
}
TaskView.extend(View);
TaskView.Template = '<input type="checkbox"/><span></span>';
TaskView.Binders = [
	new ModelBinder(new TagNameLocator('input',0), 'checked', '_complete'),
	new ModelBinder(new TagNameLocator('span', 0), 'innerHTML', '_description'),
	new EventBinder(new TagNameLocator('input', 0), 'click', '_handleCheckboxClicked')
];
TaskView.methods({
	_handleCheckboxClicked: function(event){
		if(event.target.checked){
			this.getModel().complete();
		}
	}
});

What’s going on here? The TaskView constructor just calls the super class constructor with the params it wants: model, controller, peer element, template, and binders. Thats a lot of args, and we may be able to help that with some good conventions. But what are all the args for?

  • The model is the data that the view will display.
  • The controller is meant to handle the behavior of the view. User gestures (mouse clicks and such) are ‘bound’ to methods on the controller via EventBinders.
  • The peer is the html element the view should “paint” into.
  • The Template is..well…the “template” or “mock” markup for the view.
  • The binders are what bind behavior and data to the view. ModelBinders are for binding bits of the model to bits of the view. EventBinders are for binding user gestures (html events) to methods on the controller.

OK, but how does it get put together? The View constructor will set the innerHTML of the peer element to the value of Template and then iterate over the binders telling them to ‘bind’ to the peer. Binders use Locators to find the html elements to bind to. The TagNameLocator will find elements with a particular tagName. Optionally, it will take an index which would make the locator only return the N-th element with that tagName where N is the index provided.

So, in the TaskView, there are 2 ModelBinders and 1 EventBinder. The first ModelBinder binds the ‘checked’ attribute of the first ‘input’ element to the ‘_complete’ property of the model. The second ModelBinder binds the ‘innerHTML’ attribute to the ‘_description’ property of the model. In both cases, the Binder creates a ModelBinding object which becomes an observer of the model and will keep the model and html element in sync. The EventBinder binds a ‘click’ event on the first input to the “_handleCheckBoxClicked” method on the TaskView (which is serving as the controller here).

Not too bad I’d say. Needs some work still though. My first thought is to
take the template and binders out of the call to the super constructor and make them smart defaults. If the super class constructor doesn’t have them in the call, it can look on the subclass for a ’static’ Template and Binders fields. Another thing I’d like to do is have the ModelBinder support methods as well as properties, so it could bind the return value of a method (that way we can bind to ‘getDescription’ instead of ‘_description’).

Maybe tomorrow.

Views Clearing Up

March 17, 2007

Made some more progress on the TaskList widget. Sure feels like I got off on the wrong foot or something…its been changing a lot. I guess its really just been cleaning up more than really changing. At any rate it is moving along and I’m starting to get a clearer picture of what the views are supposed to be doing and how contained they really can be. Today’s progress was made in the TaskListView2_UT.html.

I’m thinking about heading in a Template direction with it next. I really don’t like the idea of locking up all the markup into javascript dom element creation. Templates are much easier to read and easier to modify. The template work should start in TaskListView3_UT.html.

Smaller Steps or Less Wine

March 17, 2007

“They” say that you should take small steps when refactoring. Super small steps at first. Then as you become more comfortable with the pace and are more confident in your ability to do specific refactorings, you tend to start taking bigger steps. And if you have some trouble…back off the changes and take smaller steps. I was doing a refactoring last night and I took too big of a step. It took me an hour to finally back off and take smaller steps. I was SO confident in the code I’d written that I was refusing to accept it was flawed. Once I backed off it took one test to find the culprit:

$A = function(){
	var arr = new Array();
	for(var i=0;i<arguments.length;i++){
		var currArr = arguments[i];
		for(var j=0;j<currArr.length;j++){
			arr[i+j] = currArr[j];
		}
	}
	return arr;
}

That logic (problem part colored in red) made perfect sense to me…in my defense I was on my third glass of wine ;)
This is basically prototype’s function that ‘casts’ the provided object to an array. This one supports passing multiple iterable objects (any object with a length property whose members are index-accessible) and it will effectively concatenate them. There is a concat method on an array object, and I’d love to just use that, but you can’t pass the ‘arguments’ variable to the array ‘concat’ method…and that is what I needed to do.) I could have just used prototype. I really like some of what prototype provides, but (I’m sure this has been said before) I don’t want to pull the whole thing in just for a few of the functions I like. Some folks have the same issue with open source java code, but that isn’t as big an issue to me as the javascript one…anyway that’s another post.

Moral of this story: take smaller steps or drink less wine ;)

Not the Simplest Thing

March 15, 2007

I realized last night I’m probably not *REALLY* doing the “Simplest thing that could possibly work” with this Test First Javascript Widget. If you’re nodding your head thinking “Umm…yeah, you could do that with like 2 lines of javascript” you’re right. With the simple requirements I listed, you could accomplish the TaskList with and input and a button with an onclick that adds a row to a table with a checkbox. Obviously I’m diggin for more depth in the implementation.

Perhaps its because I’m the customer? I know i’m going to eventually need to persist these tasks, and potentially need to handle a back button. I also (since i also have the customer hat here) know that I’m wanting to support nested sub-tasks. When a parent task is completed, all of its child tasks are marked completed as well…and when all child tasks are completed, then the parent task is automatically marked as complete. If only part of the sub-tasks have been completed, then the parent task is put in a ‘partially completed’ or ‘in progress’ state.

So really I’m coding for more requirements than I’ve let known. I’m not sure if that’s being fair to the process…but its and experiment.

I had a little time to kill tonight so I knocked out some refactorings that I was itching to do. Check them out on the TaskListView test page. (The stuff I did today is about half-way down…I dropped in an HR and today’s date…probably should have just started a new Test file).

Test First Javascript

March 11, 2007

I want to try an experiment. My goal it is to demonstrate how good OO principles and patterns can be applied when solving a problem with javascript. To achieve this goal, I’m going to develop a custom javascript component Test First and try and document the process as I go. I’m hoping this will also help me with some ideas I’m struggling with in the javascript component arena.

The component is a Task List. The first set of requirements are:
The user can add tasks to a list
Tasks are just a short description of what is to be done
The tasks can be marked as complete

The tasks won’t be persisted right now. It will just be in the browser. I know thats not a lot…but I’m the user and I can clarify as we go ;). Each page in this experiment is a JS Unit test page. I’m gonna do my best to communicate what the thought process is for each test and for each refactoring. The ‘thoughts’ will be followed by the test code and then the Task List code that made the test pass. Changes are in red. The test code background is blu-ish…and the code background is gray.

I’ll post more blog entries as the component progresses. You can follow the progress of the tests here. Each test page will link to the next at the bottom. At the top of each test page is a link to open the jsunit test runner for the page.

Automated Tests with Junit + Selenium + JsUnit

March 21, 2006

I plan to have a more cohesive post on the process I went through and some of the specific tweaks I had to make…but right now excitement has the best of me and I’m going to let the keys fall where they may.

Recently, the project I’m on REALLY needed some automated testing. We had (have) a rich web-app (ajax/dwr) and were beginning to feel very uncomfortable without tests…a bit like going “without a net”. We had been researching Selenium for the integration/ajax testing and jsunit for some (although admittedly very few) of the javascript objects/classes/widgets we had written, but nothing automated. It was time…so I dove in.

To make a long story short, what I have today is Selenium integrated jUnit tests. The jUnit Tests look like this:

public class SomeScreenTest_UT extends BaseSeleniumTestCase{
public void testCanSearchOrders(){
open(”/products/search”);
assertNotVisible(”searchResults”);
type(”searchField”, “amber bottles”);
click(”searchButton”);
waitForValue(”searchStatus”, “complete”);
assertText(”resultsMessage”, “Found*”);
}
}

Upon execution, a browser will open to the SeleneseRunner.html and will begin running the tests. It is really pretty sweet. The base test case we’re using will open the login page and login first on setup. Then the tests do their thing and if a selenium assert or command fails, then the junit test fails.

I managed to get this working with Selenium 0.6.0.  I wound up implementing a SocketBasedCommandProcessor (can you guess what it does?) as well as a client to go with it. Extended DefaultSelenium to have SeleniumDriver (I needed to have more control over the url the browser would open…and I didn’t like the name). Also implemented a SeleniumDriverServlet to go along with it (the browser talked to the servlet…which talked to the processor via the client). I was pretty proud of it…even followed (fairly) strict TDD.

After implementing all this, I got to REALLY pouring through the Selenium code (last night) and noticed a few interesting classes…namely CommandBridge and CommandBridgeClient. In short, they do (or appear to do) what my implementation does, just without the sockets. It would have been REALLY nice to know about them first. I honestly felt I was tricked :) The docs are aparenly out of date and some of the examples refered to code that has been moved. When I couldn’t find them, I though they were just making suggestions ;) So one strike against the docs (btw not even the wiki has any mention of them). Even when reading the package structure, it wasn’t at all clear to me that the ‘outbedded’ package and the CommandBridge (which IS a servlet) were what I needed to get a servlet that talked to an external tomcat process…especially when nothing from the actual servlets package seemed to fit. Go Figure.

But after reading the forums, I’m not so sure the CommandBridge code even works. Aparently the “driven” stuff is undergoing a huge overhaul and is now going to be called “selenium remote control”. Which is good really because these guys have some good stuff under the hood and it just needs to be a bit easier to use. It could use some better names, and packaging…and definitely better docs, but it is still some great work.

Also, just today got Selenium to drive the jsunit tests for the app.  That was cool too…we needed jsunit to run in the build as well and I figured we already had this selenium setup, why not have IT drive the jsunit tests too.  It took some tweaking because jsunit expects to be the top level frame, but it worked.   I should mention that I do prefer to have jsunit run without need of the server running…and we still have that ability, this was just an easy-ish way to get it working with something we already had, just for the continuous integration.  I also know that jsunit has a server bit that ant can drive, but we wanted to be able to make it work just by running the junit test, this gives us that…no need for ant to kick anything extra off, just make sure the local server is running, which it usually is).  The test suite that selenium ‘drives’ is actually a jsp (so there IS one benefit to having the server running) that will scan the js folder for all _UT.html files, and adds the path to them to the test suite.

Gentleman’s Privates

February 25, 2006

In Javascript, you can have true private methods and fields, but it comes at a cost…both a readability cost and a performance cost. It basically involves creating closures in the constructor. Those closures are attached to ‘this’ reference and since they are closures defined in the scope of the constructor, they have access to any of the constructor’s local variables. An example may prove useful:

function Foo(){
var privateField = “Only setPrivate and getPrivate can see this field”;
this.setPrivate = function(value){
privateField = value;
}
this.getPrivate = function(){
return privateField;
}
}

I first learned about this over at Douglas Crockford’s site (this guy knows his stuff…read it!). He as great explanation of private members in javascript.

At the moment (and I’m sure this can change) I feel this is a bit overboard for most cases. I think I may be more turned-off by the readability…I just can’t bring myself to be ok with having the methods defined IN the constructor. I understand this is the only way to have TRUE private members…but I’m thinking that I’d be ok with Gentleman’s Privates. That is to say, using a notation that tells the user (developer using, reusing, extending or otherwise interacting with the class or an instance of the class) that the variable is meant to be private…”so, be a gentleman and don’t access it directly”. Sure, this leaves the door open for abuse…breaking encapsulation. But if the convention is known…then the developer KNOWS they shouldn’t be directly accessing the variable (even though the language doesn’t enforce it). And by doing so, they run the risk of becoming too tied to that implemenation of the class.
Naming conventions for private members is done all over the place…even in languages that support true private members (no I don’t). I can’t find it with a quick google, but I’m sure I first heard this approach in reference to Perl. It was something to the effect of describing Perl as a “Gentlemen’s Language”. Basically meaning that the language didn’t enforce any access restrictions, but the developers were ‘gentlemen’ about it, and followed the rules of the naming conventions. The typical convention for private members (as I understand it) is to prefix the variable with an ‘_’ character. In my experience, many developers understand this convention.

I prefer the Gentlemens approach to private members in javascript.  I don’t want to get hung up on trying to lock my object/class down to prevent any abuse: jumping through hoops trying to get access priveleges that are not enforced by the language. Let’s just be gentlemen about it.

Ok, all that said, I was thinking a bit about the naming convention itself. The ‘_’ prefix is well known, so it’s tough to just say ‘lets change it’, but I’m thinking…’lets change it’. How about ‘ _’? That is SPACE-Underscore…as a prefix for private members. This forces the developer to access the member via the bracket notation: obj[' _somePrivate']. This has a few benefits in my mind. First, it isn’t natural which means you’ll have to think about it and say “well…it IS private…maybe I should try something else”. Second, its not pretty…so a developer may decide to modify the design (if its his code) so that the member is exposed, or it supports whatever the caller was trying to do via a new method.

The negatives are actually the same as the benefits…but the caller is the class code itself. So the class has to access its private members through the same bracket notation, which is still not natural, and still not pretty. Given that the private members should (by definition) only be accessed by the owning class, this may seem like just an annoyance and may find developers quickly abandoning it.

In the end…I guess I’m up in the air about it. I like that it will make it more work for developers to access it when they shouldn’t (from outside the owning class)…but I don’t like that it will also be more work for developers to access it when the can/should (from inside the owning class). And in the end, maybe ‘_’ should send up the same flag to the developer as “[' _']“.

What are some of your thoughts?

Class.js - third time is the charm

February 24, 2006

Say you want to override a method by adding a new impl directly to the instance. callSuper should be callable from that new overriding method and it should result in the closest ancestor impl being called…even if it only has to go as far as the instance prototype (technically, the instance’s constructor’s prototype). Well…the code I had up wouldn’t really support that. It would skip over the instance prototype. The latest will support this.

Maybe I should start versioning :) I definitely need to have tests.

Class.js

Bug in Class.js

February 23, 2006

Found a bug and fixed the version that the previous posts point to: Class.js

Basically, the callSuper would not work if the method was not implemented at the beginning of the chain. For example if you have classes A, B, and C, (where B extends A and C extends B) and B and C implemented a toString then calling toString on an instance of A would result in an infinite loop. With the updated code, an array is built to represent the prototype chain, and that array is traversed IN REVERSE until it finds the calling function. Then it grabs the NEXT prototype in the chain and executes the method if it exists. No need to search and keep digging throught the chain to see where it is implemented…because the built in chain traversal will do that for us (pretty much the same reason the bug was occurring).

Anyway code is fixed and re-posted.