Friday, June 28, 2013

ReflectionClass in PHP

To know internals of any classes or interfaces, we can use ReflectionClass which is offered by PHP5. With this, we can retrieve methods, properties etc from a class. Let's checkOut a simple example ::

<?php
// User defined class a [Line No. 2]
class a
{
  const am = 10;   // Constant
  protected $aa;   // Protected Member
  public $aaa;     // Public Member
  function disp()  {  } // Public method
}

// Inheritance [Line No. 11]
class b extends a
{
  static $vendor = 1; // Static Property
  public $bbb;        // Public property
  const am = 20;      // Constant
 
  public static function get_vendor()  { } // Static Method
  function disp(){  }    // Public Method                 
}

// Print
ReflectionClass::export( 'b' );
?>


Output ::

Class [ <user> class b extends a ] {
  @@ C:\xampp\htdocs\test.php 12-20

  - Constants [1] {
    Constant [ integer am ] { 20 }
  }

  - Static properties [1] {
    Property [ public static $vendor ]
  }

  - Static methods [1] {
    Method [ <user> static public method get_vendor ] {
      @@ C:\xampp\htdocs\test.php 18 - 18
    }
  }

  - Properties [3] {
    Property [ <default> public $bbb ]
    Property [ <default> protected $aa ]
    Property [ <default> public $aaa ]
  }

  - Methods [1] {
    Method [ <user, overwrites a, prototype a> public method disp ] {
      @@ C:\xampp\htdocs\test.php 19 - 19
    }
  }
}


Discussion ::
1. The class whose internals we want to must be passed to ReflectionClass' static method export(). For example if we want to know about a class named 'employee', we would write as this ::
  ReflectionClass::export( 'employee' );
 

2. Notice the output, Constants, Static Properties, Static Methods, Methods and Properties are shown in list. Check that in the properties section, inherited properties (3) are also shown. In the method section, notice it is denoted that class b overwrites a's disp() with its own copy of disp(). ReflectionClass' export static method returns minute details about a class like number of methods and properties, method's parameters, visibility parameters (whether private, protected or public). It also tells us about the line numbers within the source code where a particular method or property was defined.

Let's try some other method ReflectionClass offers. Check another example below ::

<?php
// Class Definition as shown above ...

// Create new ReflectionClass Object
$c = new ReflectionClass('b');

// Use ReflectionClass Methods

// Get value of a Constant 'am'
echo $c->getConstant('am');

// getConstants() returns class
// constants as an array
print_r( $c->getConstants() );

// Get Constructor Name if defined
print_r($c->getConstructor());

// Get all properties including inherited ones
print_r( $c->getDefaultProperties());

// Get the filename, in which the class is defined
echo $c->getFileName();

// GET ALL Interface Names implemented in the CLASS
// getInterfaces() returns all interfaces in
// ReflectionClass objects
print_r($c->getInterfaceNames());

// Lists all local and inherited methods
print_r($c->getMethods());

// Get the class name including NameSpace
echo $c->getName();

// Get the name of Parent Class
print_r($c->getParentClass());

// GET all properties (including inherited)
// We use various Filters with this function
// IS_PROTECTED to get Protected properties
// IS_PUBLIC to get Public properties
// IS_STATIC to get static properties
// IS_PRIVATE to get static properties
// Parent's STATIC properties are also shown
print_r($c->getProperties( ReflectionProperty::IS_STATIC  ));

// Get a Particular property
echo $c->getProperty('vendor');

// List all static Properties
print_r( $c->getStaticProperties());

// GEt value of any static property
var_dump( $c->getStaticPropertyValue('vendor'));

// Check if a specific Constant exists
echo $c->hasConstant('am');

// Check if a specific Property exists
echo $c->hasProperty('aa');

// Check if a specific Method exists
echo $c->hasMethod('disp');

// Check if a Class is Abstract
var_dump( $c->isAbstract());

// Checks if a class is clonable
// A Class is NOT clonable if its magic
// method __clone() is set to private
var_dump($c->isCloneable());

// Checks if a class is FInal
var_dump($c->isFinal());

// Checks if any object is an instance
// of the current class
var_dump( $c->isInstance(new b) );

// The above statement is similar to
echo new b instanceof b;

// Check if a class is instantiable
// Interfaces, Abstract Classes and classes
// with private constructor can not be
// instantiated
var_dump( $c->IsInstantiable() );
?>


Here I repeat some important points mentioned in comments in the code above ::

i. Interfaces, Abstract classes and any class with its constrructor ( __construct() ) set to private are not instantiable.
ii. If any class' magic method __clone() is set to private, the object of such class can not be cloned any more.
iii. Parent class' Static properties can be accessed from children classes.
iv. Parent class' Constant can be accessed from children classes.


ReflectionClass is used to make documentation for a piece of code.

Count() function in PHP

The purpose of this function is to return the total count of elements in an array as shown in the example below.

<?php
 $a = array(12,13,14);
 echo count($a);  // 3
?>

 

It does not matter if the array is associative or its indices are not ordered. Check another example ::

<?php
 $a = array(12,13,14);
 $a[24] = 12;
 $a['my_name'] = 'Chandan';
 $a[134] = 102;
 echo count($a);  // 6
?>


Let's take an Multi-dimensional array and apply count().

<?php
 $a = array(
      "names" => array("John", "Martin", "Teddy"),
      "rolls" => array(10, 23, 3)
      );
 echo count($a);  // 2
?>

 

The above program prints 2 as count of primary indices "names" and "rolls". Let's modify the count() function call to get the correct element count in the array.

<?php
 $a = array(
      "names" => array("John", "Martin", "Teddy"),
      "rolls" => array(10, 23, 3)
      );
 echo count($a, COUNT_RECURSIVE);  // 8
?>


The second parameter to count() function forces it to get through each index recursively and search for sub-elements. Each of the 8 elements in the above array can be accesses as shown below :

$a['names']     // Value :: Array
$a['rolls']     // Value :: Array
$a['names'][0]  // Value :: John
$a['names'][1]  // Value :: Martin
$a['names'][2]  // Value :: Teddy
$a['rolls'][0]  // Value :: 10
$a['rolls'][1]  // Value :: 23
$a['rolls'][2]  // Value :: 3


The constant COUNT_RECURSIVE can be replaced with "1". Let's use the count() function with simple/basic type variables.

<?php
 $a = NULL;
 $b = '';
 $c = 'Smith';
 $d = 100;
 echo count($a);  // 0
 echo count($b);  // 1
 echo count($c);  // 1
 echo count($d);  // 1
?>


For any uninitialized simple/basic type variable, count returns zero. Let's use count() with objects.

<?php
class Foo
{
    public $var1 = 100;
    public $var2 = 200;
    public function display()
    {
      echo "$var1, $var2";
    }
}


$foo  = new Foo();
echo count($foo, COUNT_RECURSIVE); // 1
?>


Same behaviour noticed when we use objects instead of basic types. However we can convert an object to an array and then use count() function to know number of properties it has. Check the example below ::

<?php
$b = new stdClass;
$b->name = "John";
$b->roll_no = 100;
$b->age = 35;
$b->grade= 'b';
echo count((array)$b); // 4
?>


Let's use Countable interface which is defined in SPL (Standard PHP Library). By using this interface, we can manipulate the value count($object) returns. Check out the example below ::

<?php
class foo implements Countable
{
  private static $count = 0;
 
  public function __construct()
  {
     // Increment the count
     self::$count++;
  }
  // Our own implementation of count()
  public function count()
  {
    return self::$count;
  }
 
}
$b = new foo(); // count = 1
$c = new foo(); // count = 2

echo count($c); // 2
echo count($b); // 2
?>


Notice that the constructor is incrementing the value of static variable $count every time we create a new object. Our implementation of count() function manipulates the way count() works with our objects and it returns the value of $count (Class Property).

Thursday, June 13, 2013

String manipulation in javascript thorugh RegExp II

Problem 5 :: Swap between 1st and 3rd word in every combination of 3 words in a given string. For example, string like "I am right" would result into "right am I" i.e 1st and 3rd words are swapped.
Solution ::

<script>
// String
var str = "We are the men in red. He is the best boy.";

// Define RegExp
var patt = /(\S+)\s+(\S+)\s+(\S+)/g;

// Apply RegExp
var res = str.replace( patt, "{$3} $2 {$1}" );

// Print in Console
console.log( res );
</script>


Output ::
{the} are {We} {red.} in {men} {the} is {He} best boy.

Explanation ::
i) Regular expression (\S+)\s+(\S+)\s+(\S+) tries to capture 3 adjacent words joind with 2 occurrences of single/multiple spaces.
ii) The replace() function replaces such matched 3 words with "{$3} $2 {$1}" or 1st and 3rd words swapped.

Problem 6 :: I have a string like "I have 10 dollars in my pocket". We need to convert all numeric value ("10") to currency formatted text like "$10.00".
Solution ::

<script>
// String
var str = "0+ 1 + 10 + 10.00 + $5.00 = $26.00, right?";

// Define RegExp
var patt = /(\$*\d+\.*\d*)/g;

// Apply RegExp
var res = str.replace( patt, function($1)

{ var p = $1.replace(".00","").replace("$","");  
  return "$" + p + ".00"; 

);

// Print in Console
console.log( res );
</script>


Output ::
$0.00+ $1.00 + $10.00 + $10.00 + $5.00 = $26.00, right?

Explanation ::
The capturing group (\$*\d+\.*\d*) implies the following :
i) $ may be present at the beginning
ii) Next, series of digits
iii) A dot (.) may appear next
iv) Again a series of digits might appear.

The RegExp above would capture text like "$12" or "12" or "$12.00". Next we have a function which replace all "$" and ".00" characters from the matched word, and finally produces the resultant string by adding "$" and ".00" at the beginning and the end respectively. The replacement is required in case where texts like "$10" or "$20.00" are found.

Problem 7 :: This problem has been featured on MDN page. Converting Celsius to Fahrenheit through RegExp. Check out the code below.
Solution ::

<script>
// String
var str = "Last 7 day's temperature : 14.5C 4C 0C -3C -5.6C";

// Define RegExp
var patt = /([-]*\d+\.*\d*[C|F])/g;

// Apply RegExp
var res = str.replace( patt, function($1)
{
  var v = $1; 
 
  // GET the numeric value
  var t = parseFloat( v.substr(0, v.length - 1 ) );

  if(v.substr(-1) == 'C')
  {
     // Convert to Farenheit
     var result = ( ( t * 1.8 ) + 32 ).toFixed(2) + "F";
  }

  if(v.substr(-1) == 'F')
  {
     // Convert to Celsius
     var result = ( ( t - 32 ) / 1.8 ).toFixed(2) + "C";
  }
  return $1 + "[" + result + "]";

} );

// Print in Console
console.log( res );
</script>


Output ::
 
Last 7 day's temperature : 14.5C[58.10F] 4C[39.20F] 0C[32.00F] -3C[26.60F] -5.6C[21.92F]

Explanation ::
This is a nice program to convert Celsius to Fahrenheit and vice versa within a string. The output shows that all the temperatures in Celsius are appended with same in Fahrenheit. For example "14.5C" has been appended with "[58.10F]". Let's dissect the RegExp "/([-]*\d+\.*\d*[C|F])/g"..

i) [-]* means the number may start with a negative sign
ii) \d+\.*\d* means any sequence of digits may be followed by a dot or a series of digits. This captures numbers like "1", "12", "1.23" or "13.2".
iii) [C|F] means the number may be followed by either 'C' or 'F'.

The function we used with replace() function is very simple. We use  v.substr(0, v.length - 1) statement to extract "14.5" from "14.5C". And then we put a if-else logic to convert from Celsius to Fahrenheit or vice-versa. We use toFixed() function to round a floating point number to 2 decimal places i.e rounding 58.100000000 off to 58.10. The replace() function is responsible for making the string "14.5C"  converted to "14.5C[58.10F]".


Problem 8 :: Let's find out all words which have comma after them.
Solution ::

<script>
// String
var str = "We didn't do it, even they didn't, who did it then?";

// Define RegExp
var patt = /(\S+)(?=,)/g;

// Apply RegExp
var res = str.replace( patt, function($1){ return  "[" + $1 + "]"; } );

// Print in Console
console.log( res );
</script>


Output ::
We didn't do [it], even they [didn't], who did it then? I [did],

Explanation :: We have actually wrapped all matched words with a square bracket around them. Let's check the RegExp /(\S+)(?=,)/g ...

i) 'g' modifier is used to denote a global search
ii) (\S+) means any series of non-whitespace characters
iii) (?=,) denotes a positive lookahead regexp which starts with ?=. This means 'followed by comma' which would not be included in resultant match.

However, the above RegExp has a problem, it can match "iran,iraq," as a whole from a string like "iran,iraq, and Nepal". To get rid of this, we would change the pattern like this ::

var patt = /(\S[^\s,]+)(?=,)/g;

The inclusion of "[^\s,]" would accept all words containing comma two separate words. The output would be "[iran]" and "[iraq]".

We could have written the regexp pattern without using the positive lookahead as this ::

var patt = /(\S[^,\s]+),/g ;

 
It captures any character excluding comma and whitespace, followed by a comma. Problem is all the matched words are returned with a comma at the end. For this reason, positive lookahead is only solution to this. 


See previous article for more info on JS RegExp.

String manipulation in javascript thorugh RegExp I

Problem 1 :: Find all 3 letter words in a given string
Solution ::

<script>
// String
var str = "We are the men in red. He is the best boy.";

// Define RegExp
var patt = /\b([\w]{3})\b/g;

// Apply RegExp
var res = str.match( patt );

// Print in COnsole
console.log( res );
</script>


Output ::
["are", "the", "men", "red", "the", "boy"]

Explanation ::
i. modifier 'g' is used for global search.
ii. \b is used to denote the word boundaries
iii. ([\w]{3}) means any alphanumeric character 3 times

Problem 2 :: Wrap all 3 letter words with a pair of braces within the string given in problem 1 above.
Solution :: We need to manipulate the replace() function a little to achieve this.

// Apply RegExp
var repl_ace = str.replace( patt, "{$1}" );

console.log( repl_ace );
 

Output ::
We {are} {the} {men} in {red}. He is {the} best {boy}.

Explanation ::
The 2nd argument in replace() function can take RegExp and $1 means every match found i.e if a 3 letter word "are" is found, $1 would refer to the match "are" itself. Hence, "{$1}" would generate {actual_word} for each 3 letter words found in the string.

Problem 3 :: Convert all 3 letter words to Upper Case within the string.
Solution :: We simply change the replace() function to achieve this. Check it out below.

// Apply RegExp
var repl_ace = str.replace( patt, function($1)

   { return $1.toUpperCase();  } ); 
// Print
console.log( repl_ace );

Output ::
We ARE THE MEN in RED. He is THE best BOY.

Explanation :: The second argument to replace() function should be a string, however we used a function which returns a string. That string takes the "$1" i.e the matched word and returns it in Upper case format which the replace() function uses.

Problem 4 :: Find every 2 adjacent words in a String and swap them. Means, it would match words like "We are", "the men" etc and swap them to "are We" and "men the".
 

Solution ::
<script>
// String
var str = "We are the men in red. He is the best boy.";

// Define RegExp
var patt = /(\S+)\s+(\S+)/g;

// Apply RegExp
var res = str.replace( patt, "$2 $1" );

// Print in Console
console.log( res );
</script>


Output ::
are We men the red. in is He best the boy.

Explanation ::
i) (\S+) means any series of non-whitespace i.e "We"
ii) \s+ means any series of whitespaces.
iii) (\S+) again means non-whitespace after the whitespaces i.e "are". So, we are trying to match adjacent words like "(We) (are)" or "(the) (men)". So, for every such match $1 would hold the 1st word, $2 holds the 2nd word i.e "We" & "are" for matched word pair "(We) (are)".
iv) The replace() function replaces with "$2 $1" resulting to "are We".

More such examples can be found in my next article.

Thursday, June 06, 2013

Find character frequency in a string

This is a very common problem we are going to solve. We have a string like "abcd1abcd1abcd1" and we need to find out how many times each character appears within the string. In the string "abcd1abcd1abcd1", we see that characters "a","b","c","d","1" appear 3 times each in the string. Let's write the basic logic to achieve this ::

i) Extract unique characters from the given string
ii) Create a second array DICT with unique characters
iii) Iterate the DICT array and for each character, find total number of appearances in given string.

Let's implement the above logic in C language.

#include "stdio.h"
#include "string.h"

main()
{

 /* Example String */
 char *str = "abcd1abcd1abcd1";

 /* Define an ARRAY Where unique chars will be stored */
 static char dict[26];

 int i,j,k=0;

 /* EXTRACT Unique chars in the string */
 for(i=0;i<strlen(str); i++)
 {
   /* Check if this appears in dict array */
   int found = 0;
   for(j=0;j<sizeof(dict);j++)
   {
    if(dict[j] == str[i])
     {
       found++;
       break;
     }
   }
 
   /* If not found, then ASSIGN to dict */
   if( !found )
     dict[k++] = str[i];
 }


 /* Now find count for each unique char */
 for(i=0; dict[i] ; i++)
 {
   int count = 0;
   for(j=0;j<strlen(str);j++)
    if( str[j] == dict[i] )
     count++;
  
   /* Print the Count for each character */
   printf("\n The character [%c] appears %d times", dict[i], count );
 }
}


Output :
The character [a] appears 3 times
The character [b] appears 3 times
The character [c] appears 3 times
The character [d] appears 3 times
The character [1] appears 3 times

The advantage in the above method is that it can tell us the count of all characters including alphanumeric, special chars. However, we have another small solution to the above problem with a constraint that all the characters in the given string must be alphabets. Here we use an array called freq_count whose length is 26 to keep count of 26 characters only. For example freq_count[0] holds count of char 'a', freq_count[1] holds count of char 'b' and so on. Check it out below..

#include "stdio.h"
#include "string.h"

main()
{

 /* Example String */
 char *str = "abcdabcdabcd";

 /* Define an ARRAY for keeping Frequency count */
 static int freq_count[26];

 char ch;
 int i;

 /* Iterate through the string */
 for(i=0;i<strlen(str); i++)
 {

   /* IF CAPS alphabets */
   if( ( str[i]>=65 && str[i]<=90 ) )
   {
       freq_count[ str[i] - 65 ] ++;
   }
   

   /* For small letters */   
   else if( str[i]>=97 && str[i]<=122 )
   {
      freq_count[ str[i] - 97 ] ++;
   }
 }

 /* Now PRINT result */
 for(i=0; i<sizeof(freq_count)/2 ; i++)
 {
   /* Show count if character appears */
   if( freq_count[i] > 0 )
     printf("\n The character %c appears %d times", i + 65, freq_count[i]  );
 }
}


Output ::
The character A appears 3 times
The character B appears 3 times
The character C appears 3 times
The character D appears 3 times

The checking str[i]>=65 && str[i]<=90 and str[i]>=97 && str[i]<=122 checks for alphabets and if so then only freq_count array is updated. So, if the given string has numeric characters like '1','2' etc, they would be ignored.

We see that ASCII codes between 32 and 126 (95 characters) are printable; they contain alphanumeric and special characters including space. Hence we can easily capture their frequency also if we increase the freq_count array length. Check out the implementation below :

#include "stdio.h"
#include "string.h"

main()
{

 /* Example String */
 char *str = " aa!~~ 99! ";

 /* Define an ARRAY for keeping Frequency count */
 static int freq_count[95];

 char ch;
 int i;

 /* Iterate through the string */
 for(i=0;i<strlen(str); i++)
 {

   /* FOR any character */
   freq_count[ str[i] - 32 ] ++;
 }

 /* Now PRINT result */
 for(i=0; i<sizeof(freq_count)/2 ; i++)
 {
   /* Show count if character appears */
   if( freq_count[i] > 0 )
     printf("\n The character [%c] appears %d times", i + 32, freq_count[i]  );
 }
}


Output :
The character [ ] appears 3 times
The character [!] appears 2 times
The character [9] appears 2 times
The character [a] appears 2 times
The character [~] appears 2 times

The first line of output says count of whitespace appearing within the string.

PHP Implementation : 


Let's try to write above implementation in PHP. Check out the code below ...

<?php
 // Example String
 $str = " aa!~~ 99! ";

 // Define an ARRAY for keeping Frequency count
 $freq_count = array();

  // Iterate through the string
 for($i=0;$i<strlen($str); $i++)
 {
   // FOR any character, GET ASCII
   $index = ord($str[$i]) ;
  
   // Create Associative array
   if( isset( $freq_count[ $index ] ) )
     $freq_count[ $index ]++;
   else
     $freq_count[ $index ] = 1;
   
 }

 // Now PRINT result

 foreach($freq_count as $key=>$val)
 {
   // Convert to character
   $ch = chr($key);
   // Print
   echo "<br> The character [$ch] appears $val times" ;
 }
?>


The code above runs jolly well. PHP has an advantage in its array structures. C Array starts with index 0 while PHP associative arrays can be built with key=>value structure and that key can be anything. So, in the first loop we create array indexes like $freq_count[32] (for space) or $freq_count[97] for character 'a' etc. After the $freq_count array is created, it would look like this :

Array ( [32] => 3 [97] => 2 [33] => 2 [126] => 2 [57] => 2 )

[97] => 2 means character with ASCII 97 ('a') appears twice,
[32] => 3 means character with ASCII 32 (space) appears thrice and so on.

Finally we iterate though this array using foreach() loop construct and convert those keys to corresponding characters using chr() method. PHP's arrays are more dynamic in nature than in C. We don't have to define an array of 95 integers like in C. However above C program can be modified to create dynamic linked list at runtime to keep track of characters within the string. This would definitely save us some memory.
 

JavaScript Implementation : 

Let us write the same program in JavaScript. Check out the code snippet below.

<script>
 // Example String
 var $str = " aa!~~ 99! ";

 // Define an ARRAY for keeping Frequency count
 $freq_count = []

 // Iterate through the string
 for(var $i=0;$i<$str.length; $i++)
 {
   // FOR any character, GET ASCII
   $index =  $str.charCodeAt($i) ;
  
   // Associative array
   if( $freq_count[ $index ] === undefined )
     $freq_count[ $index ] = 1;
   else
     $freq_count[ $index ]++;
   
 }

 // Now BUILD result string
 $msg = "";
 for(var $key in $freq_count)
 {
   // Convert to character using fromCharCode()
   $msg += "[" + String.fromCharCode($key) + "]";
   $msg += " appears " + $freq_count[$key] + " times \n";
 }

 // PRINT on Screen
 alert($msg);
 </script>


The output is shown below :


We use String.charCodeAt(position) method to get the ASCII code of the character at position within the string. And we use String.fromCharCode($key) method to convert any Integer back to character. The PHP and Javascript codes are quite similar and easy to understand.

Javascript array is same as C in one respect and that is array index always starts at 0. For example if we define an array and set its 100 index to 10, all previous indexed will be created and filled up with undefined.

var arr  = []; // Define array
arr[100] = 10; // Set index 100


Index 0 to 99 would be automatically created and their values would be undefined. However when iterating through for(x in var) loop, only those key which have values other than undefined will be displayed. PHP array are not like this, they are more dynamic in nature.

// Below JS LOOP would print only 10
for(var x in arr)
  console.log( arr[x] );

Add custom method to jQuery Form Validation plugin

We have used JQuery form validation plugin many times like in "contact us" forms. Problem occurs when any field has a hint text specified. For example, suppose "firstname" text input field has a hint-text "Enter firstname here". When this plugin validates for  emptiness, the value "Enter firstname here" successfully passes the test but this is not right.

In such situations we would require to add custom validation method to jQuery Validator plugin.

I am showing one "contact us" form with 2 required fields "firstname" and "lastname". Here is the code and HTML.

<script>
  $(document).ready(function(){
   
    // Contact Form Submission Handler
    $("#contactUsForm").validate(
    {
    messages:
    {
         firstname: "Enter your firstname",
         lastname:  "Enter your lastname",
        },
   
    submitHandler: function(form)
    {
      jQuery.ajax(
      {
        url: form.action,
        type: form.method,
        data: $(form).serialize(),
        success: function(response)
        {
          if( response == "1") // Success
          {
            // Reset the form
            document.getElementById("contactUsForm").reset()
          }
          else // Failure
          {
            // Do stuff when failed
          }
       }           
     });
    }
     });
  });
</script>

<form id='contactUsForm' method="post">

<input type="text" name="firstname"  id="firstname" class="required">
<input type="text" name="lastname" id="lastname" class="required">
<input class="form-element" name="Submit" value="Submit" type="submit">

</form>


JQuery validation plugin needs class='required' to be added to the required fields. The messages parameters holds all error messages to be shown for each element specified. When the Submit button is clicked, the form is validated through the validation plugin. Error messages are shown if  required fields are empty. If any "email" field is given class='required email', then that field would be checked for both emptiness and email format. But what if the fields have hint-text as shown below? These fields get validated and they pass in empty testing which should not be the case.

<input type="text" name="firstname" id="firstname" value='Your First Name' onfocus="javascript:if(this.value=='Your First Name') this.value='';" onblur="javascript:if(this.value=='') this.value='Your First Name';" >

<input type="text" name="lastname" id="lastname" value='Your Last Name' onfocus="javascript:if(this.value=='Your Last Name') this.value='';" onblur="javascript:if(this.value=='') this.value='Your Last Name';">


To manage such situations we need to add some custom methods to the jQuery Validator object as shown below. We also need to add new Rule to it.

<script>
  $(document).ready(function(){
   
    // Our NEW custom method   
    jQuery.validator.addMethod("rem_default_val", function(value, element)
    {
       // Default Value Check for firstname
       if(element.value == "Your First Name" && element.name == "firstname")
       { jQuery('#firstname').focus(); return false; }

       // Default Value Check for lastname
       if(element.value == "Your Last Name" && element.name == "lastname")
       { jQuery('#lastname').focus(); return false; }
      
    });
   
   
    // Contact Form Submission Handler
    $("#contactUsForm").validate(
    {
    // Define a new Rule
    rules:
    {
       firstname: "required rem_default_val",
       lastname: "required rem_default_val",
    },
   
    messages:
    {
         firstname: "Enter your firstname",
         lastname:  "Enter your lastname",
        },
   
    submitHandler: function(form)
    {
      /// .... AJAX form submissions
    }
     });
  });
</script>


Notice that class='required' may not be required if we add 'required' as a rule. We also add a method called rem_default_val() as a rule which means elements have to pass this validation method which is defined using addMethod() function.

New rules have been defined here ::

rules:
{
   firstname: "required rem_default_val",
   lastname: "required rem_default_val",
}


Our new custom validation method rem_default_val() tests default values in elements and returns FALSE if certain predefined values or hint-text or default text found.

jQuery.validator.addMethod("rem_default_val", function(value, element)
{
  // Default Value Check for firstname
  if(element.value == "Your First Name" && element.name == "firstname")
  { jQuery('#firstname').focus(); return false; }

  // Default Value Check for lastname
  if(element.value == "Your Last Name" && element.name == "lastname")
  { jQuery('#lastname').focus(); return false; }

});


This way, we can validate a form with elements having hint texts in them.

Dynamic Script Loading using jQuery


We have already seen how dynamic Javascript can be inserted to the HTML document using Javascript in my previous article. Here we would see how we can get the same task done using jQuery getScript() method. This function actually loads a script from the SERVER using ajax method and then executes it. It has the following syntax :

jQuery.getScript( URL_for_script, load_success_callback( data, status, xhr ) );

The 2nd argument is optional. We can use .fail() and .done() methods with it as failure and success callbacks respectively. Let's write a small program which loads a script which is a function.

<script src='js/jquery-latest.js'></script>

<script>
// Define a variable in global scope
var click_times = 1;

// Load scripts dynamically
function load_script()
{
  jQuery.getScript("js/test.js")
 
  // SUCCESS callback
  .done(function(){
    jQuery("#status_div").html('Script Loaded');
  })
 
  // FAIL callback
  .fail(function(){
    jQuery("#status_div").html('Script Failed');
  });

}
</script>

<input type='button' value='Load Script' onclick='load_script()'>
<input type='button' value='This does not work' id='inactive_button'>
<div id='status_div'></div>


We have 2 buttons -- 'Load Script' and 'This does not work' and a DIV with id 'status_div'.


The 'This does not work' button remains inactive initially. Now when we click the 'Load Script' button, it loads a test.js file whose contents is given below ::

// Add a click event to the inactive button
jQuery('#inactive_button').on('click', function(){

// It can access global Variable also
if( click_times == 1)
 {
   // Change BUTTON TEXT only once
   jQuery(this).val('This Now WORKS !!');
 }

// Alert
alert('This button is now active, Clicked : ' + click_times + ' times');

// Increase number of click value
click_times++;

});


We used jQuery on() method to attach a "click" event to the button. So, every time the button is clicked, it alerts the message mentioning total number of clicks it got so far. Below is the screenshot :




The done() method attached to getScript() updates the DIV 'status_div' with status message. It can be done away with in below shown method ::

jQuery.getScript("js/test.js", function(data){
 
    // SUCCESS callback
    jQuery("#status_div").html('Script Loaded:' + data);
  })
 
   // FAIL callback
  .fail(function(){
    jQuery("#status_div").html('Script Failed');
  });


This code does the same stuff; however it also inserts the text received in ajax response in the div.

The only problem with the above code is that, it repeatedly attach events to the button 'inactive_button' if the "Load Script" button is clicked more than once. Assigning new procedure to 'click' event of any button does not remove the previous methods, the new procedures are just appended to the previous procedures. So, we can add a single line at the top of test.js like this to achieve that ..

// Remove the old attached events
jQuery('#inactive_button').off('click');

Monday, June 03, 2013

Dynamic Javascript Insertion

We can create dynamic script element using the simple DOM methods. We have discussed how setting element's innerHTML property fails to execute the inserted scripts at runtime. Let us check out a simple DOM method to load an external js file. Changing "src" property of any <script> element on the runtime does not work on all browses. This has been discussed at the end of this article.

<html>
<head id='header'>
<script> 
function load_script()
{
  // Get the ID of head
  var p = document.getElementById("header");
 
  // Create new script element
  var scr = document.createElement("script");
 
  // Define src
  scr.setAttribute("src","sample.js");
 
  // Append the script to header
  p.appendChild( scr );

}
</script>
</head>

<body>
<div id="mydiv">Click the button to load a script <br />
<input type="button" onclick="load_script()" value="Load Script">
</div>
</body>
</html>


The function load_script() dynamically inserts a <script> element inside the header section, and then setting up "src" property and appending the new <script> to <header> element loads and executes the external js file 'sample.js'.

Using this method we can dynamically call some server pages and get the feedback in native JavaScript code and get it executed.

We have already seen in my previous article that inserting a piece of JavaScript code in a DIV using DIV's innerHTML property does not work. To get some JS code executed, we either need to call eval() method or use the general DOM method to create Script element itself. Let's check out an Ajax example where the feedback is received in native Javascript and we are following the DOM methods to create new script element on the document.

<script>
function call_ajax()
{
 // XHR Object
 var xhr = new XMLHttpRequest();

 // CallBack on Success
 xhr.onreadystatechange = function(){
 
  if(xhr.readyState == 4 && xhr.status == 200)
  {
    // Create new script element
    var scr = document.createElement("script");

    // Create a TEXT node with Ajax Response
    var c = document.createTextNode( xhr.responseText );

    // Append the code to script
    scr.appendChild( c );

    // Append the script to document body
    document.body.appendChild( scr );
  }

 };

 // REQUEST to find_city.php with param zip=10001
 xhr.open("GET",'find_city.php?zip=10001', true);
 xhr.send();
}
</script>

<input type='button' value='Load Script thru Ajax' onclick='call_ajax()'>

<span id='city'></span>


In the above example we are sending a call to find_city.php with a zip parameter. Now, find_city.php searches a DB with given zip code, and returns the result in a native JS (in text format) as shown below.

search_result = 'New York, NY'; document.getElementById('city').innerHTML = search_result; 

Now, our JS code create a Script element with the above Ajax response and appends it to the document body. As a result, the above function gets executed which changes the content of the span (id=city). Check the screenshot below.




The screenshot shows that the ajax response text has been successfully inserted in the span element after clicking the button.

Now, suppose, the ajax response is a function call like this ::

put_search_result ( 'New York, NY', 'city_div') ;

the function "put_search_result" should have been defined prior to making the ajax call. However, we can make the function name dynamic and vary between function calls as shown in example below.

<script>
function call_ajax()
{

 // Define random no.
 var random = Math.floor( Math.random() * 10000 );

 // Define the dynamic function name
 var call_back_fn_nm = "call_back_" + random;

 // Define an anonymous function with body
 var func = function(response){ document.getElementById('city').innerHTML = response;  } ;

 // Link up dynamic function name & body
 eval(call_back_fn_nm + " = func");


 //// AJAX SECTION 
 var xhr = new XMLHttpRequest();

 xhr.onreadystatechange = function(){
 
  if(xhr.readyState == 4 && xhr.status == 200)
  {
    var p = document.getElementById('script_div');
    // Below line is IMPORTANT

    eval( xhr.responseText );
  }

 };

 xhr.open("GET",'find_city.php?zip=10001&callback=' + call_back_fn_nm, true);
 xhr.send();
}
</script>


The above program has some significant and interesting points to notice :

i. We dynamically create a function name like "call_back_1234" and assign it to variable "call_back_fn_nm". We want to fire call_back_1234() after we receive the ajax response. Suppose that 1234 was generated as a random nunber.
ii. Secondly we define an anonymous function and store it in variable func.
iii. Most important statement is call to eval(call_back_fn_nm + " = func"); which is finally evaluated to "call_back_1234 = func" which assigns the anonymous function to a variable call_back_1234 in global scope. This means we can always call call_back_1234(). We can't make a statement like "
call_back_1234 = func" and execute it without the help of eval().
iv. Next we call the server page find_city.zip with zipcode and callback function name as parameters like this ::
    find_city.php?zip=10001&callback=call_back_1234
v. The server simply returns the response in text format :: call_back_1234( 'New York, NY' );
vi. The statement eval( xhr.responseText ); simply evaluates the response and gives a call to call_back_1234( 'New York, NY' ) which inserts the text  'New York, NY' inside the span (id='city').

On many cases, web services are received in JSON object wrapped in a function call like this :

call_back_123456789( {state : 'NY', city : 'New York', zip : '10001'} );

In these situations, our solution would work provided we define the call-back function prior to the webservice call.

Such Dynamic script insertion may create and append lots of dynamic <script> tags on the document body. We could have used another method ...

<script id='dyn_src'></script>

<script>
// Dynamically changes the src property of a script element
function search_result()
{
  document.getElementById('dyn_src').src = 'find_city.php?zip=10001&calback=call_back'
}

// Function body for call back function
function call_back(city_name)
{
  document.getElementById('city').innerHTML = city_name;
}
</script>



The response of find_city.php is received as :: call_back('New York, NY') which is executed when we change the src property of the script element inside the search_result() function. So, calling search_result() function would change the content of the span element. Unfortunately this method works well in IE only.


We can use jQuery getScript() method to load a piece of JS code and execute it dynamically. This has been discussed here.

Adding BookMarks Through Javascript

Whenever we like a page on web, we can bookmark it for future consult. We need to hit CTRL+D keystrokes to bring the bookmark dialogue and after we click on "Ok" button, the current URL is saved in browser bookmark list. In IE, it gets listed in Favorites listings. Here we would be bringing the Save Bookmark dialogue box on screen though JavaScript code. Check it out ...

<script>
function bookmark_me(sURL,sTitle)
{
 // IE
 if ( window.external && document.all)
 {
  window.external.AddFavorite (sURL,sTitle);
 }
 // Now for firefox
 else if (window.sidebar) 
 {
   window.sidebar.addPanel(sTitle,sURL,'');
 }
  // Opera
 else if(window.opera)
 {
   var p = document.createElement("a");      
   p.setAttribute("title", sTitle);
   p.setAttribute('rel','sidebar');
   p.setAttribute('href','http://google.com');
   p.setAttribute('onclick','return false;');
   p.click();
   return false;
 }
}
</script>

<a rel='sidebar' href="javascript:;" onclick="bookmark_me('http://google.com','Google')">BookMark Me !!</a>


My version of firefox (v.21) has access to window.external, hence we had to use document.all check for IE. Chrome does not allow adding favorites/bookmarks though JavaScript. The "rel='sidebar'" in the above link is a must for it to work in Opera (my version is 12.15).