Friday, October 20, 2006

Using Lightbox to prevent form double submit

Some month ago I wrote a javascript class that uses a slightly modified version of Lightbox to prevent users to click twice on a form submit button.
The idea is simple: just add a lightbox layer when a user clicks on a submit button and the game is done. This is not an elegant solution, but it works in many cases.
It works also with links that try to call form.submit() method: this class saves previously defined submit functions, creates the layer and then calls old function (if it exists).


var LightboxForm = Class.create();
LightboxForm.prototype = {

yPos : 0,
xPos : 0,

initialize: function(form) {
form = $(form);
form.oldsubmitdoublesubmit = form.submit;
form._lightbox_ = this;

Event.observe(form, 'submit', this.disableWithOverlay.bindAsEventListener(form), false);
form.submit = this.disableWithOverlayJS;
},

uninstall: function(form) {
form = $(form);
form.submit = form.oldsubmitdoublesubmit;
Event.stopObserving(form, 'submit', this.disableWithOverlay.bindAsEventListener(form), false);
},

disableWithOverlay: function(event) {
if(event.returnValue != false) {
this._lightbox_.activate();
return true;
} else {
return false;
}
},

disableWithOverlayJS: function(event) {
this._lightbox_.activate();
return this.oldsubmitdoublesubmit();
},

// Turn everything on - mainly the IE fixes
activate: function(){
if (browser == 'Internet Explorer'){
this.getScroll();
this.setScroll(0,0);
this.hideSelects('hidden');
}
this.displayLightbox("block");
},

// Ie requires height to 100% and overflow hidden or else you can scroll down past the lightbox
prepareIE: function(height, overflow){
bod = document.getElementsByTagName('body')[0];
bod.style.height = height;
bod.style.overflow = overflow;

htm = document.getElementsByTagName('html')[0];
htm.style.height = height;
htm.style.overflow = overflow;
},

// In IE, select elements hover on top of the lightbox
hideSelects: function(visibility){
selects = document.getElementsByTagName('select');
for(i = 0; i < visibility =" visibility;" ypos =" self.pageYOffset;" ypos =" document.documentElement.scrollTop;" ypos =" document.body.scrollTop;" display =" display;" display =" display;" browser ="="">


When the lightbox is activated a div called lightbox is displayed, so if you want provide some information to the user you can define a div using a function like this:



// Add in markup necessary to make this work. Basically two divs:
// Overlay holds the shadow
// Lightbox is the centered square that the content is put into.
addLightboxMarkup: function() {
bod = document.getElementsByTagName('body')[0];
overlay = document.createElement('div');
overlay.id = 'overlay';
bod.appendChild(overlay);

message = document.createElement('div');
message.id = 'lightbox';
message.className = 'leightbox';
message.innerHTML = 'Request sent, please wait...';
bod.appendChild(message);
}


Somewhere in your html page you should put something like:

new PreventDoubleSubmit();


Don't forget to use the right css file. You can get a copy here
You can download a copy of this javascript code here. In this file you will find also a class that provides an hook on onload window event to allow all forms in the current page to be wrapped by the LightboxForm object.

Update 1:
The script relies on prototype.js and uses a script to detect the browser (the script was made from Chris Campbell from ParticleTree).

Update 2: due to some error in this post, the script was not working. I apologies for this: this post was made too quickly in the past.
Now I made a little example on how to integrate the script in your pages. Just download this archive and see the index.html file. It should be quite easy to understand.


Update 3: Thanks to Ken B. I added a simple and nice feature to the script: customizable html message for the submit.
Actually the message showing during submit is controlled by this line: message.innerHTML = 'Request sent, please wait...';.

I changed the source code to let you pass a custom message to the PreventDoubleSubmit object.
So now you can write something like:
PreventDoubleSubmit('

Please wait...

');
. Of course, a default message is generated if you continue to use the old syntax.
I updated the script and the example.

Thursday, October 12, 2006

Rhythmbox 0.9.6: a plugin for Gajim status message

I recently switched to Ubuntu Edgy, the new release of Ubuntu Linux. Edgy is still in beta, but works well here on my laptop.
One of the new applications that comes with Gnome 2.16 is Rhythmbox 0.9.6, the default Gnome music player. This new release has plugins support: plugins can be written in c or using the python binding.
Python is very simple, so I wrote a simple plugin that changes the status message of Gajim Jabber client according with the song you are playing in Rhythmbox.
This little piece of code uses dbus to communicate with Gajim, gconf to save the configuration and glade for the user interface.
It is a 0.1 version, so keep it "as is". It just works, and shows how to use some Rhythmbox features from a python plugin.
To try it, just extract the package into your ~/.gnome2/rhythmbox/plugins/ folder and start the player. That's all.

UPDATE to version 0.2: some make up to the code and added the possibility to customize the "no music" message.

UPDATE to version 0.3: Waiting for Gajim 0.11, I upgraded the plugin to v0.3. This version provides a [paused] message when you stop rhythmbox and some minor bug fixes.