Full CakePHP Application Part 4


Full CakePHP 1.2 Application 
As the title aptly suggests this is article 4 in my series of creating a full online DVD Catalog Application using CakePHP 1.2. Last time I quickly setup the Types and Locations Controller and Views so that I could start to add more data to the database.
In this article I'm going to create the DVDs controller and View files so that I can start to add / edit / delete DVDs from the database (I've gone for a Tarantino theme to begin with). This is going to be a bit more advanced because I am going to be uploading images to the server and I'm also going to use the jQuery Javascript library to progressively enhance a few forms and to stripe all the tables on the fly.

DVDs Controller and Views

First thing to do as usual is to create the Controller (dvds_controller.php) for the DVD Model along with the related Views for the actions.
  1. <?php  
  2.   
  3. /** 
  4.  * Dvds Controller 
  5.  * 
  6.  * file: /app/controllers/dvds_controller.php 
  7.  */  
  8. class DvdsController extends AppController {  
  9.     // good practice to include the name variable  
  10.     var $name = 'Dvds';  
  11.   
  12.     // load any helpers used in the views  
  13.     var $helpers = array('Html''Form''Javascript''Misc');  
  14.   
  15.     // global ratings variable  
  16.     var $ratings = array('0'=>'0''1'=>'1''2'=>'2''3'=>'3''4'=>'4''5'=>'5''6'=>'6''7'=>'7''8'=>'8''9'=>'9''10'=>'10');  
  17.   
  18.   
  19.     /** 
  20.      * index() 
  21.      * main index page for dvds 
  22.      * url: /dvds/index 
  23.      */  
  24.     function index() {  
  25.   
  26.     }  
  27.   
  28.     /** 
  29.      * view() 
  30.      * displays a single dvd and all related info 
  31.      * url: /dvds/view/dvd_slug 
  32.      */  
  33.     function view($slug) {  
  34.   
  35.     }  
  36.       
  37.     /** 
  38.      * admin_index() 
  39.      * main index page for admin users 
  40.      * url: /admin/dvds/index 
  41.      */  
  42.     function admin_index() {  
  43.   
  44.     }  
  45.       
  46.     /** 
  47.      * admin_add() 
  48.      * allows an admin to add a dvd 
  49.      * url: /admin/dvds/add 
  50.      */  
  51.     function admin_add() {  
  52.       
  53.     }  
  54.   
  55.     /** 
  56.      * admin_edit() 
  57.      * allows an admin to edit a dvd 
  58.      * url: /admin/dvds/edit/id 
  59.      */  
  60.     function admin_edit($id = null) {  
  61.   
  62.     }  
  63.       
  64.     /** 
  65.      * admin_delete() 
  66.      * allows an admin to delete a dvd 
  67.      * url: /admin/dvds/delete/1 
  68.      */  
  69.     function admin_delete($id = null) {  
  70.   
  71.     }  
  72. }  
  73.   
  74. ?>  
Here are the View files that I need to create:
  • /app/views/dvds/index.ctp
  • /app/views/dvds/view.ctp
  • /app/views/dvds/admin_index.ctp
  • /app/views/dvds/admin_add.ctp
  • /app/views/dvds/admin_edit.ctp

DVD Index

The index() function will be similar to the past ones I've created, retrieving the DVDs from the database that are currently active and also order the DVDs in alphabetical order. CakePHP's find methods are quite advanced and allow you to pass a number of arguments that will filter and sort the data from the database. For a full rundown of the parameters you can pass check out the Models Chapter in the cookbook.
  1. // file: /app/controllers/dvds_controller.php  
  2.   
  3. function index() {  
  4.     // get all dvds from database where status = 1  
  5.     $dvds = $this->Dvd->findAll("Dvd.status=1", null, "Dvd.name");  
  6.   
  7.     // save the dvds in a variable for the view  
  8.     $this->set('dvds'$dvds);  
  9. }  
The View is pretty similar to the previous index views with a few additions. I'm going to link to the edit page of the Format, Type and Location and I'm also going to leave out the coding for the striped table this will be accomplished with jQuery which I'll go through later in the article.
  1. // file: /app/views/dvds/admin_index.ctp  
  2.   
  3. <div class="dvds index">  
  4.   
  5.     <h2>Dvds Admin Index</h2>  
  6.     <p>Currently displaying all DVDs in the application</p>  
  7.   
  8.     <?php  
  9.     // check $dvds variable exists and is not empty  
  10.     if(isset($dvds) && !empty($dvds)) :  
  11.     ?>  
  12.   
  13.     <table>  
  14.         <thead>  
  15.             <tr>  
  16.                 <th>Name</th>  
  17.                 <th>Format</th>  
  18.                 <th>Type</th>  
  19.                 <th>Location</th>  
  20.                 <th>Rating</th>  
  21.                 <th>Created</th>  
  22.                 <th>Modified</th>  
  23.                 <th>Actions</th>  
  24.             </tr>  
  25.         </thead>  
  26.         <tbody>  
  27.             <?php foreach($dvds as $dvd): ?>  
  28.             <tr>  
  29.                 <td><?php echo $dvd['Dvd']['name']; ?></td>  
  30.                 <td><?php echo $html->link($dvd['Format']['name'], array('controller'=> 'formats''action'=>'edit'$dvd['Format']['id'])); ?></td>  
  31.                 <td><?php echo $html->link($dvd['Type']['name'], array('controller'=> 'types''action'=>'edit'$dvd['Type']['id'])); ?></td>  
  32.                 <td><?php echo $html->link($dvd['Location']['name'], array('controller'=> 'locations''action'=>'edit'$dvd['Location']['id'])); ?></td>  
  33.                 <td><?php echo $dvd['Dvd']['rating']; ?></td>  
  34.                 <td><?php echo $dvd['Dvd']['created']; ?></td>  
  35.                 <td><?php echo $dvd['Dvd']['modified']; ?></td>  
  36.                 <td>  
  37.                 <?php echo $html->link('Edit'array('action'=>'admin_edit'$dvd['Dvd']['id']) );?>  
  38.                 <?php echo $html->link('Delete'array('action'=>'admin_delete'$dvd['Dvd']['id']), null, sprintf('Are you sure you want to delete Dvd: %s?'$dvd['Dvd']['name']));?>  
  39.                 </td>  
  40.             </tr>  
  41.             <?php endforeach; ?>  
  42.         </tbody>  
  43.     </table>  
  44.   
  45.     <?php  
  46.     else:  
  47.         echo 'There are currently no DVDs in the database.';  
  48.     endif;  
  49.     ?>  
  50.       
  51.     <ul class="actions">  
  52.         <li><?php echo $html->link('Add a DVD'array('action'=>'add')); ?></li>  
  53.     </ul>  
  54. </div>  

DVD Admin Add

The admin_add() function will be quite complex so I'll break it down a little and first get the functionality working without a file upload. The main logic will be the same as any add function, I'll create a slug from the name, attempt to save the data and finally redirect the admin with an error message.
  1. // file: /app/controllers/dvds_controller.php  
  2.   
  3. function admin_add() {  
  4.     // if the form data is not empty  
  5.     if (!empty($this->data)) {  
  6.         // initialise the Dvd model  
  7.         $this->Dvd->create();  
  8.   
  9.         // create the slug  
  10.         $this->data['Dvd']['slug'] = $this->slug($this->data['Dvd']['name']);  
  11.           
  12.         // check for a dvd with the same slug  
  13.         $dvd = $this->Dvd->find('first'array(  
  14.             'conditions' => array(  
  15.                 'Dvd.slug'=>$this->data['Dvd']['slug'],  
  16.                 'Dvd.status' => '1'  
  17.             )  
  18.         ));  
  19.   
  20.         // if slug is not taken  
  21.         if(empty($dvd)) {  
  22.             // try saving the format  
  23.             if ($this->Dvd->save($this->data)) {  
  24.                 // set a flash message  
  25.                 $this->Session->setFlash('The DVD has been saved''flash_good');  
  26.   
  27.                 // redirect  
  28.                 $this->redirect(array('action'=>'index'));  
  29.             } else {  
  30.                 // set a flash message  
  31.                 $this->Session->setFlash('The DVD could not be saved. Please, try again.''flash_bad');  
  32.             }  
  33.         } else {  
  34.             // set a flash message  
  35.             $this->Session->setFlash('The DVD could not be saved. The Name has already been taken.''flash_bad');  
  36.         }  
  37.     }  
  38.       
  39.     // find dvd options in a list format  
  40.     // new 1.2 feature, can also have 'count' and 'first'  
  41.     $formats    = $this->Dvd->Format->find('list');  
  42.     $types      = $this->Dvd->Type->find('list');  
  43.     $locations  = $this->Dvd->Location->find('list');  
  44.     $ratings    = $this->ratings;  
  45.   
  46.     // set the variables so they can be accessed from the view  
  47.     $this->set(compact('formats''types''locations''ratings'));  
  48. }  
In order to select the Format, Type and Location I will need a drop down select box, CakePHP has a few very nice features that will help with creating them. First the find('list') method will automatically create an array that will be used in the form. It seems that the new 1.2 version automatically detects the type of form inputs but just to show how to create one the manual way I've included the code below. The View file will be standard and will use the Form Helper to quickly create the form inputs, CakePHP will also automatically re-fill the form if any errors occur.
  1. // file: /app/views/dvds/admin_add.ctp  
  2.   
  3. <div class="dvds form">  
  4.   
  5. <?php echo $form->create('Dvd');?>  
  6.     <fieldset>  
  7.         <legend>Add a Dvd</legend>  
  8.         <?php  
  9.         // create the form inputs  
  10.         echo $form->input('name'array('label'=>'Name: *'));  
  11.         echo $form->input('format_id'array('label'=>'Format: *''type'=>'select''options'=>$formats));  
  12.         echo $form->input('type_id'array('label'=>'Type: *''class'=>'type_select'));  
  13.         echo $form->input('location_id'array('label'=>'Location: *'));  
  14.         echo $form->input('rating'array('label'=>'Rating:'));  
  15.         echo $form->input('website'array('label'=>'Website URL:'));  
  16.         echo $form->input('imdb'array('label'=>'Imdb URL:'));  
  17.         echo $form->input('discs'array('label'=>'Number of Discs:''class'=>'tv_hide'));  
  18.         echo $form->input('episodes'array('label'=>'Number of Episodes:''class'=>'tv_hide'));  
  19.         ?>  
  20.     </fieldset>  
  21. <?php echo $form->end('Add');?>  
  22. </div>  
  23.   
  24. <ul class="actions">  
  25.     <li><?php echo $html->link('List DVDs'array('action'=>'index'));?></li>  
  26. </ul>  
Like before I'm also going to setup a few validation rules so that I cannot add empty data to the database.
  1. // file: /app/models/dvd.php  
  2.   
  3. // setup form validation for dvd  
  4. var $validate = array(  
  5.     'name' => array(  
  6.         'rule'      => VALID_NOT_EMPTY,  
  7.         'message'   => 'Please enter a Dvd Name'  
  8.     ),  
  9.     'format_id' => array(  
  10.         'rule'      => 'numeric'  
  11.     ),  
  12.     'type_id' => array(  
  13.         'rule'      => 'numeric'  
  14.     ),  
  15.     'location_id' => array(  
  16.         'rule'      => 'numeric'  
  17.     )  
  18. );  

Uploading Files

Once the add form is up and running I can now add the file functionality, there is just a few changes I need to make in the View and a bit more logic in the controller.
The first thing I need to do is make sure the form include the enctype attribute so that the server will save the file data, this is easily done by passing a variable in the form create() helper method:
  1. // file: /app/views/dvds/admin_add.ctp  
  2.   
  3. // this  
  4. <?php echo $form->create('Dvd'array('type'=>'file'));?>  
  5.   
  6. // instead of  
  7. <?php echo $form->create('Dvd');?>  
I also need to include the actual file input and this is done again by using the form helper:
  1. // file: /app/views/dvds/admin_add.ctp  
  2.   
  3. echo $form->input('File.image'array('label'=>'Image:''type'=>'file'));  
I've used the input name File.image so that when the form is submitted the file information is stored in a seperate array to the actual DVD data, this makes it easier to upload the file and also makes sure that the validation is run on the DVD information. The form data looks like this:
  1. Array  
  2. (  
  3.     [Dvd] => Array  
  4.         (  
  5.             [name] => testing  
  6.             [format_id] => 1  
  7.             [...] => ...  
  8.         )  
  9.     [File] => Array  
  10.         (  
  11.             [image] => Array  
  12.                 (  
  13.                     [name] => desperado.jpg  
  14.                     [type] => image/jpeg  
  15.                     [tmp_name] => C:\server\tmp\phpCE.tmp  
  16.                     [error] => 0  
  17.                     [size] => 44218  
  18.                 )  
  19.         )  
  20. )  
Now I need to deal with the file upload in the Controller action. I've dealt with file uploads in a previous article of mine so I've copied the upload_files() function to my app_controller.php file.
I've created a private function called _upload_image() in my dvds_controller.php to process and upload the file from the form. First I check that a file has been selected for upload by checking the error variable in the file array, then I use my upload_files() function to try and upload the file to the server. If no errors exist then I can save the url if there are errors then they are saved to be displayed in the view.
  1. // file: /app/controllers/dvds_controller.php  
  2.   
  3. /** 
  4.  * upload_image() 
  5.  * private function to upload a file if it exists in the form 
  6.  */  
  7. function _upload_image() {  
  8.     // init  
  9.     $image_ok = TRUE;  
  10.       
  11.     // if a file has been added  
  12.     if($this->data['File']['image']['error'] != 4) {  
  13.         // try to upload the file  
  14.         $result = $this->upload_files('img/dvds'$this->data['File']);  
  15.   
  16.         // if there are errors  
  17.         if(array_key_exists('errors'$result)) {  
  18.             // set image ok to false  
  19.             $image_ok = FALSE;  
  20.             // set the error for the view  
  21.             $this->set('errors'$result['errors']);  
  22.         } else {  
  23.             // save the url  
  24.             $this->data['Dvd']['image'] = $result['urls'][0];  
  25.         }  
  26.     }  
  27.   
  28. return $image_ok;  
  29. }  
I can then call this method from my admin_add() action to upload the file if it exists. The action now looks like this:
  1. // file: /app/controllers/dvds_controller.php  
  2.   
  3. function admin_add() {  
  4.     // if the form data is not empty  
  5.     if (!empty($this->data)) {  
  6.         // check for image  
  7.         $image_ok = $this->_upload_image();  
  8.   
  9.         // if the image was uploaded successfully  
  10.         if($image_ok) {  
  11.             // do same logic as before  
  12.         }  
  13.     }  
  14. // do same logic as before  
  15. }  
Full CakePHP 1.2 Application To display any file upload error messages I've created a helper that will contain my custom functions that I may need in a View. One such function displays error messages if its passed either a string or an array. Create a new file called misc.php in the /app/views/helpers folder and use this code to create a new function.
  1. <?php  
  2. /** 
  3.  * MiscHelper Class 
  4.  * has a few custom functions that are useful in a view 
  5.  * 
  6.  * file: /app/views/helpers/misc.php 
  7.  */  
  8. class MiscHelper extends AppHelper {  
  9.       
  10.     /** 
  11.      * display_errors() 
  12.      * displays a list of errors given an array or just a string 
  13.      */  
  14.     function display_errors($errors) {  
  15.         //init  
  16.         $output = '';  
  17.         $temp = '';  
  18.   
  19.         // if an array  
  20.         if(is_array($errors)) {  
  21.             // loop through errors  
  22.             foreach($errors as $error) {  
  23.                 $temp .= "<li>{$error}</li>";  
  24.             }  
  25.         } else {  
  26.             // save error  
  27.             $temp .= "<li>{$errors}</li>";  
  28.         }  
  29.   
  30.         // build up div  
  31.         $output = "<ul class='flash_bad'>{$temp}</ul>";  
  32.   
  33.     return $output;  
  34.     }  
  35. }  
  36. ?>  
This is just a simple function that will print out any error messages in an unordered list. It can be used by calling the function in a View like this:
  1. // file: /app/views/dvds/admin_add.ctp  
  2.   
  3. // if there was an error uploading the file then display errors here  
  4. if(isset($errors)) {  
  5.     echo $misc->display_errors($errors);  
  6. }  
Here's a screenshot of the final add form:
Full CakePHP 1.2 Application

DVD Admin Edit

The admin_edit() function will be very similar to the add function with a few slight differences, first I must check that the id being passed is valid and if not I'll redirect with a flash error message.
  1. // file: /app/controllers/dvds_controller.php  
  2.   
  3. // if the id is null and the form data empty  
  4. if (!$id && empty($this->data)) {  
  5.     // set a flash message  
  6.     $this->Session->setFlash('Invalid Dvd''flash_bad');  
  7.     // redirect the admin  
  8.     $this->redirect(array('action'=>'index'));  
  9. }  
This code is standard for an edit function and if you've ever used the bake script to generate your Controller code you will have something similar. Next I'm going to check if the form has been submitted, if it has then I'm going to process the form in the exact same way as the admin_add() function so I can just copy and paste that code here. If the form has not been submitted I can retreive the DVD from the database and save it to the data array.
  1. // file: /app/controllers/dvds_controller.php  
  2.   
  3. function admin_edit($id = null) {  
  4.     // if the id is null and the form data empty  
  5.     if (!$id && empty($this->data)) {  
  6.         // set a flash message  
  7.         $this->Session->setFlash('Invalid Dvd''flash_bad');  
  8.         // redirect the admin  
  9.         $this->redirect(array('action'=>'index'));  
  10.     }  
  11.   
  12.     // if the form was submitted  
  13.     if (!empty($this->data)) {  
  14.         // code from admin_add() goes here  
  15.     } else {  
  16.         // find the DVD from the database and save it in the data array  
  17.         $this->data = $this->Dvd->read(null, $id);  
  18.     }  
  19.       
  20.     // find dvd options from database in a list  
  21.     $formats = $this->Dvd->Format->find('list');  
  22.     $types = $this->Dvd->Type->find('list');  
  23.     $locations = $this->Dvd->Location->find('list');  
  24.     $ratings = $this->ratings;  
  25.     $this->set(compact('formats','types','locations''ratings'));  
  26. }  
In the View file for the admin_edit() function I'm going to display the current uploaded image (if one exists) and I also need to include the id of the DVD in the form. This ensures that CakePHP knows that this is an edit form and will change the correct DVD in the database. Here's a snippet of code from the Admin Edit View:
  1. // file: /app/views/dvds/admin_edit.ctp  
  2.   
  3. // include the id of the DVD as a form input  
  4. // CakePHP will automatically create this as a hidden element  
  5. echo $form->input('id');  
  6.   
  7. // display image if it exists  
  8. if(!empty($this->data['Dvd']['image'])): ?>  
  9. <div class="input">  
  10.     <label>Current Image:</label>  
  11.     <img src="/<?php echo $this->data['Dvd']['image']; ?>" alt="Dvd Image" width="100" />  
  12. </div>              
  13. <?php endif;  
Here's a screenshot of the Admin Edit View:
Full CakePHP 1.2 Application

DVD Admin Delete

For the delete action I'm going to change the status of the DVD from '1' to '0' in the database, this way I dont actually delete anything and if something goes wrong I can get my data back from the database. This is know as a 'soft delete' and I'm going to use this method throughout the application.
  1. // file: /app/controllers/dvds_controller.php  
  2.   
  3. // set the id of the dvd  
  4. $this->Dvd->id = $id;  
  5.   
  6. // try to change status from 1 to 0  
  7. if ($this->Dvd->saveField('status', 0)) {  
  8.   
  9. }  

Using jQuery in CakePHP 1.2

I've been using jQuery for some time now and its a great library to use in everyday web development. The first thing to do is download it from the jQuery site. I've downloaded the packed version, which is a smaller compression version which is great for keeping downloads to a minimum.
Place the library in /app/webroot/js and open up the default layout file located at /app/views/layouts/default.ctp. If this file does not exist then you will need to copy the one located at /cake/libs/view/layouts/default.ctp into your layouts folder in your app directory. This just makes sure that your default.ctp is the one that Cake will use.
Next I need to link to the jQuery library if the Javascript Helper is active in a Controller. To create a link I can use the link() function to make the library active in the View. As well as the jquery-1.2.3.pack.js I've created a new blank file called common.js, this will contain my javascript code to run on the page.
  1. // file: /app/views/layouts/default.ctp  
  2.   
  3. // if the javscript helper is set include the javascript library  
  4. if(isset($javascript)) {  
  5.     echo $javascript->link(array('jquery-1.2.3.pack''common'), true);  
  6.  
When I want to use Javascript I must now load the Helper in the Controller. I've done this before with the HTML and Form Helpers I just need to add Javascript to the array like this:
  1. // file: /app/controllers/dvds_controller.php  
  2.   
  3. // load any helpers used in the views  
  4. var $helpers = array('Html''Form''Javascript''Misc');  
Here I've checked that the Javascript files are being loaded correctly using the Firebug Firefox Extension:
Full CakePHP 1.2 Application

Striping Tables with Javascript

Now that I have jQuery at my disposal I'm first going to use it to stripe the even rows in any table that I assign a class='stripe'. This is very handy because I dont need to hard code this functionality with PHP which makes my code a little cleaner.
Open up the common.js file and enter the code below. The first ready() function is the base of all jQuery code and simply executes the code when the page has fully loaded. To read more about the basics of jQuery check out the documentation on the website. I'm going to target any Table that has a 'stripe' class and select all the even rows. Once they have all been selected I'm going to add a 'altrow' class to the row, once this is done I can then use CSS to style the class with a different colour.
  1. // file: /app/webroot/js/common.js  
  2.   
  3. // when the document is ready  
  4. $(document).ready(function(){  
  5.     // stripe all the tables in the application  
  6.     $('table.stripe tr:even').addClass('altrow');  
  7. });  
jQuery has extremely powerful 'selector' methods and also uses 'method chaining' to make things easy to select and manipulate. With just one line of code I can stripe any table throughout the application with a single class.
Here is the CSS I've used and below is a screenshot of the striping in action:
  1. // file /app/webroot/css/cake.generic.css  
  2.   
  3. table tr.altrow td {  
  4.     background#ebebeb;  
  5. }  
Full CakePHP 1.2 Application

Enhancing Forms

Currently the Admin Add Form displays two inputs (Number of Disks and Number of Episodes) that will only be used if the DVD is a 'TV Show'. So I'm going to use Javascript to hide the inputs if the DVD is a 'Film' and show the inputs if 'TV Show' is selected in the drop down menu.
To target these two form inputs I've added a 'tv_hide' class when creating the form like so:
  1. // file: /app/views/dvds/admin_add.ctp  
  2.   
  3. // add a class to the form input  
  4. echo $form->input('discs'array('label'=>'Number of Discs:''class'=>'tv_hide'));  
  5. echo $form->input('episodes'array('label'=>'Number of Episodes:''class'=>'tv_hide'));  
This will produce the following HTML code:
  1. <div class="input" style="display: block;">  
  2.     <label for="DvdDiscs">Number of Discs:</label>  
  3.     <input type="text" id="DvdDiscs" value="" maxlength="4" class="tv_hide" name="data[Dvd][discs]"/>  
  4. </div>  
Now I need to attach a Javascript event handler to the 'Type' drop down input that will find out what type has been selected and will show or hide the form inputs accordingly.
  1. // file: /app/webroot/js/common.js  
  2.   
  3. // add event handler to type select form input  
  4. $('.type_select').change(function(){  
  5.     // get the value of the selected option  
  6.     var type = $(this).find('option:selected').text();  
  7.   
  8.     // log the type for testing purposes  
  9.     console.log( type );  
  10.   
  11.     // if the type is a tv show  
  12.     if(type == "TV Show") {  
  13.         // fadein the form inputs  
  14.         $('.tv_hide').parent().fadeIn();  
  15.     } else {  
  16.         // fade out and hide the form inputs  
  17.         $('.tv_hide').parent().fadeOut();  
  18.     }  
  19. });  
Because I've added a class to the form input and not the surrounding div I make use of the .parent() method to select the correct div. This example also shows method chaining in action.
Its not quite finished yet because I need to accomodate for the Admin Edit Form and make sure that the form inputs are already displayed or hidden depending on the 'Type' the edited DVD has. To do this I use the same techniques as before and get the selected DVD type and if it doesn't equal 'TV Show' then I hide the form inputs with a 'tv_hide' class.
  1. // file: /app/webroot/js/common.js  
  2.   
  3. // get value of selected type  
  4. var current_type = $('.type_select option:selected').text();  
  5.   
  6. // if the selected option is not 'TV Show' then hide the tv options  
  7. if(current_type != "TV Show") {  
  8.     // hide the tv elements from form  
  9.     $('.tv_hide').parent().hide();  
  10. }  

Wrapping Up

I've managed to cover quite a lot of ground in this article, I've setup yet another Controller and related View files (a familiar process by now I hope) and included the ability to upload files to the server and save the URL to the database.
I've also covered including jQuery in the application and using some Javascript voodoo to stripe tables and enhance forms by showing and hiding inputs depending on a selected DVD Type. If you do have any problems with anything I've covered let me know and I'll try to sort you out.

Source Code

The source code for this article can be downloaded using this link. If these articles are helping you out why not consider donating I can always use a beer! :)

This entry was posted in . Bookmark the permalink.

Leave a Reply