Using jQuery with CakePHP: The Basics

First steps towards a drag-and-drop, calendar-based interface for assigning due dates in my StudentTracker web app.

It’s summer time, which means I finally have large(-ish) blocks of free time again.  Of course, with great time comes a great desire to accomplish something satisfying, so naturally I’m thinking about sprucing up my StudentTracker© web app.  I wrote the CakePHP-based version last summer, so that my students could submit their homework online this past year.  It’s worked well, but there’s always that extra something that I want to add to it :)

One feature that I didn’t quite get to last summer was having due dates for assignments.  This was left out partly because of time constraints, and partly because I realized that I’d hit that stage where “I can always add more features/fiddle with it needlessly!!”, so I stopped working on it.  On top of that, I had tried to use CakePHP’s nascent support for Prototype-based AJAX.  I could never quite get AJAX to work well, owing mostly to the lack of documentation for that (apparently) new feature.  That, plus the odd implementation that I found daunting (it appeared to detect changes in the selection of a drop-down menu using polling).

Of course, having taught for years I am comfortable managing due dates manually.  I tell the students when stuff is due in class, send out email notifying them of changes via the class’s Google Group, etc, etc.

But during this past year, I realized that I really did want to have that due date feature.  Not because it could auto-ding my students, but because it could provide each student with a personalized ‘TODO’ list.  Since StudentTracker knows which assignments each student has handed in, it could use the due-date information to produce a list of assignments that each student still needed to do.  I’d like to continue managing due dates myself so that consistently hard-working students who occasionally get a bit behind don’t get penalized.  StudentTracker can then tell each student what that student still needs to do.

The first step in adding this functionality is to create a way for the instructor to enter due dates for assignments, obviously.  The problem with doing this using normal HTML forms is that entering dates is a bit tricky.  Forcing the user to enter the month/day/year is awkward, and it’s easy to make mistakes.  Plus, when you’re looking to enter the due dates for 20 or more items for each of three classes, this gets real old, real fast.  Think about it – if you want to assign a due date to each of four homework assignments, and their allowed revisions, and the 10 weekly warm-up exercises, and the mid-term and final exams, and possibly the daily, 2-point ‘Are you paying attention?’ quizzes,  you can easily pile up 20-30 due dates per course that you’re teaching.  Multiply that by the number of classes you need to teach to fill out your load (three, in my case), and you can see how entering month/day/year gets tedious.

Thus, my immediate goal is to incorporate a ‘date picker’ UI widget into my web app.

After looking around for a while, I decided to use the jQuery UI’s Datepicker, because it looks nice, seems functional, and because I’ve heard a lot of good things about jQuery.  Plus, jQuery has a FullCalendar plugin that will allow me to (eventually) provide a calendar-based view of all the assignments, along with a drag-and-drop mechanism for changing due dates.  But that, along with my scheme for defining ‘relative due dates’ (to make it easier to move assignments to a new quarter), are topics for future posts.

In this post I’ll talk about how the very basics of using jQuery with CakePHP.  But just the uber-basics of using the jQuery library, and not the jQuery UI.  I’m assuming that you’ve both used jQuery a bit, and that you’ve used CakePHP a bit.  If you want help with their of those technologies on their own, you should search the web for tutorials on them.

In a nutshell:

  1. You’re now off and running with jQuery and CakePHP!

Let’s go through the above steps in more detail.

1. Create your normal CakePHP pages

File_PlacementFigure 1: Directory structure

You’ll need to create all the normal CakePHP classes, so you’ll need to create a file that contains your Controller, and a file that contains your View.  For this simple demonstration we’re going to leave out the ‘Model’, but adding that in won’t be difficult.

On the right, you can see a picture of the files, and where they go.  I’ve decided to make the web page that you’ll visit available at http://localhost/Demos/demo/jQueryDemo/, so the controller must therefore be placed in a file named demo_controller.php (in the app/controllers folder).

The contents of the controller file are pretty straightforward, and are included in this post below.  The only tricky parts are setting the $uses field to be an empty array (so that Cake does not try to use any particular model for this model-free controller), and adding the JavaScript helper in the jQueryDemo action (rather than to the entire controller).  You could easily add the JavaScript helper to the entire controller, but if you’re only using it in a limited subset of the actions, then only adding that helper where it’s used prevent clutter.

Just in case it’s useful, I’m also providing a .ZIP file that contains all the files I discuss in this post.  It’s set up so that you should be able to extract this into your app directory, and have the files and folders appear in the correct place.

<?php
class DemoController extends AppController {var $name = ‘Demo’;

// For this simple demo, make sure that

// the controller does not use any model

var $uses = array();

    function jQueryDemo() {

//        Configure::write(’debug’, 3);

$this->helpers[] = ‘Javascript’;

}

}

?>

 

You’ll notice (in the above code) I want the name of the action to be jQueryDemo, so I’ll need to create a file named j_query_demo.ctp (in the app/views folder).  The contents of this file is a little bit more interesting, as we’ll explore in the next step

2. Link to jQuery

At this point, you’ve got a couple of options.  You can either link to Google’s copy (and thus take advantage of their Content Delivery Network – CDN), or else link to your own, local copy.  Using Google’s copy is easier, but you then rely upon them continuing to provide these files.  Using your local copy means that you don’t need to worry about the files disappearing/changing versions/etc, but then you have to supply them to anyone who visits your site (and thus pay for that bandwidth).

http://encosia.com/2008/12/10/3-reasons-why-you-should-let-google-host-jquery-for-you/ makes a pretty compelling argument that one ought to use Google’s CDN for internet-facing apps, and local copies for LAN-based apps, but you can choose whichever you feel is best for your app.  I’m guessing that linking to Google’s copy and downloading a local backup copy for yourself is probably the best way to go.

We’ll look at what we’ve got here in the <?php ?> element.  Everything else in the file is straight HTML, which we’ll use later on in the jQuery code that we write. (Alternately, you could use Cake to generate some of this HTML, but the overall process is the same)

2a: Link to jQuery (Google’s copy)

This is pretty straightforward.  We’ll use the JavaScript helper that we pulled in back in the controller to link to Google’s copy.  That second ‘false’ parameter says NOT to put the code here (i.e., not to inline it), but instead to put it in the <head> of the document.

The second $javascript->link will create a link to our jQuery code, which (because we’re writing it ourselves) must reside locally.

<?php
echo $javascript->link(’http://ajax.googleapis.com/ajax/libs/jquery/1.3.2/jquery.min.js’, false);     echo $javascript->link(’demo/jQueryDemo’, false);

?>

<p id=”theTarget”>Starting Text</p>

<a href=”#”>Click me!”</a>

<p id=”clickTarget”>Number: 0</p>

 

2b: Link to jQuery (your own, local copy)

This is a tad more involved, just because you need to obtain your own copy of jQuery, and then install it into the app/webroot/js directory somewhere.  The upside is that you don’t have to worry about Google’s copy going away, or changing (such as when the ‘latest’ version changes to something newer), plus this will work if you’re going to deploy your app onto a LAN that might not be connected to the internet.

You can get yourself a copy of the core jQuery library at: http://docs.jquery.com/Downloading_jQuery

I recommend creating a app/webroot/js/jquery folder, just to keep the jQuery libraries (such as the jQuery UI) separated from all your other JavaScript.  You can see this depicted in Figure 1, above.  We’ll use the JavaScript helper that we pulled in back in the controller to link to our copy, as you can see in the code listed below.  That second ‘false’ parameter says NOT to put the code here (i.e., not to inline it), but instead to put it in the <head> of the document.

The second $javascript->link will create a link to our jQuery code, which (because we’re writing it ourselves) must reside locally.

<?php
echo $javascript->link(’jquery/jquery’, false); // in app/webroot/js/jquery folder,// link to ‘jquery.js’ file

    echo $javascript->link(’demo/jQueryDemo’, false);

?>

<p id=”theTarget”>Starting Text</p>

<a href=”#”>Click me!”</a>

<p id=”clickTarget”>Number: 0</p>

 

3. Create your own JavaScript file in the app/webroot/js directory, and link to it

The last thing to do is to create a JavaScript file that contains all your jQuery-based code.  In order to use this with Cake’s JavaScript helper, you should put it in the app/webroot/js folder, probably in a sub-folder named for your controller.  In Figure 1 (above) I put the jQueryDemo.js file into the folder app/webroot/js/demo, since the controller is named DemoController.

Remember that we linked to this file in the view (.ctp) file using the line:

    echo $javascript->link(’demo/jQueryDemo’, false);

At this point, we’ve done all the heavy Cake lifting, and from here, it’s all just using jQuery to do what we want.  If you read through a tutorial like http://docs.jquery.com/Tutorials:Getting_Started_with_jQuery, you’ll be up and running with jQuery (and now CakePHP!).  Here’s a quick, commented tour through the jQueryDemo.js file:

/*** @author Mike Panitz*/

var counter = 1;

$(document).ready(function(){

               alert(”Executing jQuery ‘onReady’ script!”);// pop up this alert when

// jQuery runs this method.  You’ll be able

// to see the “Starting Text”

// at the top of the page     $(”#theTarget”).text(”New text!”);

    // This will change the ‘Starting Text’ to

    // “New Text!”     // When any link is clicked, alert the user,

    // then change the text of #clickTarget

$(”a”).click( function() {

alert(”You clicked on the link!”);

$(”#clickTarget”).text(”Number:” + counter++);

}  );

});

4. You’re now off and running with jQuery and CakePHP!

Load up the page, and you’ll see something like:

Starting_View

Once you’ve clicked on the alert box, the top line of text will change and you’ll see something like:

After_ready

Click that link a couple of times, and you’ll see the bottom line of text update, like so:

After_several_clicks

I’d love to hear if this post helped you out, if you’ve got further questions, or if you’ve got feedback on my blog. 

June 22 2009 02:53 am | CakePHP and jQuery

Trackback URI | Comments RSS

Leave a Reply