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

HTML Select element manipulation using Javascript - II


The rest of the 5 points are being discussed below. Check out the previous part here.

6. Remove a single option from the list

Removing single option from a select element is very simple. Check the code below.

<script>
// Get the Select element
var p = document.getElementById("selectBox");

// Delete zeroth option
p.remove(0);
</script>


In the above code, zeroth option item was deleted. And as a result, all the items are moved to 1 place lower than previous position i.e the item at 1st position is now placed at 0th position and so on. The "length" property of the option list also decreased by 1.

Check another example below.





In this case, an item needs to be selected in order to delete it from the drop-down. So, we need to write the following code which will be executed on "click" event of the button.

<script>
function remove_selected_option()
{
  // Get the Select element
  var p = document.getElementById("selectBox");
 
  // Get Selected Item
  var sel = p.options.selectedIndex;
 
  // Delete that item
  p.options.remove( sel );
}
</script>


The above code would run all browsers including IE 7 and 8.

7. Remove all/multiple options from the list

To make a select element look like a list, we need to add a property called "size". If we want to enable multiple selection, we need to include the property "multiple" as shown below.

<select id='selectBox' name='selectBox'  size='10' multiple='multiple'>
 



Now, if we want to delete all options at once, then we can write the following Javascript :

<script>
  // Get the Select element
  var p = document.getElementById("selectBox");

  // Delete All Options
  p.options.length = 0;
</script>


Deleting multiple options would require some complex logic. To delete, we would use the following statement..

elementName.options.remove( OptionIndex );

Now, suppose we want to delete option index 0,1,2,3 and 4. If we simply use a for() loop and start deleting, problem would occur after the first option [0 index] deletion. The options list works quite like an array, hence when one item is deleted, all items are shifted to one position lower. So, the option with index 1 gets shifted to 0th position [index 0] after the 0th option is deleted. Hence if we delete next option with index 1, we would be removing the wrong items because option with previous index 2 is now having index 1.

So, we need to implement some other logic as described below.

i. Loop through all the options, and put all the selected items into an array
ii. Now iterate through that array of selected items, for each item of it, search the select element and remove the matched option.

The above logic is implemented below..

<script>
  // Get the Select element
  var p = document.getElementById("selectBox");

  // Put all selected options into an associative array or object
  var arr = [];
  for( var i=0; i<p.options.length; i++)
  {
    if( p.options[i].selected == true )
    {
      arr[p.options[i].value] = p.options[i].text;
    }
  }
 
  // Now Iterate the Array
  for( var key in arr )
  {
     /// Check each item in select Element
     for( var i=0;i<p.options.length; i++)
     {
        // Matching for both VALUE and TEXT property
    if( p.options[i].value == key && p.options[i].text == arr[key] )
    {
        // Remove the Item
        p.options.remove( i );
          
        // BREAK -- This is IMPORTANT
        // because p.options.length is already decreased by 1
        // as a result of the option deletion
        // But the LOOP does not know this.
        break;
    }

     }

  }

</script>


The above code runs perfectly on all browser including IE7 and IE8.

The "break" statement in the inner loop is absolutely necessary in order to run the code without any error. When any option element is deleted, the length property (p.options.length) would show a value one less than its previous value. But the loop is set to iterate till the old value of this length property. Hence the loop might look for items with indexes fall beyond the existing range. Error would occur in such cases.

8. Edit any option at any position within the list

Editing any existing option within the Options list is very easy. We just create a new option object and assign it to the existing options array as shown in the example below.

<script>
// Get the Select element
var p = document.getElementById("selectBox");

// Create new Option element
var opt = document.createElement("option");

// Set properties
opt.text  = "BMW";
opt.value = "bmw";

// Position of Old Option to be replaced
var i = 3;

// REPLACE it into Options array
p.options[i] =  opt ;
</script>


The above code is quite self-explanatory and it would replace an existing option with new one.

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

The usage of this would be minimal in web development context, but this would let us learn some more javascript. To achieve this, we would follow the following logic ::

 a. Create second "select" element
 b. Iterate though first "select" element
 c. Copy all options to second "select" element
 d. Append the second "select" element to HTML body

Now check the implementation below ::

<script>

// Get the First Select element
var s = document.getElementById("selectBox");

// Create the second "Select" element
var t = document.createElement("select");

// Iterate through options of first select element
for( var i=0; i<s.options.length; i++)
{
   // Create New Option
   var opt = document.createElement("option");

   // Set Option Properties
   opt.value = s.options[i].value;
   opt.text  = s.options[i].text;

   // Add the new option to 2nd "Select" element
   t.options.add( opt );

   // t.appendChild( opt );  -- WORKS TOO --
}

// Second element is ready
// Now append it to the HTML body
document.body.appendChild(t);

</script>


The above code runs perfectly on Firefox and Chrome. Check the statements ::

t.options.add( opt );  // Adds new Option
t.appendChild( opt );  // Does Same


We have used the first one, while the second one can be used too.

IE causes problems while creating new dynamic options. To get rid of that, we write the above code as shown below ::

<script>

// Get the First Select element
var s = document.getElementById("selectBox");

// Create the second "Select" element
var t = document.createElement("select");

// Iterate through options of first select element
for( var i=0; i<s.options.length; i++)
{
// Create New Option
var opt = new Option( s.options[i].text , s.options[i].value ) ;
  
// Add the new option to 2nd "Select" element
t.options.add( opt );
}

// Second element is ready
// Now append it to the HTML body
document.body.appendChild(t);

</script>


This version runs on all browser smoothly creating a second "select" element.

10. Sorting all options in a Select element

There is no direct method like "sort" to sort all the options in a Select element. However we can follow the following logic to sort a given select element.

a. Copy all the option to another array
b. Sort the array
c. Now iterate the array the recreate options in the Select element.

If the option value and text are same, then we don't have much trouble, the above logic work perfectly. However if they are different, the task becomes heavier. Check out the new logic ::

a. Copy all option value:text combination to an associative array [Object] for future reference
b. Copy all option TEXT to an array.
c. Sort the array
d. Iterate the array
   i. For each value (Option Text) in the array, find a corresponding option VALUE in reference array created in step 1
   ii. For each value, re-create new options in the "Select" element.

Now check the Javascript implementation below.

<script>
// Get the First Select element
var s = document.getElementById("selectBox");

// Iterate through options of first select element
// and create a reference array with option VALUE:TEXT
var opt_reference = [];
var opt_text_arry = [];

// We are not sorting the option "Select a Bike Model"
// Hence, our copying starts from Index 1 below
for( var i=1; 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-1] = 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;
} );


/// 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 1 onwards, hence i+1
  // is used in the statement below
  s.options[i+1] = opt;
}
</script>


The above code is quite self-explanatory. This sorts the whole option list leaving the first option "Select a Bike Model" intact. Try it yourself. The code above runs perfectly on all browsers including IE7 and IE8. The pitfalls are in the sort function. If you use the callback function with sort() something like this ::

opt_text_arry.sort( function(a, b) {
    if(a>b)
      return 1;
    else
      return 0;
} );


it is not going to work in IE.

11. Selecting all options in a Select element

This is possible when the select element has multple='multiple' attribute set.
To achieve this, we need to iterate through all the option elements, and add selected = 'selected' to each of them. Check the code below.

<script>
// Get the Select element
var p = document.getElementById("selectBox");

// Loop Through Options
for(var i=0; i<p.options.length; i++) 
{
    var k = p[i];
    // Set the Attribute
    k.setAttribute('selected','selected');
}
</script>

Again, to unselect all the items, we need to do just the opposite, i.e remove the selected='selected' attribute from each of these elements. So, we can change the above loop a little to get the effect. So, this time, instead of using setAttribute(), we are using removeAttribute(). Check the code below.

// Loop Through Options
for(var i=0; 
i<p.options.length; i++)
{
    var k = p[i];
    // Set the Attribute
    k.removeAttribute('selected');
}

However, there is a short-cut to the above method. When we select an element in a SelectBox, its selectedIndex property gets set to the option item's index value. So, if we set it to '-1', it will mean that no options is/are selected. However, for the case of multi-select SelectBox, all the selected option's index values are not stored in this selectedIndex property.

So, if we write the following :: 

// Get the Select element
var p = document.getElementById("selectBox");
// De-Select All options
p.options.selectedIndex = -1;

our target is achieved.