In this part of the chapter we are going to add some new features to our little module. These features are intended to make a better form, such as avoiding a full page reload by sending the form using AJAX or checking that some text has been introduced before sending it. All these are good features, though not every form needs to make use of these features. It's up to us to decide when to implement them.
But enough chat for now, work is awaiting us!
This is not going to be as hard as it may first seem, thanks to the powerful
jQuery features. What steps do we need to take to achieve AJAX form sending?
First, open our default_tmpl.php
file. Here we are going to
add an ID to our button, and change it a bit, from this:
<input type="submit" name="send" value="Send" class="sc_button"/>
to this:
<input type="button" name="send" value="Send" class="sc_button" id="send_button"/>
Apart from adding the ID, we change its type from submit
to button
. And with this our form is prepared. We need a
new file, a js
one this time, to keep things organized. So we
are going to create a js
folder, and place a
littlecontact.js
file in it, and we will have the following
path:
modules/mod_littlecontact/js/littlecontact.js
As always, we will also include this file in the
mod_littlecontact.xml
file, like this:
<filename>js/littlecontact.js</filename>
Before adding our code to the littlecontact.js
file, we are
going to add it to the header section of our site. We will do this in
the mod_littlecontact.php
file, as follows:
require_once(dirname(__FILE__).DS.'helper.php'), $document =& JFactory::getDocument(); $document->addScript(JURI::root(true).'modules'.DS.' mod_littlecontact'.DS.'js'.DS.'littlecontact.js'), JHTML::stylesheet('styles.css','modules/mod_littlecontact/css/'),
I've highlighted the changes we need to make; first we get an instance to
the global document object. Then we use the addScript
method
to add our script file to the header section.
We use JURI::root(true)
to create a correct path. So now in
our header, if we check the source code, we will see:
<script type="text/javascript" src="/modules/mod_littlecontact/js/littlecontact.js"></script>
If instead of using JURI::root(true)
, we would have
used JURI::root()
our source code would look like the
following:
<script type="text/javascript" src="http://wayofthewebninja.com/ modules/mod_littlecontact/js/littlecontact.js"></script>
We are now ready to start working on our littlecontact.js
file:
jQuery(document).ready(function($){ $('#send_button').click(function() { $.post("http://index.php", $("#sc_form").serialize()); }); });
It is a little piece of code, let's take a look at it. First we use
the ready
function, so all of our code is executed when
the DOM is ready:
jQuery(document).ready(function($){
Then we add the click
method to the
#send_button
button. This method will have a function inside with
some more code. This time we are using the post
method:
$.post("http://index.php", $("#sc_form").serialize());
The post
method will send a request to a page, defined in
the first parameter, using the HTTP post request method.
In the second parameter we can find the data we are sending to the page. We
could pass an array with some data, but instead we are using the
serialize
method on our form, with ID
sc_form
.
The serialize
method will read our form, and prepare a
string for sending the data.
And that's all; our form will be sent, without our visitors even noticing. Go ahead and try it! Also, you could take a look to the following two pages:
Here you can find some good information about these two functions. After you have taken a look at these pages, come back here, and we will continue.
Well, sending the form without page reloading is OK, we will save our visitors some time. But we need our visitors to notice that something is happening and most important, that the message has been sent.
We will now work on these two things. First of all we are going to place a message, so our readers will know that the form is being sent. This is going to be quite easy too.
First we are going to add some markup to our
default_tmpl.php
, as follows:
<?php defined('_JEXEC') or die('Direct Access to this location is not allowed.'), ?> <div id="littlecontact"> . . . <div id="sending_message" class="hidden_div"> <br/><br/><br/> <h1>Your message is being sent, <br/>wait a bit.</h1> </div> <div id="message_sent" class="hidden_div"> <br/><br/><br/> <h1>Your message has been sent. <br/>Thanks for contacting us.</h1> <br/><br/><br/> <a href="http://index.php" class="message_link" id="message_back">Back to the form</a> </div> </div>
We have added two DIVs here: sending_message
and
message_sent
. These two will help us show some messages to our
visitors. With the messages prepared, we need some CSS styles, and we will
define these in our module's styles.css
file:
#littlecontact{ position: relative; } #sending_message, #message_sent{ height: 235px; width: 284px; position: absolute; z-index: 100; background-color: #5B5751; top: 0; text-align: center; } .hidden_div{ visibility: hidden; display: none; } .show_div{ visibility: visible; display: block; } a.message_link:link, a.message_link:visited{ color: #ffffff; text-decoration: none; } a.message_link:hover{ text-decoration: underline; }
Don't worry about writing all this code; you can find it in the code
bundle, so copy it from there. Going back to the code, these are just simple CSS
styles, and some of the most important ones are the
hidden_div
and show_div
classes. These will be
used to show or hide the messages.
Ready to go to the JavaScript code? We will now return to our
littlecontact.js
file and modify it a bit:
jQuery(document).ready(function($){ $('#send_button').click(function() { $.post("http://index.php", $("#sc_form").serialize(), show_ok()); $("#sending_message").removeClass("hidden_div"); }); $("#message_back").click(function(e){ e.preventDefault(); $("#message_sent").addClass("hidden_div"); $("#sending_message").addClass("hidden_div"); }); function show_ok(){ $("#sending_message").addClass("hidden_div"); $("#message_sent").removeClass("hidden_div"); $("input:text").val(''), $("textarea").val(''), } });
Seems a lot? Don't worry, we will take a step-by-step look at it. If we
look at our previously added click
function, we can see a new
line, as follows:
$("#sending_message").removeClass("hidden_div");
This will search for our sending_message
DIV, and remove
the hidden_div
class. This way the DIV will be visible,
and we will see a screen similar to the following screenshot:
A nice message tells our visitors that the e-mail is being sent just at the moment. But we don't do only that. If we take a closer look at our previous post method, we will see some changes, as follows:
$.post("http://index.php", $("#sc_form").serialize(), show_ok());
A new third parameter! This is a callback function, which will be executed
when the request succeeds and our e-mail has been sent. But what is inside
this show_ok
function? Its contents are as
follows:
function show_ok(){ $("#sending_message").addClass("hidden_div"); $("#message_sent").removeClass("hidden_div"); $("input:text").val(''), $("textarea").val(''), }
First we add the hidden_div
class to the
sending_message
, so this sending message is not seen any more. But
instead we remove the hidden_div
class of our
message_sent
DIV, so our visitors will see this new
message:
But we are also emptying our inputs, text inputs, and
textarea
fields:
$("input:text").val(''), $("textarea").val(''),
So when visitors return to the form they are presented with a fresh one, just in case they have forgotten something and want to send a new e-mail. Hey who knows!
Our last step is to enable a back link, so that the readers can return to the form:
$("#message_back").click(function(e){ e.preventDefault(); $("#message_sent").addClass("hidden_div"); $("#sending_message").addClass("hidden_div"); });
First we target the link using its ID, and then we bind a
click
function to it. The next step is to prevent the default
event for the link. This is why the link won't behave as a link, and
won't try to load a page. This is why we are not going to load or reload a
page, instead we will continue with our code, hiding both DIVs, so the form is
visible again.
That's it! It has not been that hard, has it? Now, it would be a great moment to take a look at the code bundle, see the code, read it, and try it by yourself. Or alternatively, keep reading a bit more if you want!
Look at the site http://www.ajaxload.info/. There you will be able to generate some loader GIF images. These will act as the typical clock mouse, telling the users that something is happening. Maybe you would like to use that instead of only using text. Give it a try!
Ah! validating forms, so entertaining. It's just the kind of task everyone always wants to do. Well, maybe a bit less than others. But it's something that needs to be done. Why? Just to ensure that we are receiving the proper data, or even that we are receiving data.
Ideally we would use JavaScript validation on the client side, and PHP validation on the server side. Server-side validation is essential, so a user turning off JavaScript still gets his/her contents validated. JavaScript validation will save us the effort of having to send all the data to the server, and then come back with the errors.
We are going to use a bit of JavaScript to try to validate our form. This process is going to be quite simple too, as our form is very small.
We will be doing all of our work in our littlecontact.js
file. Remember our $('#send_button').click
function?
It looked like this:
$('#send_button').click(function() { $.post("http://index.php", $("#sc_form").serialize(), show_ok()); $("#sending_message").removeClass("hidden_div"); });
Now with some modifications, it will be more or less as follows:
$('#send_button').click(function() { //First we do some validation, //just to know that we have some data alerts = ''; if($("input[name=your_name]").val() == ''){ alerts += "we need your name "; } if($("textarea[name=your_question]").val().length < 5){ alerts += "We need a message of at least 5 characters length "; } if(alerts != ''){ alert(alerts); }else{ $.post("http://index.php", $("#sc_form").serialize(), show_ok()); $("#sending_message").removeClass("hidden_div"); } });
First, we define a new variable, to put all the messages in:
alerts = '';
Then we check our form fields (first the input text):
if($("input[name=your_name]").val() == '')
As you can see, with jQuery we can select the input with a
name
equal to your_name
and check if its value
is empty. The textarea
check is very similar:
if($("textarea[name=your_question]").val().length < 5
But we are also checking if the length of the value is greater than five.
After each one of these validations, if failed, we add a message to the
alerts
variable. Later, we will check if that variable is not
empty. If it's not empty, it would mean that some of the checks have failed,
and then we show the alerts to our visitors:
alert(alerts);
This will raise a typical alert message, much like the following screenshot:
Informative, but not really nice. But thinking about it, we already have the
jQuery UI library available, thanks to our SC jQuery Joomla! plugin. Why not use
that plugin to show a better message? Let's do it. First we need to make
some changes in the default_tmpl.php
file:
<div id="alerts" title="Errors found in the form" style="display: none;"></div>
We have added a new DIV, with an ID equal to alerts
, and
with an informative title
. Now that our markup is ready, some
changes are also necessary in our littlecontact.js
JavaScript
file.
For example, we are going to change our alert messages from the following:
alerts += "- We need your name "; . . . alerts += "- We need a message of at least 5 characters length ";
To the following:
alerts += "- We need your name<br/>"; . . . alerts += "- We need a message of at least 5 chapters length<br/>";
Why are we doing this? It is because we will show HTML in our dialog, instead of just text. How are we going to show the dialog? Quite easily, by changing the following line:
alert(alerts);
To this:
$("#alerts").html(alerts).dialog();
What are we doing here? First, we select our newly created DIV, with
ID alerts
, and then we use the html
method, passing the variable alerts
as its parameter. This
will fill our DIV with the content of the alerts
variable.
Nested in it we will find the dialog
method. This is a
jQuery UI method that will create a dialog box, as we can see in the following
screenshot:
Better than our previous alert message, isn't it? Also notice that this dialog is matching the style of all our jQuery UI elements, like the login dialog and the tabs module. If we were to change the style in the SC jQuery Joomla! plugin, the style of the dialog will also change.
Well that's it for now. This is just a small example; now don't you think it would be great to give it a try? Just open the code bundle and check it!
3.133.130.199