Anda di halaman 1dari 30

Greyhead.

net
How-to docs and tutorials

ChronoForms v4 How-to doc


Resolving jQuery problems

One of the most frequent problems we see in the ChronoForms forums is that
the form validation doesn't work. By far the most common cause is that the
site template or some other component is using the jQuery library.
jQuery is a very good JavaScript library that enables some amazing effects.
But, out of the box it is incompatible with the MooTools JavaScript library
that is standard in Joomla! and use by ChronoForms. Here we'll look at re-
solving these problems with one typical template. CHRONO
Level: moderate, requires HTML, and some JavaScript and Joomla! knowledge. v4 Forms
Greyhead.net

The Form

For this example Im going to use a simple sign-up form created in


ChronoForms v4 on Joomla! 2.5. It has two text inputs Name, with the
required validation box checked and Email with the required and
email boxes checked and a submit button. The only action is a Show
HTML action in the On Load event.
Well start out using a default Joomla! template to check that the valida-
tion is working correctly.
XXThis is an important step as there are many different things that can
cause validation errors and we wan't to be sure that we have a base-
line case where everything is OK.
On the next page is a screen shot of the form with a validation bubble
message showing.

1 The Form
Greyhead.net

Now its time to change the template and see what happens . . .

2 The Form
Greyhead.net

The template

Im going to work this example with a template from AS Designing who


produce very good looking Joomla! templates. I've chosen a recently
published Joomla! 2.5 / 1.7 template named 002032. You can see their
demo site here.
XX I have no connection with AS Designing; I picked this example
because I was asked to do this work for a client using this template.
Their templates look very nice and, with a little tweaking, they work
well with ChronoForms.
Ive installed the template and set it as my site default. Now I can
browse to my form page and see the form in the new template (see the
next page).
It looks good, but if I click submit the form submits without any valid-
tion of the inputs.

3 The template
Greyhead.net

4 The template
Greyhead.net
Check 1
There is a quick check that is often useful as it can let us know if the
problem is template related. Just add &tmpl=component to the URL in
the browser address box and refresh the page. This will tell Joomla! to
load the page without the template. Just what this means depends a
bit on the template authors some give cleaner results than others.

5 The template
Greyhead.net
As you can see, there are a couple of PHP messages but the validation is
working OK again. We can now be pretty confident that the problem is
with the template.
XXThe PHP Warning messages are showing because my development site
runs with Error Reporting set to Maximum; on a production site this
should probably be set to None and these messages would be hid-
den. They relate to a template file that can no longer be loaded.

Check 2
Well go back to viewing the page with the template (either go back in
the browser or remove the &tmpl=component from the URL and refresh
the page).
All of the modern browsers have Web Developer tools available that
are invaluable. I'm using Chrome here so I can access them with
Shift+Ctrl+I
XX Use your preferred web developer tools: click F12 in IE8 or IE9,
Shift+Ctrl+I in Chrome, install FireBug in FireFox, check out DragonFly
in Opera.
In the Developer tools I'll check the Console when I try to submit the
form and I see an error message like this:
Uncaught TypeError: Object [object Object] has no method 'getProperty'

By itself this doesnt say much but I happen to know that this is a good
indicator of a conflict between jQuery and MooTools.

6 The template
Greyhead.net
Both JavaScript libraries try to make use of $ as a short-cut for their main
function. Which-ever gets there first grabs it and gets all references to
$ passed to it. MooTools has a function getProperty() and jQuery
doesnt so gives out this error when the validtion code calls the function.
jQuery has a noConflict mode where it effectively hands over the $
and makes it available for MooTools to use. What is more there is a one-
line command that enables this mode and will solve all our problems.
But . . . there has to be a but . . . to get the command to work correctly
it has to be placed so that it runs after jQuery is loaded and before any
MooTools code is run. This can be tricker that it sounds and the rest of
this tutorial is about modifiying the template code to get this to work
smoothly.

7 The template
Greyhead.net

Inside the template

We're now going to dip into the workings of the template. Your tem-
plate may be coded differently but you'll probably see some strong
similarities at the code level.
First we'll look at the HTML in the page source. Here's the <head> block
copied from the Chrome developer view:
<link rel="stylesheet" href="/components/com_chronoforms/css/frontforms.css" type="text/
css">
<link rel="stylesheet" href="/components/com_chronoforms/css/formcheck/theme/classic/form-
check.css" type="text/css">
<link rel="stylesheet" href="/components/com_chronoforms/css/formcheck_fix.css" type="text/
css">
<script src="/media/system/js/mootools-core.js" type="text/javascript"></script>
<script src="/media/system/js/core.js" type="text/javascript"></script>
<script src="/media/system/js/mootools-more.js" type="text/javascript"></script>
<script src="/components/com_chronoforms/js/formcheck/formcheck-yui.js" type="text/javas-
cript"></script>
<script src="/components/com_chronoforms/js/formcheck/formcheck-max.js" type="text/javas-
cript"></script>
<script src="/components/com_chronoforms/js/formcheck/lang/en.js" type="text/javascript"></
script>
<script type="text/javascript">
//<![CDATA[
window.addEvent('domready', function() {
$('chronoform_test_form_template').addClass('hasValidation');
formCheck_test_form_template = new FormCheckMax('chronoform_test_form_template', {

8 Inside the template


Greyhead.net
onValidateSuccess: $empty,
display : {
showErrors : 0,
errorsLocation: 1
}
});
});
//]]>
</script>
<link rel="stylesheet" href="/templates/system/css/general.css" type="text/css">
<link rel="stylesheet" href="/templates/system/css/system.css" type="text/css">
<link rel="stylesheet" href="/templates/as002032-free/css/template.css" type="text/css">
<link rel="stylesheet" href="/templates/as002032-free/css/joomla.css" type="text/css">
<link rel="stylesheet" href="/templates/as002032-free/css/bloglayout.css" type="text/css">
<link rel="stylesheet" href="/templates/as002032-free/slider/css/slider.css" type="text/css"
media="screen">
<script type="text/javascript" src="/templates/as002032-free/scripts/general.js"></script>
<script type="text/javascript" src="/templates/as002032-free/scripts/jquery.js"></script>
<script type="text/javascript" src="/templates/as002032-free/slider/scripts/jquery-
1.6.1.min.js"></script>
<script type="text/javascript" src="/templates/as002032-free/slider/scripts/jquery.slider.
pack.js"></script>
<style> . . . </style>
<link rel="stylesheet" href="/templates/as002032-free/css/bloglayout.single.css"
type="text/css">

Ive cleaned this up a bit for clarity, simplified the URLs and skipped a
huge chunk of CSS. You can see two blocks of scripts here. One at the
top with Joomla! and ChronoForms files and one at the end with the
template scripts. If you look at the template scripts you can see that two

9 Inside the template


Greyhead.net
versions of jQuery are being loaded jquery.js (loading jQuery 1.4.2 in
this case) and jquery-1.6.1.min.js We could really do with just hav-
ing one of these to manage.
In the script snippet near the middle you can see the line window.
addEvent('domready', . . . This has the effect of stopping this code
from running until the page has loaded all the HTML and scripts. In this
snippet the $ refers to MooTools.
Further down the page there is also this script snippet that drives the
image slider in the template. In this snippet the $ refers to jQuery:
<script type="text/javascript">
$(window).load(function() {
$('#slider').nivoSlider({
animSpeed: 1000,
pauseTime: 4000 });
});
</script>

So now its time to try and fix this.

10 Inside the template


Greyhead.net

Using noConflict()

If you check the jQuery API it has some excellent notes on putting
JQuery into noConflict mode. The simplest of them is to use jQuery.
noConflict(); So well try putting this into a Load JS action in our
form.
Sometimes this works very well - but not in this case. We get this error:
Uncaught ReferenceError: jQuery is not defined
Checking in the header the problem is that the command is there OK
but is being run before JQuery is loaded.
We can add a fix to the code to avoid this error - which can be useful if
we aren't sure if jQuery will be loaded on some pages.
if ( typeof jQuery != 'undefined' ) {
jQuery.noConflict();
}

But this still leaves us with the previous error.


We can try executing the code later to be sure that it is after jQuery
loads:
window.addEvent('domready', function() {
if ( typeof jQuery != 'undefined' ) {
jQuery.noConflict();
}
});

11 Using noConflict()
Greyhead.net
But that doesnt help either. The validation still fails with the getProp-
erty() error and now we have a second error from the Slider snippet
saying:
Uncaught TypeError: Object #<Object> has no method 'nivoSlider'

We could experiment some more and maybe find a way of getting this
working but instead we'll go and look at the template code.

12 Using noConflict()
Greyhead.net

Inside index.php

Ive opened up the templates/as-002032-free/index.php file in my editor


and here is the code that creates the head section of the page:
<head>
<jdoc:include type="head" />
<link rel="stylesheet" href="<?php echo $this->baseurl ?>/templates/system/css/gen-
eral.css" type="text/css" />
<link rel="stylesheet" href="<?php echo $this->baseurl ?>/templates/system/css/system.
css" type="text/css" />
<link rel="stylesheet" href="<?php echo $this->baseurl ?>/templates/<?php echo $this-
>template ?>/css/template.css" type="text/css" />
<link rel="stylesheet" href="<?php echo $this->baseurl ?>/templates/<?php echo $this-
>template ?>/css/joomla.css" type="text/css" />
<link rel="stylesheet" href="<?php echo $this->baseurl ?>/templates/<?php echo $this-
>template ?>/css/bloglayout.css" type="text/css" />
<link rel="stylesheet" href="<?php echo $this->baseurl ?>/templates/<?php echo $this-
>template ?>/slider/css/slider.css" type="text/css" media="screen" />
<script type="text/javascript" src="templates/<?php echo $this->template ?>/scripts/
general.js"></script>
<script type="text/javascript" src="templates/<?php echo $this->template ?>/scripts/
jquery.js"></script>
<script type="text/javascript" src="templates/<?php echo $this->template ?>/slider/
scripts/jquery-1.6.1.min.js"></script>
<script type="text/javascript" src="templates/<?php echo $this->template ?>/slider/
scripts/jquery.slider.pack.js"></script>
<?php
// three lines omitted here

13 Inside index.php
Greyhead.net
if(!$leftcolumn) {
echo '<link rel="stylesheet" href="' . $this->baseurl . '/templates/' . $this-
>template . '/css/bloglayout.single.css" type="text/css" />';
}
?>
</head>

XX For clarity Ive left out some code at the beginning including the tem-
plate credits and a few lines later on that arent important for us - but
leave all these in if you edit the index.php file for your template.
Notice the second line here that I've high-lighted. That's a piece of
Joomla! code that includes all the files that Joomla! know need to be
loaded into the page header. After that come the files that the template
needs to load.
If you remember earlier we saw two groups of script files being loaded.
The first group is the Joomla! scripts; the second the template scripts.
To give us better control we're going to put all of the scripts (and the
stylesheets while we're about it) into the Joomla! managed group.
Joomla! provides some methods to load files like this in the Document
Object and we can adapt those. The basic ones are:
// to load the document object
$doc =& JFactory::getDocument();
// to add a script file
$doc->addScript('script_url');
// to add a scritp snippet
$doc->addScriptDeclaration('some script');

14 Inside index.php
Greyhead.net
// to add a stylesheet
$doc->addStylesheet('stylesheet_url');
// to add a CSS snippet
$doc->addStylesheetDeclaration('some CSS');

Before using these we need to work out what files the template actually
needs by picking them out of the code above. Here's the list I get in a
shorthand form with the second copy of jQuery struck out:
templates/system/css/general.css
templates/system/css/system.css
templates/[this_template]/css/template.css
templates/[this_template]/css/joomla.css
templates/[this_template]/css/bloglayout.css
templates/[this_template]/slider/css/slider.css media="screen"
// only if !$leftcolumn
templates/[this_template]/css/bloglayout.single.css
templates/[this_template]/scripts/general.js
templates/[this_template]/scripts/jquery.js
templates/[this_template]/slider/scripts/jquery-1.6.1.min.js
templates/[this_template]/slider/scripts/jquery.slider.pack.js

Like the template code above well use the Joomla! variables $this-
>baseurl and $this->template to complete the URLs we need.
So the code to load the first script here might be:
$doc->addScript($this->baseurl.'/templates/'.$this->template.'/scripts/general.js');

15 Inside index.php
Greyhead.net
Repeating this for all of them we get this:
<?php
$doc =& JFactory::getDocument();
$doc->addStylesheet($this->baseurl.'/templates/system/css/general.css');
$doc->addStylesheet($this->baseurl.'/templates/system/css/system.css');
$doc->addStylesheet($this->baseurl.'/templates/'.$this->template.'/css/template.css');
$doc->addStylesheet($this->baseurl.'/templates/'.$this->template.'/css/joomla.css');
$doc->addStylesheet($this->baseurl.'/templates/'.$this->template.'/css/bloglayout.css');
$doc->addStylesheet($this->baseurl.'/templates/'.$this->template.'/slider/css/slider.css',
'text/css', 'screen');
if ( !$leftcolumn) {
$doc->addStylesheet($this->baseurl.'/templates/'.$this->template.'/css/bloglayout.sin-
gle.css');
}

$doc->addScript($this->baseurl.'/templates/'.$this->template.'/scripts/general.js');
$doc->addScript($this->baseurl.'/templates/'.$this->template.'/scripts/jquery.js');
$doc->addScript($this->baseurl.'/templates/'.$this->template.'/slider/scripts/jquery.
slider.pack.js');
?>

XX Note the extra parameters for the slide.css to include the media at-
tribute.

16 Inside index.php
Greyhead.net
That leaves us with the NovaSlider script snippet to handle. Heres the
code embedded in the body section on the index.php file:
$(window).load(function() {
$('#slider').nivoSlider({
animSpeed: <?php echo $slider_speed; ?>,
pauseTime: <?php echo $slider_showtime; ?>
});
});

This is being included in the index.php file becasue it includes a couple


of parameters that are being taken from the template settings to set the
speed and showtime of the slider. Otherwise it could be included in a
file and linked in like the others.
XXThe $ in the first two lines is the jQuery $; the two later $s are in PHP
variable names.
Although the script has been placed with the slider HTML it doesn't
need to be there - its linked through the $('#slider') selector so we
can safely move it up into the head section. Well comment out the
copy in the body for the moment using <!-- --> outside the <script>
tags as its in an HTML section.

17 Inside index.php
Greyhead.net
Then up in the header we can add an equivalent snippet; and, at the
same time puch the jQuery into noConflict mode:
jQuery.noConflict();
window.addEvent('domready', function() {
jQuery('#slider').nivoSlider({
nimSpeed: {$slider_speed},
pauseTime: {$slider_showtime}
});
});

This includes the PHP variables and uses the jQuery prefix. To load this
we need to use the $doc method so the final snippet look like this:
$script ="
jQuery.noConflict();
window.addEvent('domready', function() {
jQuery('#slider').nivoSlider({
nimSpeed: {$slider_speed},
pauseTime: {$slider_showtime}
});
});
";
$doc->addScriptDeclaration($script);

XXThis is very effective and tidy but you have to be careful with quotes!!
Now the final test is to see if the validation now works as well as the
jQuery slider . . . and it does.

18 Inside index.php
Greyhead.net

Bob Janes
13 February 2012

19 Inside index.php
Greyhead.net

The edited index.php file

In this section of this document is the amended index.php file. In addi-


tion to the changes here I've also moved a Google Analytics snippet into
the header and re-formatted some of the HTML.
<?php

/************************************************/
/*
/* Designed by 'AS Designing'
/* Web: http://www.asdesigning.com
/* Email: info@asdesigning.com
/*
/************************************************/

defined( '_JEXEC' ) or die( 'Restricted access' );

/* The following line loads the MooTools JavaScript Library */


JHTML::_('behavior.framework', true);

/* The following line gets the application object */


$app = JFactory::getApplication();

include 'ie6warning.php';
include 'params.general.php';
include 'styles.php';

$doc =& JFactory::getDocument();

20 The edited index.php file


Greyhead.net
$doc->addStylesheet($this->baseurl.'/templates/system/css/general.css');
$doc->addStylesheet($this->baseurl.'/templates/system/css/system.css');
$doc->addStylesheet($this->baseurl.'/templates/'.$this->template.'/css/template.css');
$doc->addStylesheet($this->baseurl.'/templates/'.$this->template.'/css/joomla.css');
$doc->addStylesheet($this->baseurl.'/templates/'.$this->template.'/css/bloglayout.css');
$doc->addStylesheet($this->baseurl.'/templates/'.$this->template.'/slider/css/slider.css',
'text/css', 'screen');
if ( !$leftcolumn) {
$doc->addStylesheet($this->baseurl.'/templates/'.$this->template.'/css/bloglayout.sin-
gle.css');
}

$doc->addScript($this->baseurl.'/templates/'.$this->template.'/scripts/general.js');
$doc->addScript($this->baseurl.'/templates/'.$this->template.'/scripts/jquery.js');
$doc->addScript($this->baseurl.'/templates/'.$this->template.'/slider/scripts/jquery.
slider.pack.js');
$doc->addScript('http://pagead2.googlesyndication.com/pagead/show_ads.js');
$script ="
jQuery.noConflict();
window.addEvent('domready', function() {
jQuery('#slider').nivoSlider({
nimSpeed: {$slider_speed},
pauseTime: {$slider_showtime}
});
});
google_ad_client = 'ca-pub-1063867985951059';
/* AS Image 468x60 */
google_ad_slot = '1732959233';
google_ad_width = 468;
google_ad_height = 60;

21 The edited index.php file


Greyhead.net
";
$doc->addScriptDeclaration($script);
?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xht-
ml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="<?php echo $this->language; ?>"
lang="<?php echo $this->language; ?>" >
<head>
<jdoc:include type="head" />
</head>
<body>
<!-- HEADER ~~~~~ -->
<div id="header">
<div class="row1">
<div class="content">
<div id="topnavbar">
<div class="custom">
<div id="contactlink"> <a href="http://www.astemplates.com/contactus.
php" title="Contact Us"> <img src="/images/spacer.png" border="0" width="1" height="1"
style="border: 0;" /></a> </div>
<div id="searchlink"> <a href="index.php?option=com_search&amp;view=s
earch&amp;searchword=search" title="Search"> <img src="/images/spacer.png" border="0"
width="1" height="1" style="border: 0;" /></a> </div>
<div id="homelink"> <a href="http://www.astemplates.com" title="Home">
<img src="/images/spacer.png" border="0" width="1" height="1" style="border: 0;" /></
a> </div>
</div>
</div>
</div>
</div>

22 The edited index.php file


Greyhead.net
<div class="clear"></div>
<div class="row2">
<div class="content">
<div class="row2col1">
<div id="companyname"> <a href="<?php echo $this->baseurl; ?>"> <img
src="<?php echo $logo_img; ?>" alt="AS Templates"/> </a> </div>
</div>
<div class="row2col1">
<div id="topmenu">
<jdoc:include type="modules" name="position-32-1"/>
</div>
</div>
</div>
</div>
<div class="clear"></div>
<div class="row3">
<div class="content">
<div id="slideshow">
<div class="slider-wrapper">
<div id="slider" class="nivoSlider">
<img src="templates/<?php echo $this->template ?>/slider/im-
ages/slide1.jpg" width="984" height="234" />
<img src="templates/<?php echo $this->template ?>/slider/images/
slide2.jpg" width="984" height="234" />
<img src="templates/<?php echo $this->template ?>/slider/images/
slide3.jpg" width="984" height="234" />
</div>
</div>
</div>
</div>

23 The edited index.php file


Greyhead.net
</div>
<div class="clear"></div>
<?php if($this->countModules('breadcrumbsload') || $this->countModules('positi
on-32-0')): ?>
<div class="row4">
<div class="content">
<div class="row4col1">
<div id="breadcrumb">
<jdoc:include type="modules" name="breadcrumbsload" />
</div>
</div>
<div class="row4col2">
<div id="search">
<jdoc:include type="modules" name="position-32-0" />
</div>
</div>
</div>
</div>
<div class="clear"></div>
<?php endif; ?>
</div>
<!-- END OF HEADER ~~~~~ -->

<!-- CONTENT ~~~~~ -->


<div class="clear"></div>
<div id="content">
<!-- COLUMN LEFT ~~~~~ -->lumn) : ?>
<div id="colleft">
<?php if($this->countModules('position-32-40')): ?>
<div class="row1">

24 The edited index.php file


Greyhead.net
<jdoc:include type="modules" name="position-32-40" style="xhtml"/>
</div>
<?php endif; ?>
<?php if($this->countModules('position-32-41')): ?>
<div class="row2">
<jdoc:include type="modules" name="position-32-41" style="xhtml"/>
</div>
<?php endif; ?>
</div>
<?php endif; ?>
<!-- END OF COlUMN LEFT ~~~~~ -->

<!-- COLUMN MAIN ~~~~~ -->


<div id="colmain" <?php echo $maincolumn_width; ?> >
<jdoc:include type="message" />
<div id="component" <?php echo $maincolumn_cntwidth; ?> >
<jdoc:include type="component" />
</div>
<div class="clear"></div>
<div id="adsense">
<div class="innerborder"> </div>
</div>
<div class="clear"></div>
</div>
<!-- END OF COLUMN MAIN ~~~~~ -->
</div>
<div class="clear"></div>
<!-- FOOTER ~~~~~ -->
<div id="footer">
<div class="row2">

25 The edited index.php file


Greyhead.net
<div class="content">
<?php if($this->countModules('position-32-51')): ?>
<div class="row2col1">
<jdoc:include type="modules" name="position-32-51" style="xhtml"/>
</div>
<?php endif; ?>
<div class="row2col2">
<div id="trade">Copyright &copy; <?php echo date('Y'); ?> <?php echo $app-
>getCfg('sitename'); ?></div>

<!-- DO NOT REMOVE OR CHANGE THE CONTENT BELOW, THIS TEMPLATE MAY NOT WORK
PROPERLY -->
<!-- FOR MORE INFO SEE OUR COPYRIGHT NOTICE FOR FREE WEBSITE TEMPLATES:
http://astemplates.com/terms.php -->

<div id="ascopy"> &nbsp;|&nbsp; <a href="http://www.astemplates.com/" tar-


get="_blank"> DESIGNED BY:&nbsp;&nbsp;AS TEMPLATES </a> </div>

<!-- DO NOT REMOVE OR CHANGE THE CONTENT ABOVE, THIS TEMPLATE MAY NOT WORK
PROPERLY -->
<!-- FOR MORE INFO SEE OUR COPYRIGHT NOTICE FOR FREE WEBSITE TEMPLATES:
http://astemplates.com/terms.php -->
</div>
</div>
</div>
<div class="item-separator"></div>
</div>
<!-- END OF FOOTER ~~~~~ -->
</body>
</html>

26 The edited index.php file


Greyhead.net

The ChronoForms Book Bob Janes

The ChronoForms I am always interested in innovative web


Book is the miss- projects.
ing manual for the
I specialise in developing Joomla! based pro-
Joomla! Chrono-
jects using ChronoForms and ChronoCon-
Forms extension.
nectivity to create customised web applica-
In 350 pages of
tions.
clear, practical
guidance it tells Im also available for interactive chat sup-
you everything that port to developers using ChronoForms and
you need to know ChronoConnectivity. A quick message can
to create forms save you hours of hunting through docu-
on your Joomla! ments and forums.
website, email the
Ive also worked on Joomla component de-
form results and/
velopment; and on custom site functionality
or save them to a
in Joomla! and in WordPress.
database table and
much more. Drop me a line if you think that I could help
you develop your project or site with less
Click here to see the full contents list, down-
hassle and less of your time.
load a sample chapter or to buy a copy
Bob Janes
bob@bobjanes.com

27 The edited index.php file


Greyhead.net

Version history

v1.0 13 Feb 2012

28 Version history
Greyhead.net
Bob Janes is the author of the ChronoForms 3.1 for Joomla! site Cookbook
published by Packt Publishing. He provides support on the ChronoEngine
forums and works as a developer of custom applications (often using Chrono-
Forms and ChronoConnectivity) for Joomla! and WordPress.
Bob can be contacted at info@greyhead.net
ChronoForms is a Joomla! Component for creating interactive forms including
the ability to email the results, save them to a database table and much more.
ChronoConnectivity is a Joomla! Component that works with ChronoForms
to allow the easy display of lists of records from a database table. Chrono-
Connectivity and ChronoForms are published by ChronoEngine.com.
This help-sheet was written for ChronoForms v4 RC1.9
and/or ChronoConnectivity 2.0 RC3
ChronoEngine Tutorials by Bob Janes are licensed under a
Creative Commons Attribution-NonCommercial-No-
Derivs 3.0 Unported License

Disclaimer
To the best of our knowledge and belief the information in this tutorial was
substantially correct at the time of writing. Neither the author, nor ChronoEn-
gine.com shall have neither liability nor responsibility in respect of any loss or
damage caused, or alleged to have been caused, directly or indirectly, by the
information contained in this document.

29 Version history

Anda mungkin juga menyukai