Posts Tagged JQuery
JQuery: keeping your site-state in the addressbar
Posted by Morten in Uncategorized on June 9, 2009
More and more sites are doing it. Keeping their state in the address bar of the browser, enabling AJAX driven dynamic html pages to use the back and forward buttons between javascript driven views. The most common website that uses this functionality, that I know of, is GMail. If you look at the address bar in GMail when in an message you can see that they added a bookmark hash (#) specifying which message to show. The updated address bar allows the application to keep state in the browser history.
I started working on a solution for this on my own, at the time I couldn’t find any JQuery plug-ins with the desired functionality. Now however there are several. In order to reduce the amount of specific code in my own application I tried out three.
JQuery History, JQuery hashchange and JQuery address .
After looking at JQuery address I can honestly say that it has the best fail-safe of the three I looked at. It uses full page post backs as a fallback. I haven’t been able to get it to work without reloading the entire page. So for that reason I cannot use the plug-in myself.
This is my favourite. I has a nice and clean interface and does only what you tell it to do. However I couldn’t get it to work on Internet explorer 6. Which is also one of the reasons why I’m looking at the plug-ins to begin with.
JQuery history is actually the plug-in that led me to the others. I came in contact with another Mor.ph user who used it on his site. As far as I can tell from the usage of this it needs to interact with the link’s on the page in order to work properly. Catching the click events on the links. This is also a problem for me. I’d prefer just to update the bookmark hash.
Now while I couldn’t use any of these plug-ins I just wanted to give a shout out to people looking for them. They are there. A few things to think about, that I found out. Is that your page needs to be designed for this type of behaviour. If you use any of the plug-ins then your page will most likely be couple to that design. It’s also much easier to add this type of behaviour for the page in the beginning than appending it to already existing Ajax pages. These are my experiences with it.
I also lack a word for the technique of keeping your state in the address-bar.
Grails: UI-performance plugin
Posted by Morten in Uncategorized on April 12, 2009
I installed the UI-performance plugin last night. Configured it to bundle my javascript code into a single compressed file. Did the same with my CSS files.
With everything bundled and compressed the size of the the page download is reduced from 485 Kb to 187 Kb.
I only had some minor configuration problems but those were just related to my own typos. Apart from that it all now works perfectly.
The plugin saves me the time it would take me to produce a build step to produce the same output, and it even does more than the initial idea for my own build step. Thank you Burt Beckwith for a job well done!
Grails: Ajax Login using Basic Auth
Posted by Morten in Uncategorized on April 7, 2009
So I have my Grails environment setup. The point is to build a REST-service that will work as a back end to a highly dynamic JavaScript page. I chose Grails, since it builds on Hibernate and Spring.
Two frameworks Id like to examine for the purpose of seeing the differences between Castle and nHibernate in the .Net world.
Building domain-classes and having the represented as XML is straight forward in Grails, but I need to take care of the login scenario. If you’d like to know more about building REST web services with Grails, I recommend reading the Mastering Grails: RESTful Grails article. Login seems like a good place to start, to ensure that my domain-controllers can dictate login as I develop the domain.
Now Grails.org has a list of tutorials, one of them, focusing on Login. It’s a good beginners tutorial showing how to use interceptors to execute user verification before showing the actual view requested. For my scenario however it has a few problems. Lets use the tutorial as a start of point.
The problems I have with the solution is with the following code:
def checkUser() {
if(!session.user) {
// i.e. user not logged in
redirect(controller:'user',action:'login')
return false
}
}
For my scenario this has one problem, in two places. Its stateful. First of it always directs the user to the same place, of course it can be different per controller. I need it to simple say access denied.
def checkUser() {
if(!session.user) {
// i.e. user not logged in
response.sendError(401)
return false
}
}
The above code is changed to instead of redirecting the user, it simply sets the response code to Access Denied. Now there’s just one issue left, the session code.
I don’t want to use session, as it requires my server to remember each session, preferably I want the client to remember the state.
Another issue is that I want to use Mor.ph AppSpace, if I pay for the most basic of subscriptions at Mor.ph I get two Cube, i.e. two servers with a load balancers in front. As a result I can’t be sure that the same server will service the same client all the time.
If we instead choose to check for the logged in user using the authorization header. The state is always provided by the client, instead of keeping the state on the server.
def checkUser() {
if(!UserController.checkAuthorization(request, response)) {
// i.e. user not logged in
response.sendError(401)
return false
}
return true
}
I let the UserController do the checking of the user, using a static method. This will let me keep the authorization code in the same place I handle users to begin with. It also allows me to change the authorization method later by changing the code in the checkAuthorization method. We could use Dependency Injection here to inject a real instance of the UserController, or even better an object with the sole responsibility to check user access. However DI is out of scope for this post.
You can implement any way of checking the user login you want. If you want a simple solution and stick with the HTTP standard you could use Basic auth. Here is a good explaination of how to implement Basic auth for Grails. Another way is too use a cookie to hold authorization information.
For this example were just sending username:password in the authorization header. My final implementation will be Basic Auth with the password hashed to a checksum. The point of the hash is to never send plain-text password across the net.
Here is the checkAuthorization method in the UserController for this example.
static boolean checkAuthorization(HttpServletRequest request, HttpServletResponse response) {
def authString = request.getHeader('Authorization')
if (!authString) {
return false;
}
def credentials = authString.split(':')
if( credentials.length != 2 || credentials[0] == null || credentials[0] == "" || credentials[1] == "" || credentials[1] == null)
return false;
def user = User.findByEmailAndPassword(credentials[0], credentials[1])
if (user) {
return true;
}
return false;
}
Now we can create some JQuery based JavaScript code to handle login.
function RestClient() {
var self = this;
var auth;
function ShowLoginUI(afterLoginCallback) {
var dialog = document.createElement('div');
$(dialog).html("<table><tr><td>Email</td><td><input id='email' type='text'/></td></tr><tr><td>Password</td><td><input id='pass' type='password'/></td></tr></table>");
$(dialog).dialog({ buttons: {"Login": function() {
auth = $(this).find("#email").val() + ":" + $(this).find("#pass").val();
afterLoginCallback();
$(this).dialog("close");
}, "Cancel":function() {
$(this).dialog("close");
}}, modal:true});
}
this.Get = function(url) {
var data = null;
data = $.ajax({
url : url,
method : 'GET',
beforeSend : function(req) {
req.setRequestHeader('Authorization', auth);
}, cache : true,
error: function(request, textStatus, error) {
if (request.status == 401) {
ShowLoginUI(function() {
data = self.Get(url);
});
}
}});
return data;
};
}
The above code does Ajax Get-calls to the specified address. If the call failed due to Access Denied, it shows a login form and tries to execute the Ajax request again. The class remembers the authorization string, so as long as the user uses the same RestClient-object the state is maintained at the client side.
Ill leave instructions on how to wire up Grails with JQuery to someone else.
Here is a simple usage example:
var a = new RestClient();
$("#test").click(function() {
var data = a.Get("plant/create");
$(document).append(data);
});
Good luck writing scalable login scenarios using Ajax instead of page reloads.