7 min read

 

MooTools 1.3 Cookbook

MooTools 1.3 Cookbook

Over 100 highly effective recipes to turbo-charge the user interface of any web-enabled Internet application and web page

The reader can benefit from the previous article on Extending MooTools.

Extending elements—preventing multiple form submissions

Imagine a scenario where click-happy visitors may undo normalcy by double-clicking the submit button, or perhaps an otherwise normal albeit impatient user might click it a second time. Submit buttons frequently need to be disabled or removed using client-side code for just such a reason.

Users that double-click everything
It is not entirely known where double-clicking users originated from. Some believe that single-clicking-users needed to be able to double-click to survive in the wild. They therefore began to grow gills and double-click links, buttons, and menu items. Others maintain that there was a sudden, large explosion in the vapors of nothingness that resulted in hordes of users that could not fathom the ability of a link, button, or menu item that could be opened with just a single click. Either way, they are out there, and they mostly use Internet Explorer and are quickly identifiable by how they type valid URLs into search bars and then swear the desired website is no longer on the Inter-nets.

How to do it…

Extending elements uses the same syntax as extending classes. Add a method that can be called when appropriate. Our example, the following code, could be used in a library that is associated with every page so that no submit button could ever again be clicked twice, at least, without first removing the attribute that has it disabled:

Element.implement({
better_submit_buttons: function() {
if (
this.get(‘tag’)==’input’ &&
this.getProperty(‘type’)==’submit’) {

this.addEvent(‘click’, function(e) {
this.set({
‘disabled’:’disabled’,
‘value’:’Form Submitted!’
});
});
}
}
});
window.addEvent(‘load’,function() {
$$(‘input[type=submit]’).better_submit_buttons();
});


How it works…

The MooTools class Element extends DOM elements referenced by the single-dollar selector, the double-dollars selector, and the document.id selector. In the onLoad event, $$(‘input[type=submit]’).submit_only_once(); all INPUT elements that have a type equal to submit are extended with the Element class methods and properties.

Of course, before that infusion of Moo-goodness takes place, we have already implemented a new method that prevents those elements from being clicked twice by adding the property that disables the element.

There’s more…

In our example, we disable the submit button permanently and return false upon submission. The only way to get the submit button live again is to click the Try again button that calls the page again. Note that reloading the page via refresh in some browsers may not clear the disabled attribute; however, calling the page again from the URL or by clicking a link will.

On pages that submit a form to a second page for processing, the semi-permanently disabled button is desirable outright. If our form is processed via Ajax, then we can use the Ajax status events to manually remove the disabled property and reset the value of the button.

See also

Read the document on the MooTools Request class that shows the various statuses that could be used in conjunction with this extended element: http://mootools.net/docs/core/Request/Request.

 

Extending elements-prompt for confirmation on submit

Launching off the last extension, the forms on our site may also need to ask for confirmation. It is not unthinkable that a slip of the carriage return could accidentally submit a form before a user is ready. It certainly happens to all of us occasionally and perhaps to some of us regularly.

How to do it…

Mutate the HTML DOM FORM elements to act upon the onSubmit event and prompt whether to continue with the submission.

Element.implement({
polite_forms: function() {
if (this.get(‘tag’)==’form’) {
this.addEvent(‘submit’,function(e) {
if(!confirm(‘Okay to submit form?’)) {
e.stop();
}
});
}
}
});


How it works…

The polite_forms() method is added to all HTML DOM elements, but the execution is restricted to elements whose tag is form, if (this.get(‘tag’)==’form’) {…}. The onSubmit event of the form is bound to a function that prompts users via the raw JavaScript confirm() dialogue that either returns true for a positive response or false otherwise. If false, then we prevent the event from continuing by calling the MooTools-implemented Event.stop().

There’s more…

In order to mix the submit button enhancement with the polite form enhancement only a few small changes to the syntax are necessary. To stop our submit button from showing in process… if the form submission is canceled by the polite form request, we create a proprietary reset event that can be called via Element.fireEvent() and chained to the collection of INPUT children that match our double-dollar selector.

// extend all elements with the method polite forms
Element.implement({
better_submit_buttons: function() {
if (this.get(‘tag’)==’input’&&this.getProperty(‘type’)==’submit’) {
this.addEvents({
‘click’:function(e) {
this.set({‘disabled’:’disabled’,’value’:’in process…’});
},
‘reset’:function() {
this.set({‘disabled’:false,’value’:’Submit!’});
}
});
}
},
polite_forms: function() {
if (this.get(‘tag’)==’form’) {
this.addEvent(‘submit’,function(e) {
if(!confirm(‘Okay to submit form?’)) {
e.stop();
this.getChildren(‘input[type=submit]’).fireEvent(‘reset’);
}
});
}
}
});
// enhance the forms
window.addEvent(‘load’,function() {
$$(‘input[type=submit]’).better_submit_buttons();
$$(‘form’).polite_forms();
});


 

Extending typeOf, fixing undefined var testing

We could not properly return the type of an undeclared variable. This oddity has its roots in the fact that undefined, undeclared variables cannot be dereferenced during a function call.

In short, undeclared variables can not be used as arguments to a function.

Getting ready

Get ready to see how we can still extend MooTools’ typeOf function by passing a missing variable using the global scope:

// will throw a ReferenceError
myfunction(oops_var);
// will not throw a ReferenceError
myfunction(window.oops_var);

How to do it…

Extend the typeOf function with a new method and call that rather than the parent method.

// it is possible to extend functions with new methods
typeOf.extend(‘defined’,function(item) {
if (typeof(item)==’undefined’) return ‘undefined’;
else return typeOf(item);
});

//var oops_var; // commented out “on purpose”
function report_typeOf(ismoo) {
if (ismoo==0) {
document.write(‘oops_var1 is: ‘+typeof(oops_var)+'
’);
} else {
// concat parent to avoid error from derefrencing an
undeclared var
document.write(‘oops_var2 is: ‘+typeOf.defined(
window.oops_var)+'
’);
}
}


The output from calling typeof() and typeOf.defined() is identical for an undefined, undeclared variable passed via the global scope to avoid a reference error.

without moo:


with moo:


The output is:

without moo:
oops_var1 is: undefined

with moo:
oops_var2 is: undefined

How it works…

The prototype for the typeOf function object has been extended with a new method. The original method is still applied when the function is executed. However, we are now able to call the property defined, which is itself a function that can still reference and call the original function.

There’s more…

For those that are not satisfied at the new turn of syntax, the proxy pattern should suffice to help keep us using a much similar syntax.

// proxying in raw javascript is cleaner in this case
var oldTypeOf = typeOf;
var typeOf = function(item) {
if (typeof(item)==’undefined’) return ‘undefined’;
else return oldTypeOf(item);
};


The old typeOf function has been renamed using the proxy pattern but is still available. Meanwhile, all calls to typeOf are now handled by the new version.

See also

 


Subscribe to the weekly Packt Hub newsletter. We'll send you the results of our AI Now Survey, featuring data and insights from across the tech landscape.

* indicates required