ImpressCMS proudly uses SourceForge
ImpressCMS on Ohloh.net
[NewIndex :: Development :: Developing Modules :: This page]  
Tags: Development   Tutorial   Template   Xajax   AJAX  

AJAX Module

< Back to Part 2

Part 3 - Using AJAX

In this tutorial I will teach you how to use ajax in a Xoops module. I will be using xajax. This is my choice there are however many other ajax routines, some are a "php bridge" such as xajax, sajax, etc. Others are pure javascript such as scriptaculous. After tring this tutorial, feel free to experiment with others. Now you may be asking what drove me towards Xajax; well, I also tried a couple and since I mainly like to program in PHP, I felt Xajax provided me with the flexibility I needed.
What is ajax? Ajax allows you to update a piece of your webpage, without having to reload everthing. This can be very usefull and, when correctly applied, really cut down on server loads.
When should I use it? To answer this I'll use an example; suppose you have a table of data. You could use ajax to provide table sorting. Be carefull not to fall into the mistake of thinking that Ajax can solve everything. It's just a tool, that, if used correctly can help user interaction on your site.

Let's get started!

Step 1- Getting the Tutorial module.

First let's get the tutorial module. Download and install it. This uses the final module from part 2 of my tutorials. I've added a directory named class, inside it I've created another directory named xajax and added the xajax files (version 0.5 beta 4b)in it.I've also renamed index.php to index_from_part2.php and created a new skeleton index file.

Tutorial module
Tutorial module from part 2 with xajax files added
tutorial

Step 2- Getting xajax to work in xoops.


Here's the new version of index.php:

<?php
// Tutorial
// Created by KaotiK
require('../../mainfile.php');

require_once(XOOPS_ROOT_PATH.'/modules/tutorial/functions.php');
require_once(XOOPS_ROOT_PATH.'/modules/tutorial/class/xajax/xajax_core/xajax.inc.php');

$xajax = new xajax();
$xajax->registerFunction("processFormData");
//$xajax->setFlag("debug", true);
$xajax->processRequest();

$Xjavapath=XOOPS_URL.'/modules/tutorial/class/xajax';
$xajaxjava=$xajax->getJavascript($Xjavapath);

$xoopsOption['template_main'] = 'tut_main.html';
require(XOOPS_ROOT_PATH.'/header.php');

$xoopsTpl->assign('xajaxjava', $xajaxjava);

require(XOOPS_ROOT_PATH.'/footer.php');
?>

I'll explain this piece by piece:

require_once(XOOPS_ROOT_PATH.'/modules/tutorial/functions.php');
require_once(XOOPS_ROOT_PATH.'/modules/tutorial/class/xajax/xajax_core/xajax.inc.php');

The first line is a file called functions. This file will hold all my xajax and normal functions. Once you start getting experienced with xajax, you may want to create two separate files, one for xajax functions and another for normal functions. The second line includes the xajax routine.

$xajax = new xajax();
$xajax->registerFunction("processFormData");
//$xajax->setFlag("debug", true);
$xajax->processRequest();

The first line "starts" xajax. To use xajax the basic ideia is this: for each user action, we want xajax to react, as such, we create a function for each of these user actions. That's what I'm doing with the second line $xajax->registerFunction("processFormData");. I'll explain this further once we get to functions.php. The third line is commented out. I use this for troubleshooting xajax. The forth line processes all of xajax. Note: Xajax and xoops will not work unless you respect the code order as I'm showing here. If you try to do $xajax->processRequest(); after require(XOOPS_ROOT_PATH.'/header.php'); it will not work. Why? Because xajax needs to be completly processed BEFORE any html output, and that's exactly what XOOPS_ROOT_PATH.'/header.php does.

$Xjavapath=XOOPS_URL.'/modules/tutorial/class/xajax';
$xajaxjava=$xajax->getJavascript($Xjavapath);

For xajax to work it needs a javascript component. Since we are using smarty templates in our module, we will include this componente using this method. The first line assigns the path to xajax to variable (I will call variable as var from now on) $Xjavapath. I then get all of the xajax javascript and place it in var $xajaxjava.

$xoopsOption['template_main'] = 'tut_main.html';
require(XOOPS_ROOT_PATH.'/header.php');

$xoopsTpl->assign('xajaxjava', $xajaxjava);

As we have already discussed in part 2 of my tutorials, the first line gets the smarty template for this page while the second line starts html output. The third line assigns our xajax javascript code to a smarty var.

require(XOOPS_ROOT_PATH.'/footer.php');
?>

I've already explained these 2 lines in previous tutorials.

step 3- Functions.php

Now open tutorial/functions.php and write this code:

<?php
function processFormData($arg)
{
// do some stuff based on $arg like query data from a database and
// put it into a variable like $newContent
$newContent = "Value of field: ".$arg['myfield'];

// Instantiate the xajaxResponse object
$objResponse = new xajaxResponse();

// add a command to the response to assign the innerHTML attribute of
// the element with id="SomeElementId" to whatever the new content is
$objResponse->assign("thisID","innerHTML", $newContent);

//return the xajaxResponse object
return $objResponse;
}

?>

function processFormData($arg) Create a function called processFormData. This function will receive all the form data and put in a var called $arg. The form data will come as an array so $arg will also be an array.
$newContent = "Value of field: ".$arg['myfield']; Create a new var with some text and also get 'myfield' from the array of $arg.
$objResponse = new xajaxResponse(); This starts the xajax response. I normally only start this after processing all my own code.
$objResponse->assign("thisID","innerHTML", $newContent); This takes a var and places it in an ID (in this case called thisID). This ID can be a <div>, <p>, or whatever else you want. Just make sure you do <div id="thisID"> and not <div>.
Important Note:You can place anything you want inside the var, just make sure you don't do any html output. If you were to test your var in this function using print_r($arg), this would cause xajax to stop working. You can place entire html templates inside the var and then assign it to a <div> id.
Important Note: Anytime xajax stops working as expected, turn on xajax debugging by uncommenting the line $xajax->setFlag("debug", true); in index.php.
return $objResponse; Return to xajax and process this function.

Great! we now have a xajax function. Lets setup our template.

Step 4- Tut_main.html Setting the smarty template.

Open /tutorial/templates/tut_main.html. copy this code into it:

<{$xajaxjava}>

<form id="myform" name="myform" method="post" action="index.php">
<input type="text" name="myfield" id="myfield" />
<input type="button" value="Calculate" onclick="xajax_processFormData(xajax.getFormValues('myform'));" />
</form>

<div id="thisID"></div>

<{$xajaxjava}> This will receive the xajax javascript. This should normally be at the very top of your smarty templates.
<form id="myform" name="myform" method="post" action="index.php"> This starts a form named myform. The form name is important since you will be referencing it later on.
<input type="text" name="myfield" id="myfield" /> Create a text field named myfield.
<input type="button" value="Calculate" onclick="xajax_processFormData(xajax.getFormValues('myform'));" /> Now create a button that will submit this form for xajax processing. When a user presses this button, the form data from form 'myform' will be sent to xajax function processFormData.
Note:
when creating your own forms, the xajax function is called (for example) processFormData but when you write the html code you should do: xajax_processFormData.
</form> finishes this form.
Note: Internet explorer doesn't allow nested forms while firefox does. A nested form is a form inside another form. This could be very usefull when building code using ajax, however since IE doesn't support it. I've had to write my code to work around this problem. As you get experienced with xajax, you will probably also run into this problem. The solution is always close a form before starting another.
<div id="thisID"></div> This is where the response from xajax will be placed.

Step 5- Test drives
Important: Before testing make sure you have all debugging turned OFF in xoops. Xajax will NOT WORK with any type of debugging.Why? Because there can be no code output until all of xajax is processed.
Our code is ready for testing. Click on tutorial in the main menu. You should see a text field followed by a button that says calculate. Write in the text field: xajax is cool and click the button. Below you should see a response that says: Value of field: xajax is cool. So now we have a <div> named thisID that gets updated everytime a user clicks the calculate button. Pretty cool don't you think?

Step 6- Taking xajax further. Insert user form.
Now let's create a form to insert users to our DB (please refer to part 1 of my tutorials).
Open tutorial/templates/tut_form.html. replace ALL code with this:

<form id="myform" name="myform" method="post" action="index.php">
<table width="400" border="0">
<tr>
<td align="right"><{$smarty.const.TT_NAME}></td>
<td><input type="text" name="name"></td>
</tr><tr>
<td align="right"><{$smarty.const.TT_ADDRESS}></td>
<td><input type="text" name="address"></td>
</tr><tr>
<td align="right"><{$smarty.const.TT_TELEPHONE}></td>
<td><input type="text" name="tel"></td>
</tr><tr>
<td align="right"><{$smarty.const.TT_EMAIL}></td>
<td><input type="text" name="email"></td>
</tr><tr>
<td></td>
<td><input type="button" value="Submit" onclick="xajax_processFormData(xajax.getFormValues('myform'));" /></td>
</tr>
</table>
</form>

Open tutorial/functions.php. Replace all code with this:

<?php

require_once XOOPS_ROOT_PATH . '/class/template.php';
if (!isset($xoopsTpl)) {
$xoopsTpl = new XoopsTpl();
}
$xoopsTpl->xoops_setCaching(0);


function processFormData($arg)
{
// do some stuff based on $arg like query data from a database and
// put it into a variable like $newContent
$newContent = "Button pressed";

// Instantiate the xajaxResponse object
$objResponse = new xajaxResponse();

// add a command to the response to assign the innerHTML attribute of
// the element with id="SomeElementId" to whatever the new content is
$objResponse->assign("thisID","innerHTML", $newContent);

//return the xajaxResponse object
return $objResponse;
}

function showForm()
{
global $xoopsTpl;

$text = $xoopsTpl->fetch('db:tut_form.html');

$objResponse = new xajaxResponse();
$objResponse->assign("formDiv","innerHTML",$text);
return $objResponse;
}

?>

require_once XOOPS_ROOT_PATH . '/class/template.php';
if (!isset($xoopsTpl)) {
$xoopsTpl = new XoopsTpl();
}
$xoopsTpl->xoops_setCaching(0);
These lines of code are necessary only for the 2.0.x series of xoops (I mainly work with 2.2.x). Here's the problem: Open tutorial/index.php. With xoops 2.2 $xoopsTpl gets declared on line require('../../mainfile.php'); while on xoops 2.0.x only gets declared on require(XOOPS_ROOT_PATH.'/header.php'); Meaning that, if your using 2.0.17 for example the xajax code is requesting $xoopsTpl before it gets declared. The solution is for us to declare $xoopsTpl ourselves. That's what I did with these lines. I first included the file which holds the $xoopsTpl class. I then checked to see if $xoopsTpl is already included using isset. If it's NOT already declared, then declare it. I then set caching to 0 so that it will always update the templates. This way I can constantly change my templates without worring about cache. For your final module you might want to comment out this line.

$newContent = "Button pressed"; This change was necessary for xajax to work. Even php notices will cause xajax to stop behaving properly. Remember, you can always uncomment $xajax->setFlag("debug", true); to find out what's happening.

function showForm()
{
global $xoopsTpl;

$text = $xoopsTpl->fetch('db:tut_form.html');
I've created a new function called showForm and declared $xoopsTpl as a global so that it will work inside this function. Now the fun part; I've created a var called $text that will grab a smarty template from the xoops database called tut_form.html.

$objResponse->assign("formDiv","innerHTML",$text); The var $text, that has a smarty template inside it, will get assigned to the <div> formDiv.


Now open tutorial/index.php. Replace all code with this:

<?php
// Tutorial
// Created by KaotiK
require('../../mainfile.php');

require_once(XOOPS_ROOT_PATH.'/modules/tutorial/functions.php');
require_once(XOOPS_ROOT_PATH.'/modules/tutorial/class/xajax/xajax_core/xajax.inc.php');

$xajax = new xajax();
$xajax->registerFunction("processFormData");
$xajax->registerFunction("showForm");
//$xajax->setFlag("debug", true);
$xajax->processRequest();

$Xjavapath=XOOPS_URL.'/modules/tutorial/class/xajax';
$xajaxjava=$xajax->getJavascript($Xjavapath);

$xoopsOption['template_main'] = 'tut_main.html';
require(XOOPS_ROOT_PATH.'/header.php');
$xoopsTpl->assign('xajaxjava', $xajaxjava);

require(XOOPS_ROOT_PATH.'/footer.php');
?>

 

$xajax->registerFunction("showForm"); I've added another function for xajax to process.


Open tutorial/templates/tut_main.html. Replace all code with this:

<p><{$xajaxjava}></p>
<p><a href="#" onclick="xajax_showForm();return false;">formtest</a></p>
<p><div id="formDiv"></div></p>
<div id="thisID"></div>

<a href="#" onclick="xajax_showForm();return false;">formtest</a> I've added a text with a link that, when pressed will make xajax process the function showForm. return false; is to stop it from reacting as a normal text link.

Let's try it! Click on tutorial from the main menu. You now see a text link that says formtest. Click on it. A form will appear. Now click on the button submit, a new line of text appears that says Button pressed. So we now have 2 <div> that react to 2 user actions.

Step7- placing info in the DB.
The next step is to take the info from our form and place it properly in the DB.

open tutorial/functions.php and replace all code with this:

<?php

require_once XOOPS_ROOT_PATH . '/class/template.php';
if (!isset($xoopsTpl)) {
$xoopsTpl = new XoopsTpl();
}
$xoopsTpl->xoops_setCaching(0);


function processFormData($arg)
{
// do some stuff based on $arg like query data from a database and
// put it into a variable like $newContent
$newContent = addClient($arg);

// Instantiate the xajaxResponse object
$objResponse = new xajaxResponse();

// add a command to the response to assign the innerHTML attribute of
// the element with id="SomeElementId" to whatever the new content is
$objResponse->assign("thisID","innerHTML", $newContent);

//return the xajaxResponse object
return $objResponse;
}

function showForm()
{
global $xoopsTpl;

$text = $xoopsTpl->fetch('db:tut_form.html');

$objResponse = new xajaxResponse();
$objResponse->assign("formDiv","innerHTML",$text);
return $objResponse;
}

function addClient($data)
{
global $xoopsDB;
$myts = myTextSanitizer::getInstance();
$name=$myts->addslashes($data['name']);
$address=$myts->addslashes($data['address']);
$tel=$myts->addslashes($data['tel']);
$email=$myts->addslashes($data['email']);
$query = "Insert into ".$xoopsDB->prefix("tutorial_myform")." (name, address, telephone, email) values ('$name', '$address', '$tel', '$email' )";
$res=$xoopsDB->query($query);
if(!$res) {
$msg="error: $query";
} else {
$msg="Data was correctly inserted into DB!";
}
return $msg;
}

?>

I've created a function called addClient that will take the info from the form and insert it into the table called tutorial_myform. Also notice that I've changed a line in function processFormData to use this new function. This new function will return a $msg of either OK or Not OK whether the info was correctly inserted into the DB. This $msg will be displayed in <div> thisID. Try it!

Step 8- listing users.
Now let's create a list of users from our table.
open tutorial/xoops_version.php and CHANGE the template lines:

// Templates
$modversion['templates'][1]['file'] = 'tut_form.html';
$modversion['templates'][1]['description'] = '';

$modversion['templates'][2]['file'] = 'tut_client_list.html';
$modversion['templates'][2]['description'] = '';

$modversion['templates'][3]['file'] = 'tut_main.html';
$modversion['templates'][3]['description'] = '';

Create a new file: tutorial/templates/tut_client_list.html and place the following code in it:

<table width="100%" border="0" cellspacing="0" cellpadding="0">
<tr>
<td><{$smarty.const.TT_NAME}></td>
<td><{$smarty.const.TT_ADDRESS}></td>
<td><{$smarty.const.TT_TELEPHONE}></td>
<td><{$smarty.const.TT_EMAIL}></td>
</tr>
<{foreach item=cli from=$clients}>
<tr>
<td><{$cli.name}></td>
<td><{$cli.address}></td>
<td><{$cli.telephone}></td>
<td><{$cli.email}></td>
</tr>
<{/foreach}>
</table>

Go to module administration and update the module, so that xoops will process our new template.
Open tutorial/index.php and replace the code with this:

<?php
// Tutorial
// Created by KaotiK
require('../../mainfile.php');

require_once(XOOPS_ROOT_PATH.'/modules/tutorial/functions.php');
require_once(XOOPS_ROOT_PATH.'/modules/tutorial/class/xajax/xajax_core/xajax.inc.php');

$xajax = new xajax();
$xajax->registerFunction("processFormData");
$xajax->registerFunction("showForm");
$xajax->registerFunction("listClients");
//$xajax->setFlag("debug", true);
$xajax->processRequest();

$Xjavapath=XOOPS_URL.'/modules/tutorial/class/xajax';
$xajaxjava=$xajax->getJavascript($Xjavapath);

$xoopsOption['template_main'] = 'tut_main.html';
require(XOOPS_ROOT_PATH.'/header.php');
$xoopsTpl->assign('xajaxjava', $xajaxjava);

require(XOOPS_ROOT_PATH.'/footer.php');
?>

Open tutorial/functions.php and replace the code with this:

<?php

require_once XOOPS_ROOT_PATH . '/class/template.php';
if (!isset($xoopsTpl)) {
$xoopsTpl = new XoopsTpl();
}
$xoopsTpl->xoops_setCaching(0);

function processFormData($arg)
{
// do some stuff based on $arg like query data from a database and
// put it into a variable like $newContent
$newContent = addClient($arg);

// Instantiate the xajaxResponse object
$objResponse = new xajaxResponse();

// add a command to the response to assign the innerHTML attribute of
// the element with id="SomeElementId" to whatever the new content is
$objResponse->assign("thisID","innerHTML", $newContent);

//return the xajaxResponse object
return $objResponse;
}

function showForm()
{
global $xoopsTpl;

$text = $xoopsTpl->fetch('db:tut_form.html');

$objResponse = new xajaxResponse();
$objResponse->assign("formDiv","innerHTML",$text);
return $objResponse;
}

function addClient($data)
{
global $xoopsDB;
$myts = myTextSanitizer::getInstance();
$name=$myts->addslashes($data['name']);
$address=$myts->addslashes($data['address']);
$tel=$myts->addslashes($data['tel']);
$email=$myts->addslashes($data['email']);
$query = "Insert into ".$xoopsDB->prefix("tutorial_myform")." (name, address, telephone, email) values ('$name', '$address', '$tel', '$email' )";
$res=$xoopsDB->query($query);
if(!$res) {
$msg="error: $query";
} else {
$msg="Data was correctly inserted into DB!";
}
return $msg;
}

function listClients(){
global $xoopsTpl;

$clients=clientLoader();
$xoopsTpl->assign('clients', $clients);

$text = $xoopsTpl->fetch('db:tut_client_list.html');

$objResponse = new xajaxResponse();
$objResponse->assign("clientListDiv","innerHTML",$text);
return $objResponse;

}

function clientLoader(){
global $xoopsDB;
$client=array();
$q=1;
$query = $xoopsDB->query(' SELECT * FROM ' . $xoopsDB->prefix('tutorial_myform'));
while($myrow = $xoopsDB->fetchArray($query) )
{
$client[$q]['name'] = $myrow['name'];
$client[$q]['address'] = $myrow['address'];
$client[$q]['telephone'] = $myrow['telephone'];
$client[$q]['email'] = $myrow['email'];
$q++;
}
return $client;
}

?>

Open tutorial/templates/tut_main.html and replace code with this:

<p><{$xajaxjava}></p>
<p><a href="#" onclick="xajax_showForm();return false;">formtest</a></p>
<p><a href="#" onclick="xajax_listClients();return false;">List Clients</a></p>
<p><div id="formDiv"></div></p>
<p><div id="thisID"></div></p>
<p><div id="clientListDiv"></div></p>

Let's try our module! Click on tutorial from the main menu. We now have 2 text links, one says formtest and the other says List Clients. Try clicking on List Clients. A table shows up with a list of clients we have inserted into the table. Now click on formtest and the form will appear. As you can see we have 2 diferent ajax routines running that only load a small piece of the site.

Here's the completed module. Check to see if your code matches.

Tutorial module
Completed Module from part 3

Part 4 - Xoops Blocks

Last modified on 2010/11/27 by fiammybe
This page was created on 2010/11/11 by skenow
This page has been viewed 2673 time(s)

Comments
The comments are owned by the poster. We aren't responsible for their content.
ImpressCMS proudly uses SourceForge
ImpressCMS on Ohloh.net