Quantcast
Channel: lisp service
Viewing all articles
Browse latest Browse all 20

Tutorial on Javascript Events for Weblocks Form Inputs

$
0
0

As you can probably tell from other posts on this blog, we have been using Weblocks for our current project.  It's a great Lisp web framework that uses continuations and a widget-based architecture to make developing web applications much nicer (not to mention, the support and community for the framework are outstanding and very nice). 

One of the nicer things about Weblocks is how nicely it handles AJAX.  Most actions (like submitting a form or clicking a link) default to being done with AJAX and then degrade nicely if the browser does not support Javascript.  However, one of the things the current version was lacking was being able to easily add Javascript events on form inputs (like onKeyUp or onChange).  So, I made a fork of the development branch and did my best to add in some support for this.  The fork is at  http://bitbucket.org/saikat/weblocks-saikat.

So as an example of how to use the functionality, say you want to create a graph that increases in size up to as a user enters a value in a form input with the name "amount."  If we just want to show how large the number the user has entered is, we only need Javascript to handle this.  So, we create a Javascript function as follows (the function must accept a widgetId parameter):

function changeBar(widgetId) {     var userForm = document.getElementById(widgetId);     var userValue = userForm.select('[name="amount"]')[0].value;     var graph = document.getElementsByClassName('amount-graph');     thermometer.style.height = userValue + "%"; }

In our Weblocks code, we just add the :on-keyup option to our input presentation to have it use this Javascript event for the onKeyUp event as follows:

(defview test-view (:type form :persistp nil :caption "")     (amount :present-as (input :on-keyup 'change-bar)))

And that's it!  Now say that instead of increasing the size of a bar, you want to compare the value to a target value stored in your database and present some message to the user when the user changes to a different field.  This means you need to do some server side checking, but with the :on-keyup hook, you can have this check happen AJAXily.  So first, define your function to do the check on the server side:

;;Right now, the serialized form just gets passed to the server side function in the args. I am in the process of fixing this to be ;; better (defun check-amount (widget &rest args)     ;;(cadr args) gives the value in the field that has just been entered     (let ((value (cadr args))         (if (value-is-greater-than-target value)             (setf (greater-slot widget) t)             (setf (greater-slot widget) nil))         (mark-dirty widget)))

In this case, widget has a slot called "greater-slot" that, when set, will show a message in the widget about how the current value entered is greater than the target amount.*  Then, in your view, you have:

(defview test-view (:type form :persistp nil :caption "")     (amount :present-as (input :on-change #'check-amount)))

And you can now call server-side functions using AJAX in javascript events on your form!  Right now, my changes only work for text input fields and only support the onKeyUp or onChange events, though I urge you to add on to this.  

 

*Note that redrawing the widget using mark-dirty might make your form field lose focus.  One way to get around this is to use focusp either in your view's definition or in the field's definition (though focusing at the view field level is also only available at my fork right now).  This isn't the best solution though because focusp causes that field to be focused whenever the page is loaded.  Often, you want to just regain focus onto a field the user was typing in without having that field be the field that gets focus whenever the page loads.  The only way I know of doing this is to use send-script to send a javascript method activating that field in the render-widget-body code for the widget you are redrawing.

Permalink | Leave a comment  »


Viewing all articles
Browse latest Browse all 20

Trending Articles