<?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>Graphics by Greg &#187; Web Development</title>
	<atom:link href="http://www.gregphoto.net/index.php/category/web-development/feed/" rel="self" type="application/rss+xml" />
	<link>http://www.gregphoto.net</link>
	<description>Just another WordPress weblog</description>
	<lastBuildDate>Sat, 27 Jun 2009 22:11:08 +0000</lastBuildDate>
	<generator>http://wordpress.org/?v=abc</generator>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
			<item>
		<title>Playing mp3s with SoundManager 2</title>
		<link>http://www.gregphoto.net/index.php/2008/11/23/playing-mp3s-with-soundmanager-2/</link>
		<comments>http://www.gregphoto.net/index.php/2008/11/23/playing-mp3s-with-soundmanager-2/#comments</comments>
		<pubDate>Mon, 24 Nov 2008 01:10:32 +0000</pubDate>
		<dc:creator>Greg</dc:creator>
				<category><![CDATA[Music]]></category>
		<category><![CDATA[Web Development]]></category>

		<guid isPermaLink="false">http://www.gregphoto.net/?p=56</guid>
		<description><![CDATA[My friend Michael Ross is a musician and he sent me an email with a couple of the songs he recorded recently.  I asked him if he would like me to put together a simple web page for his songs so that he didn&#8217;t have to send out emails with large attachments, and a [...]]]></description>
			<content:encoded><![CDATA[<p>My friend Michael Ross is a musician and he sent me an email with a couple of the songs he recorded recently.  I asked him if he would like me to put together a simple web page for his songs so that he didn&#8217;t have to send out emails with large attachments, and a week or so later we had a new site up and running for him &#8211; <a href="http://www.michaelrossmusic.net">www.michaelrossmusic.net</a>.  He wanted a page that listed the albums, had links to download mp3 songs, and a way for people to listen to the songs without downloading them.  I had used <a href="http://www.schillmania.com/projects/soundmanager2/">SoundManager 2</a> <a href="http://www.gregandyenari.com/happyholidays">previously</a> to have mp3s play on a page, so I knew that it would be a good fit.</p>
<p>I wanted to be able to build a simple page with regular links to the mp3 files and for JavaScript to do the magic of making the songs playable in the browser &#8211; this post explains how I made it happen.  SoundManager 2 is a JavaScript library built on top of Flash &#8211; the music plays through Flash (which has much better audio support than browsers), but everything is controlled via JavaScript.  I also used <a href="http://www.prototypejs.org">Prototype</a> as a framework to build out the functionality.</p>
<p>Here&#8217;s what I did:</p>
<ol>
<li>Created a <a href="http://www.michaelrossmusic.net">simple page</a> with links to mp3 files</li>
<li>Added a SoundManager handler so that as soon as it loads it instantiates PagePlayer, a JavaScript class I created</li>
<li>PagePlayer takes a CSS selector as input (and optionally an options object) and identifies all of the links that match the selector &#8211; &#8216;a.mp3Link&#8217; in this case (all links with the class &#8216;mp3Link&#8217;).</li>
<li>For each of the identified links, PagePlayer creates a SoundManager sound object using the link to the mp3, adds a play button just prior to the song link, creates event handlers for the play button and sound object, and stores the song in a hash</li>
<li>The event handlers take care of all of the logic: playing songs, making sure that only a single song is playing, changing the state of the button from play to stop</li>
</ol>
<p>Here&#8217;s a current snapshot of the script:</p>

<div class="wp_syntax"><table><tr><td class="line_numbers"><pre>1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
</pre></td><td class="code"><pre class="javascript" style="font-family:monospace;">PagePlayer <span style="color: #339933;">=</span> <span style="color: #003366; font-weight: bold;">Class</span>.<span style="color: #660066;">create</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#123;</span>
	songCount<span style="color: #339933;">:</span> <span style="color: #CC0000;">0</span><span style="color: #339933;">,</span>
	songs<span style="color: #339933;">:</span> <span style="color: #003366; font-weight: bold;">new</span> Hash<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">,</span>
	nowPlaying<span style="color: #339933;">:</span> <span style="color: #003366; font-weight: bold;">null</span><span style="color: #339933;">,</span>
	options<span style="color: #339933;">:</span> <span style="color: #003366; font-weight: bold;">null</span><span style="color: #339933;">,</span>
&nbsp;
	initialize<span style="color: #339933;">:</span> <span style="color: #003366; font-weight: bold;">function</span><span style="color: #009900;">&#40;</span>selector<span style="color: #339933;">,</span> options<span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
		<span style="color: #000066; font-weight: bold;">this</span>.<span style="color: #660066;">options</span> <span style="color: #339933;">=</span> <span style="color: #009900;">&#123;</span>
			imgPath<span style="color: #339933;">:</span> <span style="color: #3366CC;">'images/'</span><span style="color: #339933;">,</span>
			imgPlay<span style="color: #339933;">:</span> <span style="color: #3366CC;">'control_play.png'</span><span style="color: #339933;">,</span>
			imgStop<span style="color: #339933;">:</span> <span style="color: #3366CC;">'control_stop.png'</span><span style="color: #339933;">,</span>
			mp3LinkTitle<span style="color: #339933;">:</span> <span style="color: #3366CC;">'Download song'</span>
		<span style="color: #009900;">&#125;</span><span style="color: #339933;">;</span>
		Object.<span style="color: #660066;">extend</span><span style="color: #009900;">&#40;</span><span style="color: #000066; font-weight: bold;">this</span>.<span style="color: #660066;">options</span><span style="color: #339933;">,</span> options <span style="color: #339933;">||</span> <span style="color: #009900;">&#123;</span><span style="color: #009900;">&#125;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
		$$<span style="color: #009900;">&#40;</span>selector<span style="color: #009900;">&#41;</span>.<span style="color: #660066;">each</span><span style="color: #009900;">&#40;</span><span style="color: #000066; font-weight: bold;">this</span>.<span style="color: #660066;">addSong</span><span style="color: #339933;">,</span><span style="color: #000066; font-weight: bold;">this</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
	<span style="color: #009900;">&#125;</span><span style="color: #339933;">,</span>
&nbsp;
	addSong<span style="color: #339933;">:</span> <span style="color: #003366; font-weight: bold;">function</span><span style="color: #009900;">&#40;</span>mp3Link<span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
		mp3Link.<span style="color: #660066;">title</span> <span style="color: #339933;">=</span> <span style="color: #000066; font-weight: bold;">this</span>.<span style="color: #660066;">options</span>.<span style="color: #660066;">mp3LinkTitle</span><span style="color: #339933;">;</span>
		<span style="color: #003366; font-weight: bold;">var</span> songId <span style="color: #339933;">=</span> mp3Link.<span style="color: #660066;">identify</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
		<span style="color: #003366; font-weight: bold;">var</span> soundObj <span style="color: #339933;">=</span> soundManager.<span style="color: #660066;">createSound</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#123;</span>
			id<span style="color: #339933;">:</span> songId<span style="color: #339933;">,</span>
			url<span style="color: #339933;">:</span> mp3Link.<span style="color: #660066;">href</span><span style="color: #339933;">,</span>
			onfinish<span style="color: #339933;">:</span> <span style="color: #000066; font-weight: bold;">this</span>.<span style="color: #660066;">finishHandler</span>.<span style="color: #660066;">bind</span><span style="color: #009900;">&#40;</span><span style="color: #000066; font-weight: bold;">this</span><span style="color: #339933;">,</span>songId<span style="color: #009900;">&#41;</span>
		<span style="color: #009900;">&#125;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
		<span style="color: #003366; font-weight: bold;">var</span> controlBtn <span style="color: #339933;">=</span> <span style="color: #003366; font-weight: bold;">new</span> Element<span style="color: #009900;">&#40;</span><span style="color: #3366CC;">'img'</span><span style="color: #339933;">,</span><span style="color: #009900;">&#123;</span>
			src<span style="color: #339933;">:</span> <span style="color: #000066; font-weight: bold;">this</span>.<span style="color: #660066;">options</span>.<span style="color: #660066;">imgPath</span> <span style="color: #339933;">+</span> <span style="color: #000066; font-weight: bold;">this</span>.<span style="color: #660066;">options</span>.<span style="color: #660066;">imgPlay</span><span style="color: #339933;">,</span>
			className<span style="color: #339933;">:</span> <span style="color: #3366CC;">'audioControl'</span>
		<span style="color: #009900;">&#125;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
		mp3Link.<span style="color: #660066;">insert</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#123;</span>before<span style="color: #339933;">:</span> controlBtn<span style="color: #009900;">&#125;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
		controlBtn.<span style="color: #660066;">observe</span><span style="color: #009900;">&#40;</span><span style="color: #3366CC;">'click'</span><span style="color: #339933;">,</span> <span style="color: #000066; font-weight: bold;">this</span>.<span style="color: #660066;">toggleHandler</span>.<span style="color: #660066;">bind</span><span style="color: #009900;">&#40;</span><span style="color: #000066; font-weight: bold;">this</span><span style="color: #339933;">,</span>songId<span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
		<span style="color: #000066; font-weight: bold;">this</span>.<span style="color: #660066;">songs</span>.<span style="color: #660066;">set</span><span style="color: #009900;">&#40;</span>songId<span style="color: #339933;">,</span> <span style="color: #009900;">&#123;</span>
			controlBtn<span style="color: #339933;">:</span> controlBtn<span style="color: #339933;">,</span>
			soundObj<span style="color: #339933;">:</span> soundObj
		<span style="color: #009900;">&#125;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
		<span style="color: #000066; font-weight: bold;">this</span>.<span style="color: #660066;">songCount</span><span style="color: #339933;">++;</span>
	<span style="color: #009900;">&#125;</span><span style="color: #339933;">,</span>
&nbsp;
	toggleHandler<span style="color: #339933;">:</span> <span style="color: #003366; font-weight: bold;">function</span><span style="color: #009900;">&#40;</span>songId<span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
		<span style="color: #003366; font-weight: bold;">var</span> oldSong <span style="color: #339933;">=</span> <span style="color: #000066; font-weight: bold;">this</span>.<span style="color: #660066;">nowPlaying</span><span style="color: #339933;">;</span>
		<span style="color: #003366; font-weight: bold;">var</span> newSong <span style="color: #339933;">=</span> <span style="color: #000066; font-weight: bold;">this</span>.<span style="color: #660066;">songs</span>.<span style="color: #660066;">get</span><span style="color: #009900;">&#40;</span>songId<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
		<span style="color: #000066; font-weight: bold;">if</span><span style="color: #009900;">&#40;</span>oldSong<span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
			oldSong.<span style="color: #660066;">soundObj</span>.<span style="color: #000066;">stop</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
			oldSong.<span style="color: #660066;">controlBtn</span>.<span style="color: #660066;">src</span> <span style="color: #339933;">=</span> <span style="color: #000066; font-weight: bold;">this</span>.<span style="color: #660066;">options</span>.<span style="color: #660066;">imgPath</span> <span style="color: #339933;">+</span> <span style="color: #000066; font-weight: bold;">this</span>.<span style="color: #660066;">options</span>.<span style="color: #660066;">imgPlay</span><span style="color: #339933;">;</span>
			<span style="color: #000066; font-weight: bold;">if</span><span style="color: #009900;">&#40;</span>oldSong <span style="color: #339933;">===</span> newSong<span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
				<span style="color: #000066; font-weight: bold;">this</span>.<span style="color: #660066;">nowPlaying</span> <span style="color: #339933;">=</span> <span style="color: #003366; font-weight: bold;">null</span><span style="color: #339933;">;</span>
				<span style="color: #000066; font-weight: bold;">return</span><span style="color: #339933;">;</span>
			<span style="color: #009900;">&#125;</span>
		<span style="color: #009900;">&#125;</span>
&nbsp;
		newSong.<span style="color: #660066;">controlBtn</span>.<span style="color: #660066;">src</span> <span style="color: #339933;">=</span> <span style="color: #000066; font-weight: bold;">this</span>.<span style="color: #660066;">options</span>.<span style="color: #660066;">imgPath</span> <span style="color: #339933;">+</span> <span style="color: #000066; font-weight: bold;">this</span>.<span style="color: #660066;">options</span>.<span style="color: #660066;">imgStop</span><span style="color: #339933;">;</span>
		newSong.<span style="color: #660066;">soundObj</span>.<span style="color: #660066;">play</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
		<span style="color: #000066; font-weight: bold;">this</span>.<span style="color: #660066;">nowPlaying</span> <span style="color: #339933;">=</span> newSong<span style="color: #339933;">;</span>
	<span style="color: #009900;">&#125;</span><span style="color: #339933;">,</span>
&nbsp;
	finishHandler<span style="color: #339933;">:</span> <span style="color: #003366; font-weight: bold;">function</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
		<span style="color: #000066; font-weight: bold;">this</span>.<span style="color: #660066;">nowPlaying</span>.<span style="color: #660066;">controlBtn</span>.<span style="color: #660066;">src</span> <span style="color: #339933;">=</span> <span style="color: #000066; font-weight: bold;">this</span>.<span style="color: #660066;">options</span>.<span style="color: #660066;">imgPath</span> <span style="color: #339933;">+</span> <span style="color: #000066; font-weight: bold;">this</span>.<span style="color: #660066;">options</span>.<span style="color: #660066;">imgPlay</span><span style="color: #339933;">;</span>
		<span style="color: #000066; font-weight: bold;">this</span>.<span style="color: #660066;">nowPlaying</span> <span style="color: #339933;">=</span> <span style="color: #003366; font-weight: bold;">null</span><span style="color: #339933;">;</span>
	<span style="color: #009900;">&#125;</span>
<span style="color: #009900;">&#125;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span></pre></td></tr></table></div>

<p>And on the page it is started up as follows:</p>

<div class="wp_syntax"><table><tr><td class="line_numbers"><pre>1
2
3
4
5
6
7
8
</pre></td><td class="code"><pre class="html" style="font-family:monospace;">&lt;script src=&quot;js/soundmanager2-nodebug-jsmin.js&quot;&gt;&lt;/script&gt;
&lt;script src=&quot;js/pagePlayer.js&quot;&gt;&lt;/script&gt;
&lt;script&gt;
	soundManager.url = '';
	soundManager.onload = function() {
		new PagePlayer('a.mp3Link');
	};
&lt;/script&gt;</pre></td></tr></table></div>

<p>It&#8217;s not the prettiest code, but it gets the job done in 1.58 KB of code and works at least in recent versions of Firefox, IE, Safari, and Chrome.  So, if you need to add some mp3s to a page, check out <a href="http://www.schillmania.com/projects/soundmanager2/">SoundManager 2</a> &#8211; it&#8217;s easy to use, well documented, and super flexible&#8230;</p>
]]></content:encoded>
			<wfw:commentRss>http://www.gregphoto.net/index.php/2008/11/23/playing-mp3s-with-soundmanager-2/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>Yelp for the iPhone</title>
		<link>http://www.gregphoto.net/index.php/2007/12/03/yelp-for-the-iphone/</link>
		<comments>http://www.gregphoto.net/index.php/2007/12/03/yelp-for-the-iphone/#comments</comments>
		<pubDate>Tue, 04 Dec 2007 05:51:12 +0000</pubDate>
		<dc:creator>Greg</dc:creator>
				<category><![CDATA[Web Development]]></category>

		<guid isPermaLink="false">http://www.gregphoto.net/index.php/2007/12/03/yelp-for-the-iphone/</guid>
		<description><![CDATA[I just put together my first simple website for my new toy &#8211; my iPhone.  It is a simple iPhone-specific interface for Yelp, my favorite source for restaurant and other local reviews. They have a ton of reviews for just about every local restaurant so I find myself using it all the time to [...]]]></description>
			<content:encoded><![CDATA[<p>I just put together <a href="http://www.gregphoto.net/projects/yelp">my first simple website</a> for my new toy &#8211; my iPhone.  It is a simple iPhone-specific interface for <a href="http://www.yelp.com">Yelp</a>, my favorite source for restaurant and other local reviews. They have a ton of reviews for just about every local restaurant so I find myself using it all the time to find new restaurants to go to or to find more info about restaurants I already know.  I could access the website just fine already on my phone, but it was a bit crowded and difficult to navigate on a small screen, so I decided it take this as a challenge to build my first iPhone web interface.</p>
<p>And yes, I&#8217;m probably about the 58th person to build a Yelp interface for the iPhone, but I was looking for something I&#8217;d actually use and learn from!</p>
<p>Yelp provides a REST search API that allows you to pass in a location and a search term and they return a JSON object with a list of matching businesses, their ratings, and the business info.  I used the Zend Framework and the Prototype JavaScript library to put it together.  I could have done a pure JavaScript implementation using script hacks, but figured it&#8217;d be better to have the PHP code serve as a basic proxy for the Yelp web service.</p>
<p><a href="http://www.gregphoto.net/projects/yelp">Try it out!</a></p>
]]></content:encoded>
			<wfw:commentRss>http://www.gregphoto.net/index.php/2007/12/03/yelp-for-the-iphone/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>Announcing Gregphoto_Image &#8211; a PHP5/GD2 Thumbnail Class</title>
		<link>http://www.gregphoto.net/index.php/2007/02/03/announcing-gregphoto_image-a-php5gd2-thumbnail-class/</link>
		<comments>http://www.gregphoto.net/index.php/2007/02/03/announcing-gregphoto_image-a-php5gd2-thumbnail-class/#comments</comments>
		<pubDate>Sat, 03 Feb 2007 21:41:41 +0000</pubDate>
		<dc:creator>Greg</dc:creator>
				<category><![CDATA[PHP]]></category>
		<category><![CDATA[Web Development]]></category>

		<guid isPermaLink="false">http://www.gregphoto.net/index.php/2007/02/03/announcing-gregphoto_image-a-php5gd2-thumbnail-class/</guid>
		<description><![CDATA[I put together a simple, lightweight PHP class for generating thumbnail images.  The class is compatible with PHP5 and uses the GD2 extension (included by default with PHP5) to create JPEG, PNG, and GIF thumbnails.  I&#8217;ve setup a Google Code project for it: Gregphoto_Image where you can checkout the source from SVN and [...]]]></description>
			<content:encoded><![CDATA[<p>I put together a simple, lightweight PHP class for generating thumbnail images.  The class is compatible with PHP5 and uses the GD2 extension (included by default with PHP5) to create JPEG, PNG, and GIF thumbnails.  I&#8217;ve setup a <a href="http://code.google.com/hosting">Google Code</a> project for it: <a href="http://code.google.com/p/gregphotoimage/">Gregphoto_Image</a> where you can checkout the source from SVN and file bugs.</p>
<p>The class has the following basic features:</p>
<ul>
<li>Ability to read JPEG, PNG, or GIF images</li>
<li>Ability to output JPEG, PNG, or GIF images</li>
<li>4 modes of thumbnail creation
<ul>
<li><i>MAX_HEIGHT</i> &#8211; you specify a maximum height and the dimensions are calculated based off of the height</li>
<li><i>MAX_WIDTH</i> &#8211; you specify a maximum width and the dimensions are calculated based off of the width</li>
<li><i>BEST_FIT</i> &#8211; you specify a maximum height and width and the dimensions are calculated so that the thumbnail<br />
	    is as large as possible without exceeding the maximum height or width</li>
<li><i>EXACT</i> &#8211; you specify a maximum height and width and these are directly used.  Causes distortion if the<br />
	    chosen aspect ratio is different from the aspect ratio of the image</li>
</ul>
</li>
<li>Renders/saves images in their input format by default, but allows changing the format.  For example, input a GIF but output a PNG</li>
<li>Fully documented object oriented code</li>
<li>Fluent interface for creating thumbnails with a minimal amount of code</li>
</ul>
<p>The class is licensed under the MIT license, which basically means it can be used and modified by anyone &#8211; for personal or commercial use.</p>
<p>You can <a href="http://code.google.com/p/gregphotoimage/">Download it</a> from the project page on Google Code.  You can <a href="http://www.gregphoto.net/projects/gregphoto_image/samples">view examples</a> of it running on my site &#8211; the examples are checked into SVN and can be viewed on the project site.  You can also <a href="http://www.gregphoto.net/projects/gregphoto_image/docs">view the docs</a>.</p>
<p>Example usage:</p>

<div class="wp_syntax"><table><tr><td class="line_numbers"><pre>1
2
3
4
5
6
7
</pre></td><td class="code"><pre class="php" style="font-family:monospace;"><span style="color: #b1b100;">require</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'path/to/Gregphoto_Image.php'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
<span style="color: #000088;">$image</span> <span style="color: #339933;">=</span> <span style="color: #000000; font-weight: bold;">new</span> Gregphoto_Image<span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'path/to/sample/image.jpg'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
<span style="color: #000088;">$image</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">setMaxHeight</span><span style="color: #009900;">&#40;</span><span style="color: #cc66cc;">200</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
<span style="color: #000088;">$image</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">setMaxWidth</span><span style="color: #009900;">&#40;</span><span style="color: #cc66cc;">200</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
<span style="color: #000088;">$image</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">setJpegQuality</span><span style="color: #009900;">&#40;</span><span style="color: #cc66cc;">90</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
<span style="color: #000088;">$image</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">resize</span><span style="color: #009900;">&#40;</span>Gregphoto_Image<span style="color: #339933;">::</span><span style="color: #004000;">BEST_FIT</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
<span style="color: #000088;">$image</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">showThumbnail</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span></pre></td></tr></table></div>


<div class="wp_syntax"><table><tr><td class="line_numbers"><pre>1
2
</pre></td><td class="code"><pre class="php" style="font-family:monospace;"><span style="color: #000088;">$image</span> <span style="color: #339933;">=</span> <span style="color: #000000; font-weight: bold;">new</span> Gregphoto_Image<span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'../images/fan.jpg'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
<span style="color: #000088;">$image</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">setMaxHeight</span><span style="color: #009900;">&#40;</span><span style="color: #cc66cc;">200</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">setJpegQuality</span><span style="color: #009900;">&#40;</span><span style="color: #cc66cc;">90</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">resize</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">showThumbnail</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span></pre></td></tr></table></div>


<div class="wp_syntax"><table><tr><td class="line_numbers"><pre>1
2
3
4
5
6
7
8
</pre></td><td class="code"><pre class="php" style="font-family:monospace;"><span style="color: #b1b100;">require</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'path/to/Gregphoto_Image.php'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
<span style="color: #000088;">$image</span> <span style="color: #339933;">=</span> <span style="color: #000000; font-weight: bold;">new</span> Gregphoto_Image<span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'path/to/image.jpg'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
<span style="color: #000088;">$image</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">setMaxHeight</span><span style="color: #009900;">&#40;</span><span style="color: #cc66cc;">200</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
<span style="color: #000088;">$image</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">setMaxWidth</span><span style="color: #009900;">&#40;</span><span style="color: #cc66cc;">200</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
<span style="color: #000088;">$image</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">setJpegQuality</span><span style="color: #009900;">&#40;</span><span style="color: #cc66cc;">90</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
<span style="color: #000088;">$image</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">setOutputType</span><span style="color: #009900;">&#40;</span>IMAGETYPE_PNG<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
<span style="color: #000088;">$image</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">resize</span><span style="color: #009900;">&#40;</span>Gregphoto_Image<span style="color: #339933;">::</span><span style="color: #004000;">BEST_FIT</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
<span style="color: #000088;">$image</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">saveThumbnail</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'path/to/thumbnail.png'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span></pre></td></tr></table></div>

<p>Enjoy!</p>
]]></content:encoded>
			<wfw:commentRss>http://www.gregphoto.net/index.php/2007/02/03/announcing-gregphoto_image-a-php5gd2-thumbnail-class/feed/</wfw:commentRss>
		<slash:comments>48</slash:comments>
		</item>
		<item>
		<title>Creating an Accordian Widget Class with Prototype</title>
		<link>http://www.gregphoto.net/index.php/2006/08/30/creating-an-accordian-widget-class-with-prototype/</link>
		<comments>http://www.gregphoto.net/index.php/2006/08/30/creating-an-accordian-widget-class-with-prototype/#comments</comments>
		<pubDate>Thu, 31 Aug 2006 04:24:25 +0000</pubDate>
		<dc:creator>Greg</dc:creator>
				<category><![CDATA[Web Development]]></category>

		<guid isPermaLink="false">http://www.gregphoto.net/index.php/2006/08/30/creating-an-accordian-widget-class-with-prototype/</guid>
		<description><![CDATA[Overview
The following is an example of a simple reusable widget created using the Prototype JavaScript library.  The widget is an &#8216;accordian&#8217; &#8211; a widget composed of multiple sections, of which only one is open at a time. This type of widget is available in all sorts of applications, from Microsoft Outlook (circa Outlook 2000), [...]]]></description>
			<content:encoded><![CDATA[<h3>Overview</h3>
<p>The following is an example of a simple reusable widget created using the <a href="http://prototype.conio.net/">Prototype</a> JavaScript library.  The widget is an &#8216;accordian&#8217; &#8211; a widget composed of multiple sections, of which only one is open at a time. This type of widget is available in all sorts of applications, from Microsoft Outlook (circa Outlook 2000), to web applications, and more.  In addition to showing off this simple widget, I&#8217;d like to walk through it to explain how it works and how to write something like this with Prototype.  For all of Prototype&#8217;s greatness, there is certainly a lack of documentation that makes it a little bit difficult to get into.</p>
<h3>Example</h3>
<p>Take a look at the <a href="http://www.gregphoto.net/projects/accordian">example page</a> I put together showing a few examples of accordians and their capabilities.  This article will explain how to put together the class that does this.  </p>
<h3>Explaination: Creating Reusable Classes</h3>
<p>I&#8217;ll skip with going through the HTML &#8211; you can see that on the example page if you&#8217;re interested &#8211; it would be helpful in understanding the javaScript here.  In this example I&#8217;ve used version 1.5.0_rc0 of Prototype.  The first line of the accordian.js file has the following:</p>

<div class="wp_syntax"><table><tr><td class="line_numbers"><pre>1
</pre></td><td class="code"><pre class="javascript" style="font-family:monospace;">Accordian <span style="color: #339933;">=</span> <span style="color: #003366; font-weight: bold;">Class</span>.<span style="color: #660066;">create</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span></pre></td></tr></table></div>

<p>Prototype&#8217;s Class.create() sets up Accordian as an object that can be instantiated.  When the object is instantiated the &#8216;initialize&#8217; method, its constructor, will be automatically called.  You setup all of the methods within the object by defining its prototype &#8211; an object with properties and methods.  This could be done in the following way:</p>

<div class="wp_syntax"><table><tr><td class="line_numbers"><pre>1
2
3
4
5
6
7
8
9
10
11
12
13
14
</pre></td><td class="code"><pre class="javascript" style="font-family:monospace;">Accordian.<span style="color: #660066;">prototype</span> <span style="color: #339933;">=</span> <span style="color: #009900;">&#123;</span>
	initialize<span style="color: #339933;">:</span> <span style="color: #003366; font-weight: bold;">function</span><span style="color: #009900;">&#40;</span>args<span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
		<span style="color: #006600; font-style: italic;">// do something</span>
	<span style="color: #009900;">&#125;</span><span style="color: #339933;">,</span>
	sectionClicked<span style="color: #339933;">:</span> <span style="color: #003366; font-weight: bold;">function</span><span style="color: #009900;">&#40;</span>args<span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
&nbsp;
	<span style="color: #009900;">&#125;</span><span style="color: #339933;">,</span>
	openSection<span style="color: #339933;">:</span> <span style="color: #003366; font-weight: bold;">function</span><span style="color: #009900;">&#40;</span>args<span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
&nbsp;
	<span style="color: #009900;">&#125;</span><span style="color: #339933;">,</span>
	closeExistingSection<span style="color: #339933;">:</span> <span style="color: #003366; font-weight: bold;">function</span><span style="color: #009900;">&#40;</span>args<span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
&nbsp;
	<span style="color: #009900;">&#125;</span>
<span style="color: #009900;">&#125;</span></pre></td></tr></table></div>

<p>This object could be instantiated in the following way:</p>

<div class="wp_syntax"><table><tr><td class="line_numbers"><pre>1
</pre></td><td class="code"><pre class="javascript" style="font-family:monospace;"><span style="color: #003366; font-weight: bold;">var</span> myAccordian <span style="color: #339933;">=</span> <span style="color: #003366; font-weight: bold;">new</span> Accordian<span style="color: #009900;">&#40;</span>options<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span></pre></td></tr></table></div>

<h3>Explanation: Writing the Constructor</h3>
<p>The constructor needs to take two arguments &#8211; the ID of the element that contains the accordian and the type of entry that is used for the header of each section.  The constructors main job is getting a list of all of the sections within the accordian and adds onClick event handlers to the headers so that clicking them will open the section.  The constructor is shown below:</p>

<div class="wp_syntax"><table><tr><td class="line_numbers"><pre>1
2
3
4
5
6
7
</pre></td><td class="code"><pre class="javascript" style="font-family:monospace;">initialize<span style="color: #339933;">:</span> <span style="color: #003366; font-weight: bold;">function</span><span style="color: #009900;">&#40;</span>elem<span style="color: #339933;">,</span> clickableEntity<span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
   <span style="color: #000066; font-weight: bold;">this</span>.<span style="color: #660066;">container</span> <span style="color: #339933;">=</span> $<span style="color: #009900;">&#40;</span>elem<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
   <span style="color: #003366; font-weight: bold;">var</span> headers <span style="color: #339933;">=</span> $$<span style="color: #009900;">&#40;</span><span style="color: #3366CC;">'#'</span> <span style="color: #339933;">+</span> elem <span style="color: #339933;">+</span> <span style="color: #3366CC;">' .section '</span> <span style="color: #339933;">+</span> clickableEntity<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
   headers.<span style="color: #660066;">each</span><span style="color: #009900;">&#40;</span><span style="color: #003366; font-weight: bold;">function</span><span style="color: #009900;">&#40;</span>header<span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
       Event.<span style="color: #660066;">observe</span><span style="color: #009900;">&#40;</span>header<span style="color: #339933;">,</span><span style="color: #3366CC;">'click'</span><span style="color: #339933;">,</span><span style="color: #000066; font-weight: bold;">this</span>.<span style="color: #660066;">sectionClicked</span>.<span style="color: #660066;">bindAsEventListener</span><span style="color: #009900;">&#40;</span><span style="color: #000066; font-weight: bold;">this</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
   <span style="color: #009900;">&#125;</span>.<span style="color: #660066;">bind</span><span style="color: #009900;">&#40;</span><span style="color: #000066; font-weight: bold;">this</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
<span style="color: #009900;">&#125;</span></pre></td></tr></table></div>

<p>Now to explain what&#8217;s going on in the constructor:</p>
<ul>
<li>The first line defines the function that expects two variables &#8211; the ID of the element that holds the accordian and the type of element that will serve as the header for a section.</li>
<li>The second line sets a class property, &#8216;container&#8217;, to the element passed in with variable &#8216;elem&#8217;.  It uses Prototype&#8217;s $() function, which in this case is equivalent to document.getElementById()</li>
<li>The third line uses the very powerful $$() function that returns an array of all elements that match a given css query.  In this case, the query might look like &#8216;#myAccordian .section h3&#8242;, which would return all h3 elements under an element with class &#8217;section&#8217; under the element with ID &#8216;myAccordian&#8217;.</li>
<li>Lines 4-6 setup the event handlers that will be used when the user clicks the headers.  This uses the each() function that Prototype adds to arrays in order to quickly loop through an array without using a for loop or creating a bunch of temporary variables.  This function takes a function as an argument that will be applied as an iterator over the array.  This use of this technique is similar to the foreach concept in PHP (foreach($headers as $header)) and other languages.  Because functions are objects in JavaScript, we need to add a trick at the end of the each function defined within &#8216;each&#8217; &#8211; we need to add &#8216;bind(this)&#8217;.  This means that within the new function, the &#8216;this&#8217; keyword will be bound to the Accordian object, not to the function itself.</li>
<li>Line 5 uses Prototype&#8217;s Event class to setup the observer &#8211; in this case it will bind the classes sectionClicked method to any click on the header elements. Similar to the binding needed on the function, the reference to the sectionClicked function is follwed by &#8216;bindAsEventListener(this)&#8217;, which means that inside the event handler, &#8216;this&#8217; will refer to the Accordian object, not to the clicked header element.</li>
</ul>
<h3>Explanation: Writing the Event Handler</h3>
<p>The function referenced as the event handler in the constructor is shown below:</p>

<div class="wp_syntax"><table><tr><td class="line_numbers"><pre>1
2
3
</pre></td><td class="code"><pre class="javascript" style="font-family:monospace;">  sectionClicked<span style="color: #339933;">:</span> <span style="color: #003366; font-weight: bold;">function</span><span style="color: #009900;">&#40;</span>event<span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
   <span style="color: #000066; font-weight: bold;">this</span>.<span style="color: #660066;">openSection</span><span style="color: #009900;">&#40;</span>Event.<span style="color: #660066;">element</span><span style="color: #009900;">&#40;</span>event<span style="color: #009900;">&#41;</span>.<span style="color: #660066;">parentNode</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
<span style="color: #009900;">&#125;</span></pre></td></tr></table></div>

<p>Functions called as an event always get passed an event object.  This function takes this event and uses the Prototype &#8216;Event&#8217; class to get a handle on the parent node of the element that was clicked, the section itself. It then passes this as an argument to another method in this class &#8211; openSection.</p>
<h3>Explanation: Opening a Section</h3>
<p>This function if fairly straightfoward &#8211; it checks to see if the section being opened is already open, and if not, calls a function to close the open section, and finally opens the new section.  It is shown below:</p>

<div class="wp_syntax"><table><tr><td class="line_numbers"><pre>1
2
3
4
5
6
7
8
9
</pre></td><td class="code"><pre class="javascript" style="font-family:monospace;">openSection<span style="color: #339933;">:</span> <span style="color: #003366; font-weight: bold;">function</span><span style="color: #009900;">&#40;</span>section<span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
	<span style="color: #003366; font-weight: bold;">var</span> section <span style="color: #339933;">=</span> $<span style="color: #009900;">&#40;</span>section<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
	<span style="color: #000066; font-weight: bold;">if</span><span style="color: #009900;">&#40;</span>section.<span style="color: #660066;">id</span> <span style="color: #339933;">!=</span> <span style="color: #000066; font-weight: bold;">this</span>.<span style="color: #660066;">currentSection</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
		<span style="color: #000066; font-weight: bold;">this</span>.<span style="color: #660066;">closeExistingSection</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
		<span style="color: #000066; font-weight: bold;">this</span>.<span style="color: #660066;">currentSection</span> <span style="color: #339933;">=</span> section.<span style="color: #660066;">id</span><span style="color: #339933;">;</span>
		<span style="color: #003366; font-weight: bold;">var</span> contents <span style="color: #339933;">=</span> document.<span style="color: #660066;">getElementsByClassName</span><span style="color: #009900;">&#40;</span><span style="color: #3366CC;">'contents'</span><span style="color: #339933;">,</span>section<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
		contents<span style="color: #009900;">&#91;</span><span style="color: #CC0000;">0</span><span style="color: #009900;">&#93;</span>.<span style="color: #660066;">show</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
	<span style="color: #009900;">&#125;</span>
<span style="color: #009900;">&#125;</span></pre></td></tr></table></div>

<ul>
<li>The function takes one argument, the section that is to be opened</li>
<li>The second line uses the $() function to get the DOM element.  It is important to note that this function can either take the section ID as an argument or the actual section DOM node.  The $() function adds this extra flexibility</li>
<li>The third line checks to see whether the ID of the section is the same as the currently open section.  If it is, no other logic is performed.  If it isn&#8217;t, the next few lines will open that section.</li>
<li>After line 4 calls a function to close the existing section, line 5 sets a class property &#8216;currentSection&#8217; to the new section</li>
<li>Line 6 uses Prototype&#8217;s getElementsByClassName, passing the class (contents) and the element under which it should look (the new section).  This returns an array of elements</li>
<li>Line 7 takes the first element with class contents (their should only be one), and uses Prototype&#8217;s show() function to show the element</li>
</ul>
<h3>Explanation: Closing a Section</h3>
<p>This last function is the simplest of all &#8211; it checks to see whether there is an open section, and if so, it hides it.</p>

<div class="wp_syntax"><table><tr><td class="line_numbers"><pre>1
2
3
4
5
6
</pre></td><td class="code"><pre class="javascript" style="font-family:monospace;">closeExistingSection<span style="color: #339933;">:</span> <span style="color: #003366; font-weight: bold;">function</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
	<span style="color: #000066; font-weight: bold;">if</span><span style="color: #009900;">&#40;</span><span style="color: #000066; font-weight: bold;">this</span>.<span style="color: #660066;">currentSection</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
		<span style="color: #003366; font-weight: bold;">var</span> contents <span style="color: #339933;">=</span> document.<span style="color: #660066;">getElementsByClassName</span><span style="color: #009900;">&#40;</span><span style="color: #3366CC;">'contents'</span><span style="color: #339933;">,</span><span style="color: #000066; font-weight: bold;">this</span>.<span style="color: #660066;">currentSection</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
		contents<span style="color: #009900;">&#91;</span><span style="color: #CC0000;">0</span><span style="color: #009900;">&#93;</span>.<span style="color: #660066;">hide</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
	<span style="color: #009900;">&#125;</span>
<span style="color: #009900;">&#125;</span></pre></td></tr></table></div>

<ul>
<li>The second line checks if the currentSection exists &#8211; it is only set after the first section has been opened</li>
<li>The third line uses the same technique as in the previous function &#8211; it uses getElementsByClassName to get the elements with class &#8217;section&#8217;</li>
<li>Finally, the hide function will hide this element so that the section is collapsed</li>
</ul>
<h3>The Final Script</h3>

<div class="wp_syntax"><table><tr><td class="line_numbers"><pre>1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
</pre></td><td class="code"><pre class="javascript" style="font-family:monospace;">Accordian <span style="color: #339933;">=</span> <span style="color: #003366; font-weight: bold;">Class</span>.<span style="color: #660066;">create</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
Accordian.<span style="color: #660066;">prototype</span> <span style="color: #339933;">=</span> <span style="color: #009900;">&#123;</span>
	initialize<span style="color: #339933;">:</span> <span style="color: #003366; font-weight: bold;">function</span><span style="color: #009900;">&#40;</span>elem<span style="color: #339933;">,</span> clickableEntity<span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
		<span style="color: #000066; font-weight: bold;">this</span>.<span style="color: #660066;">container</span> <span style="color: #339933;">=</span> $<span style="color: #009900;">&#40;</span>elem<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
		<span style="color: #003366; font-weight: bold;">var</span> headers <span style="color: #339933;">=</span> $$<span style="color: #009900;">&#40;</span><span style="color: #3366CC;">'#'</span> <span style="color: #339933;">+</span> elem <span style="color: #339933;">+</span> <span style="color: #3366CC;">' .section '</span> <span style="color: #339933;">+</span> clickableEntity<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
		headers.<span style="color: #660066;">each</span><span style="color: #009900;">&#40;</span><span style="color: #003366; font-weight: bold;">function</span><span style="color: #009900;">&#40;</span>header<span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
			Event.<span style="color: #660066;">observe</span><span style="color: #009900;">&#40;</span>header<span style="color: #339933;">,</span><span style="color: #3366CC;">'click'</span><span style="color: #339933;">,</span><span style="color: #000066; font-weight: bold;">this</span>.<span style="color: #660066;">sectionClicked</span>.<span style="color: #660066;">bindAsEventListener</span><span style="color: #009900;">&#40;</span><span style="color: #000066; font-weight: bold;">this</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
		<span style="color: #009900;">&#125;</span>.<span style="color: #660066;">bind</span><span style="color: #009900;">&#40;</span><span style="color: #000066; font-weight: bold;">this</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
	<span style="color: #009900;">&#125;</span><span style="color: #339933;">,</span>
	sectionClicked<span style="color: #339933;">:</span> <span style="color: #003366; font-weight: bold;">function</span><span style="color: #009900;">&#40;</span>event<span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
		<span style="color: #000066; font-weight: bold;">this</span>.<span style="color: #660066;">openSection</span><span style="color: #009900;">&#40;</span>Event.<span style="color: #660066;">element</span><span style="color: #009900;">&#40;</span>event<span style="color: #009900;">&#41;</span>.<span style="color: #660066;">parentNode</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
	<span style="color: #009900;">&#125;</span><span style="color: #339933;">,</span>
	openSection<span style="color: #339933;">:</span> <span style="color: #003366; font-weight: bold;">function</span><span style="color: #009900;">&#40;</span>section<span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
		<span style="color: #003366; font-weight: bold;">var</span> section <span style="color: #339933;">=</span> $<span style="color: #009900;">&#40;</span>section<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
		<span style="color: #000066; font-weight: bold;">if</span><span style="color: #009900;">&#40;</span>section.<span style="color: #660066;">id</span> <span style="color: #339933;">!=</span> <span style="color: #000066; font-weight: bold;">this</span>.<span style="color: #660066;">currentSection</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
			<span style="color: #000066; font-weight: bold;">this</span>.<span style="color: #660066;">closeExistingSection</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
			<span style="color: #000066; font-weight: bold;">this</span>.<span style="color: #660066;">currentSection</span> <span style="color: #339933;">=</span> section.<span style="color: #660066;">id</span><span style="color: #339933;">;</span>
			<span style="color: #003366; font-weight: bold;">var</span> contents <span style="color: #339933;">=</span> document.<span style="color: #660066;">getElementsByClassName</span><span style="color: #009900;">&#40;</span><span style="color: #3366CC;">'contents'</span><span style="color: #339933;">,</span>section<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
			contents<span style="color: #009900;">&#91;</span><span style="color: #CC0000;">0</span><span style="color: #009900;">&#93;</span>.<span style="color: #660066;">show</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
		<span style="color: #009900;">&#125;</span>
	<span style="color: #009900;">&#125;</span><span style="color: #339933;">,</span>
	closeExistingSection<span style="color: #339933;">:</span> <span style="color: #003366; font-weight: bold;">function</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
		<span style="color: #000066; font-weight: bold;">if</span><span style="color: #009900;">&#40;</span><span style="color: #000066; font-weight: bold;">this</span>.<span style="color: #660066;">currentSection</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
			<span style="color: #003366; font-weight: bold;">var</span> contents <span style="color: #339933;">=</span> document.<span style="color: #660066;">getElementsByClassName</span><span style="color: #009900;">&#40;</span><span style="color: #3366CC;">'contents'</span><span style="color: #339933;">,</span><span style="color: #000066; font-weight: bold;">this</span>.<span style="color: #660066;">currentSection</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
			contents<span style="color: #009900;">&#91;</span><span style="color: #CC0000;">0</span><span style="color: #009900;">&#93;</span>.<span style="color: #660066;">hide</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
		<span style="color: #009900;">&#125;</span>
	<span style="color: #009900;">&#125;</span>
<span style="color: #009900;">&#125;</span></pre></td></tr></table></div>

<h3>Conclusion</h3>
<p>Though this is a fairly simple example, I hope it helped to explain some of the features of the Prototype library and can get people kickstarted to writing classes with JavaScript.  Most of it is very simple&#8230;if only there were some real documentation.  The best source right now is probably <a href="http://www.sergiopereira.com/articles/prototype.js.html">Developer notes for prototype.js</a>, which covers features up to Prototype 1.4.  Another site with a compilation of links is <a href="http://www.prototypedoc.com/">http://www.prototypedoc.com/</a>.</p>
<p>Go forth and rid the world of nasty IE5 style, unreadable, browser-sniffing, hackish, global-scope JavaScript!</p>
]]></content:encoded>
			<wfw:commentRss>http://www.gregphoto.net/index.php/2006/08/30/creating-an-accordian-widget-class-with-prototype/feed/</wfw:commentRss>
		<slash:comments>14</slash:comments>
		</item>
		<item>
		<title>Ajax Form Validation</title>
		<link>http://www.gregphoto.net/index.php/2006/07/30/ajax-form-validation/</link>
		<comments>http://www.gregphoto.net/index.php/2006/07/30/ajax-form-validation/#comments</comments>
		<pubDate>Mon, 31 Jul 2006 00:04:58 +0000</pubDate>
		<dc:creator>Greg</dc:creator>
				<category><![CDATA[PHP]]></category>
		<category><![CDATA[Web Development]]></category>

		<guid isPermaLink="false">http://www.gregphoto.net/index.php/2006/07/30/ajax-form-validation/</guid>
		<description><![CDATA[Recently I put together a reusable Ajax form validation component that I&#8217;d like to share.  It is a JavaScript object that collects the values of all of the elements in a form, sends it for processing to the server, and displays any errors.  If there are no errors it submits the form.  [...]]]></description>
			<content:encoded><![CDATA[<p>Recently I put together a reusable Ajax form validation component that I&#8217;d like to share.  It is a JavaScript object that collects the values of all of the elements in a form, sends it for processing to the server, and displays any errors.  If there are no errors it submits the form.  There are several benefits to this approach</p>
<ul>
<li>Allows you to perform complex validation, such as verifying the uniqueness of a username, or checking something in the database&#8230;all without reloading the page</li>
<li>Allows you to use the same validation routine for both client-side validation and server-side validation</li>
<li>Reduces the amount of client-side code needed for validation</li>
</ul>
<p>The JavaScript used in <a href="http://www.gregphoto.net/projects/ajaxValidate">my example</a> requires the <a href="http://prototype.conio.net/">Prototype library</a>.  My example uses PHP to perform the validation &#8211; more specifically, I&#8217;ve used several components of the <a href="http://framework.zend.com">Zend Framework</a> (PHP5 only).  The example uses:</p>
<ul>
<li>Zend_Controller_* classes including the new RewriteRouter to handle the routing within the application</li>
<li>Zend_View to handle the output</li>
<li>Zend_View_Helper_* classes to build form elements</li>
<li>Zend_Config to read in configuration options</li>
<li>Zend_Filter to perform several field validations</li>
<li>Zend_Json to serialize PHP variables/objects to <a href="http://www.json.org/">JSON objects</a></li>
</ul>
<p>Did I need all of this stuff on the server-side to put together a simple form validation example? Heck no, but when I&#8217;m experimenting with new stuff I like to use a lot of new components so I can learn more about them and be prepared for when I actually do need to use all of this fire power.  I&#8217;ve been following the Zend Framework carefully, so I wanted to use some of the stuff I hadn&#8217;t used yet &#8211; particularly the controller architecture.</p>
<h3>The HTML and JavaScript</h3>
<p>Ok, back to how this JavaScript is used.  It&#8217;s actually really quite simple.  First, you need to include the JavaScript files for both Prototype and <a href="http://www.gregphoto.net/projects/ajaxValidate/static/js/ajaxFormValidate.js">AjaxFormValidator</a> in the head of your HTML document:</p>

<div class="wp_syntax"><table><tr><td class="line_numbers"><pre>1
2
</pre></td><td class="code"><pre class="html" style="font-family:monospace;">&lt;script src=&quot;/ajaxValidate/static/js/prototype.js&quot;&gt;&lt;/script&gt;
&lt;script src=&quot;/ajaxValidate/static/js/ajaxFormValidate.js&quot;&gt;&lt;/script&gt;</pre></td></tr></table></div>

<p>Next, you add an &#8216;onSubmit&#8217; handler to the form you&#8217;d like to validate &#8211; in this case, mine looks like this:</p>

<div class="wp_syntax"><table><tr><td class="line_numbers"><pre>1
</pre></td><td class="code"><pre class="html" style="font-family:monospace;">&lt;form action=&quot;/ajaxValidate/index/success&quot; method=&quot;POST&quot; onSubmit=&quot;return submitForm(this);&quot;&gt;</pre></td></tr></table></div>

<p>The form action is set to the page I&#8217;d like the script to go to if the validation is successful.  The onSubmit calls a custom function that we still need to define.  It passes &#8216;this&#8217; as an argument &#8211; the &#8216;this&#8217; refers to the form element itself.</p>
<p>Now we define the submitForm() function that the onSubmit of the form will call &#8211; it looks like the following:</p>

<div class="wp_syntax"><table><tr><td class="line_numbers"><pre>1
2
3
4
5
6
</pre></td><td class="code"><pre class="javascript" style="font-family:monospace;"><span style="color: #003366; font-weight: bold;">function</span> submitForm<span style="color: #009900;">&#40;</span>form<span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
	validator <span style="color: #339933;">=</span> <span style="color: #003366; font-weight: bold;">new</span> AjaxFormValidator<span style="color: #009900;">&#40;</span>form<span style="color: #339933;">,</span><span style="color: #3366CC;">&quot;/ajaxValidate/index/validate&quot;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
	validator.<span style="color: #660066;">errorDisplay</span> <span style="color: #339933;">=</span> <span style="color: #3366CC;">'inline'</span><span style="color: #339933;">;</span>
	validator.<span style="color: #660066;">inlineElem</span> <span style="color: #339933;">=</span> <span style="color: #3366CC;">'errorDiv'</span><span style="color: #339933;">;</span>
	<span style="color: #000066; font-weight: bold;">return</span> validator.<span style="color: #660066;">validate</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
<span style="color: #009900;">&#125;</span></pre></td></tr></table></div>

<p>This function first creates a new AjaxFormValidator object, passing it the form element (or the form id) and the url the validation request should be sent to.  The next two lines setup the type of error display that should happen.  The following error display types are supported:</p>
<ul>
<li>alert: The default option.  Displays all errors in a JavaScript alert box.</li>
<li>inline: Displays errors within an element that is defined on the page.  You need to set the element name with validator.inlineElem.  In this example, errors will be shown in a div with id=&#8221;errorDiv&#8221;.</li>
<li>none: errors won&#8217;t be shown to the user.  The will be available as an array of errors in the errors property of the validator (i.e. validator.errors).  If there are no errors the property will be set to false.  Once you have the errors you can perform more advanced error handling/display to the user.</li>
</ul>
<p>Lastly, validator.validate() will send the values in the form, in an HTTP POST, to the validation url you&#8217;ve provided (/ajaxValidate/index/validate in this case).  If there are no errors the form will be submitted, if there are errors the will be shown (or not shown if you&#8217;ve chosen &#8216;none&#8217; as the errorDisplay).</p>
<h3>The PHP</h3>
<p>Once the request is sent it will eventually arrive at the server for processing &#8211; in this case, through the magic of routing, it is going to end up in my IndexController in the validateAction method.  This function is shown below:</p>

<div class="wp_syntax"><table><tr><td class="line_numbers"><pre>1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
</pre></td><td class="code"><pre class="php" style="font-family:monospace;"><span style="color: #000000; font-weight: bold;">public</span> <span style="color: #000000; font-weight: bold;">function</span> validateAction<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
	<span style="color: #000088;">$errors</span> <span style="color: #339933;">=</span> <span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">getErrors</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$_POST</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
	<span style="color: #b1b100;">if</span><span style="color: #009900;">&#40;</span><span style="color: #990000;">count</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$errors</span><span style="color: #009900;">&#41;</span> <span style="color: #339933;">==</span> <span style="color: #cc66cc;">0</span><span style="color: #009900;">&#41;</span> <span style="color: #000088;">$errors</span> <span style="color: #339933;">=</span> <span style="color: #009900; font-weight: bold;">false</span><span style="color: #339933;">;</span>
	<span style="color: #b1b100;">echo</span> Zend_Json<span style="color: #339933;">::</span><span style="color: #004000;">encode</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$errors</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
<span style="color: #009900;">&#125;</span>
<span style="color: #339933;">&lt;/</span>php<span style="color: #339933;">&gt;</span>
This <span style="color: #000000; font-weight: bold;">function</span> calls another method within the IndexController <span style="color: #000000; font-weight: bold;">class</span> called getErrors<span style="color: #339933;">,</span> passing in the entire <span style="color: #990000;">array</span> of POST arguments <span style="color: #009900;">&#40;</span>values in the form<span style="color: #009900;">&#41;</span><span style="color: #339933;">.</span>  It receives back an <span style="color: #990000;">array</span> full of error strings<span style="color: #339933;">.</span>  <span style="color: #b1b100;">If</span> there are no errors<span style="color: #339933;">,</span> it changes the value of the <span style="color: #000088;">$error</span> variable to <span style="color: #009900; font-weight: bold;">false</span><span style="color: #339933;">.</span>  Lastly<span style="color: #339933;">,</span> it uses Zend_Json to convert the PHP <span style="color: #990000;">array</span><span style="color: #339933;">/</span>Boolean into the equivalent JavaScript <span style="color: #990000;">array</span><span style="color: #339933;">/</span>Boolean<span style="color: #339933;">.</span>  This string is printed and sent back to the client<span style="color: #339933;">.</span>
&nbsp;
The getErrors <span style="color: #000000; font-weight: bold;">function</span> itself is very straightforward <span style="color: #339933;">-</span> it just does a couple validations and returns back an <span style="color: #990000;">array</span> of the errors<span style="color: #339933;">.</span>
<span style="color: #339933;">&lt;</span>pre lang<span style="color: #339933;">=</span><span style="color: #0000ff;">&quot;php&quot;</span> line<span style="color: #339933;">=</span><span style="color: #0000ff;">&quot;1&quot;</span><span style="color: #339933;">&gt;</span>
protected <span style="color: #000000; font-weight: bold;">function</span> getErrors<span style="color: #009900;">&#40;</span><span style="color: #000088;">$values</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
	<span style="color: #000088;">$errors</span> <span style="color: #339933;">=</span> <span style="color: #990000;">array</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
	<span style="color: #b1b100;">if</span><span style="color: #009900;">&#40;</span><span style="color: #339933;">!</span>Zend_Filter<span style="color: #339933;">::</span><span style="color: #004000;">isRegex</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$values</span><span style="color: #009900;">&#91;</span><span style="color: #0000ff;">'fname'</span><span style="color: #009900;">&#93;</span><span style="color: #339933;">,</span><span style="color: #0000ff;">'/^[a-z]+[a-z 0-9-_]*$/i'</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
		<span style="color: #000088;">$errors</span><span style="color: #009900;">&#91;</span><span style="color: #009900;">&#93;</span> <span style="color: #339933;">=</span> <span style="color: #0000ff;">'First Name is required and may only contain letters, numbers, and spaces'</span><span style="color: #339933;">;</span>
	<span style="color: #009900;">&#125;</span>
	<span style="color: #b1b100;">if</span><span style="color: #009900;">&#40;</span><span style="color: #339933;">!</span>Zend_Filter<span style="color: #339933;">::</span><span style="color: #004000;">isRegex</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$values</span><span style="color: #009900;">&#91;</span><span style="color: #0000ff;">'lname'</span><span style="color: #009900;">&#93;</span><span style="color: #339933;">,</span><span style="color: #0000ff;">'/^[a-z]+[a-z 0-9-_]*$/i'</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
		<span style="color: #000088;">$errors</span><span style="color: #009900;">&#91;</span><span style="color: #009900;">&#93;</span> <span style="color: #339933;">=</span> <span style="color: #0000ff;">'Last Name is required and may only contain letters, numbers, and spaces'</span><span style="color: #339933;">;</span>
	<span style="color: #009900;">&#125;</span>
	<span style="color: #b1b100;">if</span><span style="color: #009900;">&#40;</span><span style="color: #339933;">!</span>Zend_Filter<span style="color: #339933;">::</span><span style="color: #004000;">isRegex</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$values</span><span style="color: #009900;">&#91;</span><span style="color: #0000ff;">'email'</span><span style="color: #009900;">&#93;</span><span style="color: #339933;">,</span><span style="color: #0000ff;">'/^[_a-zA-Z-]+[._a-zA-Z0-9-]+@[a-zA-Z0-9-]+\.[.a-zA-Z0-9]+$/'</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
		<span style="color: #000088;">$errors</span><span style="color: #009900;">&#91;</span><span style="color: #009900;">&#93;</span> <span style="color: #339933;">=</span> <span style="color: #0000ff;">'Email is required and must be a valid email address'</span><span style="color: #339933;">;</span>
	<span style="color: #009900;">&#125;</span>
	<span style="color: #b1b100;">if</span><span style="color: #009900;">&#40;</span><span style="color: #339933;">!</span>Zend_Filter<span style="color: #339933;">::</span><span style="color: #004000;">isAlnum</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$values</span><span style="color: #009900;">&#91;</span><span style="color: #0000ff;">'password'</span><span style="color: #009900;">&#93;</span><span style="color: #009900;">&#41;</span> <span style="color: #339933;">||</span> <span style="color: #009900;">&#40;</span><span style="color: #990000;">strlen</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$values</span><span style="color: #009900;">&#91;</span><span style="color: #0000ff;">'password'</span><span style="color: #009900;">&#93;</span><span style="color: #009900;">&#41;</span> <span style="color: #339933;">&lt;</span> <span style="color: #cc66cc;">6</span><span style="color: #009900;">&#41;</span> <span style="color: #339933;">||</span> <span style="color: #009900;">&#40;</span><span style="color: #990000;">strlen</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$values</span><span style="color: #009900;">&#91;</span><span style="color: #0000ff;">'password'</span><span style="color: #009900;">&#93;</span><span style="color: #009900;">&#41;</span> <span style="color: #339933;">&gt;</span> <span style="color: #cc66cc;">12</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
		<span style="color: #000088;">$errors</span><span style="color: #009900;">&#91;</span><span style="color: #009900;">&#93;</span> <span style="color: #339933;">=</span> <span style="color: #0000ff;">'Password must consist of only letters and numbers and must be between 6 and 12 characters'</span><span style="color: #339933;">;</span>
	<span style="color: #009900;">&#125;</span>
	<span style="color: #b1b100;">return</span> <span style="color: #000088;">$errors</span><span style="color: #339933;">;</span>
<span style="color: #009900;">&#125;</span></pre></td></tr></table></div>

<p><a href="http://www.gregphoto.net/projects/ajaxValidate">Check it out, in action</a>.  And that&#8217;s about it &#8211; pretty simple, huh?</p>
<p>You can download:</p>
<ul>
<li><a href="http://www.gregphoto.net/projects/ajaxValidate/static/js/ajaxFormValidate.js">The JavaScript</a></li>
<li><a href="http://www.gregphoto.net/projects/ajaxValidate/ajaxFormValidate.zip">The whole PHP project</a></li>
</ul>
]]></content:encoded>
			<wfw:commentRss>http://www.gregphoto.net/index.php/2006/07/30/ajax-form-validation/feed/</wfw:commentRss>
		<slash:comments>15</slash:comments>
		</item>
		<item>
		<title>Experimenting with Google Checkout and PHP</title>
		<link>http://www.gregphoto.net/index.php/2006/07/01/experimenting-with-google-checkout-and-php/</link>
		<comments>http://www.gregphoto.net/index.php/2006/07/01/experimenting-with-google-checkout-and-php/#comments</comments>
		<pubDate>Sat, 01 Jul 2006 20:14:02 +0000</pubDate>
		<dc:creator>Greg</dc:creator>
				<category><![CDATA[PHP]]></category>
		<category><![CDATA[Technology]]></category>
		<category><![CDATA[Web Development]]></category>

		<guid isPermaLink="false">http://www.gregphoto.net/index.php/2006/07/01/experimenting-with-google-checkout-and-php/</guid>
		<description><![CDATA[Having put together a couple websites (Redstone Studios and Althea) that integrate with Paypal for providing checkout capabilities, I was very interested to look at Google Checkout when it was released this past week.  My experience with the Paypal integration was not so good &#8211; while I eventually got it to work, it took [...]]]></description>
			<content:encoded><![CDATA[<p>Having put together a couple websites (<a href="http://www.redstonestudios.com">Redstone Studios</a> and <a href="http://www.althearocks.com">Althea</a>) that integrate with Paypal for providing checkout capabilities, I was very interested to look at <a href="http://checkout.google.com">Google Checkout</a> when it was released this past week.  My experience with the Paypal integration was not so good &#8211; while I eventually got it to work, it took a ton of experimentation, searching for documentation, and guessing why things weren&#8217;t working (i.e. no meaningful error messages).  Luckily, Google Checkout doesn&#8217;t seem to suffer from these problems &#8211; I had it up and running in no time and it seems very solid for what it does.  What does it do?  Well, it&#8217;s basically a checkout system where you can pass in a cart, users can pay by credit card, and then the money gets deposited in your bank account.  Google charges 2% of the transaction amount plus twenty cents.  The two percent covers the percent Google has to pay the credit card companies, and the twenty cents is some extra cash for Google.  If you use Google Adwords, you get a free credit on Google Checkout &#8211; for every 1 dollar spent on Adwords you get 10 dollars of sales with no costs.</p>
<p>Google provides sample PHP code for getting the integration going, but unfortunately the code is PHP4 only, and it is ugly ugly ugly code.  I decided to put together a simple class that allows simple integration with Google Checkout.  The class is PHP5 only because it uses PHP5&#8217;s DOM extension.</p>
<p>To use Google Checkout you need to create a Google Checkout account.  From there, you can get your merchant id and merchant key, both of which are needed to communicate with Google Checkout.  The Google Checkout API works by POSTING XML over HTTP.  While <a href="http://code.google.com/apis/checkout/developer/index.html#api_details">Google&#8217;s API</a> is very flexible, I&#8217;ve chosen to implement a subset that I think would be useful for many people.  Also, I&#8217;ve only implemented this class to support the creation of the cart and submission to Google, I haven&#8217;t included any functionality for greater integration.  This greater integration would involve creating web services that Google could call to update the website on changes to the order status, shipping, etc.  The way I&#8217;ve set this up, all of that is skipped, and store owner would receive orders via email or Google&#8217;s Checkout interface.</p>
<p>Limitations:</p>
<ul>
<li>No support for cart expiration</li>
<li>No support for merchant calculations for tax/shipping/gift certificates as these require HTTPS and I don&#8217;t have it and don&#8217;t care to use it</li>
<li>No support for requesting the buyers phone number because I didn&#8217;t notice that field until just now!</li>
<li>No support for shipping restrictions &#8211; i.e. shipping option 1 is only available in these zip codes/states/etc</li>
<li>No support for complicated tax rules.  Tax can be setup on a state by state basis.  One alternative tax rule &#8216;taxfree&#8217; is setup to allow certain items to be tax free.  No support for other alternative tax rules.</li>
<li>Currently doesn&#8217;t support customization of the form and checkout image</li>
</ul>
<p>In order to work around some of these limitations, I&#8217;ve provided a method called setDefaultXML which allows the developer to specify a default XML file to be used.  The class will then fill in the items, do the encryption, and generate the form and checkout image.  This allows much greater flexibility and support for all of Google&#8217;s options, when needed.</p>
<p>Here&#8217;s a simple example of how I might use it:</p>

<div class="wp_syntax"><table><tr><td class="line_numbers"><pre>1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
</pre></td><td class="code"><pre class="php" style="font-family:monospace;"><span style="color: #b1b100;">require</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'GoogleCheckout.php'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
<span style="color: #000088;">$merchant_id</span> <span style="color: #339933;">=</span> <span style="color: #0000ff;">'XXXXXXXXXXXXXXX'</span><span style="color: #339933;">;</span>
<span style="color: #000088;">$merchant_key</span> <span style="color: #339933;">=</span> <span style="color: #0000ff;">'XXXXXXXXXXXXXXXXXXXXXX'</span><span style="color: #339933;">;</span>
&nbsp;
<span style="color: #000088;">$google</span> <span style="color: #339933;">=</span> <span style="color: #000000; font-weight: bold;">new</span> Gregphoto_Service_Google_Checkout<span style="color: #009900;">&#40;</span><span style="color: #000088;">$merchant_id</span><span style="color: #339933;">,</span><span style="color: #000088;">$merchant_key</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
<span style="color: #000088;">$google</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">setMode</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'sandbox'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
<span style="color: #000088;">$google</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">addItem</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'Doolittle'</span><span style="color: #339933;">,</span><span style="color: #0000ff;">'Doolitle CD by The Pixies (1989)'</span><span style="color: #339933;">,</span><span style="color: #0000ff;">'11.98'</span><span style="color: #339933;">,</span><span style="color: #cc66cc;">1</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
<span style="color: #000088;">$google</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">addItem</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'PSCREEN18'</span><span style="color: #339933;">,</span><span style="color: #0000ff;">'18 inch Pizza Screen'</span><span style="color: #339933;">,</span><span style="color: #0000ff;">'7.99'</span><span style="color: #339933;">,</span><span style="color: #cc66cc;">3</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
<span style="color: #000088;">$google</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">addItem</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'MYWIDGET01'</span><span style="color: #339933;">,</span><span style="color: #0000ff;">'New tax free widget - Student Use Only'</span><span style="color: #339933;">,</span><span style="color: #0000ff;">'149.21'</span><span style="color: #339933;">,</span><span style="color: #cc66cc;">1</span><span style="color: #339933;">,</span><span style="color: #0000ff;">''</span><span style="color: #339933;">,</span><span style="color: #0000ff;">'taxfree'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
<span style="color: #000088;">$google</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">addItem</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'NDISC01'</span><span style="color: #339933;">,</span><span style="color: #0000ff;">'New Customer Discount'</span><span style="color: #339933;">,</span><span style="color: #0000ff;">'-10'</span><span style="color: #339933;">,</span><span style="color: #cc66cc;">1</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
<span style="color: #000088;">$google</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">editCartUrl</span> <span style="color: #339933;">=</span> <span style="color: #0000ff;">'http://www.gregphoto.net/index.php?action=editcart&amp;source=google'</span><span style="color: #339933;">;</span>
<span style="color: #000088;">$google</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">continueShoppingUrl</span> <span style="color: #339933;">=</span> <span style="color: #0000ff;">'http://www.gregphoto.net'</span><span style="color: #339933;">;</span>
<span style="color: #000088;">$google</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">setShipping</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'UPS Ground'</span><span style="color: #339933;">,</span><span style="color:#800080;">19.99</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
<span style="color: #000088;">$google</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">setShipping</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'UPS Next Day'</span><span style="color: #339933;">,</span><span style="color:#800080;">27.99</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
<span style="color: #000088;">$google</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">setShipping</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'Instore Pickup'</span><span style="color: #339933;">,</span><span style="color:#800080;">4.99</span><span style="color: #339933;">,</span><span style="color: #0000ff;">'pickup'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
<span style="color: #000088;">$google</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">setStateTax</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'CA'</span><span style="color: #339933;">,</span><span style="color:#800080;">.0875</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
<span style="color: #000088;">$google</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">setStateTax</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'IL'</span><span style="color: #339933;">,</span><span style="color:#800080;">.0525</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
<span style="color: #b1b100;">echo</span> <span style="color: #000088;">$google</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">getHTMLForm</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
<span style="color: #000088;">$google</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">printXML</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span></pre></td></tr></table></div>

<p>Now, for what&#8217;s going on:</p>
<ul>
<li>Line 1 includes the class</li>
<li>Lines 3 and 4 setup variables for the merchant id and merchant key</li>
<li>Line 6 instantiates the class, passing in the merchant id and key</li>
<li>Line 7 sets the class to use the Google Checkout Sandbox &#8211; this is a testing sandbox where you can setup fake accounts to use while creating your site.  Paypal offerers a much richer sandbox functionality.</li>
<li>Lines 8-11 add new line items to the cart, setting there name, description, price, quantity, notes, and special tax rules</li>
<li>Lines 12 and 13 setup the URLs the user should be sent to if the choose to edit the cart or continue shopping</li>
<li>Lines 14-16 setup various shipping options including their prices</li>
<li>Lines 17 and 18 setup taxes for the users in specific states.  Google Checkout supports much richer rules around taxation, but I kept it simple on a state-by-state level.</li>
<li>Line 20 outputs the HTML form and checkout image that will send the cart to Google Checkout and bring the user to the Google Checkout page</li>
<li>Line 21 shows the XML cart, for debugging purposes</li>
</ul>
<p><a href="http://www.gregphoto.net/projects/googlecheckout/">View this example running on my site</a><br />
<a href="http://www.gregphoto.net/projects/googlecheckout/docs">View the API of Gregphoto_Service_Google_Checkout</a><br />
<a href="http://www.gregphoto.net/projects/googlecheckout/googlecheckout.zip">Download the class and API docs</a><br />
<a href="http://code.google.com/apis/checkout/developer/index.html">View Google&#8217;s Develper Guide for Google Checkout</a></p>
]]></content:encoded>
			<wfw:commentRss>http://www.gregphoto.net/index.php/2006/07/01/experimenting-with-google-checkout-and-php/feed/</wfw:commentRss>
		<slash:comments>16</slash:comments>
		</item>
		<item>
		<title>Akismet and the Zend Framework</title>
		<link>http://www.gregphoto.net/index.php/2006/06/11/akismet-and-the-zend-framework/</link>
		<comments>http://www.gregphoto.net/index.php/2006/06/11/akismet-and-the-zend-framework/#comments</comments>
		<pubDate>Mon, 12 Jun 2006 00:52:55 +0000</pubDate>
		<dc:creator>Greg</dc:creator>
				<category><![CDATA[PHP]]></category>
		<category><![CDATA[Web Development]]></category>

		<guid isPermaLink="false">http://www.gregphoto.net/index.php/2006/06/11/akismet-and-the-zend-framework/</guid>
		<description><![CDATA[Inspired by Akismet is my Hero on blog.phpdeveloper.org and by the fact that Akismet has already stopped several thousand spam comments on my own Wordpress blog, I decided to put together an Akismet class using the Zend Framework (resulting in this being PHP 5 only).  For those of you who don&#8217;t know, Akismet is [...]]]></description>
			<content:encoded><![CDATA[<p>Inspired by <a href="http://blog.phpdeveloper.org/?p=34">Akismet is my Hero</a> on blog.phpdeveloper.org and by the fact that Akismet has already stopped several thousand spam comments on my own Wordpress blog, I decided to put together an Akismet class using the Zend Framework (resulting in this being PHP 5 only).  For those of you who don&#8217;t know, Akismet is a web service that you can send comments to and they&#8217;ll let you know whether or not they think it&#8217;s spam.  It does a great job of spotting spam and was a great addition to Wordpress.</p>
<p>This class, which you can <a href="http://www.gregphoto.net/projects/akismet/akismet.zip">download along with api docs</a> uses the Zend Framework&#8217;s Zend_Http_Client functionality to perform HTTP posts to Akismet and get the responses back.  More specifically, it uses the version of Zend_Http_Client that&#8217;s currently in the incubator, not the one in the regular library.</p>
<p>Here&#8217;s a simple usage example:</p>

<div class="wp_syntax"><table><tr><td class="line_numbers"><pre>1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
</pre></td><td class="code"><pre class="php" style="font-family:monospace;"><span style="color: #000088;">$api_key</span> <span style="color: #339933;">=</span> <span style="color: #0000ff;">'your api key here'</span><span style="color: #339933;">;</span>
<span style="color: #000088;">$website_front_page</span> <span style="color: #339933;">=</span> <span style="color: #0000ff;">'http://www.gregphoto.net'</span><span style="color: #339933;">;</span>
<span style="color: #000088;">$message</span> <span style="color: #339933;">=</span> <span style="color: #990000;">array</span><span style="color: #009900;">&#40;</span>
	<span style="color: #0000ff;">'comment_author'</span> <span style="color: #339933;">=&gt;</span> <span style="color: #0000ff;">'viagra-test-123'</span><span style="color: #339933;">,</span>
	<span style="color: #0000ff;">'comment_author_email'</span> <span style="color: #339933;">=&gt;</span> <span style="color: #0000ff;">'viagra-test-123@hotmails.com'</span><span style="color: #339933;">,</span>
	<span style="color: #0000ff;">'comment_author_url'</span> <span style="color: #339933;">=&gt;</span> <span style="color: #0000ff;">'http://www.viagra-test-123.com/ilovespam/'</span><span style="color: #339933;">,</span>
	<span style="color: #0000ff;">'comment_content'</span> <span style="color: #339933;">=&gt;</span> <span style="color: #0000ff;">&quot;Please buy my spam.  Mechanically separated meat tastes great!&quot;</span>
<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
<span style="color: #000088;">$akismet</span> <span style="color: #339933;">=</span> <span style="color: #000000; font-weight: bold;">new</span> Gregphoto_Service_Akismet<span style="color: #009900;">&#40;</span><span style="color: #000088;">$api_key</span><span style="color: #339933;">,</span><span style="color: #000088;">$website_front_page</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
<span style="color: #b1b100;">if</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$akismet</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">checkIsSpam</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$message</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
	<span style="color: #b1b100;">echo</span> <span style="color: #0000ff;">'it is spam!'</span><span style="color: #339933;">;</span>
<span style="color: #009900;">&#125;</span> <span style="color: #b1b100;">else</span> <span style="color: #009900;">&#123;</span>
	<span style="color: #b1b100;">echo</span> <span style="color: #0000ff;">'it is not spam!!'</span><span style="color: #339933;">;</span>
<span style="color: #009900;">&#125;</span></pre></td></tr></table></div>

<p>In addition to checking whether a message is spam (Gregphoto_Service_Akismet::checkIsSpam), the following methods are provided, covering the entirety of the <a href="http://akismet.com/development/api/">Akismet API</a>:</p>
<ul>
<li>Gregphoto_Service_Akismet::validateKey &#8211; checks whether or not your api key is valid</li>
<li>Gregphoto_Service_Akismet::submitSpam &#8211; submits a message to Akismet telling it that it is spam (normally a message that Akismet identified as not being spam)</li>
<li>Gregphoto_Service_Akismet::submitHam &#8211; tell Akismet that a message it identified as spam is not actually spam</li>
</ul>
<p>To get an API key for yourself, follow the instructions printed on blog.phpdeveloper.org:</p>
<blockquote><p>You’ll need to go signup over on WordPress.com and, once logged in, go to your “My Dashboard” (top left link), go to the “Users” tab at the top and right there at the top of the page you’ll see “Your WordPress.com API key is…”. Easy as pie.</p></blockquote>
<p>Signup for a free blog, but don&#8217;t worry&#8230;you only need to sign up in order to get a key &#8211; you don&#8217;t actually have to use the wordpress.com account for anything else&#8230;</p>
<p>For anyone looking to build a site or application using the Zend Framework that accepts comments &#8211; this could be a good little tool that should integrate very cleanly.</p>
<p>Enjoy, and let me know what you think.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.gregphoto.net/index.php/2006/06/11/akismet-and-the-zend-framework/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>Updated Scriplaculous Sortable Demo</title>
		<link>http://www.gregphoto.net/index.php/2006/05/30/updated-scriplaculous-sortable-demo/</link>
		<comments>http://www.gregphoto.net/index.php/2006/05/30/updated-scriplaculous-sortable-demo/#comments</comments>
		<pubDate>Wed, 31 May 2006 04:09:54 +0000</pubDate>
		<dc:creator>Greg</dc:creator>
				<category><![CDATA[Web Development]]></category>

		<guid isPermaLink="false">http://www.gregphoto.net/index.php/2006/05/30/updated-scriplaculous-sortable-demo/</guid>
		<description><![CDATA[I&#8217;ve updated the Scriptaculous demo that I put up a while back.  You can see it here.  There were a large number of comments on the initial post, many of them wondering why the example didn&#8217;t work in Scriptaculous 1.6.X.  I took a look at it today and after some experimentation made [...]]]></description>
			<content:encoded><![CDATA[<p>I&#8217;ve updated the <a href="http://script.aculo.us">Scriptaculous</a> demo that I put up a while back.  You can <a href="http://www.gregphoto.net/sortable/advanced">see it here</a>.  There were a large number of comments on the <a href="http://www.gregphoto.net/index.php/2006/03/09/sorting-sortables-and-dragging-between-lists-with-scriptaculous/">initial post</a>, many of them wondering why the example didn&#8217;t work in Scriptaculous 1.6.X.  I took a look at it today and after some experimentation made the following changes to get it to work:</p>
<ul>
<li>Reversed the order of creating the sortables &#8211; for whatever reason, it seems that the outer most sortable must now be created last, whereas it worked fine when created first before</li>
<li><strike>Removed the code to &#8216;destroy&#8217; the sortables before recreating them &#8211; this was necessary before, but it seems that they are automatically destroyed now when creating a sortable on the same element.  While this slimmed down the code, it wasn&#8217;t essential to get it to work</strike>  Scratch that.  I noticed a bug where dropping elements on the sections wasn&#8217;t working if a new group had been created before any of the line items had been added to a group.  Adding back the destruction of the line item sortables did the trick.  It still seems to be working without the destruction of the page-level sortable though.</li>
<li>Added a prefix to the new section id for consistency sake (as per John&#8217;s comment)</li>
<li>Other miscellaneous JavaScript and CSS cleanup</li>
</ul>
<p>There were also several comments questioning whether this positioning can be saved to the database.  That&#8217;s exactly what the debug function is aimed at doing &#8211; showing the user how to get at the positioning information with JavaScript.  Once you&#8217;ve got it into a JavaScript string/array/object, it&#8217;s trivial to put it into an input and submit a form.</p>
<p>Enjoy.</p>
<p>Greg</p>
]]></content:encoded>
			<wfw:commentRss>http://www.gregphoto.net/index.php/2006/05/30/updated-scriplaculous-sortable-demo/feed/</wfw:commentRss>
		<slash:comments>58</slash:comments>
		</item>
		<item>
		<title>Zdbform: Simple database admin forms with the Zend Framework</title>
		<link>http://www.gregphoto.net/index.php/2006/03/25/zdbform-simple-database-admin-forms-with-the-zend-framework/</link>
		<comments>http://www.gregphoto.net/index.php/2006/03/25/zdbform-simple-database-admin-forms-with-the-zend-framework/#comments</comments>
		<pubDate>Sat, 25 Mar 2006 23:03:10 +0000</pubDate>
		<dc:creator>Greg</dc:creator>
				<category><![CDATA[PHP]]></category>
		<category><![CDATA[Web Development]]></category>

		<guid isPermaLink="false">http://www.gregphoto.net/index.php/2006/03/25/zdbform-simple-database-admin-forms-with-the-zend-framework/</guid>
		<description><![CDATA[I&#8217;ve put together a database admin application using the database functionality provided by the Zend Framework.  Basically, it&#8217;s a generic set of classes that allows people to quickly add, edit, delete, and view data in a database table.  The nice thing is that this uses the Zend_DB_Table classes, so it should presumably work [...]]]></description>
			<content:encoded><![CDATA[<p>I&#8217;ve put together a database admin application using the database functionality provided by the <a href="http://framework.zend.com">Zend Framework</a>.  Basically, it&#8217;s a generic set of classes that allows people to quickly add, edit, delete, and view data in a database table.  The nice thing is that this uses the Zend_DB_Table classes, so it should presumably work with just about any database supported by the Zend Framework.  I&#8217;ve tried this on mySQL and sqlite, and it worked just fine on both.  There are some limitations of course.  Right now this will only work on tables that have auto-increment primary keys.  I don&#8217;t quite know how this would work with databases that don&#8217;t have auto-increment such as Oracle &#8211; maybe this could have support for defining the sequence that should be used when inserting data.  This is a PHP5 only class due to it&#8217;s reliance on the Zend Framework.</p>
<p>The intention of Zdbform is to have a quick way to put up a database admin page for webapp control panel that is easier to use than tools such as phpMyAdmin.  Something that can provide validation, customization of the view, integration within other pages, </p>
<p>You can see an <a href="http://www.gregphoto.net/projects/zdbform" target="_blank">example</a> of this running or check out the <a href="http://www.gregphoto.net/projects/zdbform/docs">API docs</a>. </p>
<p>Zdbform has the following features:</p>
<ul>
<li>Simple maintenance of database tables</li>
<li>View table data with pagination, searching, and sorting of columns</li>
<li>Ability to change the display names of columns</li>
<li>Ability to hide columns in view, add, and edit</li>
<li>Extendable set of widgets to show data in table / forms</li>
<li>Extendable set of validators to validate column data</li>
<li>Ability to add row validators that validate the full contents of a newly inserted or edited row</li>
</ul>
<p>Other items that I would like to add in the future are:</p>
<ul>
<li>Custom callbacks on add / edit / delete</li>
<li>Think about defining Zdbform as extension of Zend_DB_Form</li>
<li>If definition of class settings is externalized it could open up opportunities for export of data, ajax editing, ajax validation, etc.</li>
<li>Rename classes to fit within naming standards of Zend Framework.  Think about how this fits into the MVC parts of the Zend Framework.</li>
</ul>
<p>The page that defined <a href="http://www.gregphoto.net/projects/zdbform" target="_blank">the example</a> is shown below:</p>

<div class="wp_syntax"><table><tr><td class="line_numbers"><pre>1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
</pre></td><td class="code"><pre class="php" style="font-family:monospace;"><span style="color: #000000; font-weight: bold;">&lt;?php</span>
<span style="color: #b1b100;">require_once</span> <span style="color: #0000ff;">'Zend/Db.php'</span><span style="color: #339933;">;</span>
<span style="color: #b1b100;">require_once</span> <span style="color: #0000ff;">'Zend/Db/Table.php'</span><span style="color: #339933;">;</span>
<span style="color: #b1b100;">require_once</span> <span style="color: #0000ff;">'zdbform.class.php'</span><span style="color: #339933;">;</span>
<span style="color: #b1b100;">require_once</span> <span style="color: #0000ff;">'zdbform_widgets.class.php'</span><span style="color: #339933;">;</span>
<span style="color: #b1b100;">require_once</span> <span style="color: #0000ff;">'zdbform_validations.php'</span><span style="color: #339933;">;</span>
<span style="color: #000088;">$params</span> <span style="color: #339933;">=</span> <span style="color: #990000;">array</span> <span style="color: #009900;">&#40;</span>
    <span style="color: #0000ff;">'host'</span>     <span style="color: #339933;">=&gt;</span> <span style="color: #0000ff;">'localhost'</span><span style="color: #339933;">,</span>
    <span style="color: #0000ff;">'username'</span> <span style="color: #339933;">=&gt;</span> <span style="color: #0000ff;">'test'</span><span style="color: #339933;">,</span>
    <span style="color: #0000ff;">'password'</span> <span style="color: #339933;">=&gt;</span> <span style="color: #0000ff;">'test'</span><span style="color: #339933;">,</span>
    <span style="color: #0000ff;">'dbname'</span>   <span style="color: #339933;">=&gt;</span> <span style="color: #0000ff;">'delicious.db'</span>
<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
<span style="color: #000088;">$db</span> <span style="color: #339933;">=</span> Zend_Db<span style="color: #339933;">::</span><span style="color: #004000;">factory</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'pdoSqlite'</span><span style="color: #339933;">,</span> <span style="color: #000088;">$params</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
Zend_Db_Table<span style="color: #339933;">::</span><span style="color: #004000;">setDefaultAdapter</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$db</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
<span style="color: #000000; font-weight: bold;">class</span> Posts <span style="color: #000000; font-weight: bold;">extends</span> Zend_Db_Table <span style="color: #009900;">&#123;</span><span style="color: #009900;">&#125;</span>
&nbsp;
<span style="color: #000088;">$dbform</span> <span style="color: #339933;">=</span> <span style="color: #000000; font-weight: bold;">new</span> Zdbform<span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'Posts'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
<span style="color: #000088;">$dbform</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">setWidget</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'posted'</span><span style="color: #339933;">,</span> <span style="color: #0000ff;">'timestamp'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
<span style="color: #000088;">$dbform</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">setWidget</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'description'</span><span style="color: #339933;">,</span> <span style="color: #0000ff;">'html'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
<span style="color: #000088;">$dbform</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">setWidget</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'href'</span><span style="color: #339933;">,</span> <span style="color: #0000ff;">'link'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
<span style="color: #000088;">$dbform</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">setDisplayName</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'id'</span><span style="color: #339933;">,</span> <span style="color: #0000ff;">'ID'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
<span style="color: #000088;">$dbform</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">setDisplayName</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'href'</span><span style="color: #339933;">,</span> <span style="color: #0000ff;">'Link'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
<span style="color: #000088;">$dbform</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">hideColumns</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'posted'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
<span style="color: #000088;">$dbform</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">setWidgetOption</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'href'</span><span style="color: #339933;">,</span><span style="color: #0000ff;">'width'</span><span style="color: #339933;">,</span><span style="color: #cc66cc;">70</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
<span style="color: #000088;">$dbform</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">setHelpText</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'posted'</span><span style="color: #339933;">,</span> <span style="color: #0000ff;">'m/d/y format'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
<span style="color: #000088;">$dbform</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">setHelpText</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'tags'</span><span style="color: #339933;">,</span> <span style="color: #0000ff;">'Enter one or more tags, separated by commas'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
<span style="color: #000088;">$dbform</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">tableTitle</span> <span style="color: #339933;">=</span> <span style="color: #0000ff;">&quot;Backed up delicious links&quot;</span><span style="color: #339933;">;</span>
<span style="color: #000088;">$dbform</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">editTitle</span> <span style="color: #339933;">=</span> <span style="color: #0000ff;">&quot;Edit link information&quot;</span><span style="color: #339933;">;</span>
<span style="color: #000088;">$dbform</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">addTitle</span> <span style="color: #339933;">=</span> <span style="color: #0000ff;">&quot;Add new link&quot;</span><span style="color: #339933;">;</span>
<span style="color: #000088;">$dbform</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">addColumnValidator</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'tags'</span><span style="color: #339933;">,</span><span style="color: #0000ff;">'validate_minlength'</span><span style="color: #339933;">,</span><span style="color: #990000;">array</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'minlength'</span> <span style="color: #339933;">=&gt;</span> <span style="color: #cc66cc;">4</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
<span style="color: #000088;">$dbform</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">addColumnValidator</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'href,description'</span><span style="color: #339933;">,</span><span style="color: #0000ff;">'validate_required'</span><span style="color: #339933;">,</span><span style="color: #990000;">array</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
<span style="color: #000088;">$dbform</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">rowsPerPage</span> <span style="color: #339933;">=</span> <span style="color: #cc66cc;">15</span><span style="color: #339933;">;</span>
<span style="color: #000088;">$dbform</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">processForms</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
<span style="color: #000000; font-weight: bold;">?&gt;</span>
&lt;!DOCTYPE HTML PUBLIC &quot;-//W3C//DTD HTML 4.01 Transitional//EN&quot;
&quot;http://www.w3.org/TR/html4/loose.dtd&quot;&gt;
&lt;html&gt;
&lt;head&gt;
&lt;meta http-equiv=&quot;Content-Type&quot; content=&quot;text/html; charset=iso-8859-1&quot;&gt;
&lt;title&gt;ZDBFORM: Manage Posts Table&lt;/title&gt;
&lt;link type=&quot;text/css&quot; rel=&quot;stylesheet&quot; href=&quot;zdbform.css&quot; /&gt;
&lt;/head&gt;
&nbsp;
&lt;body&gt;
<span style="color: #000000; font-weight: bold;">&lt;?php</span>
<span style="color: #000088;">$dbform</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">showForms</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
<span style="color: #000088;">$dbform</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">showTable</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
<span style="color: #000000; font-weight: bold;">?&gt;</span>
&lt;/body&gt;
&lt;/html&gt;</pre></td></tr></table></div>

<p>Here are the main steps:</p>
<ul>
<li>Lines 2-6 include the required libraries for this to work.  It&#8217;s important to note that you need to have the Zend Framework classes in your include path for PHP.  Alternatively, you can use the set_include_path at the top of the script.
<li>
<li>Lines 7-13 sets up database parameters and then creates a Zend DB Adapter using the options provided.  In this case it&#8217;s a sqlite database.  Typically this stuff would probably just be defined in one place in your application, and then included, but for this case I&#8217;ve put everything on one page
<li>
<li>Lines 14-15 set the newly created Zend DB Adapter to be the default adapter for Zend DB Table and then defines &#8216;Posts&#8217; a class that extends Zend_DB_Table.  The name of the class is important &#8211; it is the name of the database table we want to manage.</li>
<li>Line 17 is the first place where we see Zdbform.  Here, we create an instance of Zdbform, passing it the name of the table we want to manage.</li>
<li>Lines 18-32 set various options for our table.  For example, Line 18 sets the posted column&#8217;s widget to timestamp, which will show a dropdown for selection of a date.  Line 19 sets the description column&#8217;s widget to html, which will use <a href="http://www.fckeditor.net/">FCKeditor</a> (a JavaScript HTML editor) when adding and editing data.  Lines 30 and 31 set various validators that will validate data on edit or insert.  All of these steps are optional and only enhance the behavior / look and feel of Zdbform.</li>
<li>Line 33 calls Zdbform::processForms(), which will process any data that has been submitted for add, edit, or delete</li>
<li>Finally, lines 47 and 48 display the forms and display the table of data</li>
</ul>
<p><a href="http://www.gregphoto.net/projects/zdbform/zdbform.zip">Download the code and example</a></p>
]]></content:encoded>
			<wfw:commentRss>http://www.gregphoto.net/index.php/2006/03/25/zdbform-simple-database-admin-forms-with-the-zend-framework/feed/</wfw:commentRss>
		<slash:comments>19</slash:comments>
		</item>
		<item>
		<title>Sorting sortables and dragging between lists with Scriptaculous</title>
		<link>http://www.gregphoto.net/index.php/2006/03/09/sorting-sortables-and-dragging-between-lists-with-scriptaculous/</link>
		<comments>http://www.gregphoto.net/index.php/2006/03/09/sorting-sortables-and-dragging-between-lists-with-scriptaculous/#comments</comments>
		<pubDate>Fri, 10 Mar 2006 06:20:28 +0000</pubDate>
		<dc:creator>Greg</dc:creator>
				<category><![CDATA[Web Development]]></category>

		<guid isPermaLink="false">http://www.gregphoto.net/index.php/2006/03/09/sorting-sortables-and-dragging-between-lists-with-scriptaculous/</guid>
		<description><![CDATA[I&#8217;ve put up an example page that takes advantage of a number of Scriptaculous features to allow the following:

Drag and drop items within a group
Drag and drop items between a group
Drag and drop groups
Create new groups and drag items into the new group

In doing this, I used a couple Scriptaculous features I hadn&#8217;t used before:

Many [...]]]></description>
			<content:encoded><![CDATA[<p>I&#8217;ve put up an <a href="http://www.gregphoto.net/sortable/advanced">example page</a> that takes advantage of a number of <a href="http://script.aculo.us">Scriptaculous </a>features to allow the following:</p>
<ul>
<li>Drag and drop items within a group</li>
<li>Drag and drop items between a group</li>
<li>Drag and drop groups</li>
<li>Create new groups and drag items into the new group</li>
</ul>
<p>In doing this, I used a couple Scriptaculous features I hadn&#8217;t used before:</p>
<ul>
<li>Many of the options in <a href="http://wiki.script.aculo.us/scriptaculous/show/Sortable.create">creating sortables</a> to limit where the item could be dropped</li>
<li>The <a href="http://wiki.script.aculo.us/scriptaculous/show/Builder">Bulider</a> object to create new groups</li>
<li>The Sortable.sequence function to get the order of items in a sortable as a JavaScript array</li>
</ul>
<p>A lot of people have posted comments here asking if there is a way to drag items between lists.  Obviously, Scriptaculous has provided this functionality for a long time, but there aren&#8217;t many examples out on the web showing how to use it&#8230;so <a href="http://www.gregphoto.net/sortable/advanced">my new example page</a> is an attempt to show it off &#8211; congrats to <a href="http://mir.aculo.us/">Thomas Fuchs</a> for putting together such a useful library that is such a pleasure to use.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.gregphoto.net/index.php/2006/03/09/sorting-sortables-and-dragging-between-lists-with-scriptaculous/feed/</wfw:commentRss>
		<slash:comments>43</slash:comments>
		</item>
	</channel>
</rss>
