PHP and JavaScript, Pooling Your Resources (continued)

In this article, you will learn how to combine PHP and JavaScript to create two SELECT menus, one containing categories, and the other containing only those options applicable to the category selected.

What We’ve Learned So Far

In part one of this article we learned about PHP’s ‘header’ function, and how it can be used to send text to a browser in a variety of ways. We also learned how to attach additional PHP/JavaScript files to a web page after the page has finished loading. Using these two bits of information, we created a simple application that attached an external PHP file (rendered as a JavaScript file) each time the user clicked an anchor tag on our original page. This simple example allowed us to track and increment a PHP SESSION variable each time the link was clicked, as well as update the content of our original page depending on what value that variable contained, without ever reloading the original page.

A simple example, this application is not very useful by itself. However, our main goal was to present an easily understood model of interaction between PHP and Javascript. Now that we understand the basics, we’re ready to move on to a more practical example.

What Will Our Application Do?

We are now ready to create a more useful implementation of the tactics we discussed in part one, but what should our sample application do? There are a variety of possibilities so let’s just pick one of the more common ones.

SELECT menus are fairly common to dynamic websites. Furthermore, it is often useful for the values in one SELECT menu to depend in some way on values stored within another menu. Our example application then will create two such menus – one containing categories, and the other containing only those options applicable to the category selected. For the purposes of our example, we’ll create two categories: “Days of the Week” and “US Timezones”.

In order to continue following along you will need access to a MySQL database and a web server supporting PHP. Before beginning you will need to run the following SQL statements:

– Generate SQL Tables
CREATE TABLE `php_js_parent_menu` (
  `id` int(2) unsigned zerofill NOT NULL auto_increment,
  `name` varchar(25) NOT NULL default ”,
  `description` text NOT NULL,
  PRIMARY KEY  (`id`)
);
CREATE TABLE `php_js_child_menu` (
  `id` int(2) unsigned zerofill NOT NULL auto_increment,
  `parent_id` int(2) unsigned zerofill NOT NULL default ’00’,
  `name` varchar(25) NOT NULL default ”,
  PRIMARY KEY  (`id`), 
  KEY `parent_id` (`parent_id`)
);

– Insert main parent menu options
INSERT INTO `php_js_parent_menu` VALUES (01, ‘Days of the Week’, ‘Displays each day of the week.’);
INSERT INTO `php_js_parent_menu` VALUES (02, ‘US Timezones’, ‘Displays a list of all US Timezones.’);

– Insert child menu options
INSERT INTO `php_js_child_menu` VALUES (01, 01, ‘Sunday’);
INSERT INTO `php_js_child_menu` VALUES (02, 01, ‘Monday’);
INSERT INTO `php_js_child_menu` VALUES (03, 01, ‘Tuesday’);
INSERT INTO `php_js_child_menu` VALUES (04, 01, ‘Wednesday’);
INSERT INTO `php_js_child_menu` VALUES (05, 01, ‘Thursday’);
INSERT INTO `php_js_child_menu` VALUES (06, 01, ‘Friday’);
INSERT INTO `php_js_child_menu` VALUES (07, 01, ‘Saturday’);
INSERT INTO `php_js_child_menu` VALUES (08, 02, ‘Atlantic’);
INSERT INTO `php_js_child_menu` VALUES (09, 02, ‘Eastern’);
INSERT INTO `php_js_child_menu` VALUES (10, 02, ‘Central’);
INSERT INTO `php_js_child_menu` VALUES (11, 02, ‘Mountain’);
INSERT INTO `php_js_child_menu` VALUES (12, 02, ‘Pacific’);
INSERT INTO `php_js_child_menu` VALUES (13, 02, ‘Alaska’);
INSERT INTO `php_js_child_menu` VALUES (14, 02, ‘Hawaii’);
INSERT INTO `php_js_child_menu` VALUES (15, 02, ‘Samoa’);

The above SQL code creates two tables: one storing values for our “parent” menu, and the other holding values for our “child” menu. Now let’s take a look at the PHP and JavaScript for our project.

{mospagebreak title=Separating the Logic}

Although more complex in nature than our previous application, this example will still be relatively simple. However it is good practice to separate the various elements of our project so that the logic and the display do not get unnecessarily mixed together. To help keep things separate, we will create the following files:

index.php        This is our main display file, containing mostly HTML.

functions.php    A helper file, used to retrieve SQL information.

external.php     PHP file used to generate external Javascript code.

javascript.js    Javascript helper file, contains misc. JS functions.

stylesheet.css   Stylesheet for our document, controls visual layout.

Again, many of these files could be combined, but by separating them we are making our code easier to maintain and expand later. Let’s take a closer look now at each of the files.

What About the Javascript?

Our Javascript file, ‘javascript.js’, contains five basic functions. The first will look familiar, but we made a couple of subtle changes that may warrant explanation:

// call to external Javascript/PHP file and pass Parent ID
function update_child( p_parent_option ) {     

      // create new script element and set its relative URL
(including ID argument)
      script = document.createElement( ‘script’ );
      script.src = ‘external.php?parent_id=’ +
p_parent_option.value;     

      // attach (load) script element to document head
      document.getElementsByTagName( ‘head’ )[0].appendChild( script );
}

As you can see from its commenting, the ‘update_child’ function receives an OPTION tag as a parameter (more specifically, the OPTION tag that has just been selected by the user). It then creates a new script element as before, and attaches it to the document’s <head>. One difference in this updated version is that it also passes a URL argument along to the external JavaScript file: the currently selected OPTION’s value, (which is in this case the primary key for our ‘parent_menu’ SQL record).

The other four functions are also pretty simple, but can be very useful in terms of user interface design. As you will see shortly, our basic HTML file contains a <pre> element with the ID ‘hint_box’. This box is set to display “Ready…” by default, but will be updated when our ‘parent’ menu’s onChange event is fired. This is done in order to display helpful information to the user about our ‘parent’ SELECT menu and the information it contains. The functions we’ve written to do this are as follows:

// update hint box value
function display_hint( p_hint_text ) {
            document.getElementById( ‘hint_box’ ).innerHTML =
 ‘<strong>Status</strong>: ‘ + p_hint_text;
}

// clear interval (if one has been set) & update hint box value
using helper function
function reset_hint() {
            window.clearInterval( document.getElementById
( ‘hint_box’ ).interval );
            display_hint( ‘Ready…’ );
}

// clear interval (if one has been set) & update hint box value
using helper function
function show_hint( p_hint_text ) {
            window.clearInterval( document.getElementById
( ‘hint_box’ ).interval );
            display_hint( p_hint_text );
}

// set new interval
function set_timeout() {
            document.getElementById( ‘hint_box’ ).interval =
window.setInterval( ‘reset_hint()’, 2000 );
}

Each function is relatively simple, and probably self-explanatory with the help of the inline commenting. However, let’s take a brief look at each to make sure there is no confusion.

The ‘display_hint’ function receives as a parameter a simple string of text. It then appends to that string the text “Status: ”, and updates our ‘hint box’ to display the resulting string. This function acts as a helper for ‘reset_hint’ and ‘show_hint’, which we will now look at.

The ‘reset_hint’ function does two things. First it clears any interval that may be set for our ‘hint box’, then it updates the status text to show “Ready” using our helper function, ‘display_hint’.

The ‘show_hint’ function acts in much the same way as the ‘reset_hint’ function does. First it clears any pre-existing interval, then it updates the ‘hint box’ display value using our helper function, ‘display_hint’. The only exception is that ‘show_hint’ displays the text it receives as a parameter, instead of displaying a default value.

Lastly, the ‘set_timeout’ function simply creates an interval, and attaches it to our ‘hint box’. This interval then waits for approximately two seconds to elapse before calling the ‘reset_hint’ function to clear any rollover text and return to the default “Ready” message.

{mospagebreak title=What Does PHP Do?}

The reasons for using HTML in our project are obvious, as are the reasons for using JavaScript (hopefully) – but why do we need PHP? PHP provides us with an enormous range of programming options, one of which is an easy mechanism through which to query a MySQL database and receive a result set. This is primarily what we will be using our helper function to do. Let’s take a look now at the code:

<?php
      function get_parent_menu() {
            $select_menu      = NULL;
            # establish connection to the MySQL server
            mysql_connect( ‘localhost’, ‘root’, ” );
            mysql_select_db( ‘devshed’ );           

            # append empty option (to be default)
            $select_menu      .= “t” . “<OPTION
onMouseOver=”show_hint( ‘Please select an option from the list
below.’ );” onMouseOut=”set_timeout();” value=”” SELECTED>-
– select – -</OPTION>” . “rn”;     

            # retrieve a list of all parent values
            $db_query   = ‘SELECT * FROM php_js_parent_menu;';
            $db_result  = mysql_query( $db_query );         

            # output a SELECT menu option for each row returned
            if ( $db_result ) {
                  while ( $l_db_row = mysql_fetch_assoc( $db_result ) ) {                 

                        # retrieve and format (if necessary) SQL
results
                        $l_description    = $l_db_row
['description'];
                        $l_id       = stripslashes( $l_db_row
['id'] );
                        $l_name           = stripslashes
( $l_db_row['name'] );                 

                        # output SELECT menu with JS attributes
                        $select_menu      .= “t” . “<OPTION
onMouseOver=”show_hint( ‘$l_description’ );”
onMouseOut=”set_timeout();” value=”$l_id”>$l_name</OPTION>” .
“rn”;
           

                  } # END while rows
            } # END if rows           

            # return SELECT menu
            return $select_menu;           

      } # END get_parent_menu()
?>


As you can see above, the ‘get_parent_menu’ function does two basic things. First, it queries the SQL database for all values stored in our ‘parent_menu’ table. It then takes those values, and outputs them in the form of <OPTION> tags for our ‘parent’ SELECT menu.

The only thing that may need additional explanation here is the use of the onMouseOver and onMouseOut events. The application we are developing is pretty self-explanatory to an end-user, but it never hurts to make our systems a little easier to use and understand to someone who may not be adept with computers. Because of that, we have chosen to implement a “hint box” to display helpful tips to the user in real-time. When the user hovers over a menu option, a brief explanation of that option will be displayed in our hint box. When the user moves on a timeout is set to erase the hint after a couple of seconds. This is all done through the use of the JavaScript functions we discussed in the previous section.

We’re now ready to move on to our application’s stylesheet.

How’s it Looking?

Our stylesheet, “stylesheet.css”, is very simple. One class is used to control the appearance and formatting of our SELECT menus, and another is used to control the previously mentioned “hint box”. Those classes are as follows:

select {
      width: 300px;
      font-family: Tahoma, Arial, Helvetica, sans-serif;
      font-size: 11px;
}
#hint_box {
      width: 290px;
      background-color: #DDDDDD;
      border: 1px solid #000000;
      padding: 5px;
      font-family: Tahoma, Arial, Helvetica, sans-serif;
      font-size: 11px;
}

There is nothing too complex here, so let’s move on now to our index file.


{mospagebreak title=Main Layout}

We’ve saved the ‘index.php’ file to nearly the end because it simply pieces together all of the individual elements of our application. Those elements, which we have already covered, each handle various aspects of our program – but aren’t really useful on their own. Once they’re put together in the proper order though, the pieces start to fall into place. Let’s take a look at how that’s done:

<HTML>
<head>
      <title>PHP & Javascript – Example</title>
      <link rel=”stylesheet” type=”text/css”
href=”stylesheet.css” />
      <SCRIPT type=”text/javascript”
src=”javascript.js”></SCRIPT>
</head>    
<body onLoad=”reset_hint()”>

<pre id=”hint_box”></pre><br>

<SELECT name=”parent” id=”parent” onChange=”show_hint
( ‘Retrieving list values…’ ); update_child( this.options
[ this.selectedIndex ] );”>
<?
      include_once ‘functions.php';
      echo get_parent_menu();
?>
</SELECT>

<br><br>

<SELECT name=”child” id=”child” onChange=””>
</SELECT>

</body>
</HTML>

Again, this is nothing too complex. We began by cleaning up the source from our previous example. This was done by moving both the CSS and JavaScript code into their own, dedicated files. We have also removed the ‘anchor’ tag in favor of two SELECT tags: ‘parent’ and ‘child’. The names of these SELECT menus are indicative of their purposes. The ‘parent’ menu contains a simple list of categories while the ‘child’ menu contains options for the category selected. The “hint box”, which we have already mentioned, is positioned above the ‘parent’ SELECT menu in order to make it easily visible at all times.

In the code above, the ‘parent’ menu is populated with data from our ‘parent_menu’ SQL table using a helper function located inside ‘functions.php’. We’ve already reviewed that function, but one thing we did not mention was the menu’s onChange event handler. Our ‘parent’ SELECT menu has two JavaScript event handlers assigned to the onChange event. This means that each time we select a different menu option, the Javascript functions ‘show_hint’ and ‘update_child’ will execute. We’ve already looked at both of those functions, but by way of review ‘show_hint’ will temporarily display a helpful message to the user (via the “hint box”) and ‘update_child’ will load our external PHP/Javascript file (complete with URL arguments).

We’re now ready to take a look at that external file.

{mospagebreak title=Is it PHP? Or Javascript?}

Our external file may have a .php extension, but our index page thinks it’s a JavaScript file. This is made possible through the use of PHP’s ‘header’ function, as previously discussed in part one of this article. By using this function, we’re able to harness the power of PHP along with the power of JavaScript to produce some pretty interesting results. Let’s take a look at our file:

<?php
      # set appropriate content type – to tell the browser we’re
returning Javascript
      header( ‘Content-Type: text/javascript’ );
      # establish connection to the MySQL server

      mysql_connect( ‘localhost’, ‘root’, ” );
      mysql_select_db( ‘devshed’ );
?>

      // set quick reference to child menu object
      var child_menu_obj      = document.getElementById( ‘child’ );

      // erase all current (child) SELECT menu options
      while ( 0 < child_menu_obj.options.length )
            child_menu_obj.remove( 0 );     

// (code generated by PHP loop)
<?php
      # retrieve Parent ID from URL
      $parent_id  = mysql_escape_string( $_GET['parent_id'] );     

      # run SQL query to return all child menu options
      $db_query   = “SELECT * FROM php_js_child_menu WHERE
parent_id = $parent_id;”;
      $db_result  = mysql_query( $db_query );     

      # outout a SELECT menu option for each row returned
      if ( $db_result ) {
            while ( $l_db_row = mysql_fetch_assoc( $db_result ) )
{           

                  # show all retrieved (child) SELECT menu
options
                  $l_child_id = $l_db_row['id'];
                  $l_child_name     = $l_db_row
['name'];                 

                  # add new option to child menu
?>
                  var option_obj = new Option( ‘<?php echo
$l_child_name; ?>’, ‘<?php echo $l_child_id; ?>’ );
                  var option_rank =
child_menu_obj.options.length;
                  child_menu_obj.options[ option_rank ] =
option_obj;
<?
            } # END while results
      } # END if results
?>
// erase loading message in parent window
reset_hint();


There are a couple of important steps within this file. The first, as previously described, is the use of the ‘header’ function to tell the document that this file is actually a JavaScript file. We’ve already talked about that one, so we’ll skip over it now.

The second function of this file is to retrieve all ‘child’ menu options for the given ‘parent’ menu option that has been selected. If you remember earlier, when a ‘parent’ menu option is selected, it calls the external PHP file. When it does this, it also passes URL arguments along with the call, namely the primary key of the ‘parent’ menu’s SQL record. Our external file then can retrieve that ID from the URL and use PHP’s native SQL querying functions to retrieve all associated ‘child’ records.

Once we have done that, our PHP code loops through the resulting records and prints a few lines of JavaScript code for each. Remember that once our file has been rendered by the server, the client’s browser will think it is actually a JavaScript file. Because of that, we can output plain JavaScript code and it will be executed as any other JavaScript code would be.

Let’s look one more time at the JavaScript code being generated by our PHP file:

// set quick reference to child menu object
var child_menu_obj      = document.getElementById( ‘child’ );

// erase all current (child) SELECT menu options
while ( 0 < child_menu_obj.options.length )
     child_menu_obj.remove( 0 );

// (code generated by PHP loop)
var option_obj = new Option( ‘NAME’, ‘ID’ );
var option_rank = child_menu_obj.options.length;
child_menu_obj.options[ option_rank ] = option_obj;

// erase loading message in parent window
reset_hint();

As you can see, the JavaScript is actually very simple. First we retrieve a reference to our child SELECT menu object. Then we erase all options currently found in that menu, to give us a clean slate to work with. Next, our PHP script generates a create statement for each SQL option returned. This code simply creates a new SELECT menu option by passing it a name and a value. In this case, we’ve chosen the record’s primary key as the value to be processed when a user submits our form. Lastly, we call the ‘reset_hint’ function, to erase the “Retrieving list values” message.


What Have We Learned?

Our sample application is now complete, and I encourage you to try it out for yourself to get a better feel for just how powerful the techniques we’ve discussed can be. It doesn’t take much imagination to realize how this type of approach can easily be used to clean up existing user interfaces, and make them more user-friendly.

The code we have developed for this application is also pretty browser-friendly, having been tested in Mozilla Firefox 1.0, Netscape 7.2, and IE 6.0. (It is worth mentioning that our application will not run properly in Opera, as of version 7.23.)

If you would like to view a completed version of the application, please visit the following URL:

http://portfolio.boynamedbri.com/devshed/php_and_js/

If you would like to download the source code, you may do so here:

http://portfolio.boynamedbri.com/devshed/php_and_js/php_and_js.source.zip

That’s it for now. Thanks for reading, and hopefully I’ll see you soon!

[gp-comments width="770" linklove="off" ]
antalya escort bayan antalya escort bayan