Best way to detect browser state changes - javascript

And with state I mean URL changes, preserving browser history.back() and being able to update the page (through a callback I guess) when there is any change.
I've tried several methods, and each one has its pros and cons.
For example, I like the way Backbone.js manages the URLs with its Router because it works via the window.location.hash (#) and if you change the URL manually it's catched by the Router allowing you to perform manual changes in an easy way.
The thing I don't like about Backbone is the URLs being in this format "#/a/b/c/d/e" (against the classic http standard "?a=1&b=2&c=3". That means that the URL parameters needs to be in certain order and they don't have name. Of course you can fix that parsing the URL and treating the Router expression as a single string, so it's not a big problem.
Also, I think using Backbone just for its Router it's a bit overkill (including the whole BackBone just for that), so I'd like other solutions.
The next one is History.js, which is supossed to provide compatibility for the new HTML5 standard?
But I don't like its behaviour as much as the Backbone's one. I mean, in an HTML5 browser, the # is converted to ? and if you change something in the URL the whole page is reloaded.
Also, due to its lack of Router, you need to set some more listeners, like $(window).bind('statechange') and $(window).bind('hashchange'). Again this is not a big problem, but I'd like to know if there are other ways to do this.
I always say that "there's no a right way to do something, but different ways to achieve it". But to be able to choose one of that ways, I'd like to know about different possibilities.
What do you think about this problem, which is more and more common when developing Single Pages?
I've researched a bit, but all the answers I found are quite old (> 1 year+) so I'm interested on the state of art...

Related

How to Manage Changing of Views?

Should I use a router to manage changing of views? Currently, I'm using a 'parent' view to handle 'child' view management.
I have multiple 'child' views within a single parent. Child views/pages are changed by clicking links, which also modifies the URL. The changing of the displayed view is handled by the parent view -- NOT a router. The router in question has nothing of value coded, I created the 'dummy' router so I could use Backbone.history
I suppose you searching for some sort of validation that this is a proper way to construct your application. From the limited information you've given, it's hard to say, and even if you did provide some code, your question might not be definitively answerable, either.
So, let me just put it this way. I don't think there is any flaw in creating Backbone.js views that are composed of other views. I do think there's something wrong if you're putting everything related to view changing in the router--unless you're giving some sort of high level description there--like passing in views the parent view should show/attach events to/something else.
Another point. How are the child views related? Might some of them have a common (high-level) interface? Or does your parent view wrap disparate things, like a search form and some grids and labels? Or both? Is there some chance that this parent view might be useful on another page, or is it just going to manage this particular pages views, etc. All this matters.
I suppose there might even a reason to question as to whether or not your parent view should strictly extend from Backbone.View or should have some other sort of "base" class. But if it works and has some reasonable connection to being a "view" I wouldn't bother asking that question. As Jeff Attwood has said, "meta is murder". At some point these kinds of discussions become impractical, and when there are still important issues to be fixed or implemented, it's best to leave reasonable solutions be.
My thinking is if you are using the router to control and delegate things to the parent view, and let the parent view do it's things with it's child views, you probably fine.
You might want to consider passing in the child views through parent view's constructor in the router, though. It's often better, but not always better, to have a separate thing determine the composition of an object than to let the object create it's composition itself. But always go for transparency as well. Sometimes the freedom you get with dependency injection isn't worth the obtuseness of abstraction your code; especially if you're not quite sure what you're doing. Figure out what you're doing, then consider the abstractions you may not have thought of.
If you want to know if you are doing things consistent with the community's ways of doing certain things, you probably ought to go to the backbone.js Google discussion group and review or ask questions the questions there as well.

Versioning a JavaScript single page web app? (querystring)

I have a Single Page App with some static routes such as:
example.org/#!/tools/
example.org/#!/stories/story-1/
These are examples of routes that don't need any versioning. Either the "page" exists, it has been redirected or it is non-existent.
But then I have other resources I'd like to version (because they can have internal states - denoted with a querystring of > 10 parameters):
example.org/#!/tools/population-tool/ + ?a=b&c=d[...]
Because the querystring paramaters might change over time (as the tool might allow more options), I'd like to add a version parameter to these "pages":
example.org/#!/tools/population-tool/ + ?v=1.1&a=b&c=d[...]
So that when a user navigates to the URL without any parameters, the default state and version is automatically added:
example.org/#!/tools/population-tool/ =>
example.org/#!/tools/population-tool/ + version + default state
In case the user decides to share/bookmark this URL, the version paramater will always allow me to remap the paramaters from one version to another.
Can you suggest a better approach?
Perhaps the version should be a part of the url for all routes?
example.org/#!/v1/tools/population-tool/
Or perhaps versioning the querystring is the wrong approach
altogether? Perhaps I should have a method that guesstimates the
right "API" based on the parameters given?
Thanks.
Guessing the right API from parameters can be tedious and will lead to unnecessary complexities in your routing sub-system. It is much more cleaner to having the version information clearly specified in the URL.
Now whether the approach to be followed is 1 or 2 is much of a matter of taste. In my opinion it depends on how perceivable your application version is to the end user. If your end user does not perceive an change in the front-end (ie. if you are following an MVC architecture and the change is only the Model layer while the view layer remains unchanged then approach 1 is more recommended. Where as if it is important for the user to be aware of which version he is using or if the user-interface visible to end user is different across versions then approach 2 is a better option because it puts the version information in a prominent position in the url.
Another way of looking at it can be asking the question if application state is different between versions. A url (sans the query parameters) represents the application state and in case the answer is true then 2nd approach should be followed. However if the version information is abstracted away from the main application code and is relevant only to certain abstracted sub-sections eg. only a few model classes then approach 1 should be followed.

How Can I Modify/"Spoof" Standard Browser JS DOM Objects (Window.location) at Runtime?

I'd like to dynamically change some of the standard JS DOM objects from within a web browser.
For instance, when I execute:
var site = location;
I want to specify a new value for my browser's "window.location" object other than the "correct" one (the URL used to access the requested page) at run time, either through a debugger-like interface or even programmatically if need be.
Although Firebug advertises the capability to do something similar via its "DOM Inspector," whenever I try to modify any of the DOM values while I've paused the Javascript via its debugger, it simply ignores the new value I enter. After doing some research, it seems that this is a known issue according to this bug report: http://code.google.com/p/fbug/issues/detail?id=1707 .
Theoretically, I could write a program to simply open up an HTTP socket and emulate a browser "user agent," but this seems like a lot of trouble for my purposes. While I'm asking, does anyone know a good Java/C# library with functions/objects that emulate HTTP headers and parse the received HTML/JS? I've long dreamt about the existence of such a library but most of the ones I've tried (Java's Apache HttpClient, C#'s System.Net.HttpWebRequest) are far too low-level to make anything worthwhile with minimal planning and a short period of time.
Thanks in advance for recommendations and advice you can provide!
Not sure if I understand you correctly, but if you want to change the loaded URL you can do that by setting window.location.href.
If your intent is to replace DOM buildins then you will be sad to hear, that most build-in objects (host objects) aren't regular JavaScript objects and their behaviour is not clearly defined. Some browsers may allow you to replace and/or extend some objects while in other browsers they won't be replaceable/extendable at all.
If you want to "script a browser" using JavaScript, you should definitly have a look at node.js and it's http module. There's also a thirdparty module called html5 that simulates the DOM in node.js and even allows the usage of jQuery.

Handling standard user facing scenarios

*I was wondering if i could do all these in javascript, as opposed to having rails helpers
In my application, there are several types of "if-else" UI cases. This is a fairly common scenario, and i wonder if anyone has a tidy way to do these?
EG 1) There might be several types of links with the same behavior: "upvote", etc.
If it is the user's own article, i do not want it to be passed to the server, but pop up a dialog box
EG 2) There might be a several links called "follow", "become a fan", etc
If the user already have done the given action before, it should be a text "followed" instead of a link.
Normally you'd use helpers for this. You write helpers called, based on your examples, upvote_button (which might take a user as a parameter) or follow_button (where this one might take true/false for already-following/not-following.
If you can be more specific as to what you need, I can probably be more specific in my answer.

how do you folks handle complex state situations where order of operations is important?

I'm getting in to a situation where I have several interacting widgets (on a web UI), all of whom can be in multiple different states, and whose behavior depends on others the others. I'm running in to situations where, for example, a set of data gets sorted twice, or the data gets displayed before it's sorted, rather than the other way around. It's a little bit of a wack-a-mole problem, where I think I've simplified things and gotten it working, only to find out I've broken things somewhere else.
I have functions that do things like:
widgetAFunction
load data into widget B
tell widget B to sort the data
tell widget B to display the data
My love of code reuse makes me want to do something like write a loadData function in widget A that goes something like this:
widgetBLoadDataFunction
update data
sort the data
refresh the view
So that all widgetA has to do is call one function on widgetB. But then there are cases where I just want to sort the data, without updating the data, so I write:
widgetBSortFunction
sort the data
refresh the view
And then maybe I want a filter function
widgetBFilterFunction
filter the data
refresh the view
And maybe I want to be update the data but not sort it, so I have
widgetBNoSortLoadDataFunction
update data
refresh the view
It doesn't seem that complex, but I wind up with these really long, very brittle chains of function calls, or a bunch of very similar calls. As Martin Fowler would say, the code is getting a little smelly.
So, what other alternatives do I have? I did something on a recent project where I did a state machine kind of thing, where I registered a bunch of functions with a set of conditions, or states which would trigger their execution. That worked somewhat well, and I'm thinking that approach might be good to use again.
Does anyone know what I'm talking about here, and even better, can anyone point me toward some patterns that will help me get my head around this better?
What you need is a finite state machine implementation. Basically every finite state machine needs:
Events that the program responds to
States where the program waits between events
Transitions between states in response to events
Actions taken during transitions
Variables that hold values needed by actions between events
A good article from IBM teachs you a way of implementing it by means of Javascript.
Edit: Here is a FSM builder, so you don't have to build your own.
Fernando already mentioned FSMs, and gave good info and links. :)
In addition, I'll add that your classes should already incorporate enough state so that you're not worried about sorting twice, etc. I.e., widgetB.sort() should check if it's been sorted since last update and just return if so. There's practically no downside to doing this, and it can improve performance (and also guard consistency).

Categories