Tuesday, May 28, 2013

String trimming with C

Trimming means removing whitespaces from beginning and end of a string. First we would write a function which removes all trailing whitespaces from a given string.

The logic is ::

i) Scan a string from right end in a loop
ii) If a whitespace found at location n and location n-1 holds any non-whitespace, then we put a '\0' NULL character there and stop.
iii) Otherwise for every whitespace, we replace it with a NULL character.

#include"stdio.h"
#include"string.h"
main()
{
  char str[35] = "  India  is my   country  " ;
 
  /* TRIM end whitespaces */
  right_trim(str); 
 
  /* Print After right Trimming*/
  printf("\n %s",str);
}


/* Right Trim function definition */
right_trim(char *str)
{
  int i,len;
  len = strlen(str);
  i = len - 1;
 
  /* Make sure STRING is not empty */
  if( len > 0 )
  {

       /* This Loop scans the string from end */
       while(str[i])
       {
         /* If a space is found at nth position
            and n-1 position holds a character
*/
         if( str[i] == ' ' && str[i-1]!=' ' && i > 0 )
         {
           str[i] = 0;

           /* BREAK THE LOOP - Important*/
           break;
         }
         else if( str[i] == ' ' )
         {
            str[i] = 0;
         }
               
         i--;
       }
   
   }
}


The right_trim() function takes a pointer to a string which means it works on the original string, not a copy of it. There is a main loop which scans a given string from right end and it places a NULL character at any position if the following conditions satisfy..

a. If any whitespace is found and its previous character is a non-whitespace, then we can assume that it is end of the word/string, hence we put a NULL character at that position.

Suppose we have a string "PHP  " (2 whitespaces at the end) with character 'P' at index 0 and ' ' (space) at index 3 and 4. When the loop scans the string from the end (From index 4), in the first pass, the condition "str[i] == ' '" is evaluated to be true, hence a NULL is placed at position 4. In the second pass the condition " str[i] == ' ' && str[i-1]!=' ' && i > 0 "  becomes true and null character is placed at position 3 making the string "PHP". After this point, we should break out of the loop.

For another example string "Nice PHP  " (2 spaces at the end), after it puts '\0' at 8th position when condition " str[i] == ' ' && str[i-1]!=' ' && i > 0" (i=8) satisfies, if we don't break the loop, it satisfies the similar condition at position 4 and puts a '\0' at 4th position making the string "Nice" which is not what we want.

b. The else part's condition  str[i] == ' ' is equally important to right-trim empty string like  "    ". It continuously places a '\0' on every occurrence of whitespaces.

Now check out how to left-trim a given string like "   NICE PHP   " with 3 whitespace at both front and end. Here is the logic ::

i)Start scanning the string from beginning
ii) If a position has whitespace (" ") and next character is a non-whitespace, break the loop. That is the valid starting point of the string. We can copy from this position into another array or the same array
iii) Else we keep putting 0 in every position if it is a whitespace.

The step (iii) is for trimming empty strings like "  " (2 whitespaces). Now check the implementation below ..
   
#include"stdio.h"
#include"string.h"
main()
{

  char str[35] = "  NICE PHP  " ;
 
  /* TRIM beginning whitespaces */
  left_trim(str); 
 
  /* Print After LEFT Trimming */
  printf("\n %s",str);
}


/* LEFT Trim function definition */
left_trim(char *str)
{
  int i,len, copy_flag=0;
  len = strlen(str);
  i = 0;
 
  /* Make sure STRING is not empty */
  if( len > 0  )
  {

       /* This Loop scans the string from beginning */
       while(str[i])
       {
         /* If a space is found at nth position
            and n+1 position holds a character
*/
         if( str[i] == ' ' && str[i+1]!=' ' && i < len-1 )
         {

           /* Set the FLAG to denote that Shifting/Copying is required */
           copy_flag = 1; 

           /* BREAK THE LOOP - Important */
           break;
         }
         else if( str[i] == ' ' )
         {
            str[i] = 0;
         }
               
         i++;
       }
   
   }
   

   /* LEft Shifting is required */
   if( copy_flag )
   {
      /* i+1 holds valid start of the string as
         prior to that, all position holds whitespaces

      */
      int fpos = i+1;
      int target_pos = 0;
     
      /* start shifting the string towards left */
      while( str[fpos] )
      {
        /* Write/Shift */
        str[target_pos] = str[fpos];

        target_pos++;
        fpos++;
      }
     
      /* Denote new ending */
      str[target_pos] = 0;

   }

}


The loop while(str[i]) determines where the first non-whitespace character appears within the string. If any such non-whitespace character is found, its location is stored and we beak out the loop with a flag set to denote that the array values need to be shifted towards left. Then we shift the array towards left. If any non-whitespace character is not found, '\0' is inserted at every position which does not cause any harm. For example a string is "  NICE PHP  " (with 2 spaces at the beginning and end), in the 2nd pass of the loop the string becomes "0 NICE PHP  " as the first position gets a '\0' due to the code block :

else if( str[i] == ' ' )
{
  str[i] = 0;
}


The above condition satisfies when the i has a value of 0. But it does not harm because rest of the string "NICE PHP  " are shifted towards left and such NULL characters are over-written.

This was a very lengthy approach, let's take another small approach to left trim a given string. Here we would keep on left shift array characters until the first character becomes a non-whitespace character. Check the implementation below.

#include"stdio.h"
#include"string.h"
main()
{

  char str[35] = "  NICE PHP  " ;
 
  /* TRIM beginning whitespaces */
  left_trim(str); 
 
  /* Print After LEFT Trimming */
  printf("\n %s",str);
}


/* LEFT Trim function definition */
left_trim(char *str)
{
        int i=0, j , len;
      
       /* This Loop scans only the 1st position */
       while(  strlen( str ) > 0 && str[0] == ' ')
       {
           len = strlen( str );
           /* Put a NULL at 0 position */
           str[0] = '\0';

           /* LEFT Shift array characters */
           j = 1;
           while( str[j] )
           {
             str[j-1] = str[j];
             j++;
           }
         
           /* Denote End of the string */
           str[j-1] = 0;
           
       }
}


The 2nd approach requires less lines of code and easy to understand. The output is "NICE PHP  ".

Monday, May 27, 2013

Generate RSS feed with PHP

Generating RSS feed with PHP is vey easy. We need to maintain the basic RSS XML format in the output.

<?xml version='1.0' encoding='UTF-8'?>
<rss version='2.0'>
<channel>
<title> Any Title</title>
<link> Any URL </link>
<description> Any Description </description>
<lastBuildDate> Last Build Date</lastBuildDate>
<atom:link href="http://example.com/rss.xml" rel="self" type="application/rss+xml" />
<language>en-us</language>

<item>
<title> Item1 Title</title>
<link> Item1 URL </link>
<description> Item1 Description </description>
</item>

<item>
<title> Item2 Title</title>
<link> Item2 URL </link>
<description> Item2 Description </description>
</item>

</channel>
</rss>


The above XML shows two feed items enclosed within "<item>" tags and each item has its own "title", "link" and "description" tags. The whole item-node construct is enclosed in <channel> and <rss> tags which is important. The "<atom:link ...." tag is totally optional and it's href property should hold the URL of current feed. Using such "<atom:link>" tag has some advantage of being portable and easier to cache. RSS 2.0 requires "title", "link" and "description" tags to be present in the output whereas Atom 1.0 requires "id","title", "link", "author", "updated" elements.

Now, suppose we have a DB table called 'article' with fields 'title', 'url' and 'description' and 'content' fields. We would be making a simple SELECT query, then iterate though the rows and create the final XML as displayed in the PHP program below ::

<?php
// Database Stuffs
$con = mysql_connect("localhost","root","");
mysql_select_db("test");
$sql = "Select title, url, description from article";
$res = mysql_query($sql);

$xml_data = "";

// MAIN LOOP starts
while( $row = mysql_fetch_array($res))
{
  $xml_data .= "<title>". htmlentities($row['title']) ."</title>";
  $xml_data .= "<link>". htmlentities($row['url']) ."</link>";
  $xml_data .= "<description>". htmlentities($row['description']) ."</description>";
}

// Set the output document type through header() function
header("Content-Type: application/rss+xml; charset=utf-8");

// Next, GENERATE the RSS Content
echo '<?xml version="1.0" encoding="utf-8"?>';
echo '<rss version="2.0">';
echo '<channel>';
echo '<title> All Article Listings</title>';
echo '<link>http://www.example.org/aticle-listing-rss.php</link>';
echo '<description>Get Listing of all Articles</description>';
echo '<lastBuildDate>' . date('d M Y h:i:s ') . '+0000' . '</lastBuildDate>';
echo '<language>en</language>';

// Render the DB content
echo $xml_data;

// Concluding Tags
echo '</channel>';
echo '</rss>';
?>


The above code is very simple and easy to understand. However some output characters like single quote or ampersand can cause error. That's why we have used htmlentities() function to convert them to HTML compatible. After we create an RSS feed this way, we may get it checked by validator.w3.org. The output on firefox is shown below ::



If we want to include any article images in the output we can do it two ways :

$xml_data .= "<description>". htmlentities("<a href='". $row['link'] ."'><img src='". $row['image'] ."'></a>") ."</description>";

We created the <img> tag enclosed in an anchor tag to linkify the image. We used htmlentities() function to make these data not available for XML parsing. Characters like "<" and "&" are illegal in XML elements. htmlentities() function would convert <img> to "&lt;img&gt;" which then would not be parsed as XML node. But browser can still build the <img> tag and show the corresponding image on screen in the output.

Similar effect we can achieve through using "CDATA". Check the code below.

$xml_data .= "<description>"  . "<![CDATA[<a href='". $row['link'] ."'><img src='". $row['image'] ."' ></a>]]>" . "</description>";

A CDATA section within XML document starts with "<![CDATA[" and ends with "]]>" and hence it can not contain the string "]]>". Nested CDATA section are also not allowed. Texts like Javascript code should be placed inside CDATA section in XML document.

Download: Fast, Fun, Awesome

Tuesday, May 21, 2013

Fun using css "background-position"


Last week I had checked a beautiful demo of a moving background here and I decided to shell out my own version. Check the image below to learn what I was upto.




The above graphic was done by modifying the background picture position of a DIV using Javascript.

It has four buttons at the bottom, if we click on the "<" button, the digits seem to flow from right to left; by clicking on the '^' button, the digits seem to flow from bottom to top etc. How the whole stuff actually works is described below.

a. First we create an image of digits. Example image is given here..



b. Second, we create a PNG image where the text "PHP" section is totally transparent. Example image is given here..In the picture below, some part is transparent, hence nothing is seen on browser. 


c. We take a DIV with same hight and width as of the PNG image mentioned in step (b) above.
d. We set the background image of the above DIV to the digits image we created in step (a)
e. Now if we change the background-position of the background image of the DIV in a constant manner, the above animation can be achieved.

We set the background image of the DIV through CSS, but we change the "background-position" through Javascript as shown below.

document.getElementById("scrollDiv").style.backgroundPosition = '10px 13px';

The value '10px 13px' defines x-position and y-position of the image. If we increase constantly the y-position from 13px, it would cross the height of the image and hence the image would be gone away and the animated effect would stop. That's why we use "repeat" while setting the background image for the DIV. This would repeat the background image even when we cross the image height/width limit. However, we have put a check in our JS logic that when during scrolling the background image, if any x-position or y-position values are crossing their limit, they are reset to 0.

The Javascript works the following way ::
a. When a button is clicked, we call use-defined scroll() function with a parameter denoting the direction.
b. scroll() function sets a timer so that scr_oll() function is called every 50 milliseconds.
c. The scr_oll() also takes the direction value as a parameter. This function reads the existing background-position style attribute (initially '0px 0px' or '0% 0%') from the DIV. It then clears the 'px' or '%' characters from that value, extracts correct x-pos and y-pos values, then does some maths to set a new value to that background-position style attribute of the DIV. We also check if the x-pos/y-pos values remain within range;

Check the implementation below.

<html>
<head>
<script>
var max_bottom = 300; // Image height of digits.jpg
var max_right  = 599; // Image width of digits.jpg
var timer = '';       // For timer

function scroll(dir)
{
  // Clear any Old Interval if exists
  clearInterval( timer );
  // Set new Interval
  timer = setInterval( function () { scr_oll(dir); }, 50 );
}

// Main function which scrolls the background image
function scr_oll(dir )
{

 // GEt existing background-position
 var backp_css = document.getElementById("scrollDiv").style.backgroundPosition;

 // Remove spl chars
 backp_css = backp_css.replace(/%/g,'');
 backp_css = backp_css.replace(/px/g,'');

 // Split to get xpos and ypos values
 var arr = backp_css.split(" ");

 // Scrolling from top to bottom
 if(dir == 1)
 {
   // For top-to-bottom scroll, we would
   // incerase the ypos value by 1
   var ypos = parseInt(arr[1]) + 1;
  
   // If crossing the maximum, reset
   if( ypos > max_bottom ) ypos = 0;
  
   // Build the final CSS string
   var css_str = arr[0] + 'px ' + ypos + 'px';
 }

 // Scrolling from bottom to top
 if(dir == 3)
 {
   // For bottom-to-top scroll, we would
   // decerase the ypos value by 1
   var ypos = parseInt(arr[1]) - 1;
  
   // If crossing the minimum low, reset
   if( ypos < 0 ) ypos = max_bottom;
  
   // Build the final CSS string
   var css_str = arr[0] + 'px ' + ypos + 'px';
 }

 // Scrolling from right to left
 if(dir == 2)
 {
   // For right-to-left scroll, we would
   // decerase the xpos value by 1
   var xpos = parseInt(arr[0]) - 1;
  
   // If crossing the minimum low, reset
   if( xpos < 0 ) xpos = max_right;
  
   // Build the final CSS string
   var css_str = xpos + 'px ' + arr[1] + 'px';
 }

 // Scrolling from left to right
 if(dir == 4)
 {
   // For left-to-right scroll, we would
   // incerase the xpos value by 1
   var xpos = parseInt(arr[0]) + 1;
  
   // If crossing the minimum low, reset
   if( xpos > max_right ) xpos = 0;
  
   // Build the final CSS string
   var css_str = xpos + 'px ' + arr[1] + 'px';
 }

 // Set new background-position
 document.getElementById("scrollDiv").style.backgroundPosition = css_str;
}
</script>
</head>

<body>



<!-- We set the background Image to the DIV -->
<div id='scrollDiv' style="background:url('digits.jpg');height:250px;width:300px;border:0px solid tomato">
 <img src='php.png' style='display:block'>
</div>

<!-- Direction Buttons -->
<input type='button' value='<' title='Left' onclick='scroll(2)'>
<input type='button' value='>' title='Right' onclick='scroll(4)'>
<input type='button' value='˄' title='Top' onclick='scroll(3)'>
<input type='button' value='˅' title='Bottom' onclick='scroll(1)'>

</body>
</html>


Copy-paste the above code and supply the images used, this would run on all browsers.

The scroll() function clears any previous timer set, by calling clearInterval() function. It is necessary otherwise n number of timer might get created and force the browser to execute all of them at the same interval.

Tuesday, May 14, 2013

File and Folder Iterator in PHP


Problem  : We want to show all files and folders in the curent folder including subdirectories and their content.
Solution : We would be solving this issue using 3 methods as listed below.

a. Using Directories extension
b. Glob method
c. RecursiveDirectoryIterator method

a. The "Directory" extension consists of various useful functions like opendir(), readdir(), closedir(), scandir() etc. Let's use them.

We have a directory stucture as shown in the picture. We would be traversing through each folder recursively and get their respective contents and show them on screen.



Before we fully develop the full solution, here let's write a small program for showing content of current folder. Check the code below.

<?php
print_r( scandir("dir1",0) );
?>


Scandir simply shows all files and folder listings inside the specified path. The output is ..

Array
(
    [0] => .
    [1] => ..
    [2] => 1a.txt
    [3] => 1b.txt
    [4] => dir2
)

The output quite matches the output of DOS "dir" command where single dot "." means current folder and two dots ".." refer to parent folder. The second argument is given for sorting order.. 0 is for ascending order while 1 is for descending order. The folder "dir2" resides inside "dir1" folder and we can get inside "dir2" by implementing one recursive algorithm as shown below...

<?php
// Define a folder to scan
$root_folder = "dir1";

// Call the function for folder browsing
browse_folder( $root_folder );

// Function Definition
function browse_folder( $root_folder )
{
  // Scan the specified path
  $tree = scandir( $root_folder ,  0 );

  // Print Current folder Tree
  echo "<br> Showing content of $root_folder ::<br>";
  print_r($tree);

  // Check if any subfolder exists
  // Ignoring 0th and 1st index
  for($i=2;$i<count($tree);$i++)
  {
    // Check each item using is_dir() for sub-folder checking
    if( is_dir( $root_folder . "/" . $tree[$i] ) )
    {
       // Get into that sub-folder and show content
       // Notice, that this is a recursive call
       browse_folder( $root_folder . "/" . $tree[$i] );
    }
  }

}
?>


The above code traverses all subfolders of specified path and displays all contents inside. If any subfolder is found, then that folder is also browsed and its contents are displayed. We use a recursive call here. All the folders' real path has to be provided to the browse_folder function. That's why we had to use a "/" in the function call ::

browse_folder( $root_folder . "/" . $tree[$i] );

which actually builds the corect path to any subfolder found with respect to the current working directory which in my case is "htdocs". To get your current working directory, write this:

<?php
echo getcwd();
// In my case, it shows C:\xampp\htdocs

// change the current folder to something else
chdir("dir1/dir2");

echo getcwd();
// In my case, it shows C:\xampp\htdocs\dir1\dir2
?>


Another function in Diectories extension is "dir()" which opens a directory and then through read() method we iterate through each item inside.

<?php
// Define a folder to scan
$root_folder = "dir1";

// Open a directory
$fp = dir( $root_folder );

// List files in it
while ( ($file = $fp->read()) !== false)
{
  echo "File: " . $file . "";
  echo is_dir( $root_folder . "/" . $file) ? "[dir]" : "[file]" ;
  echo "<br/>";
}

// Close the directory
$fp->close();
?>


The dir() method creates an instance of Directory class with two member variable namely "path" and "handle". The above code would generate a list of all file and folders inside the directory specified.

Let's solve this folder browsing problem once again using opendir() and readdir() methods. Check the code below.

<?php
// Define a folder to scan
$root_folder = "dir1";

// Call the function for folder browsing
browse_folder( $root_folder );

// Function Definition
function browse_folder( $root_folder )
{
   // Check if it a dir
   if( is_dir( $root_folder ) )
   {
     // TRY to open a handle for the dir
     $fp = opendir($root_folder);
    
     // dir opening problem may occur due to file
     // pemission or other file system error
     if($fp !== false )
     {
        echo "<br> Showing content of [$root_folder] ....";
       
        // Read next entry from directory handle
        // in the order in which they are stored
        // in the fileSystem
       while ( ($file = readdir($fp))  !== false)
       {
         // File or Folder with Relative Path

         $fi_le = $root_folder . "/" . $file ;

         // Display file/folder name etc
         echo "<br> filename: [$file], filetype: [" . filetype(
$fi_le ) . "]" ;
   
         // If it is a Sub folder, then again get inside it
        if( $file!= "."  && $file!=".." )
        {
         if( filetype(
$fi_le ) == "dir" )
         {
           // Make the recursive call
           browse_folder(
$fi_le );
         }
        }
       } // While closes
      } // If closes

     // Close the directory Handle
     closedir($fp);
   }
}
?>


The above code would beautifully display all your folder contents. Check the output below :



Couple of points to be noted here ..
i. opendir() should be accompanied by a respective closedir() method which closes the directory handle opened by opendir()
ii. We use filetype() function which returns "dir"/"file" if the supplied item is a "directory"/"file" respectively.
iii. We ignored the "." and ".." folders
iv. readdir() function reads next item within the specified directory and retuns "FALSE" if anything goes wrong. In my case, files are displayed ahead of folders which is why I could avoid the pain in displaying the contents. Say, if readdir() reads a folder content as shown below...

file1.txt [file]
file2.txt [file]
folder1   [dir]
file3.txt [file]
folder2   [dir]
file4.txt [file]


In this case the above code would first print "file1.txt" and "file2.txt" and then it recursively calls the browse_folder() function to show contents of "folder1", then again "file3.txt" would be displayed and next contents of "folder2" would be displayed and so on... This way the output may become totally unordered. This problem may arise because we are using a single loop for displaying items and browsing sub-folders. However this problem can always be overcome by the following logic.. Just using two separate loops for displaying and subfolder-browsing.

i) Display all contents of current folder using readdir() in a loop
ii) Rewind the directory handle by using rewinddir($fp) statement
iii) Again start a loop using readdir() to see if any folder is sub-folder. If a sub-folder is found, then call the browse_folder() method

Glob method is discussed in article Using Glob in PHP

DirectoryIterator methods are discussed in article DirectoryIterator in PHP

HTML Select element manipulation using jQuery - II

We have already discussed a few points on Select element manipulation with jQuery in my previous article, here we would be discussing few more points.

Check the HTML below, it contains the select element which we would be working upon.

<select id='selectBox1' name='select' size='10' multiple='multiple'>
 <option value='apr'> Aprilia </option>
 <option value='duc'> Ducati </option>
 <option value='hro'> Hero </option>
 <option value='hnd'> Honda </option>
 <option value='hyo'> Hyosung </option>
 <option value='kwk'> Kawasaki </option>
 <option value='suz'> Suzuki </option>   
 <option value='yam'> Yamaha </option>
</select>


6. Remove a single option from the list

If we want to remove the " Aprilia " from the list, we can take following steps...

i. Iterate through the loop options
ii. If option's text matches with text, then we remove it.

Check the jquery implementation..

<script>
// Use each() function
j("$selectBox1 option").each(

// Callback function for each()
function()
{
 
  /// Option Text is being matched here
  if( j(this).text() == " Aprilia " )
   {
      // Remove the Option
      j( this ).remove();

      // Break;  -- WE can't write a BREAK here
      // Hence each() function will iterate till
      // the last option in th list even if
      // an option is found and deleted.
   }

} // CallBack ends

); // each() ends
</script>


However, we can use a different selector to select an option directly and remove it.

<script>
// Remove the second child from the top
j("#selectBox1 option:nth-child(2)").remove();

// Get total count of all the options
alert ( j("#selectBox1 option").length );
</script>


As discussed earlier, children indexes start from 1 for nth-child selector.

Suppose, we need to delete option " Suzuki " immediately before the last option " Yamaha ". We can use another approach other than the option text matching method discussed above. Check the code below.

<script>
// Get total count
var l = j("#selectBox1 option").length;

// We need to remove the item immediately before index l
l = l-1;

// Build the selector
var str = "#selectBox1 option:nth-child(" + l + ")" ;

// Now remove the item
j(str).remove();

</script>


For a long list with 20000/30000 options, we can surely use the above method.

Here is another approach which is much easier in case we want to delete items/options closer to last item or first item.

<script>
// Get the previous item to the last item
j("#selectBox1 option:last").prev().remove();

// Or we can refer to as many previous items as we wish
j("#selectBox1 option:last").prev().prev().prev().prev().remove();
</script>


7. Remove all/multiple options from the list
To remove all options from a listbox, we can write the following statement...

<script>
// Remove all options at one go
j("#selectBox1 option").empty();
</script>


But the above statement clears all the option texts, the option elements still exist with their respective values. This happens because we have used a wrong selector. "#selectBox1 option" means we referring to all options under "#selectBox1" select element and clearing each of them. And as a result, all option elements are cleared off their texts. The right syntax would be :

<script>
// Remove all options at one go
j("#selectBox1").empty();
</script>


To remove all selected options from a list box, we need to write the following jQuery...

<script>
// Remove all Selected options at one go
j("#selectBox1 option:selected").remove();
</script>


The selector "option:selected" refers to all options in the list which are selected. Another longer approach..

<script>
j("#selectBox1 option:selected").each( function(){ j(this).remove();} );
</script>


Here, we are iterating each selected item with each function... and then delete item.

See, how easier it is to do with jQuery. It would have been much difficult to achieve the same thing as discussed in article HTML Select element manipulation using Javascript - II.

8. Edit any option at any position within the list

Suppose, we want to edit the first option " Aprilia " and change it to "BMW", we can use the jQuery text() and val() functions for achieving this.

<script>
j("#selectBox1 option:first").text(" BMW ").val("bmw");
</script>

The selector "option:first" refes to the first item in the list, the text() function changes its content text while the val() function changes its value. More complex statment can be built like ..

<script>


// refer to 3rd option, then 2 prev() call would
// get us to the fist option itself.
j("#selectBox1 option:nth-child(3)").prev().prev().text(" BMW ").val("bmw");
 

</script>

9. Create a copy of the select element and append it to the body

With jQuery, solving complex tasks like this becomes very easier. Check the following code...

<script>
// Create a clone of existing select element
var p = j("#selectBox1").clone();

// Now append it to document body
// document.body is Native JS
j( p ).appendTo( document.body );

// Now try to append again
// j(document.body) is jQuery
// But this does not seem to work
// Same node can not be inserted again
j( p ).appendTo( j(document.body) );

// Workaround ?? Try this ...
j( j(p).clone() ).appendTo( j(document.body) ); // It works

</script>


An node/element, after its creation, can be inserted to the HTML DOM only once. Further insertion statements does not successfully insert new node.

The above code, clones a select element and inserts into HTML DOM but it creates multiple select element with same ID. Hence we must change newly created element's ID to something else as shown in the example below.

<script>
// Create a clone of existing select element
var p = j("#selectBox1").clone();

// Now set its ID property
j( p ).attr('id','selectBox2');

// Append to an existing form with ID 'frm'
j( p ).appendTo( j( "#frm" ) );

// Create another ANother
j( j(p).clone().attr("id","selectBox4") ).appendTo( j("#frm") );
</script>


Notice, we are adding the "id" attribute to a cloned node and then appending it to an existing form on the document body.

10. Sorting all options in a Select element

We had to do huge stuffs while achieving this with Javascript. With jQuery, we have to follow similar steps but we would write lesser statements. Check out the code below..

<script>
// Create an array of all option nodes
var p = j("#selectBox1 option");

// Sort the array of nodes according to
// their TEXT content
p.sort(function(a,b) {
    if (a.text > b.text) return 1;
    else if (a.text < b.text) return -1;
    else return 0
})

// Now clear the Select element
j("#selectBox1").empty();

// Re-build all options into the Select element
j("#selectBox1").append( p );

</script>


Check the previous part Here.

For having filtering options on a select element, visit this. It has some really great example of a jQuery filtering plugin usage.


11. Selecting/Unselecting all options in a Select element

This is achievable when it is a Multi-select Selectbox element. To do this, we need to assign selected='selected' to each option within the select element. Check the code below.

// Select All Options
jQuery("#selectBox1 option").each(
   function()
   {
     // Add Attribute
     jQuery(this).attr('selected','selected');
   });

// Un-Select All Options
jQuery("#selectBox1 option").each(
   function()
   {
     // Add Attribute
     jQuery(this).removeAttr('selected');
   });

Monday, May 13, 2013

HTML Select element manipulation using jQuery - I

We have already discussed select element manipulation with javascript, here we would be solving similar problems using very popular Javascript Framework called jQuery. Using jQuery minimizes the cross-browser conflicts, saves lot of time as we don't have to write long native Javascript statements. jQuery statements are a bit complex, but very compact which means a few lines of jQuery may take the workload of hundred lines of Javascript.

Check the HTML below, it contains the select element which we would be working upon.

<select id='selectBox1' name='select'>
 <option value='apr'> Aprilia </option>
 <option value='duc'> Ducati </option>
 <option value='hro'> Hero </option>
 <option value='hnd'> Honda </option>
 <option value='hyo'> Hyosung </option>
 <option value='kwk'> Kawasaki </option>
 <option value='suz'> Suzuki </option>   
 <option value='yam'> Yamaha </option>
</select>


1. List All options and their values

<!-- LOAD JQUERY LIBRARY -->
<script src="http://ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min.js"></script>

<script type='text/javascript'>
var j = jQuery.noConflict(); // Avoid Collisions among Libraries

// Define a string
var str="";

// Iterate and Fetch each options and their values
j("#selectBox1 option").each(function(){

  str += j(this).val() + ":" + j(this).text() + "\n";

});

// ALERT
alert(str);
</script>


The code above is much easier to remember and write. j("#selectBox1 option") means we are referring to all option elements contained by the element with ID 'selectBox1'. To access each of the options, we use jQuery each() function which takes a callback function means when jQuery access a single option element it would execute the callback function's contents. val() function returns the option value and text() function returns option text.

To access a paticular option whose value (say, 'suz') is known to us, we can use the following jQuery ...

alert( j("#selectBox1 option[value='suz']").text(); ); 

// Would return " Suzuki "

The equivalent Javascript would be ::

alert( document
.querySelectorAll("#selectBox1 option[value='suz']") .item(0).innerText ) ;

The above statement uses "innerText" would run perfectly on IE8 onwards. To get it run on other browsers, 'innerHTML' or 'textContent' can be used. Because of such browser compatibility issues, developers prefer jQuery to native Javascript.

2. Show selected option's text and value

It is just a one line code..

<script>
alert( j("#selectBox1 option:selected").val() + ":" + j("#selectBox1 option:selected").text() );
</script>

If the select element was a listbox with multiple option selection capability, the we need to give little more effort to get all the selected item's text and value. Check the example below ..

<select id='selectBox1' name='select' multiple='multiple' size='10'>
 <option value='apr'> Aprilia </option>
 <option value='duc'> Ducati </option>
 <option value='hro' selected='selected'> Hero </option>
 <option value='hnd'> Honda </option>
 <option value='hyo'> Hyosung </option>
 <option value='kwk' selected='selected'> Kawasaki </option>
 <option value='suz' selected='selected'> Suzuki </option>   
 <option value='yam'> Yamaha </option>
</select>


Check that " Hero ", " Kawasaki " and " Suzuki " options are selected. Now the jQuery would be like this ::

<script>
// Define a string
var str="";

// Iterate and Fetch each of selected options & their values
j("#selectBox1 option:selected").each(function(){

  str += j(this).val() + ":" + j(this).text() + "\n";

});
// ALERT
alert(str);
</script>


The above code alerts the message as per our expectation... all selected option text and their values are shown.

3. Append new options at the end of the list

A single jQuery statement is sufficient to do this. Check this out..

<script>

j("<option value='bmw'> BMW </option>").appendTo("#selectBox1");

</script>


A new HTML is being referred to when we say j("<option value='bmw'>BMW</option>") which is then appended to the element with ID "selectBox1" using the appendTo() function. We can write the same thing using "append()" function as shown below ..

<script>

j("#selectBox1").append("<option value='bmw'> BMW </option>");

</script>


If the select element does not have any options in the beginning, we can create new options using the above methods. Needless to say that this would work on all browsers including IE7 and IE8.

4. Add a new options at the top of the list

Similarly We can use the "prepend()" and "prependTo()" functions to insert new options at the beginning of the option list.

<script>

// USE prepend() function
j("#selectBox1").prepend("<option value='bmw'> BMW </option>"); 

// USE prependTo() function
j("<option value='bmw'> BMW </option>").prependTo("#selectBox1");

</script>


5. Add new options at any position of the list

Suppose, in a case where we need to insert a new option "BMW" after first option "Aprilia", we can write the following code...

<script>
// Get the option containing "Aprilia"
var t = j("#selectBox1").find("option:contains('Aprilia')");

// Now insert new option after it
j(t).after("<option val='bmw'> BMW </option>");

// Insert the option before it
j(t).before("<option val='bmw'> BMW </option>");
</script>


The node t should be converted to jQuery node by wrapping a j() around it.

Options can be accessed through its index also as we did with Javascript in the other article. It is shown below..

<script>
// This would return Aprilia option's text ( First Child )
var opt = j("#selectBox1 option:nth-child(1)").text(); 
</script>


We use nth-child selector and children indexes start with 1 instead of 0. The first and last child can be accessed using ":first" and ":last" selectors respectively.

<script>
// This would return first option "Aprilia"
var optf = j("#selectBox1 option:first"); 

// This would return last option "Yamaha"
var optl = j("#selectBox1 option:last");  

// Insert a new Node before the first option "Aprilia"
j( optf ). before ("<option value='peu'>Peugeot</option>");

// Insert a new Node after the last option "Yamaha"
j( optl ). after ("<option value='lml'>LML</option>");

// Insert a new node before 2 nodes to last option "Yamaha"
j( optl ). prev() . prev() . before ("<option value='nrt'>Norton</option>");

// Insert a new node 2 nodes down to first option "Aprilia"
j( optf ). next() . next() . before ("<option value='mtt'>MTT</option>");

</script>


All the above codes should run on all browsers. Check the part II of this article here. Check  Implementation in native Javascript of above problems here.

Friday, May 10, 2013

Submit select element with multiple options selected

We have seen select element with multiple options selected in previous arrticle. Here I would discuss what happens when we try to submit  a form with a selectBox having multiple options selected. Check out the form below.

Check the HTML below :

<body>
Which Bike Models you like?
<form name='f' method='POST'>
<table border='0'>
 <tr>
  <td>
    <select id='selectBox1' size='10' multiple='multiple' style='width:100px' name='select'>
    <option value='apr'> Aprilia </option>
    <option value='duc'> Ducati </option>
    <option value='hro'> Hero </option>
    <option value='hnd'> Honda </option>
    <option value='hyo'> Hyosung </option>
    <option value='kwk'> Kawasaki </option>
    <option value='suz'> Suzuki </option>   
    <option value='yam'> Yamaha </option>
    </select>
    <br>
    <input type='submit' value='submit'>
  </td>
 </tr>
</table>
</form>
</body>


Notice that the select element has a name 'select' and the form's method is 'post'. Now when we try to submit this, we get only a single value at the PHP server end. The $_POST/$_REQUEST array would look like this :

Array
(
    [select] => suz
)


Even if we try to change the form's action method to 'GET', situation hardly improves. The URL of the page would be appended with '?select=hnd&select=suz' and $_REQUEST would still get only the last value 'suz' ignoring all other submitted values.

To get rid of this, we just need to use an array-like name for the select element.

<select id='selectBox1' size='10' multiple='multiple' style='width:100px' name='select[]'>

By using this, we would get all selected options in an array form at the PHP's end. Now the $_POST/$_REQUEST would look like this :

Array
(
    [select] => Array
        (
            [0] => hro
            [1] => suz
        )

)


Even if we change the form's action method to 'GET', the URL is appended with '?select[]=hnd&select[]=suz' but the $_REQUEST/$_GET still shows the above structure which proves that it gets all values in an array format. Now it becomes very convenient to run a loop and iterate through the array item and work on them.

Render/Highlight PHP code on browser

To render any PHP file [the code itself] on screen we can use highlight_string() function. Check the following example.

<?php
highlight_string("
 <?php
  \$sal = 10000;
  echo 'Hello';
  echo 'Salary is ' . \$sal;
 ?>
");
?>

 

The function takes a string ( PHP code ) as its argument. It uses the in-built syntax highlighter and adds necessary wrapper tags around PHP keywords and then echoes on screen. The above code renders the following output ::



Notice all the special characters need to be escaped. For example if we use
<?php
highlight_string("
<?php
 $sal = 10000;
?>

");
?>

PHP would look for a variable called $sal during variable expansion  which is not defined earlier. Hence it may generate an error.

We can load a whole PHP file and render the whole code on screen with the highlight_file() function. Check the example below.

<?php
highlight_file("index.php");
?>


And here is the output. It is showing the whole code of "index.php" within "htdocs" folder of my Xampp installation. 




An URL can be passed as argument with the highlight_file() function as shown in the below example.

<?php
highlight_file("http://localhost/index.php");
?>


But you can't see the PHP coding in this case as the PHP file in the URL is first executed and then resultant HTML is shown on screen. This is obvious as otherwise server-side codes can be easily exposed to unauthorized users.

To use http URLs with highlight_file() function, "allow_url_include" must be set to "on" in php.ini configuration file.

However, HTMLs and JavaScripts are not highlighted.

Tuesday, May 07, 2013

IE Error :: IE has stopped working - Fix

This is a very annoying expeience I had recently with IE 9 on Windows 7. And when this error occurs, the messagebox, asking to restart the program or search for a solution, keeps on appearing even if I close the messagebox. When I try to close the messagebox, the page is reloaded and again after some time, the messagebox is shown which asks either to restart the program or search a solution for it on Internet. IE simply becomes unusable as a result.

The followings are the solutions to it. If any one of them does not solve the issue, try all of them.

1. Visit Microsoft Community Site :: Go Here and do as suggested on this Microsoft Community site.

2. Disable Protected Mode :: RUN IE, goto "Tools > Internet Options > Security Tab". Disable the "Enable Protected Mode" checkbox option.

3. Run IE Without Extensions :: From WIn7 start menu, goto "All Programs > Accssories > System Tools > Internet Explorer (No Add-ons)" .. which runs the IE with all the browser extensions disabled. This is done to see if any loaded plugins conflict with IE.

4. Reset IE :: RUN IE, goto goto "Tools > Internet Options > Advanced Tab". At the bottom, there is a "Reset" button, click it to Reset IE.

5. Disable GPU Rendering :: RUN IE, goto goto "Tools > Internet Options > Advanced Tab". Notice the very fist checkbox option saying
   "Use software rendering instead of GPU rendering" ... check it.


I hope the above solutions would definitely help people to get rid of this annoying error on IE.

Copy/Move options from one Select element to another


The above picture tells the problem we are going to solve now. It is two select elements with 4 buttons. The functions of all the buttons are described below.

1. First button moves multiple selected options from left to right select element
2. Second button moves all options from left to right select element
3. Third button moves multiple selected options from right to left select element
4. Fourth button moves all options from right to left select element

We would use the same techniques which were discussed in my previous posts. We would write some functions against the "click" events of those buttons. Now check out the HTML below..

<table border='0'>
 <tr>
  <td>
    <select id='selectBox1' size='10' multiple='multiple' style='width:100px'>
   <option value='apr'> Aprilia </option>
    <option value='duc'> Ducati </option>
    <option value='hro'> Hero </option>
    <option value='hnd'> Honda </option>
    <option value='hyo'> Hyosung </option>
    <option value='kwk'> Kawasaki </option>
    <option value='suz'> Suzuki </option>   
    <option value='yam'> Yamaha </option>

    </select>
  </td>
  <td valign='middle'>
    <!-- FOUR BUTTONS -->
    <input type='button' onclick="move_selected('selectBox1','selectBox2')" value='>' style='width:30px'> <br />
     <input type='button' onclick="move_all('selectBox1','selectBox2')" value='>>' style='width:30px'> <br />
     <input type='button' onclick="move_selected('selectBox2','selectBox1')" value='<' style='width:30px'> <br />
     <input type='button' onclick="move_all('selectBox2','selectBox1')" value='<<' style='width:30px'> <br />

  </td>
  <td>
    <select id='selectBox2' size='10' multiple='multiple' style='width:100px'>
   
    </select>
  </td>
 </tr>
</table>


The select elements are having IDs 'selectBox1' and 'selectBox2'. We call two user-defined functions namely "move_selected" and "move_all". The "move_selected" function takes two parameters, source and target select elements. The second function works with same parameters. We have kept the second select element empty.

Moving selected options from one select element to another would involve following steps ..

a. Copy all selected options from source element to an array
b. Also copy index of items which has been selected and would be deleted after move
c. Next, create options for the target element from the array
d. Delete the moved items from source elements
e. Sort the Target element to keep it neat [Optional]

Moving all items from one to another involves following steps ..

a. Copy all options from source element to target directly
b. Delete the moved items from source elements
c. Sort the Target element to keep it neat [Optional]

Now check out the Javascript functions below which are quite self-explanatory.

<script type="text/javascript">

// Move Selected Items from one to other SelectBox
function move_selected( from, to )
{
  // Get the Select Elements
  var s = document.getElementById(from);
  var t = document.getElementById(to);
 
  // Put the selected elements in an array
  var opt = [];
  var to_be_deleted = [];
  var j = 0;
  var i = 0;
  for( i=0;i<s.options.length;i++)
  { 
    if( s.options[i].selected == true )
    {
      // Copy Value+TEXT for moving
      opt[ s.options[i].value ]  =  s.options[i].text;
     
      // Store the Index, for Deletion
      to_be_deleted[j] = i;
      j++;
    }
  }
 
  // Delete the selected Option from Source select element
  for( i=0;i<to_be_deleted.length;i++)
   s.options.remove( to_be_deleted[i] );
  
  // Iterate thorough all Saved option Value+Text
  // and Insert Into the Target Select element
  for( var key in opt )
  {
    // Create new Option
    var no = new Option( opt[key], key );
   
    // Insert
    t.options[ t.options.length ] = no;
  }
 
  // SORT the Target Select Element
  select_elem_sort(to);
}


// Move ALL Items from one to other SelectBox
function move_all( from, to )
{
  // Get the Select Elements
  var s = document.getElementById(from);
  var t = document.getElementById(to);
 
  // ITERATE Source Element's Option List
  var i = 0;
  for( i=0;i<s.options.length;i++)
  { 
      // Create new Option
      var no = new Option( s.options[i].text, s.options[i].value );
   
      // Insert
      t.options[ t.options.length ] = no;
  }
 
  // Delete All options from source Element
  s.options.length = 0;
 
  // SORT the Target Select Element
  select_elem_sort(to);
}

// This is for sorting the Option List
function select_elem_sort(t)
{
   
    // Get the TARGET Select element
    var s = document.getElementById(t);
   
    // Iterate through its options and create
    // a reference array with option VALUE:TEXT
    var opt_reference = [];
    var opt_text_arry = [];

    // Our copying starts from Index 0
    for( var i=0; i<s.options.length; i++)
    {
       // Store Option value and text to reference array
       opt_reference [ s.options[i].value ] = s.options[i].text ;
     
       // Store only the TEXT to the second array for sorting
       opt_text_arry[i] = s.options[i].text;
    }

    // Sort the Array Ascending
    opt_text_arry.sort( function(a, b) {
        if(a>b) return 1;
        if(a<b) return -1;
        return 0;
    } );

    var i=0;
    /// Iterate the array and Re-create options
    for(i=0; i<opt_text_arry.length; i++ )
    {
      var option_text = opt_text_arry[i];
   
      /// FETCH the corresponding option value
      /// against the option text
      var option_val = "";
      for( var key in opt_reference)
      {
         // Option Text matched
         if( opt_reference[key] == option_text )
         {
           option_val = key;
           break;
         }
      
      }

      // Create the new Option
      var opt = new Option( option_text, option_val);
   
      // Put the new option in the Options Array
      // of Select element. We are re-creating
      // new options from index 0 onwards
      s.options[i] = opt;
    }
}
</script>


The above code runs fine on all browsers including IE7 and IE8. 


You can find some more discussions on HTML Select element here