<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>Mike Panitz&#039;s Blog &#187; CakePHP</title>
	<atom:link href="http://panitzco.com/Mike/category/tech/cakephp/feed/" rel="self" type="application/rss+xml" />
	<link>http://panitzco.com/Mike</link>
	<description>Some tech, some teaching, and some other stuff</description>
	<lastBuildDate>Tue, 29 Sep 2009 06:00:40 +0000</lastBuildDate>
	<generator>http://wordpress.org/?v=2.8</generator>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
			<item>
		<title>Using jQuery-based Date/Time Picker controls in CakePHP</title>
		<link>http://panitzco.com/Mike/tech/jquery/using-jquery-based-datetime-picker-controls-in-cakephp/</link>
		<comments>http://panitzco.com/Mike/tech/jquery/using-jquery-based-datetime-picker-controls-in-cakephp/#comments</comments>
		<pubDate>Sat, 12 Sep 2009 21:16:26 +0000</pubDate>
		<dc:creator>Mike</dc:creator>
				<category><![CDATA[CakePHP]]></category>
		<category><![CDATA[jQuery]]></category>

		<guid isPermaLink="false">http://panitzco.com/Mike/?p=80</guid>
		<description><![CDATA[An overview of your jQuery options, by Mike Panitz
As the summer winds down here in beautiful, increasingly overcast Washington state, I have to face certain facts.&#160; Fact: if I don&#8217;t get that stationary trainer set up, I&#8217;m not going to ride my bicycle this winter.&#160; Fact: I really, really need a haircut.&#160; Fact: I&#8217;m not [...]]]></description>
			<content:encoded><![CDATA[<p>An overview of your jQuery options, by Mike Panitz</p>
<p>As the summer winds down here in beautiful, increasingly overcast Washington state, I have to face certain facts.&#160; Fact: if I don&#8217;t get that stationary trainer set up, I&#8217;m not going to ride my bicycle this winter.&#160; Fact: I really, really need a haircut.&#160; Fact: I&#8217;m not going to implement the &#8216;due date&#8217; functionality in my homework hand-in web application by the time school starts again in two weeks.&#160; This last fact is sad, but not tragic, especially since I got other Really Important Stuff done this summer.&#160; And I got figured out how to use jQuery with a calendar sort of control/widget, starting with choosing a date (or time) picker for my web app.</p>
<p>To be clear, my motivation is that I want a a DHTML date/time picker that will make my otherwise plain old input form that much better.&#160; There&#8217;s no AJAX involved here, just DHTML interactive goodness.&#160; I&#8217;m going to use the <a href="http://jquery.com/">jQuery</a> / <a href="http://jqueryui.com/">jQuery UI</a> stuff because it&#8217;s easy to use, elegant, and because I&#8217;m planning on using it for other things, in the future.&#160; I&#8217;ll be continuing to use CakePHP for the backend, since it&#8217;s &#8216;convention over configuration&#8217; approach is refreshingly XML-free, their MVC abstraction is clean, and their ORM implementation is quickly and easily used.</p>
<p>After much fiddling, I&#8217;ve decided on one date/time picker control to use.&#160; I&#8217;ve also found some strategies for trying this stuff out.&#160; So I&#8217;ll start by talking through the strategies, then I&#8217;ll talk about the contenders, then finally I&#8217;ll call out the winner.&#160; If I have time, I&#8217;ll walk you through using the winner in my next post (which will include nitty-gritty details like the exact CakePHP code you&#8217;ll need to use <img src='http://panitzco.com/Mike/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' /> &#160; )</p>
<h2>Suggested strategy for deciding on a UI widget/control:</h2>
<p>In general, this seemed to work well:</p>
<ol>
<li><strong>Find a widget</strong>      <br />This is the &#8216;Google around for it&#8217; stage.&#160; You&#8217;re just looking for options at this point.</li>
<li><strong>Look through the control&#8217;s home page, paying special attention to the demo page        <br /></strong>The home page will help make it clear how polished/full-featured the control is.&#160; It should contain a link to a page that contains clear documentation for all the options, and the documentation should contain code samples.&#160; Especially for projects run by individuals, sample code is crucial for figuring out how the author expects you to use it.
<p>You really, really want to find a &#8216;demo page&#8217;, which shows off the UI widget.&#160; Not only will this let you quickly get a feel for how the widget works, but will serve as a complete, working example for the &#8216;copy locally&#8217; step (#4, below). </li>
<li><strong>Repeat the above steps until you find something that you like        <br /></strong>&#8216;Nuff said <img src='http://panitzco.com/Mike/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' />  </li>
<li><strong>Copy the demo page into a local directory &amp; make sure it works        <br /></strong>The local directory can either be something in the file system, or something that&#8217;s served up by a web server that you&#8217;ve got control over.&#160; <a href="http://www.apachefriends.org/en/xampp.html">XAMPP</a> is perfect for this step.
<p>The real goal here is to make sure that you&#8217;ve got everything working, so that when you go to integrate it into CakePHP, you&#8217;ve got a working copy to compare your Cake-ified version to.&#160; This is especially useful if you&#8217;re making local copies of the various libraries &amp; files that the control depends on.       </p>
<p>This step can also be useful to make sure that you can make the control appear (and behave) the way you want, before investing time to Cake-ify it. </li>
<li><strong>Cake-ify it        <br /></strong>First get the UI part to work, then verify that you can get the data you need back to the server (back to the Cake controller).&#160; Then, and only then, should you fiddle with the control&#8217;s options extensively. </li>
</ol>
<p>Having outlined my suggested strategy for figuring out which control you want, let&#8217;s look at the options that I found.&#160; These aren&#8217;t the only options, but these are the ones that I found, that seemed to work well.</p>
<h2>The Contenders:</h2>
<h4>Cake&#8217;s default date/time picker</h4>
<div style="text-align: center; padding-bottom: 5px; border-right-width: 0px; margin: 5px; padding-left: 5px; padding-right: 5px; float: right; border-top-width: 0px; border-bottom-width: 0px; font-size: 80%; border-left-width: 0px; padding-top: 5px"><a href="http://panitzco.com/Mike/wp-content/uploads/2009/09/Cake_DATETIME_Default2.png"><img style="border-right-width: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px" title="Cake_DATETIME_Default" border="0" alt="Cake_DATETIME_Default" src="http://panitzco.com/Mike/wp-content/uploads/2009/09/Cake_DATETIME_Default_thumb2.png" width="413" height="454" /></a>     <br /><strong><a name="Fig1">Figure 1:</a></strong> Cake&#8217;s default control(s) for a DATETIME field</div>
<p>While not actually jQuery based, I figured that I&#8217;d point this out just because of how quick-and-easy this is to program.&#160; It&#8217;s built into Cake (obviously), and so you don&#8217;t have to do much for this to work.&#160; Just use the FormHelper&#8217;s input method on a database field that&#8217;s a DATETIME, and Cake takes care of the rest.&#160; </p>
<p>Cake auto-magically provides the user with a collection of drop-down menus that let the user safely pick out the date and time, as shown in <a href="#Fig1">Figure #1</a>.</p>
<p>If you&#8217;ve got something that doesn&#8217;t need to be AJAX-y, this is an option worth considering, simply because of how fast, easy, and reliable it is.</p>
<h4>jQuery&#8217;s Datepicker</h4>
<p>Home Page: <a href="http://docs.jquery.com/UI/Datepicker">http://docs.jquery.com/UI/Datepicker</a></p>
<p>Demo Page: <a href="http://jqueryui.com/demos/datepicker/">http://jqueryui.com/demos/datepicker/</a>&#160; <br />(there&#8217;s another demo in the home page, too)</p>
<p align="center"><a href="http://panitzco.com/Mike/wp-content/uploads/2009/09/DatePicker.png"><img style="border-right-width: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px" title="DatePicker" border="0" alt="DatePicker" src="http://panitzco.com/Mike/wp-content/uploads/2009/09/DatePicker_thumb.png" width="440" height="250" /></a>&#160;&#160; <br /><strong><a name="Fig2">Figure 2:</a></strong> The jQuery UI&#8217;s Datepicker control</p>
<p>This is the only date/time picker that&#8217;s a standard part of the jQuery UI, so it&#8217;s easy to get your hands on, easily documented, and you can get CDN-hosting benefits.&#160; The upside of this is that it&#8217;s really nicely done &#8211; solid documentation, full-featured, and easy to use.&#160; As you can see in <a href="#Fig2">Figure 2</a>, above, Datepicker supports the jQuery UI <a href="http://jqueryui.com/themeroller/">ThemeRoller</a> custom themes, slide-out visual effects, and such nice perks as having the widget &#8216;output&#8217; a differently formatted string into another form field (in this case it&#8217;s outputting &quot;Thursday, 17 December, 2009&quot; into the text input field on the right).&#160;&#160; </p>
<p>The major downside is that this control <em>only</em> allows the user to pick the date.&#160; If you want to pick the time as well, you&#8217;re on your own &#8211; there aren&#8217;t any time-picking widgets in the standard jQuery UI.&#160; So the Datepicker widget is a great choice if you&#8217;ve got a DATE field in your (MySQL) database, and want the user to have a slick, calendar-based way of picking a date. </p>
<blockquote><p><strong>A word of warning: </strong>You&#8217;ll need to watch the format &#8211; the default format for the Datepicker isn&#8217;t the exact same as the MySQL DATE format, which will cause problems for <a href="http://cakephp.org/">CakePHP</a>.&#160; You&#8217;ll need to use one of the format parameters to make sure that the Datepicker widget puts a properly formatted string into the text field, so that Cake can auto-convert it).</p>
</blockquote>
<blockquote><p><strong>An aside: what if you want to use the Datepicker as part of a solution?</strong></p>
<p>Let&#8217;s say that we want the user to be able to pick both the date AND the time.&#160; One option would be to use a separate DATE and TIME field in the database, and have each one nicely tied to a single jQuery widget.&#160; This will make the UI fairly straightforward, but will then complicate later queries.&#160; If we&#8217;re interested in determining if the student&#8217;s homework submission is late, we&#8217;d have to do convoluted queries like &quot;An assignment is be late if it was handed in after the due DATE, or if it was handed in on the due DATE and after the TIME it is due&quot;).&#160; Questions like &#8216;How many days late is the submitted homework&#8217; should be even more fun <img src='http://panitzco.com/Mike/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' /> </p>
<p>Luckily , MySQL provides both DATETIME and TIMESTAMP data types &#8211; they appear to be pretty much identical (which clearly indicates that I just haven&#8217;t researched the differences enough <img src='http://panitzco.com/Mike/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' /> &#160; ).&#160; They can be compared directly, and there are PHP routines for dealing with DateTimes (<a href="http://us.php.net/manual/en/class.datetime.php">http://us.php.net/manual/en/class.datetime.php</a>), so using a single DATETIME in the database layer, and multiple input fields in the UI layer, seems like a reasonable approach.</p>
<p>The jQuery Datepicker doesn&#8217;t do anything with time, but we&#8217;ve got a couple of options.&#160; The worst option is to set up the Datepicker&#8217;s format string to include an arbitrary, unchanging time (e.g., &quot;12:00:00&quot;), but if we&#8217;re going to do that, then why waste the space &amp; effort on recording the time at all?&#160; </p>
<p>If we&#8217;re not going to hard-code a time into the field, then we&#8217;ll have to ask the user for for the time using a separate widget.&#160; We can do this using two separate widgets in the UI layer.&#160; The question then becomes &quot;Where should I merge those two separate fields into the single DATETIME field?&#160; In JavaScript (on the web page), or in PHP (in the Cake controller method)?&quot;&#160; A friend who&#8217;s been doing web programming for a while says that doing such merging work in PHP (in the controller method) is the way to go.&#160; Thinking about it, I agree with him, mostly because using JavaScript to manipulate the automatically generated Cake input form fields seems brittle.&#160; The various arrays (mostly $this-&gt;data) in the controller seem much more stable.&#160; For example, the documentation clearly <a href="http://book.cakephp.org/view/75/Saving-Your-Data">defines the format used</a>, and this definition is so fundamental to how Cake works that it would be a major, breaking change for them to alter it.&#160; An added bonus for putting this &#8216;merging&#8217; logic into the controller is that the UI can display anything you want, so long as your controller code can parse the fields, then merge and reformat the fields into a single, properly formatted DATETIME string that Cake&#8217;s model code is expecting.</p>
<p>So if you&#8217;re going to use the jQuery UI&#8217;s Datepicker widget to let your users pick the date/time, then you&#8217;ll probably want to have a second field that will allow them to pick the time, and then merge these two fields into one DATETIME in the Cake controller method.</p>
</blockquote>
<h4>timepickr</h4>
<p>Home Page: <a href="http://haineault.com/media/jquery/ui-timepickr/page/">http://haineault.com/media/jquery/ui-timepickr/page/</a></p>
<p>Demo Page: (at the top of the home page)</p>
<p align="center"><a href="http://panitzco.com/Mike/wp-content/uploads/2009/09/timepickr.png"><strong><img style="border-right-width: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px" title="timepickr" border="0" alt="timepickr" src="http://panitzco.com/Mike/wp-content/uploads/2009/09/timepickr_thumb.png" width="421" height="136" /></strong></a><strong>      <br /><a name="Fig3">Figure 3:</a> </strong>The timepickr widget</p>
<p>This widget only picks out the time &#8211; there&#8217;s no support for picking out the date.&#160; I&#8217;m only&#160; mentioning this control at all in case you want to use the approach of providing a Datepicker to pick the date, and something like this timepickr to pick the time.</p>
<p>As you can see in <a href="#Fig3">Figure 3</a>, above, the widget is a tad odd.&#160; Essentially, you click on the field ( &quot;{suffix}&quot;, in this case), and then the first row of numbers pops out beneath it.&#160; You then choose the hour (&quot;06&quot;, in Figure 3) by moving your mouse over it, and the next row pops out.&#160; You then select the minutes ( &quot;30&quot; ), and finally AM/PM (unless you&#8217;re using a 24 hour timepickr).&#160; </p>
<p>It&#8217;s a really nice interface, actually &#8211; not one I would have thought of, but once you use it a couple times, it works really well.</p>
<h4>dtpicker </h4>
<p>Home Page: <a href="http://code.google.com/p/jquery-dtpicker/">http://code.google.com/p/jquery-dtpicker/</a></p>
<p>Demo Page: <a href="http://jquery-dtpicker.vndv.com/">http://jquery-dtpicker.vndv.com/</a><a href="http://panitzco.com/Mike/wp-content/uploads/2009/09/dtpicker.png">     <br /></a>
<p><img style="border-right-width: 0px; display: block; float: none; border-top-width: 0px; border-bottom-width: 0px; margin-left: auto; border-left-width: 0px; margin-right: auto" title="dtpicker" border="0" alt="dtpicker" src="http://panitzco.com/Mike/wp-content/uploads/2009/09/dtpicker_thumb.png" width="475" height="407" /></p>
</p>
<p align="center">&#160;<strong><a name="Fig4">Figure 4</a>: </strong>The dtpicker widget</p>
<p>This is the first combined date and time picker widget that I found.&#160; It&#8217;s very similar to the timepickr control, in the sense that you click on the input form (in <a href="#Fig4">Figure 4</a>, above, I clicked on the text field under the &quot;event&quot; label), and it displays the first column of choices &#8211; the years, in the above figure.&#160; Once you move the mouse over a year, it lets you pick the month ( &quot;March&quot; ), then a range of days (&quot;20-29&quot;), then a specific day ( &quot;22&quot; ), then an hour ( &quot;09:&quot; ), then a minute ( &quot;20 ).&#160; It&#8217;s a slick interface, and I liked it.&#160; I could quickly and easily pick out the date and time that I wanted, especially after the timepickr widget familiarized me with how this style of widget worked.</p>
<p>There are two reasons that I didn&#8217;t go with with widget.&#160; First, I wanted something that looks like a calendar, since this will be used to pick out due dates for homework assignments.&#160; It&#8217;s invaluable to see how far apart dues are, visually, so that it&#8217;s clear how much time (a week?&#160; two weeks?) the students will have to work on any given project.&#160; Secondly, this widget doesn&#8217;t appear to play nicely with Cake&#8217;s CSS &#8216;out of the box&#8217;. </p>
<blockquote><p><strong>A word of warning: </strong>Watch out for the type of the input field that you attach the dtpicker to.&#160; The dtpicker doesn&#8217;t appear to work when attached to a text input (e.g., &lt;input type=&quot;text&quot;&gt;), but instead you must attach it to one of the custom &quot;date&quot; input types that it requires (e.g., &lt;input type=&quot;date&quot;&gt;)</p>
</blockquote>
<h4>dyndatetime</h4>
<p>Home Page: <a href="http://code.google.com/p/dyndatetime/">http://code.google.com/p/dyndatetime/</a></p>
<p>Demo Page: <a href="http://www.mechanicalmarksy.com/hosted/toolman/dyndatetime/example.html">http://www.mechanicalmarksy.com/hosted/toolman/dyndatetime/example.html</a></p>
<p align="center"><a href="http://panitzco.com/Mike/wp-content/uploads/2009/09/dynDateTime.png"><img style="border-bottom: 0px; border-left: 0px; display: block; float: none; margin-left: auto; border-top: 0px; margin-right: auto; border-right: 0px" title="dynDateTime" border="0" alt="dynDateTime" src="http://panitzco.com/Mike/wp-content/uploads/2009/09/dynDateTime_thumb.png" width="267" height="224" /></a> <strong><a name="Fig5">Figure 5</a>: </strong>The dyndatetime widget</p>
<p>As you can see in <a href="#Fig5">Figure 5</a>, above, the dyndatetime widget looks like a calendar with a space for time at the bottom.&#160; You activate it by clicking on something (in this case, the button labeled &#8216;PICKER&quot;, but you can attach it to the text field instead).&#160; The widget then appears on the screen, and you can pick the time, then pick the date.&#160; The time picker isn&#8217;t entirely intuitive (you can SHIFT+Click to increase the hour/minute individually, or you can click-and-hold on the hour (or minute), and then drag the mouse left or right to adjust the time), but once you figure it out, it works pretty well.</p>
<h2>The Winner: dynDateTime</h2>
<p>dyndatetime, based on the based on Dynarch date time calendar, is what I&#8217;m going to use.&#160; It looks pretty slick, seems to work well, and will produce a single field that contains both date and time.&#160; </p>
<p>It seems to be reasonably full-featured, including things like formatting the input field one way, and then formatting another field in a different way.&#160; This will make it easy to have a field that Cake&#8217;s server-side code will use to automatically populate the DATETIME database field.&#160; </p>
<p>There&#8217;s also a bunch of pre-fab .CSS and language options, too, so you can customize how it looks, or which language you&#8217;ll be using it with.&#160; Speaking of which, dyndatetime&#8217;s CSS plays pretty well (but not perfectly) with Cake&#8217;s default CSS, which is nice.&#160; Generally, there are lots of nice options (<a href="http://code.google.com/p/dyndatetime/wiki/Home">http://code.google.com/p/dyndatetime/wiki/Home</a>), and the date/time formatting that can both support MySQL&#8217;s DATETIME, and more human-readable formats.</p>
]]></content:encoded>
			<wfw:commentRss>http://panitzco.com/Mike/tech/jquery/using-jquery-based-datetime-picker-controls-in-cakephp/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>Generating jQuery code from your CakePHP Controller/View</title>
		<link>http://panitzco.com/Mike/tech/generating-jquery-code-from-your-cakephp-controllerview/</link>
		<comments>http://panitzco.com/Mike/tech/generating-jquery-code-from-your-cakephp-controllerview/#comments</comments>
		<pubDate>Tue, 07 Jul 2009 03:17:20 +0000</pubDate>
		<dc:creator>Mike</dc:creator>
				<category><![CDATA[CakePHP]]></category>
		<category><![CDATA[Technology]]></category>
		<category><![CDATA[jQuery]]></category>

		<guid isPermaLink="false">http://panitzco.com/Mike/?p=70</guid>
		<description><![CDATA[An adventure in PHP&#8217;s include, eval, and JavaScript!
I am looking at using jQuery and AJAX as a means of making some of my forms in my StudentTracker© web app more streamlined.&#160; Currently, I&#8217;m dynamically creating forms so that all the students&#8217; assignments are listed on a single page, no matter how many assignments there are.&#160; [...]]]></description>
			<content:encoded><![CDATA[<p>An adventure in PHP&#8217;s include, eval, and JavaScript!</p>
<p>I am looking at using jQuery and AJAX as a means of making some of my forms in my StudentTracker© web app more streamlined.&#160; Currently, I&#8217;m dynamically creating forms so that all the students&#8217; assignments are listed on a single page, no matter how many assignments there are.&#160; By putting each item into a separate form element (i.e., one text field for the student-visible name, another for the number of points it&#8217;s worth, etc, etc), I can allow the user (me! <img src='http://panitzco.com/Mike/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' /> &#160; ) to edit each one directly and in-place, without having to visit a separate page for each assignment.&#160; This approach works well, even in spite of the &#8216;reload the entire page after each edit&#8217; workflow that StudentTracker&#8217;s non-AJAX pages use.&#160; The problem is that if I wanted to use, say, jQuery to create a rich user experience, it seems like I&#8217;d need a way to generate some JavaScript code <em>per element</em>, in order to do things like send AJAX messages back to the server when a form element gets changed.&#160; </p>
<p>After thinking about it for a while, I&#8217;m not so sure that&#8217;s true.&#160; I think that for my situation, not only will it be possible to use jQuery to handle a bunch of different elements individually, but it will actually be better to go with that approach.&#160; I say this with the confidence of one who hasn&#8217;t actually tried it yet <img src='http://panitzco.com/Mike/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' /> </p>
<p>That said, I was playing around with both <a href="http://cakephp.org/">CakePHP</a> and some simple jQuery, and thinking that if I could use (Cake)PHP to write <a href="http://jquery.com/">jQuery</a> code directly into my JavaScript file then I could dynamically generate some JavaScript to go with my dynamically generated form.&#160; Specifically, I wanted the PHP page that generated the JavaScript to have access to all the PHP variables that I have defined in my Cake view.&#160; I also wanted to do so using an approach that could be reused within the Cake controller, if I chose.</p>
<p>After thinking about it, I&#8217;ve come up with a fun, clever, very very hack-y way to do it.&#160; It&#8217;s so much fun, in fact, that I&#8217;m posting it here, even though I think I&#8217;ve got a better way to accomplish my original goal <img src='http://panitzco.com/Mike/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' /> .</p>
<blockquote><p><u>Side-note:</u> If all you want to do is execute PHP code in your JavaScript file, then you can rename the <strong>webroot/js/&#8230;/foo.js </strong>file to be <strong>foo.js<font color="#ff0000">.php</font></strong>, and CakePHP will correctly interpret the code first as a normal PHP file.&#160; <u>You&#8217;ll need to link to foo.js.php</u> (instead of foo.js), but except for that change, the browser will interpret that file as a JavaScript file.</p>
<p>The problem I have with this solution is that you can&#8217;t get to anything from the original context &#8211; any local variables in your view (or helpers that your controller defined, etc) will be UNAVAILABLE in the JavaScript-generating PHP file.&#160; </p>
<p>This is because the .js.php file is separate from your controller/view files, which means that the browser needs to make a separate request to the web server to retrieve the JavaScript file &#8211; by the time the JS is being served up, the original controller/view methods have long since finished!</p>
</blockquote>
<h3>I started by asking myself &quot;What about using PHP&#8217;s <a href="http://us3.php.net/manual/en/function.include.php">include</a> function?&quot;</h3>
<p><a href="http://us3.php.net/manual/en/function.include.php">include</a> will open a file, pull it&#8217;s contents into the current .PHP page, and then evaluate the file&#8217;s contents, which is exactly what we want.&#160; What&#8217;s also very handy is that the include code will be evaluated as if it really had been pasted into that line, including having access to all the local variables available at the time that include is called.&#160; Incidentally, include with also drop back out of &#8216;PHP mode&#8217;, and into &#8216;HTML mode&#8217;, which we also want.&#160; This mode switch will mean that include will basically ignore anything that&#8217;s not wrapped in &lt;?php ?&gt; tags, which is perfect.</p>
<p>At first blush, this seems like it should solve the problem easily and elegantly &#8211; we can pull the .js file into the view/controller, and evaluate all the (Cake)PHP elements in the file with full access to the view&#8217;s local variables.</p>
<p>But include this doesn&#8217;t <em>quite</em> work, because it will (effectively) paste the included (JavaScript) code directly into the controller/view method.&#160; Instead, what we want is to have include do it&#8217;s work, and then have it hand us a string that contains results of that work (i.e., the evaluated contents of the included file).</p>
<p>Luckily for us, the PHP manual page spells out how to do exactly this.&#160; We can use output buffering to include the file, then put that into a string.&#160; My code below is basically a simple variation on <a href="http://us3.php.net/manual/en/function.include.php">http://us3.php.net/manual/en/function.include.php</a> &#8211; specifically the &quot;<strong>Example #6 Using output buffering to include a PHP file into a string</strong>&quot;</p>
<h3><strong>I said to myself &quot;Let&#8217;s put this logic into a function and call it!&quot;</strong></h3>
<p>The code that I got from the PHP manual wasn&#8217;t the most tricky thing in the world, but it wasn&#8217;t really something I wanted to have littered throughout my CakePHP code.&#160; So putting this into a function is a natural and normal way to place it into a well-understood and reusable package.</p>
<p>The only problem is that if we call include from a function, then all of <em>that function&#8217;s</em> local variables will be in scope, and so we won&#8217;t be able to access the controller/view&#8217;s variables.</p>
<h3>I told myself that I&#8217;d finally found a fun reason to use PHP&#8217;s <a href="http://us3.php.net/manual/en/function.eval.php">eval</a> function!</h3>
<p>The basic approach is to define a string that is valid PHP code for including the JavaScript file.&#160; The output buffering goes into this block, too, but I&#8217;m going to leave most of the error-checking/input massaging out of this example to keep things simple.&#160; When PHP&#8217;s eval is called on the block, then it will execute the &#8216;include&#8217; statement, in the context of the eval line.</p>
<p>Because the code runs in the context of the eval line, we should should be clear any variables that we create (or stomp on) will still exist after the call to eval is done.&#160; (By &#8217;stomp on&#8217;, I mean &#8216;overwrite&#8217;.)&#160; Because of this, we shouldn&#8217;t create local variables (or stomp on existing variables) in the script that we&#8217;ll be evaluating.&#160;&#160; We can achieve this by creating a CakePHP helper, having the controller import that helper, and then using instance variables on that helper object instead of local variables.&#160; In order to make that work, we&#8217;ll need to have a variable that contains the name of the helper.&#160; </p>
<p>Thus, the final product: the JavascriptEval helper, with instance variables that&#8217;ll substitute for parameters and return values (and locals, if I had any).&#160; The code for the helper (and example files to demonstrate the use of the helper) are listed below; if you want a .ZIP file that contains all of these files, you can find it at <a href="http://panitzco.com/Files/JavascriptEval_Demo.zip">http://panitzco.com/Files/JavascriptEval_Demo.zip</a>.&#160; All the files in the .ZIP should be set up so that you can extract it into your /app/ directory, and everything will end up where it needs to go.&#160; </p>
<table border="1" cellspacing="0" cellpadding="2" width="100%">
<tbody>
<tr>
<td valign="top" width="598">
<p><strong><font size="4">javascript_eval.php</font></strong>             <br />(this is the new, reusable helper &#8211; to be placed into /app/views/helpers)</p>
</td>
</tr>
<tr>
<td valign="top" width="598"><code>
<p>&lt;?php              <br />/**               <br />* JavaScript Helper class file.               <br />*               <br />* @license <a href="http://www.opensource.org/licenses/mit-license.php">http://www.opensource.org/licenses/mit-license.php</a> The MIT License               <br />*/               <br />/**               <br />* JavascriptEx Helper class for easy use of (Cake)PHP to generate               <br />* JavaScript, from within a view/controller file.               <br />*               <br />*/               <br />class JavascriptEvalHelper extends AppHelper { </p>
<p>/**              <br />* File to evaluate in the current context               <br />* This needs to be a path (in the file system) to the JavaScript file -               <br />*&#160;&#160;&#160;&#160; it will be passed to the call to include               <br />*               <br />* You should set this before eval'ing evalScript               <br />*               <br />* @var string               <br />* @access public               <br />*/               <br />&#160;&#160;&#160; var $scriptToEvaluate = false; </p>
<p>/**              <br />* Code that needs to be passed to PHP's eval function. This               <br />*&#160;&#160;&#160;&#160; is set in the helper's constructor.               <br />*               <br />* You shouldn't need to change this, normally.               <br />*               <br />* @var string               <br />* @access public               <br />*/               <br />&#160;&#160;&#160; var $evalScript = false; </p>
<p>/**              <br />* The resulting, evaluated script               <br />*               <br />* This is roughly equivalent to a return value, if               <br />*&#160;&#160;&#160;&#160; this had been done using functions, instead of this               <br />*&#160;&#160;&#160;&#160; hacky eval thing <img src='http://panitzco.com/Mike/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' />                <br />*               <br />* @var string               <br />* @access public               <br />*/               <br />&#160;&#160;&#160; var $scriptResults = null; </p>
<p>&#160;&#160;&#160; function __construct() {              <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160; parent::__construct();               <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160; $this-&gt;scriptToEvaluate = &quot;&quot;; </p>
<p>$this-&gt;evalScript = &lt;&lt;&lt;THESCRIPT              <br />&#160;&#160;&#160; if( !isset( \$name_of_javascript_eval_object ) ) {               <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160; \$name_of_javascript_eval_object = &quot;javascriptEval&quot;;               <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160; // probably should do better error handling, here               <br />&#160;&#160;&#160; } </p>
<p>&#160;&#160;&#160; if ( \$\$name_of_javascript_eval_object-&gt;scriptToEvaluate == &quot;&quot; ) {              <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160; \$\$name_of_javascript_eval_object-&gt;scriptResults = &quot;NO SCRIPT TO EVALUATE&quot;;               <br />&#160;&#160;&#160; }               <br />&#160;&#160;&#160; else               <br />&#160;&#160;&#160; {               <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160; // pre-pend the /.../app/webroot/js/ onto the given filename               <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160; \$\$name_of_javascript_eval_object-&gt;scriptToEvaluate = APP.'webroot'.DS.'js'.DS. \$\$name_of_javascript_eval_object-&gt;scriptToEvaluate ;               <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160; if&#160;&#160;&#160; (!is_file(\$\$name_of_javascript_eval_object-&gt;scriptToEvaluate )) {               <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; \$\$name_of_javascript_eval_object-&gt;scriptResults = 'FILENAME ('.               <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; \$\$name_of_javascript_eval_object-&gt;scriptToEvaluate . ') IS NOT A VALID FILE!';               <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160; }               <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160; else {               <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; ob_start();               <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; include \$\$name_of_javascript_eval_object-&gt;scriptToEvaluate ;               <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; \$\$name_of_javascript_eval_object-&gt;scriptResults= ob_get_contents();               <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; ob_end_clean();               <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160; }               <br />&#160;&#160;&#160; }               <br />THESCRIPT;               <br />&#160;&#160;&#160; }               <br />}               <br />?&gt;</p>
<p>         </code></td>
</tr>
</tbody>
</table>
<p>You&#8217;ll notice that all the action is in the script that the constructor assigns to <strong>evalScript</strong>, using a <a href="http://php.net/manual/en/language.types.string.php#language.types.string.syntax.heredoc">heredoc</a>.&#160; Within the script, we check and see if $name_of_javascript_eval_object is defined, and if not, then we assign it a name that should typically work for view code (i.e,. in .CTP files).&#160; Next we check if scriptToEvaluate has been set (it must be set to a file underneath the /app/webroot/js/ directory).&#160; Following that, we assume the file&#8217;s name refers to something in the /app/webroot/js/ directory, and so we pre-pend /app/webroot/js/ to the provided script name.&#160; If that file doesn&#8217;t exist, then we stop, otherwise we go ahead and include it. </p>
<p>Note the clever use of <a href="http://us2.php.net/manual/en/language.variables.variable.php">variable variables</a> to allow someone to re-use this script in, say, a controller, by setting name_of_javascript_eval_object to be something other than the default javascriptEval.&#160; This does mean that we&#8217;re creating a local variable in the scope that wants to do the include, but name_of_javascript_eval_object seems like a sufficiently unique name that I just go ahead &amp; create it without checking.&#160; if you wanted to, you could check that it doesn&#8217;t already exist and/or <a href="http://us2.php.net/unset">unset</a> it before the script ends.</p>
<p>Here&#8217;s an example that uses this:</p>
<p>Controller file:</p>
<table border="1" cellspacing="0" cellpadding="2" width="600">
<tbody>
<tr>
<td valign="top" width="598">
<p><strong><font size="4">jse_controller.php</font></strong>             <br />(this is the controller &#8211; to be placed into /app/controllers/jse_controller.php)</p>
</td>
</tr>
<tr>
<td valign="top" width="598"><code>
<p>&lt;?php              <br />class JseController extends AppController { </p>
<p>&#160;&#160;&#160; var $name = 'Jse';              </p>
<p>&#160;&#160;&#160; // For this simple demo, make sure that               <br />&#160;&#160;&#160; // the controller does not use any model(s)               <br />&#160;&#160;&#160; var $uses = array();               </p>
<p>&#160;&#160;&#160; function demoEvaluator() {               <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160; $this-&gt;helpers[] = 'JavascriptEval';               <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160; $this-&gt;helpers[] = 'JavaScript';               <br />&#160;&#160;&#160; } </p>
<p>}              <br />?&gt;</p>
<p>         </code></td>
</tr>
</tbody>
</table>
<p>Other than adding the new JavascriptEval class and the core JavaScript class to the helpers array, this really doesn&#8217;t do much. </p>
<table border="1" cellspacing="0" cellpadding="2" width="600">
<tbody>
<tr>
<td valign="top" width="598">
<p><strong><font size="4">demo_evaluator.php</font></strong>             <br />(this is the view &#8211; to be placed into /app/views/jse/demo_evaluator.php)</p>
</td>
</tr>
<tr>
<td valign="top" width="598"><code>
<p>&lt;?php              <br />App::import('Sanitize'); </p>
<p>&#160;&#160;&#160; echo $javascript-&gt;link('jquery/jquery.js', false); // pull in jQuery </p>
<p>&#160;&#160;&#160; // Test #1: Forgot to set the evalScript field              <br />&#160;&#160;&#160; eval( $javascriptEval-&gt;evalScript );               <br />&#160;&#160;&#160; echo 'This should read \'NO SCRIPT TO EVALUATE\'&lt;br/&gt;&lt;pre&gt;'.Sanitize::html( $javascriptEval-&gt;scriptResults ).'&lt;/pre&gt;&lt;br/&gt;&lt;hr/&gt;'; </p>
<p>&#160;&#160;&#160; // Test #2: Didn't provide a valid filename (into the local filesystem)              <br />&#160;&#160;&#160; $javascriptEval-&gt;scriptToEvaluate = 'NonexistentFile.js';               <br />&#160;&#160;&#160; eval( $javascriptEval-&gt;evalScript );               <br />&#160;&#160;&#160; echo 'This should read \'FILENAME (...) IS NOT A VALID FILE\'&lt;br/&gt;&lt;pre&gt;'.Sanitize::html( $javascriptEval-&gt;scriptResults ).'&lt;/pre&gt;&lt;br/&gt;&lt;hr/&gt;';</p>
<p>&#160;&#160;&#160; // Test #3: This should include the JavaScript file, and evaluate it              <br />&#160;&#160;&#160; //&#160;&#160;&#160;&#160; as if it was copy-and-pasted in, right here               <br />&#160;&#160;&#160; $javascriptEval-&gt;scriptToEvaluate = 'JavaScriptToEval.js';               <br />&#160;&#160;&#160; eval( $javascriptEval-&gt;evalScript );               <br />&#160;&#160;&#160; echo Sanitize::html( 'This should be the JavaScript file, with &lt;?php ?&gt; element evaluated').               <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160; '&lt;br/&gt;&lt;pre&gt;'. Sanitize::html( $javascriptEval-&gt;scriptResults ).'&lt;/pre&gt;'; </p>
<p>&#160;&#160;&#160; // Normally, you'll want to include the resulting script in your page, like so:&#160;&#160;&#160; <br />&#160;&#160;&#160; $javascript-&gt;codeBlock( $javascriptEval-&gt;scriptResults, array('inline'=&gt;false)&#160; );               <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160; // Because we're using the 'inline' =&gt; false setting, Cake will put the code into a               <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160; // SCRIPT block in the head of the document.               <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160; // Therefore we don't need to echo it to the document here....               <br />?&gt;               <br />&lt;br/&gt;               <br />&lt;br/&gt;               <br />&lt;hr/&gt;               <br />&lt;br/&gt;               <br />&lt;br/&gt;               <br />&lt;h1&gt;This is the jQuery/CakePHP demo for the 'JavascriptEval' helper&lt;/h1&gt;               <br />&lt;p&gt;These lines were generated using normal CakePHP routines&lt;/p&gt; </p>
<p>&lt;?php              <br />&#160;&#160;&#160; // Simple, jQuery link that we'll use in the JavaScript               <br />&#160;&#160;&#160; echo $html-&gt;link(&quot;Click here!&quot;, &quot;#&quot;, array(&quot;id&quot;=&gt;'theLink'));               <br />?&gt;</p>
<p>         </code></td>
</tr>
</tbody>
</table>
<p>This does a couple of quick unit tests on the provided helper.&#160; It makes sure that the script will detect a missing filename, an incorrect filename, and that it will function correctly when given a correct filename.&#160; Note that the core of this (the &#8216;typical usage&#8217;) boils down to three key steps:</p>
<ol>
<li>Set the scriptToEvaluate field to the relative path of the file within /app/webroot/js/. </li>
<li>Use PHP&#8217;s eval function on the scriptToEvaluate field </li>
<li>Retrieve the scriptResults field, and then use the core JavaScript helper to put the evaluated script into the head of the document. </li>
</ol>
<table border="1" cellspacing="0" cellpadding="2" width="600">
<tbody>
<tr>
<td valign="top" width="598"><strong>Typical usage:</strong></td>
</tr>
<tr>
<td valign="top" width="598"><code>
<p>&lt;?php&#160; <br />&#160;&#160;&#160; $javascriptEval-&gt;scriptToEvaluate = 'JavaScriptToEval.js';</p>
<p>&#160;&#160;&#160; eval( $javascriptEval-&gt;evalScript );</p>
<p>&#160;&#160;&#160; $javascript-&gt;codeBlock( $javascriptEval-&gt;scriptResults, array('inline'=&gt;false)&#160; );              <br />?&gt;</p>
<p>         </code></td>
</tr>
</tbody>
</table>
<p>Note that because the helper assumes that we&#8217;ll be using it in a view, we do not need to set the <strong>name_of_javascript_eval_object</strong> variable.&#160; </p>
<table border="1" cellspacing="0" cellpadding="2" width="600">
<tbody>
<tr>
<td valign="top" width="598">
<p><strong><font size="4">JavascriptToEval.php</font></strong>             <br />(this is the JavaScript&#160; &#8211; to be placed into /app/webroot/js/JavascriptToEval.js)</p>
</td>
</tr>
<tr>
<td valign="top" width="598"><code>
<p>/**              <br />* @author Panitz               <br />*/ </p>
<p>alert(&quot;Hello, from evaluated JavaScript!&quot;); </p>
<p>var outputString = &lt;?php </p>
<p>echo '&quot;hello, world!\n'; // note the &quot; inside to start the string </p>
<p>for( $i = 0; $i &lt; 4; $i++) {              <br />&#160;&#160;&#160; echo 'Iteration '. $i .'\n';               <br />}               <br />echo '&quot;               <br />'; // don't forget to close the string! </p>
<p>// The real goal: Note the use of the CakePHP things that we're              <br />// using, just as if this code was executing inside the .CTP file               <br />//&#160;&#160;&#160; (which it is <img src='http://panitzco.com/Mike/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' /> &#160; )               <br />$testHTML=&quot;&lt;h1&gt;BigTitle&lt;/h1&gt;&quot;;               <br />echo 'alert(&quot;sanitized html:\n'. Sanitize::html($testHTML) .'&quot;);'; </p>
<p>echo $javascript-&gt;codeBlock(&quot;//Using the core JavaScript Helper!&quot;, array('inline'=&gt;false)) </p>
<p>?&gt; </p>
<p>$(document).ready(function(){              <br />&#160;&#160;&#160; $(&quot;#theLink&quot;).click( function() {               <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160; alert(outputString);               <br />&#160;&#160;&#160; } ); </p>
<p>});</p>
<p>         </code></td>
</tr>
</tbody>
</table>
<p>This basically contains a bunch of small tests, in order to demonstrate what you can do with this helper.&#160; When you actually use this helper yourself, you&#8217;d want to replace the contents of this file with the JavaScript that you want to dynamically generate using (Cake)PHP.&#160; </p>
<p>The first alert confirms that the JavaScript is loading correctly.&#160; We then use PHP to generate a JavaScript string that we&#8217;ll use later on.</p>
<p>We then get into the really useful/interesting stuff &#8211; since the view imported the Sanitize class, we can use it here.&#160; Similarly, we can use the helpers that the view has access to, such as the $javascript helper.</p>
<p>Following all that, we have an ultra-simple use of jQuery (which I talked about in my <a href="http://panitzco.com/Mike/tech/jquery/using-jquery-with-cakephp-the-basics/">prior post</a>)</p>
<h3>A better way?</h3>
<p>My original motivation for doing this was being able to create JavaScript code that could deal with dynamically created forms.&#160; For example, I might want to create a single page that contains a list of all the assignments the students will do in a term, with a bit of JavaScript/jQuery attached to each item, so that each and every item can have it&#8217;s own rich interface (for example, having each item include a <a href="http://docs.jquery.com/UI/Datepicker">datepicker control</a>).</p>
<p>In retrospect, I think that it&#8217;s possible (and better) to write the jQuery code so that it will attach event handlers to all of the UI elements (possibly by &#8216;tagging&#8217; each one with a CSS class), and then just use that one, single, cache-able, normal JavaScript file instead of dynamically generating code for each client.</p>
<p>Still, the above hack is pretty darn cool, and was fun to try out <img src='http://panitzco.com/Mike/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' /> </p>
<p><strong><font color="#0000ff">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. </font></strong></p>
]]></content:encoded>
			<wfw:commentRss>http://panitzco.com/Mike/tech/generating-jquery-code-from-your-cakephp-controllerview/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Using jQuery with CakePHP: The Basics</title>
		<link>http://panitzco.com/Mike/tech/jquery/using-jquery-with-cakephp-the-basics/</link>
		<comments>http://panitzco.com/Mike/tech/jquery/using-jquery-with-cakephp-the-basics/#comments</comments>
		<pubDate>Mon, 22 Jun 2009 09:53:39 +0000</pubDate>
		<dc:creator>Mike</dc:creator>
				<category><![CDATA[CakePHP]]></category>
		<category><![CDATA[jQuery]]></category>

		<guid isPermaLink="false">http://panitzco.com/Mike/?p=43</guid>
		<description><![CDATA[First steps towards a drag-and-drop, calendar-based interface for assigning due dates in my StudentTracker web app.
It&#8217;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&#8217;m thinking about sprucing up my StudentTracker&#169; web app.  I wrote [...]]]></description>
			<content:encoded><![CDATA[<h6>First steps towards a drag-and-drop, calendar-based interface for assigning due dates in my StudentTracker web app.</h6>
<p>It&#8217;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&#8217;m thinking about sprucing up my StudentTracker&copy; web app.  I wrote the <a href="http://cakephp.org/">CakePHP</a>-based version last summer, so that my students could submit their homework online this past year.  It&#8217;s worked well, but there&#8217;s always that extra something that I want to add to it <img src='http://panitzco.com/Mike/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' /> </p>
<p>One feature that I didn&#8217;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&#8217;d hit that stage where &#8220;I can always add more features/fiddle with it needlessly!!&#8221;, so I stopped working on it.  On top of that, I had tried to use CakePHP&#8217;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 <em>polling</em>).</p>
<p>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&#8217;s Google Group, etc, etc.</p>
<p>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 &#8216;TODO&#8217; 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&#8217;d like to continue managing due dates myself so that consistently hard-working students who occasionally get a bit behind don&#8217;t get penalized.  StudentTracker can then tell each student what that student still needs to do.</p>
<p>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&#8217;s easy to make mistakes.  Plus, when you&#8217;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 &#8211; 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 &#8216;Are you paying attention?&#8217; quizzes,  you can easily pile up 20-30 due dates per course that you&#8217;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.</p>
<p>Thus, my immediate goal is to incorporate a &#8216;date picker&#8217; UI widget into my web app.</p>
<p>After looking around for a while, I decided to use the <a href="http://jqueryui.com/">jQuery UI</a>&#8217;s <a href="http://jqueryui.com/demos/datepicker/">Datepicker</a>, because it looks nice, seems functional, and because I&#8217;ve heard a lot of good things about jQuery.  Plus, jQuery has a <a href="http://plugins.jquery.com/project/fullcalendar">FullCalendar</a> 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 &#8216;relative due dates&#8217; (to make it easier to move assignments to a new quarter), are topics for future posts.</p>
<p>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&#8217;m assuming that you&#8217;ve both used jQuery a bit, and that you&#8217;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.</p>
<table border="1" cellspacing="0" cellpadding="2" width="100%">
<tbody>
<tr>
<td width="668" valign="top">
<p align="center"><strong><span style="font-size: large">In a nutshell:</span></strong></p>
<ol>
<li>
<div><a href="#Step_1">Create your normal CakePHP pages: the controller file, the view file, and all the required code therein.</a></div>
</li>
<li>
<div><a href="#Step_2">Link to jQuery (either to Google’s copy, or to your own local copy) from the view (.ctp) file</a></div>
</li>
<li>
<div><a href="#Step_3">Create your own JavaScript file in the app/webroot/js directory, and link to it</a></div>
</li>
<li><a href="#Step_4">You’re now off and running with jQuery and CakePHP!</a></li>
</ol>
</td>
</tr>
</tbody>
</table>
<p>Let’s go through the above steps in more detail.</p>
<p>1. <strong><a name="Step_1">Create</a> your normal CakePHP pages</strong></p>
<div style="text-align: center; padding-bottom: 5px; border-right-width: 0px; margin: 5px; padding-left: 5px; padding-right: 5px; float: right; border-top-width: 0px; border-bottom-width: 0px; font-size: 80%; border-left-width: 0px; padding-top: 5px"><a name="file_placement"><img title="File_Placement" src="http://panitzco.com/Mike/wp-content/uploads/2009/06/File_Placement1.png" border="0" alt="File_Placement" width="230" height="460" /></a><strong>Figure 1:</strong> Directory structure</div>
<p>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 &#8216;Model&#8217;, but adding that in won’t be difficult.</p>
<p>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 <a href="http://localhost/Demos/demo/jQueryDemo/"><span style="color: #c0c0c0">http://localhost/Demos/</span><strong>demo/jQueryDemo/</strong></a>, so the controller must therefore be placed in a file named demo_controller.php (in the <strong>app/controllers</strong> folder).</p>
<p>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.</p>
<p>Just in case it&#8217;s useful, I&#8217;m also providing <a href="http://panitzco.com/Files/app.zip">a .ZIP file that contains all the files I discuss in this post</a>.  It&#8217;s set up so that you should be able to extract this into your <strong>app</strong> directory, and have the files and folders appear in the correct place.</p>
<table border="1" cellspacing="0" cellpadding="2" width="100%">
<tbody>
<tr>
<td width="460" valign="top"><span style="font-family: courier new">&lt;?php<br/>class DemoController extends AppController {var $name = &#8216;Demo&#8217;;</p>
<p>// For this simple demo, make sure that</p>
<p>// the controller does not use any model</p>
<p>var $uses = array();</p>
<p><span style="font-family: courier new"><span style="font-family: courier new">    function jQueryDemo() {</span> </span></p>
<p>//        Configure::write(&#8217;debug&#8217;, 3);</p>
<p>$this-&gt;helpers[] = &#8216;Javascript&#8217;;</p>
<p>}</p>
<p>}</p>
<p>?&gt;</p>
<p> </p>
<p></span></td>
</tr>
</tbody>
</table>
<p>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 <strong>app/views</strong> folder).  The contents of this file is a little bit more interesting, as we’ll explore in the next step</p>
<p align="left">2. <strong><a name="Step_2">Link</a> to jQuery </strong></p>
<p align="left">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).</p>
<p><a href="http://encosia.com/2008/12/10/3-reasons-why-you-should-let-google-host-jquery-for-you/">http://encosia.com/2008/12/10/3-reasons-why-you-should-let-google-host-jquery-for-you/</a> 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&#8217;m guessing that linking to Google&#8217;s copy and <em>downloading a local backup copy for yourself</em> is probably the best way to go.</p>
<p>We’ll look at what we’ve got here in the &lt;?php ?&gt; 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)</p>
<p align="left">2a:<strong> Link to jQuery (Google’s copy) </strong></p>
<p align="left">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 &#8216;false&#8217; parameter says NOT to put the code here (i.e., not to inline it), but instead to put it in the &lt;head&gt; of the document.</p>
<p align="left">The second $javascript-&gt;link will create a link to our jQuery code, which (because we’re writing it ourselves) must reside locally.</p>
<table border="1" cellspacing="0" cellpadding="2" width="100%">
<tbody>
<tr>
<td width="695" valign="top"><span style="font-family: courier new">&lt;?php<br/>echo $javascript-&gt;link(&#8217;<a href="http://ajax.googleapis.com/ajax/libs/jquery/1.3.2/jquery.min.js'"><span style="font-family: courier new">http://ajax.googleapis.com/ajax/libs/jquery/1.3.2/jquery.min.js&#8217;</span></a><span style="font-family: courier new">, false); </span><span style="font-family: courier new">    echo $javascript-&gt;link(&#8217;demo/jQueryDemo&#8217;, false);</span></p>
<p>?&gt;</p>
<p>&lt;p id=&#8221;theTarget&#8221;&gt;Starting Text&lt;/p&gt;</p>
<p><span style="font-family: courier new">&lt;a href=&#8221;#&#8221;&gt;Click me!&#8221;&lt;/a&gt; </span></p>
<p><span style="font-family: courier new">&lt;p id=&#8221;clickTarget&#8221;&gt;Number: 0&lt;/p&gt;</span></p>
<p> </p>
<p></span></td>
</tr>
</tbody>
</table>
<p align="left">
<p align="left">2b:<strong> Link to jQuery (your own, local copy) </strong></p>
<p align="left">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&#8217;t have to worry about Google&#8217;s copy going away, or changing (such as when the &#8216;latest&#8217; version changes to something newer), plus this will work if you&#8217;re going to deploy your app onto a LAN that might not be connected to the internet.</p>
<p align="left">You can get yourself a copy of the core jQuery library at: <a title="http://docs.jquery.com/Downloading_jQuery" href="http://docs.jquery.com/Downloading_jQuery">http://docs.jquery.com/Downloading_jQuery</a></p>
<p align="left">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 <a href="#file_placement">depicted in Figure 1, above</a>.  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 &#8216;false&#8217; parameter says NOT to put the code here (i.e., not to inline it), but instead to put it in the &lt;head&gt; of the document.</p>
<p align="left">The second $javascript-&gt;link will create a link to our jQuery code, which (because we’re writing it ourselves) must reside locally.</p>
<table border="1" cellspacing="0" cellpadding="2" width="100%">
<tbody>
<tr>
<td width="695" valign="top"><span style="font-family: courier new">&lt;?php<br/>echo $javascript-&gt;link(&#8217;jquery/jquery&#8217;, false); // in app/webroot/js/jquery folder,// link to &#8216;jquery.js&#8217; file</p>
<p><span style="font-family: courier new">    echo $javascript-&gt;link(&#8217;demo/jQueryDemo&#8217;, false);</span></p>
<p>?&gt;</p>
<p>&lt;p id=&#8221;theTarget&#8221;&gt;Starting Text&lt;/p&gt;</p>
<p><span style="font-family: courier new">&lt;a href=&#8221;#&#8221;&gt;Click me!&#8221;&lt;/a&gt; </span></p>
<p><span style="font-family: courier new">&lt;p id=&#8221;clickTarget&#8221;&gt;Number: 0&lt;/p&gt;</span></p>
<p> </p>
<p></span></td>
</tr>
</tbody>
</table>
<p align="left">
<p align="left">
<p align="left">3. <strong><a name="Step_3">Create</a> your own JavaScript file in the app/webroot/js directory, and link to it</strong></p>
<p>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&#8217;s JavaScript helper, you should put it in the app/webroot/js folder, probably in a sub-folder named for your controller.  <a href="#file_placement">In Figure 1 (above)</a> I put the jQueryDemo.js file into the folder <strong>app/webroot/js/demo</strong>, since the controller is named DemoController.</p>
<p>Remember that we linked to this file in the view (.ctp) file using the line:</p>
<p><span style="font-family: courier new">    echo $javascript-&gt;link(&#8217;demo/jQueryDemo&#8217;, false); </span></p>
<p>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 <a href="http://docs.jquery.com/Tutorials:Getting_Started_with_jQuery">http://docs.jquery.com/Tutorials:Getting_Started_with_jQuery</a>, you’ll be up and running with jQuery (and now CakePHP!).  Here&#8217;s a quick, commented tour through the jQueryDemo.js file:</p>
<table border="1" cellspacing="0" cellpadding="2" width="100%">
<tbody>
<tr>
<td width="598" valign="top"><span style="font-family: courier new">/*** @author Mike Panitz*/</p>
<p><span style="font-family: courier new">var counter = 1; </span></p>
<p><span style="font-family: courier new"><strong>$(document).ready(function(){</strong> </span></p>
<p>               alert(&#8221;Executing jQuery &#8216;onReady&#8217; script!&#8221;);// pop up this alert when</p>
<p>// jQuery runs this method.  You’ll be able</p>
<p>// to see the &#8220;Starting Text&#8221;</p>
<p>// at the top of the page <span style="font-family: courier new"><span style="font-family: courier new">    $(&#8221;#theTarget&#8221;).text(&#8221;New text!&#8221;);</span> </span></p>
<p><span style="font-family: courier new">    // This will change the &#8216;Starting Text&#8217; to</span></p>
<p><span style="font-family: courier new">    // &#8220;New Text!&#8221; <span style="font-family: courier new"><span style="font-family: courier new">    // When any link is clicked, alert the user,</span> </span></span></p>
<p><span style="font-family: courier new">    // then change the text of #clickTarget</span></p>
<p>$(&#8221;a&#8221;).click( function() {</p>
<p>alert(&#8221;You clicked on the link!&#8221;);</p>
<p>$(&#8221;#clickTarget&#8221;).text(&#8221;Number:&#8221; + counter++);</p>
<p>}  );</p>
<p><strong>});</strong></p>
<p></span></td>
</tr>
</tbody>
</table>
<p align="left">4. <strong><a name="Step_4">You’re</a> now off and running with jQuery and CakePHP!</strong></p>
<p>Load up the page, and you&#8217;ll see something like:</p>
<p><a href="http://panitzco.com/Mike/wp-content/uploads/2009/06/Starting_View.png"><img style="border-right-width: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px" title="Starting_View" src="http://panitzco.com/Mike/wp-content/uploads/2009/06/Starting_View_thumb.png" border="0" alt="Starting_View" width="512" height="161" /></a></p>
<p>Once you&#8217;ve clicked on the alert box, the top line of text will change and you&#8217;ll see something like:</p>
<p><a href="http://panitzco.com/Mike/wp-content/uploads/2009/06/After_ready.png"><img style="border-right-width: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px" title="After_ready" src="http://panitzco.com/Mike/wp-content/uploads/2009/06/After_ready_thumb.png" border="0" alt="After_ready" width="432" height="117" /></a></p>
<p>Click that link a couple of times, and you&#8217;ll see the bottom line of text update, like so:</p>
<p><a href="http://panitzco.com/Mike/wp-content/uploads/2009/06/After_several_clicks.png"><img style="border-right-width: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px" title="After_several_clicks" src="http://panitzco.com/Mike/wp-content/uploads/2009/06/After_several_clicks_thumb1.png" border="0" alt="After_several_clicks" width="496" height="107" /></a></p>
<p><strong><span style="color: #0000ff">I&#8217;d love to hear if this post helped you out, if you&#8217;ve got further questions, or if you&#8217;ve got feedback on my blog.  </span></strong></p>
]]></content:encoded>
			<wfw:commentRss>http://panitzco.com/Mike/tech/jquery/using-jquery-with-cakephp-the-basics/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
	</channel>
</rss>
