21 tháng 12, 2007

Module Hello World 3

Introduction
This tutorial aims to further build on the helloworld module we expanded in part three. You will learn how to use parameters to fine tune some of the information that is displayed. We will also look at looking at ways to 'skin' your module output..
Requirements
You need for this tutorial:
• Joomla 1.0 or greater
Let's Roll
You will recall that we finished part 2 with your module displaying a list of the most hit times. Unfortunately we were stuck with displaying only 5 items and could not change the ordering. What we will do in this example is learn how to add parameters to the module so that you can vary these conditions.
Setting up the Parameters
We need to revisit the XML file that we created in part 1. We define all our parameters in this file. First let's consider what variables we want to allow the user to change:
1. We want a variable to change the number of items displayed.
2. We want to be able to select the ordering of the items from a list.
3. We want to be able to select a template to use to change the display of the items (sort of like skinning).
To do this we add a number of param tags to the params tag. Open the mod_helloworld.xml file. Delete its contents and replace it with the following code:
<?xml version="1.0" encoding="iso-8859-1"?>
<mosinstall type="module" version="4.5.2">
<name>Hello World</name>
<author>Andrew Eddie</author>
<creationDate>March 2005</creationDate>
<copyright>(C) 2005 Andrew Eddie</copyright>
<license>http://www.gnu.org/copyleft/gpl.html GNU/GPL</license>
<version>2.0</version>
<description>A module that says hello and displays a list of the
most hit content items</description>
<files>
<filename module="mod_helloworld">mod_helloworld.php</filename>
<filename>mod_helloworld/default.html</filename>
</files>
<params>
<param name="moduleclass_sfx" type="text" default=""
label="Module Class Suffix"
description="A suffix to be applied to the css class of the module
(table.moduletable), this allows individual module styling" />

<param name="@spacer" type="spacer" default="" label="" description="" />
<param name="count" type="text" size="20" default=""
label="Number of items" description="The number of items to display" />
<param name="ordering" type="list" default="hits" label="Back Button"
description="Show/Hide a Back Button, that returns you to the previously
view page">
<option value="hits">Hits</option>
<option value="title">Title</option>
</param>
<param name="@spacer" type="spacer" default="" label="" description="" />
<param name="skin" type="list" default="default" label="Module Skin"
description="The skin for the module display">
<option value="default">Default</option>
<option value="bullets">Bullets</option>
</param>
</params>
</mosinstall>
Each param tag has a number of common attributes:
nameThe name of the html form field and also the name of the paremeter that you will access in your module code.typeThis is the type of field. The standard types are:
• text - a normal text field
• textarea - a normal textarea field. You can also add attributes for the rows and cols.
• list - a normal select list form field. Lists can have any number of option child tags.
• radio - a radio group. The radio type can have any number of option child tags
• spacer - shows a html horizontal rule.
• imagelist - shows a select list of images. You also provide a required directory attibute (the default is /images/stories), an optional hide_none attribute (either 0 or 1, where 1 will show a "Use no image" option) and a hide_default attribute (either 0 or 1, where 1 will show a "Use default image" option).
• mos_category - shows a select list of Joomla content categories
• mos_section - shows a select list of Joomla content sections.
• mos_menu - shows a list of Joomla menu items.
defaultA default value for the form field if no value is provided.
labelA label for the form field.descriptionA description (or tooltip) for the form field
There are some additonal attributes based on the type of parameter as described above. For those parameters that allow for options, a standard html option tag is used, usually with a value attribute.

Let's have a look at each param tag in the params tag (each parameter will be identified by it's name attribute): moduleclass_sfx This is a standard parameter to include in all modules. Most modules are placed in a wrapper (unless you are using the loadModules template macro with a style of less than zero) and this wrapper has a css class of moduleclass. You can include your own variant of this class and suffix it with a unique identifier, for example, moduleclass_hello. To use your custom class you would enter _hello in this field@spacerThis param simply displays as a horizontal rule. It is useful for visually separating groups of associated parameters.countThis will define the number of items we will showorderingThis will show a list of possible options for ordering the list of items@spacerAnother spacer.skinThis will show a list of the available 'skins' for the output of the module. When you updated the xml file, navigate to Modules -> Site Modules from the menu in the Administrator. Click on the linked name for the Hello World module (it might be on another page of the list depending on it's position).

When the edit screen appears you should see that the parameters show at the bottom of the first column of the form.

You can see how the spacer works, separating the parameters into groups. You can also see that the lists are populated with the options defined in the xml file. For now you can leave the count blank, but when we have finished altering all the code, come back to this edit form and experiment with different values. Note that the Page Class Suffix will only be relevant if you have a custom style in the style sheet for your site template.
Coding for Module Parameters
Our next step is to retrieve the parameters in our module and apply them. Open the module php file, mod_helloworld.php, in your editor, delete the code and replace it with the following:
<?php
/**
* @version 1.0 $
* @package HelloWorld
* @copyright (C) 2005 Andrew Eddie
* @license http://www.gnu.org/copyleft/gpl.html GNU/GPL
*/

/** ensure this file is being included by a parent file */
defined( '_VALID_MOS' ) or
die( 'Direct Access to this location is not allowed.' );

// COLLECT DATA

// assemble query
global $mosConfig_offset;

$now = date( 'Y-m-d H:i:s', time() + $mosConfig_offset * 3600 );

// Retreive parameters

$count = intval( $params->get( 'count', 10 ) );
$ordering = $params->get( 'ordering', 'hits' );
$skin = $params->get( 'skin', 'default' );

// Assign ordering

switch ($ordering) {
case 'title':
$orderBy = 'title ASC';
break;
case 'hits':
default:
$orderBy = 'hits DESC';
break;
}

$query = '
SELECT id, title, hits
FROM #__content
WHERE ( state = \'1\' AND checked_out = \'0\' )
AND ( publish_up = \'0000-00-00 00:00:00\' OR publish_up <= \''
. $now . '\' )
AND ( publish_down = \'0000-00-00 00:00:00\' OR publish_down >= \''
. $now . '\' )
AND access <= \'' . $my->gid .'\'
ORDER BY ' . $orderBy . '
LIMIT ' . $count
;

// prepare the query in the database connector
$database->setQuery( $query );

// retrieve the rows as objects
$rows = $database->loadObjectList();

// DISPLAY DATA

// load the patTemplate library
require_once( $mosConfig_absolute_path . '/includes/patTemplate/patTemplate.php' );

// create the template
$tmpl =& patFactory::createTemplate( '', false, false );

// set the path to look for html files
$tmpl->setRoot( dirname( __FILE__ ) . '/mod_helloworld' );

// load the template based on the selected skin
$tmpl->readTemplatesFromInput( $skin . '.html' );

// add the 'rows' to the rows template with a prefix
$tmpl->addObject( 'rows', $rows, 'row_' );

// output the template
$tmpl->displayParsedTemplate( 'helloworld' );
?>
You will see that after the "retrieve parameters" comment we've added a few lines. An object variable called $params is already made available to the module. It has a method called get. This method takes two arguments; the first is the name of the parameter, the second is the default value to assign it if the user has not given it a value.

Once we have the parameters in variable form, you'll see we use them to modify the ordering of the query and also the number of items returned by the query. Further down you can see we use the $skin variable to load the selected skin for the output.
Adding Another Skin
Last of all we need to add our alternative skin. We are going to display the resulted in a bullet list instead of a table. Recall that our template current template file is called default.html in the mod_helloworld directory. In that same directory create a new file called bullets.html and copy the following code into it:
<mos:comment>
@version 1.0
@package HelloWorld
@copyright (C) 2005 Andrew Eddie
@license http://www.gnu.org/copyleft/gpl.html GNU/GPL
</mos:comment>

<mos:tmpl name="helloworld">
<h1>Hello World</h1>
How is this for a change.
<ul>
<mos:tmpl name="rows">
<li>
{ROW_TITLE} <em>( {ROW_HITS} )</em></li>
</mos:tmpl>
</ul>
</mos:tmpl>

When you are finished, go back to the module edit screen and change some of the values and see what happens.
What we are demonstrating here is the ability to present the same data in different ways without having to re-engineer the core php code. The change to the presentation layer is done in familiar HTML files, making Joomla even easier to tune to your specific needs.
You can download the files for this tutorial mod_helloworld_3.zip
-->đọc tiếp...

Module Hello World 2

Introduction
This tutorial aims to build on the helloworld module started in part one. You will learn how to retrieve information from the database and how to present this data is a table using patTemplate.
Requirements
You need for this tutorial:
• Joomla 1.0 or greater
Let's Roll
You will recall that we finished part 1 with your module displaying a message and the current time. This is all very interesting but far more interesting is the information held in the tables of the Joomla database. What we will do in this example is develop a type of Current News module.
The Presentation Layer
Let's start with the output of the module. Because the code (or the logic) of the module is now separated from the presentation layer (the HTML), it gives the graphic designer an opportunity to design the output separate from the module.

The module code designer has informed us that a list of content items will be provided to the template. The content item data will include the item id, the title of the item, and the number of hits the item has received.

Now, open the default.html file (remember we saved this in the /mod_helloworld directory). Delete what is there and replace it with the following code:
<mos:comment>
@version 1.0
@package HelloWorld
@copyright (C) 2005 Andrew Eddie
@license http://www.gnu.org/copyleft/gpl.html GNU/GPL
</mos:comment>

<mos:tmpl name="helloworld">
<h1>Hello World</h1>
This is the latest and the greatest from <strong>{SITENAME}</strong>
<table>
<tr>
<th>
Title
</th>
<th>
Hits
</th>
</tr>
<mos:tmpl name="rows">
<tr>
<td>
{ROW_TITLE}
</td>
<td>
{ROW_HITS}
</td>
</tr>
</mos:tmpl>
</table>
</mos:tmpl>
As in part 1, we wrap our whole module output in a template that we've named helloworld. It all looks like standard HTML except for a few things.

You'll see we display a message with the {SITENAME} variable. This variable has already been defined for you in the template. It's equivalent to printing the $mosConfig_sitename variable. Other predefined variables include {SITEURL} and {ADMINURL}. These map to the URL of the site and administrator repsectively.

The other thing you'll notice is an embedded template that we have named rows. It enclosed a single row of the HTML table. The module designer has told us that he has prefixed all variables in the rows template with "row_", and that he has provided at least the Title, which therefore maps to {ROW_TITLE}, and the Hits, which maps to {ROW_HITS}.

Well, that's the template finished (is it that easy I hear you say?).
The Data Layer
Let's move back to the module file, mod_helloworld.php, where we will assemble the data to pass to the template. Open the file in your editor, delete the code and replace it with the following:
<?php
/**
* @version 1.0 $
* @package HelloWorld
* @copyright (C) 2005 Andrew Eddie
* @license http://www.gnu.org/copyleft/gpl.html GNU/GPL
*/

/** ensure this file is being included by a parent file */
defined( '_VALID_MOS' ) or
die( 'Direct Access to this location is not allowed.' );

// COLLECT DATA

// assemble query
$query = '
SELECT id, title, hits
FROM #__content
ORDER BY hits DESC
LIMIT 5
';

// prepare the query in the database connector
$database->setQuery( $query );

// retrieve the rows as objects
$rows = $database->loadObjectList();

// DISPLAY DATA

// load the patTemplate library
require_once( $mosConfig_absolute_path
. '/includes/patTemplate/patTemplate.php' );

// create the template
$tmpl =& patFactory::createTemplate( '', false, false );

// set the path to look for html files
$tmpl->setRoot( dirname( __FILE__ ) . '/mod_helloworld' );

// load the template
$tmpl->readTemplatesFromInput( 'default.html' );

// add the 'rows' to the rows template with a prefix
$tmpl->addObject( 'rows', $rows, 'row_' );

// output the template
$tmpl->displayParsedTemplate( 'helloworld' );
?>
Let's examine what's happening here:
• We start with the standard comment and security block.
• We then prepare our query. The data we want is in the mos_content table. Because we don't always know if the "mos_" prefix has been used, we use "#__" (hash, underscore, underscore) instead. This is automatically replaced with the correct database table prefix. You'll notice we are retrieving three fields, the id, the title and the hits. We are ordering them by the number of hits in descending order and limiting the number of results to a maximum of five (that is, the top five).
• Next we initialise the query in the database connector ($database, which is always available to module files) using the setQuery method.
• Following this we call the loadObjectList method to retrieve the results from the database as an array of PHP objects. This is stored in the variable $rows.
That's it for the first half of the module, that is, the collecting of the data. The last half of the module is much that same as our original module from part 1. The only difference is that we use the addObject method to add the array to the rows template.
Note: the addObject method can take either a single object or an array of objects.

The thing to note here is that for each array member in $rows, the rows template in the HTML file will display a copy of itself. In other words, if there are five elements in the $rows array (that is, the database was able to retrive five rows of records), then the rows template will cycle, or iterate, five times. The rows template acts much like a foreach loop in PHP.

Save all files and refresh your browser. You should see that the module now displays an opening message that includes the name of your site, and also a table of the most hit content items.

What's wrong with this picture. Well, you'll see that the query takes no account for publishing dates, whether they are indeed published at all and the security level of the items. You have to apply that logic yourself. To do this, modifying the query variable in the following way:
// assemble query
global $mosConfig_offset;

$now = date( 'Y-m-d H:i:s', time() + $mosConfig_offset * 3600 );

$query = '
SELECT id, title, hits
FROM #__content
WHERE ( state = \'1\' AND checked_out = \'0\' )
AND ( publish_up = \'0000-00-00 00:00:00\'
OR publish_up <= \'' . $now . '\' )
AND ( publish_down = \'0000-00-00 00:00:00\'
OR publish_down >= \'' . $now . '\' )
AND access <= \'' . $my->gid .'\'
ORDER BY hits DESC
LIMIT 5
';
In the next part of this series, we will look at adding parameters to the module.
You can download the files for the final part of the tutorial here (mod_helloworld_2.zip)
-->đọc tiếp...

Module Hello World 1

Introduction
This tutorial aims to give you a grounding in the basic concepts for writing Joomla! modules. It will develop a very simple Hello World module and then extend it using patTemplate, a powerful set of functions that help separate the presentation (HTML) from the application logic (PHP) using templates. Full documentation for patTemplate can be found on their website.
Requirements
You need for this tutorial:
• Joomla! 1.0 or greater
Let's Roll
We will be creating two files in this tutorial in the folder called /modules/. Let's look at the files we need.
mod_helloworld.php
This file is the actually engine for the module.
mod_helloword.xml
This file is the XML setup file for the module. It defines the information required for the module to be installed.
Installing the Basic Module
You cannot create a module from scratch from the Joomla! Administrator, so we have to make some basic files first and then install them as a module.

Let's make the actual module first. Save the following code as mod_helloworld.php.
<?php
/**
* @version 1.0 $
* @package HelloWorld
* @copyright (C) 2005 Andrew Eddie
* @license http://www.gnu.org/copyleft/gpl.html GNU/GPL
*/

/** ensure this file is being included by a parent file */
defined( '_VALID_MOS' ) or die( 'Direct Access to this location is not allowed.' );

?>
<h1>Hello World</h1>
Next save the following code in a file named mod_helloworld.xml.
<?xml version="1.0" encoding="iso-8859-1"?>
<mosinstall type="module" version="4.5.2">
<name>Hello World</name>
<author>Andrew Eddie</author>
<creationDate>February 2005</creationDate>
<copyright>(C) 2005 Andrew Eddie</copyright>
<license>http://www.gnu.org/copyleft/gpl.html GNU/GPL</license>
<version>1.0</version>
<description>A module that says hello</description>
<files>
<filename module="mod_helloworld">mod_helloworld.php</filename>
</files>
<params />
</mosinstall>
The first line of the file is a definition statement. You do not have to worry to much about what it means, but it must be in the file and it must be the first line (there cannot be any spaces before it). The other tags mean:
mosinstall
This is the parent tag that defines the rest of the installer file for Joomla!. It has an attribute for type which in this case is module. It also takes a value for the version of Joomla! it can run on.
name
This is the name of your module.
author
This is the name of the author for the module.
creationDate
This is the date the module was created.
copyright
This is the copyright holder of the module's code.
license
This is the name of, or a reference to, the license under which the module is released.
version
This is the version of the module.
description
This is a free text description of the module.
files
This is a collection of the files included with the module.
filename
This is a file that is used by the module. Any number of files can be listed, including files in a subdirectory. The file that Joomla! calls to invoke the module must contain the module attribute that takes a value of the name of the file without the .php extension.
Now, zip these two files up into a file called mod_helloworld.zip or you can download a copy here (mod_helloworld.zip).

Follow these instructions to install the basic module:
1. Log into the Joomla! Administrator.
2. Select Installers -> Modules from the menu.
3. In the Upload Package File area, click the Browse button and select the zip file you just created or downloaded. Then click the Upload File and Install button.
If all goes well, you should now see a message indicating a successful install. Click on the Continue link.

While you are still logged into the Joomla! Administrator, select Modules -> Site Modules from the Menu. Scroll down until you see the listing for Hello World. You will see that the module is unpublished and assigned to the left position in the template. Click on the red X in the published column to publish the module.

Preview your site. You should see your module saying hi to you.

Congratulations, you have built and deployed your first module. Now that it is installed we can modify the files directly to add more features.
Improving the Presentation
You will find that you new module has been installed in the /modules directory of your site. First we will separate the presentation layer from the module file.

Create a new directory under /modules called /mod_helloworld. In this new directory create a file called default.html. Copy the following code in this file:
<mos:comment>
@version 4.5.2
@package HelloWorld
@copyright (C) 2005 Andrew Eddie
@license http://www.gnu.org/copyleft/gpl.html GNU/GPL
</mos:comment>
<mos:tmpl name="helloworld">
<h1>Hello World</h1>
The time is {TIME}
</mos:tmpl>

We have added a little extra code here to demonstrate how to add a variable to your module template. You will also notice that the HTML is wrapped in a mos:tmpl tag. This defines a template and we have given the template the name of helloworld.

Now, find mod_helloworld.php in the /modules directory and open it in your editor.
Tip: There are many quality editors that are available for free, PSPad and HTML-Kit to name a few. For something a little more powerful, you might like to try out Eclipse.

Delete the existing code and replace it with the following:
<?php
/**
* @version 1.0
* @package HelloWorld
* @copyright (C) 2005 Andrew Eddie
* @license http://www.gnu.org/copyleft/gpl.html GNU/GPL
*/

/** ensure this file is being included by a parent file */
defined( '_VALID_MOS' ) or die( 'Direct Access to this location is not allowed.' );

// load the patTemplate library
require_once( $mosConfig_absolute_path . '/includes/patTemplate/patTemplate.php' );

// create the template
$tmpl =& patFactory::createTemplate( '', false, false );

// set the path to look for html files
$tmpl->setRoot( dirname( __FILE__ ) . '/mod_helloworld' );

$tmpl->readTemplatesFromInput( 'default.html' );

$tmpl->addVar( 'helloworld', 'time', date( 'H:i:s' ) );

$tmpl->displayParsedTemplate( 'helloworld' );
?>
Let's examine what is happening in this file.
• The comment block at the top of the file defines meta data about the file, in particular the license and the copyright. This block has some special notations that are able to be parsed by an application called phpDocumentor. It is used to assemble API (Application Programming Interface) documentation. The important thing here is to have a version and explicitly state the copyright and license terms for the file.
• Next we look for a constant called _VALID_MOS. Because this constant is defined elsewhere in Joomla!, it ensures that only Joomla! is able to access this file. It prevents a user from opening the file explicitly in a browser.
• We then include the patTemplate library.
• The patTemplate object is created and then we set the root directory for template (HTML) files to the /mod_helloworld directory in your module.
• Because we have set the root directory, we can just read in the default.html file with the readTemplatesFromInput method.
• Next we want to give the {TIME} variable in our template a value. To do this we use the addVar method of the template object. The method takes three arguments. The first is the name of the template, the second is the name of the template variable and the last is the actual value to assign to it.
• Last of all we display the helloworld template.

Save all your files and refresh your browser. You should see that the module now displays the time.

You can download the files for the final part of the tutorial here (mod_helloworld_1.zip). Note that the XML file has been updated to include the new HTML file.
-->đọc tiếp...

Writing a Simple Module in joomla

As an example, we will create a module that will list any content items that have keywords that match those in the one that is being viewed.
Where do we start?
First decide on a module name. We are going to call this a Related Items module. The module name will be mod_relcontent. All module names must be prefixed with "mod_" and the "relcontent" just stands for "related content" in our case.
In a scratch area on your file system, create a directory called mod_relcontent. In this directory, just create two empty files for the moment; one called mod_relcontent.php and the other called mod_relcontent.xml. Let's build the XML file first. This is a definition file that tells the Joomla installer, most importantly, what files are required and other metadata about the module. [Please ignore this dummy sentence which is intended to deflect the glossary bot from incorrectly autocapitalising the word "{glossarbot=disable}author" in the XML sample below] Copy and paste the following code into the XML file:
<?xml version="1.0" ?>
<mosinstall type="module">
<name>Related Items</name>
<creationDate>19/Aug/2003</creationDate>
<author>Andrew Eddie</author>
<copyright>This template is released under the GNU/GPL License</copyright>
<authorEmail>eddieajau(at)users.sourceforge.net</authorEmail>
<authorUrl></authorUrl>
<version>1.0</version>
<description>Shows related content items based on
keywords in the meta key field</description>
<files>
<filename module="mod_relcontent">mod_relcontent.php</filename>
</files>
</mosinstall>
The important tags here are:
name
The name used in menus.
files
There is only one file required for a module.

Save the XML file and move to the php file. Modules used to store their output in a $content variable. This is still supported, but you can now either use echo statements or escape in and out of php to provide the output. The complete code is shown at the end of this article. Let's step through it.
The first line after the comment block is extremely important. This prevents direct and potentially malicious execution of the script.
Next, a couple of URL variables are collected. When you are writing your modules, never assume that variables you need from the URL are already available. This is not good programming practice and they simply may not be within the scope of the code. For example, this module code is actually called from within a function, so many global variables simply are not visible. However, several code variables are made available, like $database.
The script then checks to see if you are viewing a content item. If you are, it selects the value of the `metakey` field from the item.
The Database Connector
First you need to "initialise" the query. The main reason for this is that the query string you supply is parsed for a hash-underscore-underscore. This is replaced by the database prefix stored in the system configuration variables.
$database->setQuery( "SELECT metakey FROM #__content WHERE id='$id'" );
OK, we've set up our query. This query returns only a single value. This is a really common exercise so we've provided a method called loadResult() just to grab that single value. Having got the value and checked that it contains something, we explode the string on commas. We then use arrays to help build a new database query that, in rough pseudo-code says "get all the id's of the content items where their metakey field is like *this* or *that*".
Now you'll see we have another common operation, that is, getting a list of results from a query. Here we use the database class method called loadObjectList() to return an array of rows where each row is stored as an object. The method returns null if the query fails to facilitate error checking.
Having received your list of matched records, it's now a trivial exercise to loop through the array and print out a list of links.
Finishing Up
Well, now we've got some code, how do we get it into Joomla. The module installer now requires a zip file of the php and XML file under it's parent directory (that is, in this case, mod_relcontent). Zip the two files up. Then, in the Joomla Administrator, select Modules > Install from the menubar. At the bottom of the list you'll see an upload area. Browse to the zip file and upload it. Viola, all going well, your new module is now installed and ready to use.
Go to Modules > Manage Modules to publish and select the 'side' and pages you want the module to appear on.
Now, in a couple of content items, put in a couple of different matching keywords in the Metadata tabs. From the front-end, view the items. You should get a list of other records that have matching keywords.
<?php
//Related Content//
/**
* Related Content Module
* @package Joomla
* @copyright Copyright (C) 2005 Open Source Matters. All rights reserved.
* @license http://www.gnu.org/copyleft/gpl.html GNU/GPL, see LICENSE.php
* Joomla! is free software and parts of it may contain or be derived from the
* GNU General Public License or other free or open source software licenses.
* See COPYRIGHT.php for copyright notices and details.
*/

defined( '_VALID_MOS' ) or die( 'Direct Access to this location is not allowed.' );

$option = trim( mosGetParam( $_REQUEST, 'option', null ) );
$task = trim( mosGetParam( $_REQUEST, 'task', null ) );
$id = intval( mosGetParam( $_REQUEST, 'id', null ) );

if ($option == 'content' && $task == 'view' && $id) {

// select the meta keywords from the item
$query = "SELECT metakey FROM #__content WHERE id='$id'";
$database->setQuery( $query );

if ($metakey = trim( $database->loadResult() )) {
// explode the meta keys on a comma
$keys = explode( ',', $metakey );
$likes = array();

// assemble any non-blank word(s)
foreach ($keys as $key) {
$key = trim( $key );
if ($key) {
$likes[] = $key;
}
}

if (count( $likes )) {
// select other items based on the metakey field 'like' the keys found
$query = "SELECT id, title"
. "nFROM #__content"
. "nWHERE id<>$id AND state=1 AND access <=$my->gid AND (metakey LIKE '%";
$query .= implode( "%' OR metakey LIKE '%", $likes );
$query .= "%')";

$database->setQuery( $query );
if ($related = $database->loadObjectList()) {
foreach ($related as $item) {
echo "<a href="index.php?option=content&task=view&id=$item->id">"
."$item->title</a><br />";
}
}
echo $database->getErrorMsg();
}
}
}
?>
-->đọc tiếp...

20 tháng 12, 2007

bảng quảng cáo hay một bảng thông tin tự động trượt đến một vị trí được chỉ định

Thỉnh thoảng có lúc bạn muốn có một bảng quảng cáo hay một bảng thông tin tự động trượt đến một vị trí được chỉ định khi visitor scroll trang web lên-xuống. Đây là cách rất tốt để ưu ái quảng cáo của những đối tượng sẵn sàng chí trả nhiều tiền. Cách làm như sau:

Mở file index.php của template bạn đang sử dụng bằng bất kỳ trình soạn thảo văn bản nào và...

1. Ngay trước thẻ </head> thêm đoạn code sau:
Code:
<!-- Floating Object container \-->
<script type="text/javascript">
var isDOM, floaterObj;
var isNS, pageHeight;
var paddingX, paddingY, scrollTop, currentY, targetY, A, B, C, D;
var slideTime;

/*
h - height in pixel of the floating object
x - padding in pixel from the left side of floating object to the left side of browser window
y - padding in pixel from the top side of floating object to the top side of browser window
z - slide time in milisecond
*/
function setUp(h, x, y, z) {
if (document.getElementById) {
isDOM = true;
floaterObj = document.getElementById("floater").style;
} else {
isDOM = false;
floaterObj = document.floater;
}
if (navigator.appName == 'Netscape') {
isNS = true;
} else {
isNS = false;
}

paddingX = x;
paddingY = y;
slideTime = z;

floaterObj.left = paddingX + (isDOM ? 'px' : '');
floaterObj.top = '-' + h + (isDOM ? 'px' : '');

window.onresize = refreshValues;
window.setInterval("placeFloater()", 10);

refreshValues();
}

function refreshValues() {
if (isNS) {
pageHeight = window.innerHeight - 20;
} else {
pageHeight = document.body.clientHeight;
}

placeFloater();
}

function placeFloater() {
if (isNS) {
scrollTop = window.pageYOffset;
} else {
scrollTop = document.body.scrollTop;
}

currentY = parseInt(floaterObj.top);

mainTrigger();

}

function mainTrigger() {
var newTargetY = scrollTop + paddingY;
if ( currentY != newTargetY ) {
if ( newTargetY != targetY ) {
targetY = newTargetY;
floatStart();
}
animator();
}
}

function floatStart() {
var now = new Date();
A = targetY - currentY;
B = Math.PI / ( 2 * slideTime );
C = now.getTime();
if (Math.abs(A) > pageHeight) {
D = A > 0 ? targetY - pageHeight : targetY + pageHeight;
A = A > 0 ? pageHeight : -pageHeight;
} else {
D = currentY;
}
}

function animator() {
var now = new Date();
var newY = A * Math.sin( B * ( now.getTime() - C ) ) + D;
newY = Math.round(newY);
if (( A > 0 && newY > currentY ) || ( A < 0 && newY < currentY )) {
floaterObj.top = newY + (isDOM ? 'px' : '');
}
}
</script>
<!-- Floating Object container /-->
2. Sửa thẻ <body> thành
Code:
<body onload="setUp(60, 15, 15, 1500)">
Function setUp có những thông số lần lượt là

* Chiều cao (đơn vị pixel) của module tự trượt.
* Khoảng cách (đơn vị pixel) từ lề trái của module tự trượt đến lề trái của cửa sổ trình duyệt
* Khoảng cách (đơn vị pixel) từ lề trên của module tự trượt đến lề trên của cửa sổ trình duyệt
* Khoảng thời gian (đơn vị milisecond) để module trượt từ vị trí cũ đến vị trí mới khi visitor scroll lên-xuống trang web.


3. Ngay trước thẻ </body> thêm đoạn code sau:
Code:
<!-- Floating Object container \-->
<div id="floater" name="floater" style="position: absolute; z-index: 1000">
<!-- Banner Module code \-->
<?php if (mosCountModules('banner')) mosLoadModules('banner'); ?>
<!-- Banner Module code /-->
</div>
<!-- Floating Object container /-->
...lưu lại các thay đổi trong file index.php của template rồi đăng nhập vào trang quản trị của Joomla để cấu module hiển thị bảng quảng cáo hoặc bảng thông tin để hiện ở vị trí (position) banner.

Chúc may.
-->đọc tiếp...

modify mod_latestnew & mod_mostread to show the image

<?php
// no direct access
defined( '_VALID_MOS' ) or die( 'Restricted access' );

global $mosConfig_offset, $mosConfig_live_site, $mainframe;

$type = intval( $params->get( 'type', 1 ) );
$count = intval( $params->get( 'count', 5 ) );
$catid = trim( $params->get( 'catid' ) );
$secid = trim( $params->get( 'secid' ) );
$show_front = $params->get( 'show_front', 1 );
$now = date( 'Y-m-d H:i:s', time() );
$access = !$mainframe->getCfg( 'shownoauth' );

$nullDate = $database->getNullDate();
// select between Content Items, Static Content or both
switch ( $type ) {
case 2:
//Static Content only
$query = "SELECT distinct a.id, a.title, a.images"
. "\n FROM #__content AS a"
. "\n WHERE ( a.state = 1 AND a.sectionid = 0 )"
. "\n AND ( a.publish_up = '$nullDate' OR a.publish_up <= '$now' )"
. "\n AND ( a.publish_down = '$nullDate' OR a.publish_down >= '$now' )"
. ( $access ? "\n AND a.access <= $my->gid" : '' )
. "\n ORDER BY a.created DESC"
. "\n LIMIT $count"
;
$database->setQuery( $query );
$rows = $database->loadObjectList();
break;

case 3:
//Both
$query = "SELECT distinct a.id, a.title, a.sectionid, a.catid, a.images, cc.access AS cat_access, s.access AS sec_access, cc.published AS cat_state, s.published AS sec_state"
. "\n FROM #__content AS a"
. "\n LEFT JOIN #__content_frontpage AS f ON f.content_id = a.id"
. "\n LEFT JOIN #__categories AS cc ON cc.id = a.catid"
. "\n LEFT JOIN #__sections AS s ON s.id = a.sectionid"
. "\n WHERE a.state = 1"
. "\n AND ( a.publish_up = '$nullDate' OR a.publish_up <= '$now' )"
. "\n AND ( a.publish_down = '$nullDate' OR a.publish_down >= '$now' )"
. "\n AND a.sectionid != 11 AND a.sectionid != 12 AND a.sectionid !=26"
. ( $access ? "\n AND a.access <= $my->gid" : '' )
. ( $catid ? "\n AND ( a.catid IN ( $catid ) )" : '' )
. ( $secid ? "\n AND ( a.sectionid IN ( $secid ) )" : '' )
. ( $show_front == '0' ? "\n AND f.content_id IS NULL" : '' )
. "\n ORDER BY a.created DESC"
. "\n LIMIT $count"
;
$database->setQuery( $query );
$temp = $database->loadObjectList();

$rows = array();
if (count($temp)) {
foreach ($temp as $row ) {
if (($row->cat_state == 1 || $row->cat_state == '') && ($row->sec_state == 1 || $row->sec_state == '') && ($row->cat_access <= $my->gid || $row->cat_access == '' || !$access) && ($row->sec_access <= $my->gid || $row->sec_access == '' || !$access)) {
$rows[] = $row;
}
}
}
unset($temp);
break;

case 1:
default:
//Content Items only
$query = "SELECT distinct a.id, a.title, a.sectionid, a.catid, a.images"
. "\n FROM #__content AS a"
. "\n LEFT JOIN #__content_frontpage AS f ON f.content_id = a.id"
. "\n INNER JOIN #__categories AS cc ON cc.id = a.catid"
. "\n INNER JOIN #__sections AS s ON s.id = a.sectionid"
. "\n WHERE ( a.state = 1 AND a.sectionid > 0 )"
. "\n AND ( a.publish_up = '$nullDate' OR a.publish_up <= '$now' )"
. "\n AND ( a.publish_down = '$nullDate' OR a.publish_down >= '$now' )"
. ( $access ? "\n AND a.access <= $my->gid AND cc.access <= $my->gid AND s.access <= $my->gid" : '' )
. ( $catid ? "\n AND ( a.catid IN ( $catid ) )" : '' )
. ( $secid ? "\n AND ( a.sectionid IN ( $secid ) )" : '' )
. ( $show_front == '0' ? "\n AND f.content_id IS NULL" : '' )
. "\n AND s.published = 1"
. "\n AND cc.published = 1"
. "\n ORDER BY a.created DESC"
. "\n LIMIT $count"
;
$database->setQuery( $query );
$rows = $database->loadObjectList();
break;
}

// needed to reduce queries used by getItemid for Content Items
if ( ( $type == 1 ) || ( $type == 3 ) ) {
$bs = $mainframe->getBlogSectionCount();
$bc = $mainframe->getBlogCategoryCount();
$gbs = $mainframe->getGlobalBlogSectionCount();
}

// Output
?>
<table width="100%" cellpadding="0" cellspacing="0" border="0">
...

$link = sefRelToAbs( 'index.php?option=com_content&task=view&id='. $row->id . $Itemid );
// ở đây cần xử lý Thumbnails cho image nhé.
if ($row->images!='') {
$images=explode('|',$row->images); //lấy ảnh đầu tiên của bài viết
} else $images[0]='default/default2.jpg';//nếu ko có ảnh thì thay bằng ảnh mặc định
?>
<tr>
<td>
<a href="<?php echo $link; ?>">
<img src="<?php echo $mosConfig_live_site.'/images/stories/'.$images[0];?>" border="0" width="50" height="50">
</a>
</td>
<td style="padding-left:5px; padding-bottom:5px; text-align:justify;">
<a href="<?php echo $link; ?>" class="latestnews<?php echo $moduleclass_sfx; ?>">
<?php echo $row->title; ?>
</a>
</td>
</tr>
<?php
}
?>
</table>
Xử lý tương tự cho module kia
-->đọc tiếp...

Cross-window scripting

var newwindow = '';

function popitup(url) {
if (!newwindow.closed && newwindow.location) {
newwindow.location.href = url;
}
else {
newwindow=window.open(url,'name','height=200,width=150');
if (!newwindow.opener) newwindow.opener = self;
}
if (window.focus) {newwindow.focus()}
return false;
}
-->đọc tiếp...

thay đổi code trong module latest_news.

$secid = trim( $params->get( 'secid' ) );
thêm đoạn code này vào để lấy $secid
global $option, $task;
if ($option == 'com_content') {
switch($task) {
case 'view':
$query = "SELECT a.sectionid"
. "\n FROM #__content AS a"
. "\n WHERE ( a.id = ".$_GET['id']." )";
$database->setQuery( $query, 0, $count );
$rows = $database->loadObjectList();

$sectionrow = $rows[0];
$secid = $sectionrow->sectionid;
break;
case 'section';
$secid = $_REQUEST['id'];
}
}
Như thế là ta đã có section id khi đó mọi việc trở nên đơn giản. Chỉ cần chỉnh câu lệnh SQL để lấy a.sectionid = $secid là xong.
-->đọc tiếp...

19 tháng 12, 2007

A Better Ajax Back Button Solution

If you've spent any time coding an Ajax application you know that the one of the problems with Ajax is that it breaks the back button. You have probably seen solutions that use an iframe and a hash (#) in the url to fix this issue. While this works there is a much simpler way that I've been using in my applications for the last year or so.

The key is the A tag (also known as the anchor tag) and the name parameter with a hash in the url. The trick is to either dynamically create the element or to just change the value of the name parameter to the matching value of the hash.

Below is an example of changing the name of the anchor tag.

//Anchor Rename Object this could also be a simple function if preferred.
var AnchorRename=new Object();
AnchorRename.CreateObject=function(anchorname, anchorid){
this.anchorid=anchorid; //This is the id of the anchor element
this.anchorname=anchorname;
this.RenameAnchor(anchorname, anchorholerid);
};
AnchorRename.CreateObject.prototype={
RenameAnchor:function(anchorname, anchorid){
document.getElementById(anchorid).name = anchorname;
}
};

In this example you would pass in the new value of the name (which must be the same value as after the hash in the url) and the id of the anchor element.

Below is an example of dynamically creating the tag and name values.

//Anchor Rename Object
var AnchorRename=new Object();
AnchorRename.CreateObject=function(anchorname, anchorholderid){
this.anchorholerid=anchorholderid; //This is the id of the element to hold the new anchor
this.anchorname=anchorname;
this.RenameAnchor(anchorname, anchorholderid);
};
AnchorRename.CreateObject.prototype={
RenameAnchor:function(anchorname, anchorholderid){
var AnchorCode=document.createElement("a");
AnchorCode.setAttribute("name", anchorname);
document.getElementById(anchorholderid).appendChild(AnchorCode);
}
};
In this example you would pass in the new value of the name (which again must be the same value as after the hash in the url) and the id of the anchor element.

Now the question that you may be asking is how does creating or renaming the anchor element help with fixing the back button. That is where when you call the object comes into play. You need to create or rename the object before a link is clicked. So, I would recommend using an onmouseover and an onfocus event to call the create or rename of the element so that before a link is clicked the required anchor element will be created.

I hope that this post has shown an easier solution to fix the back button problem that occurs when we create Ajax applications. Now go out there and try using it on your applications!
-->đọc tiếp...

simple sample code that shows how you can persist state into a hidden form

<html>
<head>
<script language="JavaScript">
function initialize() {
var sessionField = document.getElementById("sessionField");
var sessionValue = sessionField.value;
if (sessionValue == "empty") {
alert("Storing new session value");
sessionField.value = "Hello World";
}
else {
alert("Old session value: " + sessionValue);
}
}
</script>
</head>

<body onload="initialize()">
<form id="sessionForm">
<textarea id="sessionField">empty</textarea>
</form>
</body>
</html>
-->đọc tiếp...

AJAX Tutorial: Saving Session Across Page Loads Without Cookies, On The Client Side

<html>
<head>
<script language="JavaScript">
function initialize() {
if (sessionExists() == false) {
saveState("Hello World 1");
// some browsers need a bit of a timeout
window.setTimeout("saveState('Hello World 2')", 300);
window.setTimeout("saveState('Hello World 3')", 600);
}
}

function getIFrameDocument() {
var historyFrame =
document.getElementById("historyFrame");
var doc = historyFrame.contentDocument;
if (doc == undefined) // Internet Explorer
doc = historyFrame.contentWindow.document;

return doc;
}

function sessionExists() {
var doc = getIFrameDocument();
try {
if (doc.body.innerHTML == "")
return false;
else
return true;
}
catch (exp) {
// sometimes an exception is thrown if a
// value is already in the iframe
return true;
}
}

function saveState(message) {
// get our template that we will
// write into the history iframe
var templateDiv =
document.getElementById("iframeTemplate");
var currentElement = templateDiv.firstChild;

// loop until we get a COMMENT_NODE
while (currentElement &&
currentElement.nodeType != 8) {
currentElement = currentElement.nextSibling;
}
var template = currentElement.nodeValue;

// replace the templated value in the
// constants with our new value
var newContent =
template.replace(/\%message\%/, message);

// now write out the new contents
var doc = getIFrameDocument();
doc.open();
doc.write(newContent);
doc.close();
}
</script>
</head>

<body onload="initialize()">
<div id="iframeTemplate">
<!--
<html>
<body>
<p>%message%</p>
</body>
</html>
-->
</div>

<iframe id="historyFrame"></iframe>
</body>

<html>
-->đọc tiếp...

18 tháng 12, 2007

Dưới đây là bảng danh sách phím tắt chủ yếu dùng cho cả hai trình duyệt IE và Firefox

Dưới đây là bảng danh sách phím tắt chủ yếu dùng cho cả hai trình duyệt IE và Firefox
(Trên Macintosh, Command thay thế cho Ctrl và tuỳ chọn cho Alt)

Các phím tắt thông thường sử dụng cho cả Firefox và Internet Explorer
Phím tổ hợp Cách dùng

Ctrl+A

Chọn tất cả nội dung

Ctrl+C

Copy nội dung chọn

Ctrl+D

Thêm một bookmark

Ctrl+H

Thể hiện thanh nách History

Ctrl+I hay Ctrl+B

Mở thanh nách Bookmarks

Ctrl+N

Mở cửa sổ mới

Ctrl+O

Mở file

Ctrl+P

In trang hiện tại

Ctrl+R hay F5

Load lại trang hiện tại

Ctrl+Shift+R hay Ctrl+F5

Load lại trang hiện tại từ trang gốc

Ctrl+V

Dán nội dung copy hiện tại

Ctrl+W hay Ctrl+F4

Đóng tab hiện tại

Ctrl+X

Cắt nội dung chọn hiện tại

Ctrl+Y hay Ctrl+Shift+Z

Thực hiện lại hoạt động cuối

Ctrl+Z

Khôi phục lại hoạt động cuối

Alt

Bắt đầu cho sự lựa chọn menu

Alt+D hay F6

Tập trung và làm nổi bật thanh lựa chọn

Alt+F4 hay Ctrl+Shift+W

Đóng cửa sổ hiện tại

Alt+Home

Trở lại trang chủ

Alt+mũi tên sang trái hay Backspace

Trở lại trang trước

Alt+mũi tên sang phải hay Shift+Backspace

Tới trang sau

Delete

Xoá lựa chọn hiện thời

End

Chuyển xuống cuối trang

Esc

Ngừng hoạt động hiện tại

F11

Xem nội dung ở màn hình lớn

Home

Chuyển tới đầu trang

Firefox cũng có một số tổ hợp phím riêng. Bảng tiếp theo thể hiện các tổ hợp phím thông thường đó (không có trong Internet Explorer)

Các tổ hợp phím chỉ có trong Firefox

Tổ hợp phím

Cách dùng

Ctrl + - (dấu trừ) Giảm kích thước văn bản
Ctrl + + (dấu cộng) Tăng kích thước văn bản
Ctrl+0 (Ctrl+số không) Phục hồi văn bản theo kích thước thông thường
Ctrl + phím xuống Chọn công cụ tiếp theo trong thanh cục bộ
Ctrl+F hay / Tìm nội dung theo xâu ký tự
Ctrl+G hay F3 Lặp lại hoạt động tìm kiếm
Ctrl+J (Ctrl+Y trên Linux) Mở cửa sổ quản lý download
Ctrl+K Tìm kiếm web sử dụng công cụ tìm kiếm hiện tại và từ khoá
Ctrl+n (n là một số) Tới tab thứ n
Ctrl+S Ghi lại trang hiện tại như một file
Ctrl+T Mở tab mới
Ctrl+Tab hoặc Ctrl+Page Down Chuyển tới tab tiếp theo
Ctrl+Shift+Tab hoặc Ctrl+Page Up Chuyển lại tab trước đó
Ctrl+U Xem nguồn của trang
' Tìm liên kết bằng thuật ngữ tìm kiếm
Alt+Enter Mở đường dẫn URL trong tab mới
F6 Chuyển sang khung tiếp theo
F7 Đường dẫn Toggle caret
Shift+F3 Lặp lại hoạt động tìm kiếm cuối cùng

-->đọc tiếp...

Disable right click script and no alert

// JavaScript Document
<script type="text/javascript" language="JavaScript1.2">
/**Start hiding from IE Mac */
<!-- // Begin
//Disable right click script and no alert
var message="";
///////////////////////////////////
function clickIE() {if (document.all) {(message);return false;}}
function clickNS(e) {
if (document.layers||(document.getElementById&&!document.all)) {
if (e.which==2||e.which==3) {(message);return false;}
}
}
if (document.layers){document.captureEvents(Event.MOUSEDOWN);document.onmousedown=clickNS;}
else{document.onmouseup=clickNS;document.oncontextmenu=clickIE;}
document.oncontextmenu=new Function("return false")
// End -->
/**Stop hiding from IE Mac */
</script>
insert this script in &lthead>
-->đọc tiếp...

xajax dhtmlHistory-Extension (Bookmark and Backbutton)

Based on Brad Neuberg's "Really Simple History". See: <a href="http://code.google.com/p/reallysimplehistory/" target="new">his page</a> for details

This plugin makes it possible to handle the browsers backbutton functionality and provides a simple bookmarking management.
It works with IE and FF and with the new RSH Version also with Opera and even Safari. <h2>xajax 0.5 Beta4 - Really Simple History 0.6</h2><b>Last changed: 2007-12-03</b>
The package contains the following files:

<table border="1"> <tbody><tr><th>file</th><th>folder</th><th>comment</th></tr> <tr><td colspan="3"><b>plugin files</b></td></tr> <tr><td>dhtmlHistory.inc.php</td><td>./xajax/xajax_plugins/response</td><td>the xajax plugin</td></tr> <tr><td>rsh.compressed.js</td><td>./xajax/xajax_plugins/response</td><td>the original rsh javascript</td></tr> <tr><td>json2007.js</td><td>./xajax/xajax_plugins/response</td><td>default JSON parser supplied with the original rsh javascript</td></tr> <tr><td>blank.html</td><td>./</td><td>a helper file for the IE iframe solution. must be located in the same folder as index.php</td></tr> <tr><td colspan="3"><b>sample files</b></td></tr> <tr><td>index.php</td><td>./</td><td>an example implementation as a simple showcase</td></tr> <tr><td>waypoint.inc.php</td><td>./</td><td>an helper file for the example implementation. implements the waypoint handler</td></tr> </tbody></table>

<h3>Quickstart</h3> 1. Copy the plugin files to your server into the above named folders

2. In your version of "index.php": <ul><li>Call dhtmlHistoryAdd($objResponse, $sWaypointName, $aWaypointData) in your xajax response functions to add waypoints for the backbutton handling</li></ul> 3. In your version of waypoint.inc.php: <ul><li>Implement a xajax response function which will be called when the backbutton is clicked. $sWaypointName and $aWaypointData will be given to you to restore the old waypoint.</li></ul> <h3>Tutorial</h3> <h4>One general ajax "disadvantage"</h4> You may have some kind of menu which calls xajax functions to modify the page content:

<pre><ul id="top_menu">
<li><a href="http://www.blogger.com/post-edit.g?blogID=4291973661386596812&postID=5701704131189757312#" onclick="xajax_top_menu(1); return false;">menu1</a></li>
<li><a href="http://www.blogger.com/post-edit.g?blogID=4291973661386596812&postID=5701704131189757312#" onclick="xajax_top_menu(2); return false;">menu2</a></li>
<li><a href="http://www.blogger.com/post-edit.g?blogID=4291973661386596812&postID=5701704131189757312#" onclick="xajax_top_menu(3); return false;">menu3</a></li>
<li><a href="http://www.blogger.com/post-edit.g?blogID=4291973661386596812&postID=5701704131189757312#" onclick="xajax_top_menu(4); return false;">menu4</a></li>
<li><a href="http://www.blogger.com/post-edit.g?blogID=4291973661386596812&postID=5701704131189757312#" onclick="xajax_top_menu(5); return false;">menu5</a></li>
<li><a href="http://www.blogger.com/post-edit.g?blogID=4291973661386596812&postID=5701704131189757312#" onclick="xajax_top_menu(6); return false;">menu6</a></li>
</ul></pre> <pre>function top_menu($nMenu)
{
$objResponse = new xajaxResponse();
$objResponse->assign('content', 'innerHTML', 'NEW CONTENT');
return $objResponse;
}</pre> <p>Using that kind of navigation you will get no browser history entries and therefore the browsers backbutton can not be used. Here's where the plugin comes in.</p> <h4>Adding a waypoint</h4> <p> By adding a single function call into your response function you can set a browser history entry also called "waypoint". </p> <pre>dhtmlHistoryAdd($objResponse, $sWaypointName, $aWaypointData); </pre> <p> sWaypointName: name of the waypoint which is used like an anchor (string)
aWaypointData: data which is needed to recover this very waypoint (mixed)

Please note that the waypoint data will be lost if the user leaves the actual page since it is stored using a hidden form element. </p> <p> This will lead to: </p> <pre>function top_menu($nMenu)
{
$sWaypointName = 'menu'.$nMenu;
$aWaypointData = array('my data to recover','this waypoint');

$objResponse = new xajaxResponse();

dhtmlHistoryAdd($objResponse, $sWaypointName, $aWaypointData);

$objResponse->assign('content', 'innerHTML', 'NEW CONTENT');
return $objResponse;
}</pre> <h4>Including the plugin</h4> <p> The function dhtmlHistoryAdd() is provided with the plugin in the file <em class="mono">dhtmlHistory.inc.php</em>. It has to be copied into the xajax/xajax_plugins/response folder to be loaded when creating an instance of the xajax class. </p> <p> The heart of the plugin is the javascript code <em class="mono">dhtmlHistory.js</em> which could be copied into the same folder. </p> <p> The plugin has to be included at the begining: </p> <pre>$xajax = new xajax();
require $xajaxPlugins . '/response/dhtmlHistory.inc.php';</pre> <h4>Implementing the waypoint handler</h4> <p> The last step is to provide a "waypoint handler". This is the function which will be called when the user clicks the browsers backbutton. The waypoint handler is a xajax response function which has to be registered... </p> <pre>$xajax->registerFunction('waypoint_handler','waypoint.inc.php'); </pre> <p> ... and certainly implemented. The function name must be "waypoint_handler" for the time being.
You need to code <b>your</b> logic to rebuild the situation which was saved when adding the waypoint by using the parameters you saved to that waypoint. </p> <pre>function waypoint_handler($sWaypointName, $sWaypointData)
{
$objResponse = new xajaxResponse();
if ($sWaypointName!='')
{
$aWaypointData = decodeWaypointData($sWaypointData);

//TODO: recover your content using the parameters

$objResponse->assign("content", "innerHTML", "YOUR RECOVERED CONTENT");
//or maybe
$objResponse->script("xajax_topmenu('".$aWaypointData[0]."')");
}
return $objResponse;
}</pre> <p> The function call decodeWaypointData() is neccessary because the waypoint data is stored in a serialized format and need to be deserialized to be used. I did not yet hide the decoding within the plugin. </p> <p> That's it.
Please see the inline comments for more details.
Feel free to comment or <a href="mailto:ralf@goldenzazu.de">contact me</a> on any issues or suggestions. </p>
-->đọc tiếp...

17 tháng 12, 2007

show the message & hide the message

Often, we want to notify the end user that an operation is in process; to let them know they may need to wait a bit for the operation to finish.
First, let's define the message, what to do to show the message and what to do to hide the message:

and later (in the HTML of the page):
Loading, please wait a moment...

----------
With xajax 0.2.4 (the current release), you can accomplish this with the following javascript code:

----------
With xajax 0.5 (the current beta release), you can accomplish this with the following javascript code:
on a global level:

on a per call basis:

Indeed, same question. Would it be loaded by onLoad?

We need a bit more information on this one.

I have a very simple .js called under my body tag, which uses a YUI Panel to display an Ajax loader icon (created with www.ajaxload.info), but I'd like to increase the delay time to about 500 milli or even one full second. Some of the database calls are slow and my users click several times sometimes, which make matters worse.

Here is the code below. Feel free to reuse.

YAHOO.namespace('example.container');

YAHOO.example.container.loader = new YAHOO.widget.Panel("loader", { width:"230px",height:"80px",fixedcenter:true,close:false,draggable:true,modal:true,visible:false} );
YAHOO.example.container.loader.setHeader('Processing, please wait...');
YAHOO.example.container.loader.setBody("
Loading...
");
YAHOO.example.container.loader.render(document.body);
showLoading = function() {YAHOO.example.container.loader.show();};
hideLoading = function() {YAHOO.example.container.loader.hide();}
xajax.callback.global.onResponseDelay = showLoading;
xajax.callback.global.onComplete = hideLoading;
-->đọc tiếp...

Using xajax 0.5 beta 2, you can now use the following (callback objects)

Using xajax 0.5 beta 2, you can now use the following (callback objects) to accomplish this:

loadingPage = xajax.callback.create(300, 10000);
loadingSomeSelectOptions = xajax.callback.create(300, 10000);
loadingOtherSelectOptions = xajax.callback.create(100, 10000);

Then, provide the operations to perform:

loadingPage.onResponseDelay = function() { ... show loading message ... }
loadingPage.onComplete = function() { ... hide loading message ... }

loadingSomeSelectOptions.onRequest = function() { ... show loading message over select box ... }
loadingSomeSelectOptions.onComplete = function() { ... hide loading message ... }

loadingOtherSelectOptions.onResponseDelay = function() { ... show loading msg over other select box ... }
loadingOtherSelectOptions.onComplete = function() { ... hide loading message ... }

Then:

xajax.call('loadPage', { callback: loadingPage });
xajax.call('loadSomeSelectOptions', { callback: loadingSomeSelectOptions });
etc...

As an alternative, you could even:

showLoading = function(oRequest) {
if ('loadPage' == oRequest.functionName) { ... show page loading message ... }
else if ('loadSomeSelectOptions' == oRequest.functionName) { ... show loading message over select ... }
}

hideLoading = function(oRequest) {
if ('loadPage' == oRequest.functionName) { ... hide page loading message ... }
else if ('loadSomeSelectOptions' == oRequest.functionName) { ... hide loading message ... }
}

handleLoadingMessage = xajax.callback.create(400, 10000);
handleLoadingMessage.onResponseDelay = showLoading;
handleLoadingMessage.onComplete = hideLoading;

xajax.call('loadPage', { callback: handleLoadingMessage });
// add description
myCallBackObject = xajax.callbacks.create( *1, *2 )
*1 = response delay time
*2 = expiration timeout
both are optional
Hope that helps.
-->đọc tiếp...
BlogWeb: tạo từ Blog của Google
Nội dung: lấy từ nhiều Nguồn khác nhau.
Mục đích: note lại bài Hướng dẫn hay và Đáng đọc.
Kết quả: nghiện Internet Nặng.
Tương lại: xuống lỗ Vẫn Nghiện nếu không có ai giúp.
Blog Web của: Trí Dũng đến từ Việt Nam - Liên kết đến trang Blog Cá Nhân
Tôi biết (^_^)
Thông tin về Tác giả. Chi Tiết
Sử dụng (FireFox | Google Chrome on Ubuntu) để xem tốt nhất. Học Nhiều Hơn Tại Đây
©2009 Google Blogger - HuuNguyen's Home