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...

14 tháng 12, 2007

disable the F5 and Refresh button using Javascript

if (document.all){
document.onkeydown = function (){
var key_f5 = 116; // 116 = F5

if (key_f11==event.keyCode){
alert("F5 pressed");
return false;
}
}
}
function document.onKeyPress()
{
if(event.keyCode=116)return false;
}
-->đọc tiếp...

Get URL Parameters Using Javascript

Get URL Parameters Using Javascript
function getURLParam(strParamName){
var strReturn = "";
var strHref = window.location.href;
if ( strHref.indexOf("?") > -1 ){
var strQueryString = strHref.substr(strHref.indexOf("?")).toLowerCase();
var aQueryString = strQueryString.split("&");
for ( var iParam = 0; iParam < aQueryString.length; iParam++ ){
if (
aQueryString[iParam].indexOf(strParamName.toLowerCase() + "=") > -1 ){
var aParam = aQueryString[iParam].split("=");
strReturn = aParam[1];
break;
}
}
}
return unescape(strReturn);
}
function getURLParam(name){
name = name.replace(/[\[]/,"\\\[").replace(/[\]]/,"\\\]");
var regexS = "[\\?&]"+name+"=([^&#]*)";
var regex = new RegExp( regexS );
var results = regex.exec( window.location.href );
if( results == null )
return "no";
else
return results[1];
}
-->đọc tiếp...

This is one that I use. It has no warning pop-up window. It simply prevents them from right clicking on a page.

This is one that I use. It has no warning pop-up window. It simply prevents them from right clicking on a page.
Code:
//Disable right click script
//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")
This doesn't stop anyone who knows enough, but it will frustrate the newbies!
-->đọc tiếp...

25 tháng 10, 2007

My Code:
code google 
 
-->đọc tiếp...

14 tháng 6, 2007

20 Lý Do Để Bạn Thiết Lập Website Cho Doanh Nghiệp Của Mình

Website giống như nhân viên truyền thông của công ty có thể giới thiệu công ty của bạn suốt 24h/ngày, 7 ngày/tuần tới đối tượng khách hàng mục tiêu.
Xây dựng một website có vai trò rất quan trọng trong thời đại bùng nổ internet như hiện nay, nó giống như nhân viên truyền thông của công ty có thể giới thiệu công ty của bạn suốt 24 tiếng trong ngày và 7 ngày trong tuần tới đối tượng khách hàng mục tiêu, vậy tại sao lại không lập một website ngay bây giờ nhỉ?

1. Thiết lập sự hiện diện

Có xấp xỉ 300 triệu người trên thế giới đã truy cập vào mạng Internet và số lượng này không ngừng được tăng lên hàng ngày. Việc tiếp cận được dù chỉ 1% nhóm khách hàng này cũng là 1 thành công của doanh nghiệp.

Đó là một phần không nhỏ của cộng đồng xã hội, hãy cho họ biết rằng bạn quan tâm tới việc phục vụ cả cộng đồng này, bạn cần phải có mặt trên mạng Internet. Bạn nên biết rằng, đối thủ cạnh tranh của bạn cũng đang làm như vậy.

2. Tận dụng hoàn toàn các cơ hội tiếp xúc

Nhiều khi công việc kinh doanh được hiểu một cách đơn giản là giao tiếp với khách hàng. Mọi doanh nhân khôn ngoan đều hiểu rằng: "Bí quyết thành công không nằm ở chỗ những gì bạn biết mà chính là ở chỗ bạn biết tới những khách hàng nào". Các doanh nhân đều muốn tận dụng các cuộc gặp gỡ thông thường thành công việc kinh doanh có lợi và việc trao danh thiếp là một việc được coi trọng trong quá trình này. Nhưng điều gì sẽ xảy ra khi doanh nghiệp cần phải gặp gỡ hàng ngàn, thậm chí hàng triệu đối tác làm ăn, liệu các doanh nghiệp có thể tiếp xúc cùng một lúc với tất cả các khách hàng. Điều này có thể được giải quyết hết sức đơn giản, tại mọi lúc, mọi nơi, mọi thời điểm thông qua các trang Web trên mạng Internet.

3. Tạo ra nguồn thông tin sẵn có cho đối tác

Khi bạn muốn tạo các trang thông tin, quảng cáo, có thể bạn sẽ đăng chúng trên mục quảng cáo, trang vàng, nhưng thời gian sẽ làm cho bạn phải tính lại. Vì, làm thế nào để khách hàng quan tâm có thể liên hệ được ngay với bạn? Phương thức thanh toán trong mỗi dịch vụ sẽ như thế nào? Quảng cáo trang vàng sẽ khó khăn trong việc này vì đây vẫn chỉ là một loại phương tiện truyền thông có khoảng cách. Trong thời đại hiện nay, các thông tin đòi hỏi phải nhanh chóng hơn và mang tính đa chiều hơn. Internet sẽ giúp bạn làm được điều đó thông qua những trang thông tin được duy trì liên tục 24/24 giờ trong ngày và 07 ngày trong tuần. Khách hàng có thể xem thông tin về doanh nghiệp của bạn bất kỳ lúc nào họ muốn, thậm chí ngay cả khi bạn đang ngủ.

4. Phục vụ khách hàng hiệu quả

Công nghệ Internet sẽ mang lại cho doanh nghiệp của bạn nhiều cách hơn để phục vụ khách hàng. Liệu bạn có đủ đội ngũ nhân viên trực điện thoại để tiếp nhận các yêu cầu của khách hàng về cung cấp thông tin dịch vụ mà họ cần? Liệu khách hàng có thể tự động tra cứu vào cơ sở dữ liệu, tìm kiếm các thông tin về dịch vụ bạn đang tiến hành mà họ muốn không? Tất cả điều này khách hàng có thể là được 1 cách đơn giản và nhanh chóng thông qua chính Website của doanh nghiệp bạn.

5. Thu hút sự quan tâm của dân chúng


Bạn khó mà thuyết phục được các tạp chí đăng bài về việc bạn khai trương một cửa hàng mới nhưng bạn lại có thể thuyết phục được họ đăng bài nêu tên Website của bạn vì trang Web đó mới và có nhiều điều thú vị. Với các thông tin như vậy, bất kỳ người sử dụng Internet nào cũng có thể truy cập vào Website để tìm hiểu về doanh nghiệp của bạn và có thể trở thành khách hàng tiềm năng.

6. Công bố thông tin vào bất kỳ thời gian nào

Nếu bạn cần phải công bố các tài liệu trước lúc nửa đêm thì sẽ như thế nào? Giả sử đó là tin khẩn cấp, công bố các giải thưởng của chương trình khuyến mại,... Nếu bạn gửi các tin này tới các tòa soạn báo thì bạn sẽ gặp phải trở ngại về thời gian: Thông tin của bạn chỉ được phát hành cùng với giờ phát hành của báo và không thể thay đổi sau khi báo đã được phát hành. Với Internet, bạn hoàn toàn có thể thay đổi tin tức mới cho Website của doanh nghiệp trong vòng vài giây đồng hồ, những thông tin mới nhất sẽ được cập nhật và sẽ được chuyển tới những người mong đợi mà không phải qua bất kỳ người đưa tin nào.

7. Để bán hàng hóa

Internet đem lại cho doanh nghiệp của bạn một cơ hội lớn để bạn có thể bán hàng hóa. Sự phát triển của Internet trên toàn thế giới kéo theo sự ra đời và mở rộng của một thị trường khách hàng mới đầy tiềm năng - cộng đồng người sử dụng Internet. Liệu bạn có nên chần chừ khi mà các đối thủ cạnh tranh trong kinh doanh của bạn đang dần từng bước thâm nhập và chiếm lĩnh thị phần trên Internet?

8. Giới thiệu sản phẩm sinh động

Nếu sản phẩm của bạn là những chiếc máy thì khách hàng sẽ thực sự bị thuyết phục khi nhìn thấy nó hoạt động ra sao. Internet mở ra cho bạn nhiều cách thức để giới thiệu sản phẩm thật sinh động tới khách hàng thông qua Website bằng hình ảnh, âm thanh, các đoạn phim ngắn, điều này sẽ khiến các khách hàng tiềm năng sẽ đến với bạn nhiều hơn, không một quyển sách giới thiệu nào có thể làm được như vậy.

9. Vươn tới một thị trường dân chúng có thu nhập cao

Số lượng người tham gia vào mạng Internet có thể tạo ra một thị trường sẵn có đông đảo nhất. Những người sử dụng Internet thường là những người có trình độ học vấn, có hiểu biết và địa vị ổn định, thu nhập cao trong xã hội. Chính vì vậy, tiếp cận được và chiếm lĩnh thị trường khách hàng này là điều mà bất kỳ doanh nghiệp kinh doanh nào cũng mong muốn đạt được.

10. Trả lời các câu hỏi thường gặp

Bất kỳ người trực điện thoại nào trong công ty bạn cũng đều nói rằng họ dùng phần lớn thời gian của mình để trả lời các câu hỏi gần như giống nhau. Đó là những câu hỏi mà các khách hàng muốn hỏi trước khi họ giao dịch với bạn. Đưa những câu hỏi này lên Website sẽ giúp bạn loại bỏ được những rào chắn đối với công việc kinh doanh và giải phóng bớt thời gian cho nhân viên trực điện thoại.

Xây dựng một website có vai trò rất quan trọng trong thời đại bùng nổ internet như hiện nay, nó giống như nhân viên truyền thông của công ty có thể giới thiệu công ty của bạn suốt 24 tiếng torng ngày và 7 ngày trong tuần tới đối tượng khách hàng mục tiêu, vậy tại sao lại không lập một website ngay bây giờ nhỉ?

11. Giải quyết thông tin nội bộ


Các nhân viên bán hàng lưu động có thể cần những thông tin cập nhật từng phút để giúp họ bán hàng cũng như giúp cho việc kinh doanh luôn ăn ý. Nếu bạn biết thông tin gì cần thiết, bạn có thể đưa chúng lên 1 Website riêng. Với một cuộc truy cập Internet thông qua điện thoại nội hạt, nhân viên bán hàng của doanh nghiệp bạn ở bất kỳ nơi đâu trên thế giới sẽ nhận được những thông tin đầy đủ nhất mà không phải trả cước phí đường dài và những nhân viên ở văn phòng không bận rộn thêm.

12. Mở rộng ra thị trường quốc tế

Với việc kinh doanh thông thường bạn không thể gửi thư, điện thoại hay phổ biến các quy định tới tất cả mọi khách hàng tiềm năng trên thị trường thế giới, nhưng với Website bạn có thể hội thoại trực tiếp với khách hàng quốc tế như là với một khách hàng trong nội hạt. Khi doanh nghiệp của bạn có các văn phòng đại diện ở nước ngoài, họ sẽ truy cập vào nguồn thông tin của văn phòng trong nước với chi phí phải trả vhỉ bằng một cuộc điện thoại gọi nội hạt.

13. Hình thành dịch vụ 24 giờ

Chúng ta không phải lúc nào cũng có những công việc cùng chung một lịch trình. Công việc kinh doanh là khắp mọi lúc, mọi nơi chứ không phải chỉ là thời gian ở công sở. Khi công việc kinh doanh giữa Châu Âu và Châu Á đang thực hiện thì sự khác biệt về thời gian sẽ là điều cản trở lớn. Các Website sẽ phục vụ khách hàng và các đối tác của bạn 24/24 giờ trong ngày, 07/07 ngày trong tuần. Thông tin có thể được khách hàng lựa chọn theo nhu cầu và các thông tin mà họ coi là quan trọng, chính điều này sẽ đưa bạn dẫn đầu trong cuộc cạnh tranh ngay cả khi bạn ở ngoài văn phòng làm việc.

14. Thay đổi thông tin hiện thời 1 cách nhanh chóng

Có những thông tin bị thay đổi trước khi nó được in ra. Và bạn sẽ có một đống giấy tờ có cũng như không có giá trị lẫn lộn nhau. Các ấn phẩm điện tử có thể thay đổi theo nhu cầu của bạn mà không cần đến giấy tờ, bút mực hay hóa đơn. Bạn còn có thể gắn Website của doanh nghiệp với 1 cơ sở dữ liệu mà bạn có thể thay đổi bao nhiêu lần trong 1 ngày cũng được tùy theo yêu cầu. Chẳng có giấy tờ nào có thể giúp bạn thực hiện được sự năng động đó.

15. Cho phép bạn tiếp nhận thông tin phản hồi từ phía khách hàng

Với Website bạn có thể yêu cầu thông tin phản hồi từ phía khách hàng ngay lập tức khi họ đang ghé thăm Website của doanh nghiệp bạn. Điều này giúp bạn tiết kiệm được rất nhiều thời gian và tiền bạc để hoạch định các chiến lược quảng cáo và kinh doanh trên cơ sở những thông tin nắm bắt được từ phía khách hàng mà không phải mất thêm khoản chi nào nữa. Câu trả lời của khách hàng được đưa lên Website ngay khi khách hàng tìm hiểu sản phẩm và được chuyển lập tức tới địa chỉ e-mail của bạn.

16. Thử nghiệm dịch vụ và sản phẩm mới trên thị trường

Khi đưa ra một sản phẩm mới trên thị trường, điều mà tất cả các doanh nghiệp phải làm là quảng cáo và giới thiệu sản phẩm đó. Với các phương pháp quảng cáo truyền thống, đây sẽ là một công đoạn rất tốn kém và đòi hỏi kinh phí lớn. Nhưng nếu bạn giới thiệu, quảng cáo sản phẩm mới trên Website của doanh nghiệp bạn, bạn sẽ biết rằng có thể chờ đợi gì từ những khách hàng truy cập vào Website, họ chính là thị trường ít tốn kém nhất mà bạn vươn tới. Họ còn có thể cho bạn biết họ nghĩ gì về sản phẩm của bạn 1 cách nhanh nhất, dễ dàng nhất với một chi phí ít hơn bất kỳ thị trường nào mà bạn vươn tới.

17. Phương tiện truyền thông linh hoạt


Ngày nay, Internet được đánh giá là hệ thống truyền dẫn chuyên nghiệp nhất bởi vì sản phẩm chính của nó là các thông tin được tiếp cận một cách dễ dàng, nhanh chóng và rẻ tiền. Tất cả các ấn phẩm được truyền trên Internet đang ngày càng trở nên phổ biến bởi vì các công việc đều được thực hiện trong môi trường kỹ thuật số từ rất nhiều nguồn thông tin cung cấp. Tất cả những công việc này thực hiện một cách dễ dàng thông qua các trang Web trên chính Website của doanh nghiệp bạn.

18. Tiếp cận một thị trường của giới trẻ và mang tính giáo dục

Ở hầu hết các trường đại học đều đã cho sinh viên tiếp cận vào Internet, giới học sinh phổ thông sẽ từng bước làm quen và sử dụng dịch vụ Internet trong nhiều năm tới. Nhu cầu về sách vở, trang phục thể thao, các khóa học, thời trang trẻ và rất nhiều thứ khác sẽ trở thành nhu cầu đa dạng của thị trường trên Internet. Thậm chí ngay cả khi áp dụng dịch vụ thương mại điện tử trên mạng và tuổi thọ trung bình có phần tăng lên thì sự tăng trưởng của khu vực thị trường tuổi dưới 25 vẫn tiếp tục.

19. Tiếp cận một thị trường có tính chuyên nghiệp

Mạng Internet không đơn thuần chỉ là những máy tính mà nó còn là nơi mọi người có thể mua bán, trao đổi bất kỳ thứ gì từ chiếc bàn chải đánh răng, các tác phẩm nghệ thuật cho đến các bài học tiếng Anh,... Với 70 triệu người sử dụng thường xuyên và số lượng người sử dụng tăng lên hàng ngày, thông tin kinh doanh của bạn có thể được giới thiệu cho một số lượng người rất lớn.

20. Phục vụ tại thị trường địa phương

Chúng ta đã nói về sức mạnh của việc phục vụ nhu cầu trên thị trường quốc tế thông qua Internet, nhưng còn khu vực thị trường ở ngay địa phương của bạn thì sao? Câu trả lời là: chính khách hàng trong địa phương bạn thông qua các hoạt động marketing, họ sẽ biết tới Website, truy cập thông tin trên Internet và mang lại lợi nhuận cho công ty bạn. Cho nên dù công ty được đặt ở đâu thì thông qua mạng Internet, những khách hàng tiềm năng vẫn biết đến bạn và bạn cũng sẽ sẵn sàng phục vụ họ.

Theo Giaiphaptructuyen
-->đọ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