jQuery Plugin Authoring – Step by Step

.

If you interested in JavaScript and jQuery plugin development then this one is for you(who have at-least jQuery plugin usage)

.

1. Add a new function property to the jQuery.fn object:

jQuery.fn.myPlugin = function() {

// plugin goes here

};

jQuery.fn is shortcut form of jQuery.prototype

2. Wrap up it with a self executing closure.

(function( $ ){
$.fn.myPlugin = function() {

// plugin goes here

};
})( jQuery );

$ in place of jQuery
it’s a best practice to pass jQuery to a self executing function (closure) that maps it to the dollar sign
so it can’t be overwritten by another library in the scope of its execution.

3. In the immediate scope of the plugin function, the this keyword refers to the jQuery object the plugin was invoked on.

(function( $ ){
$.fn.myPlugin = function() {

this.hide(); //the this keyword is the jQuery object of the DOM element on which you are pluging-in

};
})( jQuery );

4. jQuery selector query can match zero, one or more elements. This scenarios need to be considered when designing plugin

$.fn.myPlugin = function() {

this.each(function(){
//each() provides implicit iteration
});

};

5. Method chaining are a required behavior. Most cases We need to return a jQuery object from all plugin methods.

$.fn.myPlugin = function() {

return this.each(function(){
var $this = $(this);//have the jQuery object of the invoked element cahced for further use

});

};
With this we can chain our plugin method with built-in methods like

$('div').myPlugin().css('color', 'red');

6. Make your plugin configurable and put some default options too

$.fn.myPlugin = function(options) {

var defaults = {
 speed: 30, //some test data options here
 duration: 2000,
 frequency: 10000,
 //.....
 spread: 3
 }; //default options

//inherit from provided configuration (if any)
var options = $.extend(defaults, options);

return this.each(function(){

    var $this = $(this);
    //more stuffs goes here
});
};

7. Add some more functions

$.fn.myPlugin = function(options) {

var defaults = {
 speed: 30,
 duration: 2000,
 frequency: 10000,
 //.......
 spread: 3
 }; //default options

//inherit from provided configuration
var options = $.extend(defaults, options);

return this.each(function(){

    var $this = $(this);

    //some more functions added here
    var function1 = function(){};
    var function2 = function(){};

   function1(); //call functions to perform

});

};
8. Namespacing

Properly Namspacing your plugin assures that your plugin will have a very low chance of being overwritten by other plugins or code living on the same page.

9. Documentation
In-file documentation should be prepended to each function or method definition in proper format.

10. Example plugin:

A demo “Shake an Element” plugin created for more understanding of jQuery plugin structure which can be download from here ūüôā

11. Usage

All plugin files must be named jQuery.myPlugin.js where myPlugin is the name of the plug-in.

Append your jQuery.myPlugin.js at the head section of your HTML Document.

<head>
<script type="text/javascript" src="jquery.min.js"></script>
<script type="text/javascript" src="jQuery.myPlugin.js"></script>
<script>
$(document).ready(function($) {
$('selctorQuery').myPlugin({speed:10,duration:3000,..spread:5});
});

</script>
</head>
12. Optional but useful ūüôā

Compress and Minify your plugin codes

Packer

This JavaScript compressor/obfuscator by Dean Edwards is used to compress the jQuery source code. It’s available as a web-based tool or as a free download. The resulting code is very efficient in file size, at a cost of a small increase in execution time:

http://dean.edwards.name/packer/

http://dean.edwards.name/download/#packer

JSMin

Created by Douglas Crockford, JSMin is a filter that removes comments and unnecessary white space from JavaScript files. It typically reduces file size by half, resulting in faster downloads:

http://www.crockford.com/javascript/jsmin.html

Good JavaScript Study Resources

ūüôā

Rules, Naming , Conventions

Google JavaScript Style Guide

JavaScript: The World’s Most Misunderstood Programming Language by Douglas Crockford (2001)

http://javascript.crockford.com/javascript.html

“Private Members in JavaScript” by Douglas Crockford (2001)

http://www.crockford.com/javascript/private.html

Code Conventions for the JavaScript Programming Language

http://javascript.crockford.com/code.html

ECMA-262-3 in detail

http://dmitrysoshnikov.com/

OOP: The general theory.

http://dmitrysoshnikov.com/ecmascript/chapter-7-1-oop-general-theory/

Object Oriented Programming in JavaScript

http://mckoss.com/jscript/object.htm

.

Cache PHP output for high traffic websites. PEAR: Cache_Lite

Intro…

Now days the WebPages are outcome of heavy script processing in order to provide more dynamicity to page visitors. The utility of server side scripting is to adopt more engineering on web. When the page gets more visitors or becomes more popular, you have to ensure that, that traffic doesn’t stack or queued in front of your freaky web server. All you have to do is to serve them with your page and ofcourse serve it faster. Again server side scripting requires processing and compiling.

In order to serve pages faster, to make light use of server side processing and compiling and to survive within heavy traffic, caching dynamic script output is needed.

The Need For Speed…

Every time a request hits your web server, PHP has to do a lot of processing, all of your codes have to be compiled and executed for a single traffic hit every time. Interesting thing will be if the outcomes of all these processing is identical for each visitors. Say, processing happens every time for visitor 24500 and 24501 while the outputs are so same. Argh!!

What would be if we save the flat HTML generated for visitor 24500 and serve that to 24501 as well??? That will be awesome ūüėÄ coz this leads to less processing and faster page handover. This da mechanism we are talking about, yeah! Cache PHP output ūüėÄ

Well we can write such optimization system but there is a smart package in PEAR called Cache_Lite that can do this job for us. Let’s check out why Cache_Lite:

  • It saves time of writing new caching codes ūüėÄ
  • It’s optimized for high traffic websites
  • Robust, easy to implement
  • Have time to time documentation
  • Bunch of cool features. ūüôā

Installation…

The Cache_Lite class comes courtesy of PEAR, the ‚ÄúPHP Extension and Application Repository‚ÄĚ (http://pear.php.net). In case you didn’t know, PEAR is an online repository of free PHP software, including classes and modules for everything from data archiving to XML parsing. When you install PHP, a whole bunch of PEAR modules get installed as well; the Cache_Lite class is one of them.

In case not installed then…

It is just like coding hello world!! ūüėÄ

On ubuntu:

sudo aptitude -y update
sudo aptitude install php-pear

Now that we have PEAR, i would use it to install the Cache_Lite extension

sudo pear install Cache_Lite

Perfect! ūüėÄ

Checking whether installed/ checking PEAR verson:

Both pear and pecl tools should be available everywhere on command line. For that to work, pear’s binary (bin) directory should be in your PATH variable.

To verify it works, simply type pear. A list of commands should be shown:

$ pear
Commands:
build                  Build an Extension From C Source
bundle                 Unpacks a Pecl Package
channel-add            Add a Channel
...

You should further test that PEAR is up to date:

$ pear version
PEAR Version: 1.7.2
PHP Version: 5.2.6RC4-pl0-gentoo
Zend Engine Version: 2.2.0
Running on: Linux ...

More installation queries here: http://pear.php.net/manual/en/installation.checking.php

Implementation…

<?php

// Include the package
require_once('Cache/Lite.php'); // make sure cache_lite script path

// Set a id for this cache
$id = '123';

// Set a few options
$options = array(
    'cacheDir' => '/tmp/',
    'lifeTime' => 3600
);

// Create a Cache_Lite object
$Cache_Lite = new Cache_Lite($options);

// Test if thereis a valide cache for this id
if ($data = $Cache_Lite->get($id)) {

    // Cache hit !
    // Content is in $data
    // (...)

} else { // No valid cache found (you have to make the page)

    // Cache miss !
    // Put in $data datas to put in cache
    // (...)
    $Cache_Lite->save($data);

}

?>

 

More clearly…


<?php
require_once "Cache/Lite.php";

$options = array(
    'cacheDir' => '/tmp/',
    'lifeTime' => 7200,
    'pearErrorMode' => CACHE_LITE_ERROR_DIE
);
$cache = new Cache_Lite($options);

if ($data = $cache->get('id_of_the_page')) {

    // Cache hit !
    // Content is in $data
    echo $data;

} else {

    // No valid cache found (you have to make and save the page)
    $data = '<html><head><title>test</title></head><body><p>this is a test</p></body></html>';
    echo $data;
    $cache->save($data);

}

?>

If you wish use a cache per block and not a global cache, take as example the following script:

<?php
require_once('Cache/Lite.php');

$options = array(
    'cacheDir' => '/tmp/',
    'lifeTime' => 3600
);

// Create a Cache_Lite object
$Cache_Lite = new Cache_Lite($options);

if ($data = $Cache_Lite->get('block1')) {
    echo($data);
} else {
    $data = 'Data of the block 1';
    $Cache_Lite->save($data);
}

echo('<br><br>Non cached line !<br><br>');

if ($data = $Cache_Lite->get('block2')) {
    echo($data);
} else {
    $data = 'Data of the block 2';
    $Cache_Lite->save($data);
}

?>

Little bit implementation:

The key point is Cache_Lite maintains a unique identifier for every page. Cache_Lite will check for that identifier used before. If so, it will retrieve the stored HTML from disk (can use RAM as turbo charged storage i.e. mount tmpfs in RAM memory) and echo it right away. If not, we:

  • turn on output buffereing so we can catch all following content
  • we include the original PHP code
  • catch the output buffer, and let Cache_Lite store it on disk for the next time.
  • and then echo it

Example:

<?php

/* Include the class */
require_once 'Cache/Lite.php';

/* Set a key for this cache item */
$id = 'newsitem1';

/* Set a few options */
$options = array(
    'cacheDir' => '/var/www/www.mywebsite.com/cache/',
    'lifeTime' => 3600
);

/* Create a Cache_Lite object */
$Cache_Lite = new Cache_Lite($options);

/* Test if there is a valid cache-entry for this key */
if ($data = $Cache_Lite->get($id)) {
    /* Cache hit! We've got the cached content stored in $data! */
} else {
    /* Cache miss! Use ob_start to catch all the output that comes next*/
    ob_start();

    /* The original content, which is now saved in the output buffer */
    include "requiredPhpFile.php";

    /* We've got fresh content stored in $data! */
    $data = ob_get_contents();

    /* Let's store our fresh content, so next
     * time we won't have to generate it! */
    $Cache_Lite->save($data, $id);
    ob_get_clean();
}
echo $data;

?>

A Special case…

Say a case, is to automatically purge an article’s cache when a comment has been placed. You could for example place this before Cache_Lite checks if it’s got a cache page for a specific $id:


<?php
if(isset($_POST["add_comment"]) && $_POST["add_comment"]){
    $Cache_Lite->remove($id);
}

?>

Docs for Cahe_Lite here:

http://pear.php.net/manual/en/package.caching.cache-lite.php

Tricky concepts in PHP

Include Vs Require

include() and require() are slightly different.Basically, include is conditional and require is not.

This would include ‘somefile’ if $something is true:

if($something){

include(“somefile”);

}

This would include ‘somefile’ unconditionally

if($something){

require(“somefile”);

}

This would have VERY strange effects if somefile looked like:

} echo “Ha!I’m here regardless of something: $something<br>n”;

if (false) {

Another interesting example is to consider what will happen if you use include() or require() inside a loop.

$i = 1;

while ($i < 3) {

require(somefile.$i);

$i ;

}

Using require() as above will cause the same file to be used every single iteration.Clearly this is not the intention since the file name should be changing in each iteration of the loop.We need to use include() as below.Include() will be evaluated at each iteration of the loop including somefile.0, somefile.1, etc as expected.

$i = 1;

while ($i < 3) {

include(somefile.$i);

$i ;

}

The only interesting question that remains is what file will be required above.It turns out that PHP uses the value of $i when it reads the require() statement for the first time.So, the require() loop above will include something.1 two times.The include() loop includes something.1 and something.2.


Echo Vs Print

There is a difference between the two, but speed-wise it should be irrelevant which one you use.print() behaves like a function in that you can do:

$ret = print “Hello World”;

and $ret will be 1.

That means that print can be used as part of a more complex expression where echo cannot.print is also part of the precedence table which it needs to be if it is to be used within a complex expression.It is just about at the bottom of the precedence list though.Only “,” AND, OR and XOR are lower.

echo is marginally faster since it doesn’t set a return value if you really want to get down to the nitty gritty.

If the grammar is:

echo expression [, expression[, expression] … ]

Then

echo ( expression, expression )

is not valid.( expression ) reduces to just an expression so this would be valid:

echo (“howdy”),(“partner”);

but you would simply write this as:

echo “howdy”,”partner”;

if you wanted to use two expressions.Putting the brackets in there serves no purpose since there is no operator precedence issue with a single expression like that.