<?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; Uncategorized</title>
	<atom:link href="http://www.gregphoto.net/index.php/category/uncategorized/feed/" rel="self" type="application/rss+xml" />
	<link>http://www.gregphoto.net</link>
	<description>Just another WordPress weblog</description>
	<lastBuildDate>Tue, 27 Dec 2011 00:24:00 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
			<item>
		<title>A walk on the beach</title>
		<link>http://www.gregphoto.net/index.php/2008/10/19/a-walk-on-the-beach/</link>
		<comments>http://www.gregphoto.net/index.php/2008/10/19/a-walk-on-the-beach/#comments</comments>
		<pubDate>Sun, 19 Oct 2008 23:36:40 +0000</pubDate>
		<dc:creator>Greg</dc:creator>
				<category><![CDATA[Uncategorized]]></category>

		<guid isPermaLink="false">http://www.gregphoto.net/?p=49</guid>
		<description><![CDATA[Its been a long time since I&#8217;ve written anything here&#8230;mostly due to a very busy year which included Yenari and me getting married in June. I&#8217;ll try my best to be more active (i.e. more than one post a year), but for now, I&#8217;ll just provide a link to a little experiment I put together [...]]]></description>
			<content:encoded><![CDATA[<p>Its been a long time since I&#8217;ve written anything here&#8230;mostly due to a very busy year which included Yenari and me getting married in June.  I&#8217;ll try my best to be more active (i.e. more than one post a year), but for now, I&#8217;ll just provide a link to a little experiment I put together from some pictures from our honeymoon in the Cook Islands.  It&#8217;s a little slideshow-like page, built with JavaScript:</p>
<p><a href="http://www.gregphoto.net/projects/beach">Walking into the Ocean</a></p>
<p>Nothing too crazy on the JavaScript side &#8211; just playing around with some stuff I hadn&#8217;t done before.  I wrote about three quarters of this a few months ago and just finished it off this afternoon.  I had to write a simple, but hopefully effective, image preloader that has nice callbacks and a decent api.  The actual slideshow could be written better, but it works, and that&#8217;s all I was going for&#8230;</p>
]]></content:encoded>
			<wfw:commentRss>http://www.gregphoto.net/index.php/2008/10/19/a-walk-on-the-beach/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Photos from South Korea, India, and Singapore</title>
		<link>http://www.gregphoto.net/index.php/2007/06/10/photos-from-south-korea-india-and-singapore/</link>
		<comments>http://www.gregphoto.net/index.php/2007/06/10/photos-from-south-korea-india-and-singapore/#comments</comments>
		<pubDate>Mon, 11 Jun 2007 00:57:30 +0000</pubDate>
		<dc:creator>Greg</dc:creator>
				<category><![CDATA[Uncategorized]]></category>

		<guid isPermaLink="false">http://www.gregphoto.net/index.php/2007/06/10/photos-from-south-korea-india-and-singapore/</guid>
		<description><![CDATA[I just got back from 20 days of traveling to South Korea, India, and Singapore. I went to South Korea with Yenari to see her family and friends for about a week. After this I headed to Bangalore (India) for work while Yenari stayed in South Korea a bit longer. On the way back home [...]]]></description>
			<content:encoded><![CDATA[<p>I just got back from 20 days of traveling to South Korea, India, and Singapore.  I went to South Korea with Yenari to see her family and friends for about a week.  After this I headed to Bangalore (India) for <a href="http://www.stratify.com">work</a> while Yenari stayed in South Korea a bit longer.  On the way back home I had a long layover (9 hours) in Singapore and got a chance to check out the city.</p>
<p>Check out my pictures here: <a href="http://picasaweb.google.com/gneustaetter/SouthKoreaIndiaAndSingapore">http://picasaweb.google.com/gneustaetter/SouthKoreaIndiaAndSingapore</a></p>
]]></content:encoded>
			<wfw:commentRss>http://www.gregphoto.net/index.php/2007/06/10/photos-from-south-korea-india-and-singapore/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Scriptaculous Sortables with Ajax Callback</title>
		<link>http://www.gregphoto.net/index.php/2007/01/16/scriptaculous-sortables-with-ajax-callback/</link>
		<comments>http://www.gregphoto.net/index.php/2007/01/16/scriptaculous-sortables-with-ajax-callback/#comments</comments>
		<pubDate>Wed, 17 Jan 2007 06:15:34 +0000</pubDate>
		<dc:creator>Greg</dc:creator>
				<category><![CDATA[Uncategorized]]></category>

		<guid isPermaLink="false">http://www.gregphoto.net/index.php/2007/01/16/scriptaculous-sortables-with-ajax-callback/</guid>
		<description><![CDATA[I haven&#8217;t written anything in a long time so I figured it is time to write something up. Because a huge portion of my traffic seems to be related to my scriptaculous examples I&#8217;ve put up, I figured I&#8217;d add another one that covers the process of updating a database with the results of drag/drop [...]]]></description>
			<content:encoded><![CDATA[<p>I haven&#8217;t written anything in a long time so I figured it is time to write something up.  Because a huge portion of my traffic seems to be related to my <a href="http://script.aculo.us">scriptaculous </a>examples I&#8217;ve put up, I figured I&#8217;d add another one that covers the process of updating a database with the results of drag/drop with an Ajax call.  Each time the user changes an item&#8217;s position in the list it updates the database.</p>
<p><a href="http://www.gregphoto.net/projects/scriptaculous17">See the example</a> (note: example uses Scriptaculous 1.7 Beta 2)</p>
<p>The methodology behind this is quite simple:</p>
<ol>
<li>Load the list values from the DB and show them on the screen</li>
<li>Using JavaScript, setup the sortables</li>
<li>Add a JavaScript callback to the drag/drop that points to a function that serializes the list and sends an Ajax request to the server</li>
<li>On the server, loop through the list and update the database with the proper order</li>
</ol>
<p>To do this I created three main files:</p>
<ul>
<li>index.php &#8211; the UI that shows the list and has the JavaScript</li>
<li>ajax.php &#8211; the page that processes the Ajax request</li>
<li>db.php &#8211; a simple database class included in both index.php and ajax.php that makes the connection to the DB and has methods to get the current list and to update the list</li>
</ul>
<h3>Reviewing Index.php</h3>
<p>Index.php looks like this:</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;?</span>
<span style="color: #b1b100;">require</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'db.php'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
<span style="color: #000088;">$demo</span> <span style="color: #339933;">=</span> <span style="color: #000000; font-weight: bold;">new</span> SortableExample<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
<span style="color: #000088;">$list</span> <span style="color: #339933;">=</span> <span style="color: #000088;">$demo</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">getList</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;!DOCTYPE HTML PUBLIC &quot;-//W3C//DTD HTML 4.01//EN&quot; &quot;http://www.w3.org/TR/html4/strict.dtd&quot;&gt;
&lt;html&gt;
&lt;head&gt;
	&lt;title&gt;Scriptaculous 1.7 Sortables Ajax Example&lt;/title&gt;
	&lt;link rel=&quot;stylesheet&quot; type=&quot;text/css&quot; href=&quot;style.css&quot;&gt;
	&lt;script src=&quot;js/prototype.js&quot;&gt;&lt;/script&gt;
	&lt;script src=&quot;js/scriptaculous.js&quot;&gt;&lt;/script&gt;
	&lt;script&gt;
		Event.observe(window,'load',init,false);
		function init() {
			Sortable.create('listContainer',{tag:'div',onUpdate:updateList});
		}
		function updateList(container) {
			var url = 'ajax.php';
			var params = Sortable.serialize(container.id);
			var ajax = new Ajax.Request(url,{
				method: 'post',
				parameters: params,
				onLoading: function(){$('workingMsg').show()},
				onLoaded: function(){$('workingMsg').hide()}
			});
		}
		function handleResponse(req) {
			// this function will fire after the ajax request is complete...but we have nothing to do here
		}
	&lt;/script&gt;
&lt;/head&gt;
&lt;body&gt;
&nbsp;
&lt;h2&gt;Scriptaculous Sortables Demo with Ajax Callback&lt;/h2&gt;
Built with Scriptaculous 1.7 Beta 2.  Drag items in the list below.  Each time you update the list an Ajax call is made
that updated the database with the new order.&lt;br&gt;&lt;br&gt;
&nbsp;
&lt;div id=&quot;listContainer&quot;&gt;
	<span style="color: #000000; font-weight: bold;">&lt;?</span>
	<span style="color: #b1b100;">foreach</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$list</span> <span style="color: #b1b100;">as</span> <span style="color: #000088;">$item</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
		<span style="color: #000000; font-weight: bold;">?&gt;</span>
		&lt;div id=&quot;item_<span style="color: #000000; font-weight: bold;">&lt;?=</span><span style="color: #000088;">$item</span><span style="color: #009900;">&#91;</span><span style="color: #0000ff;">'catid'</span><span style="color: #009900;">&#93;</span><span style="color: #339933;">;</span><span style="color: #000000; font-weight: bold;">?&gt;</span>&quot;&gt;<span style="color: #000000; font-weight: bold;">&lt;?=</span><span style="color: #000088;">$item</span><span style="color: #009900;">&#91;</span><span style="color: #0000ff;">'category'</span><span style="color: #009900;">&#93;</span><span style="color: #339933;">;</span><span style="color: #000000; font-weight: bold;">?&gt;</span>&lt;/div&gt;
		<span style="color: #000000; font-weight: bold;">&lt;?</span>
	<span style="color: #009900;">&#125;</span>
	<span style="color: #000000; font-weight: bold;">?&gt;</span>
&lt;/div&gt;
&lt;div id=&quot;workingMsg&quot; style=&quot;display:none;&quot;&gt;Updating database...&lt;/div&gt;
&nbsp;
&lt;/body&gt;
&lt;/html&gt;</pre></td></tr></table></div>

<p>Let&#8217;s look at this in reverse order.  At the bottom of the file there is a div with id &#8216;containerDiv&#8217; (line 36).  This is the container for our list.  Within this is a small snippet of PHP that loops through an associative array and prints out each list item as a div with id &#8216;item_12&#8242; where 12 is the ID for that record in the database (line 40).  Lines 2-4 contain the PHP code that include the db.php file and use it&#8217;s class to get the associative array that is used here.</p>
<p>Underneath the container div is another div that has the text &#8216;Updating database&#8230;&#8217; &#8211; this div is hidden by default and will be shown while Ajax calls are in progress (line 45).</p>
<p>Now to the JavaScript&#8230;it starts off on line 14 with a call to Event.observe that tells the browser to call the init function after the page loads.  The init function (line 15) creates a new sortable list on the listContainer element, setting all divs within it to be sortable and setting the updateList function as a callback whenever the list is updated.  This means that when the order of items in the list change, this function will be called with the list element passed as an argument.  This function will perform the Ajax request to update the database.</p>
<p>The updateList function (line 18) first sets a simple variable for the url used for the Ajax request.  Next (line 20) it calls Sortable.serialize, passing the id of the container as an argument, which serializes the list to a format such as listContainer[]=5,listContainer[]=7,listContainer[]=2 &#8211; here, the first three items of the list would be the items 5, 7, and 2 and the divs representing these items would have the following id values: item_5, item_7, and item_2.  This serialized list is set in the variable &#8216;params&#8217;.  Next, on line 21, an Ajax request is opened with Prototype&#8217;s Ajax.Request class.  It is called with two arguments, the url and an object with various options.  The options include the type of request (POST in this example, parameters to pass (the params variable constructed on line 20), and two functions (onLoading/onLoaded) that handle the showing and hiding of the &#8216;Updating database&#8230;&#8217; div.  Normally in an Ajax request I&#8217;d also add a callback for onComplete to handle the response from the server, but in this case the Ajax response doesn&#8217;t really matter to me because it is really only a one way communication in this demo &#8211; in a real application I&#8217;d have more error handling and would need to handle error conditions.</p>
<p>That&#8217;s about it for the index page&#8230;not too bad, right?</p>
<h3>Reviewing ajax.php</h3>
<p>The file ajax.php is a simple file that is designed to receive the Ajax request and call the appropriate methods defined in db.php to update the list.  Its contents are shown below:</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="php" style="font-family:monospace;"><span style="color: #000000; font-weight: bold;">&lt;?</span>
<span style="color: #990000;">session_start</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
<span style="color: #b1b100;">require</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'db.php'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
<span style="color: #000088;">$demo</span> <span style="color: #339933;">=</span> <span style="color: #000000; font-weight: bold;">new</span> SortableExample<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
<span style="color: #000088;">$demo</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">updateList</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$_POST</span><span style="color: #009900;">&#91;</span><span style="color: #0000ff;">'listContainer'</span><span style="color: #009900;">&#93;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
<span style="color: #000000; font-weight: bold;">?&gt;</span></pre></td></tr></table></div>

<p>Yup, that&#8217;s it.  Basically it starts off by calling session_start() &#8211; I typically call session_start() at the top of pages like this because starting the session sends the right http headers to prevent the file from being cached and I&#8217;m too lazy to look up what the right headers are!  Next it requires the db.php file, instantiates an object, and calls the updateList method of the object, passing the listContainer variable from the POST request (containing our serialized list).  That&#8217;s it for the ajax.php page.</p>
<h3>Reviewing db.php</h3>
<p>The file db.php is a simple database class that connects to the database and has methods to get the list and to update the order of the list.  In a &#8216;real&#8217; application I would definitely have a much cleaner implementation of the database access and would use other DB libraries to connect to the db &#8211; I used the simple mysql db functions to minimize on the number of lines needed here.  Here are the contents of the file:</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
</pre></td><td class="code"><pre class="php" style="font-family:monospace;"><span style="color: #000000; font-weight: bold;">&lt;?</span>
<span style="color: #000000; font-weight: bold;">class</span> SortableExample <span style="color: #009900;">&#123;</span>
	<span style="color: #000000; font-weight: bold;">protected</span> <span style="color: #000088;">$conn</span><span style="color: #339933;">;</span>
	<span style="color: #000000; font-weight: bold;">protected</span> <span style="color: #000088;">$user</span> <span style="color: #339933;">=</span> <span style="color: #0000ff;">'test'</span><span style="color: #339933;">;</span>
	<span style="color: #000000; font-weight: bold;">protected</span> <span style="color: #000088;">$pass</span> <span style="color: #339933;">=</span> <span style="color: #0000ff;">'test'</span><span style="color: #339933;">;</span>
	<span style="color: #000000; font-weight: bold;">protected</span> <span style="color: #000088;">$dbname</span> <span style="color: #339933;">=</span> <span style="color: #0000ff;">'scriptaculous'</span><span style="color: #339933;">;</span>
	<span style="color: #000000; font-weight: bold;">protected</span> <span style="color: #000088;">$host</span> <span style="color: #339933;">=</span> <span style="color: #0000ff;">'localhost'</span><span style="color: #339933;">;</span>
&nbsp;
	<span style="color: #000000; font-weight: bold;">public</span> <span style="color: #000000; font-weight: bold;">function</span> __construct<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
		<span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">conn</span> <span style="color: #339933;">=</span> <span style="color: #990000;">mysql_connect</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">host</span><span style="color: #339933;">,</span> <span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">user</span><span style="color: #339933;">,</span> <span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">pass</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
		<span style="color: #990000;">mysql_select_db</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">dbname</span><span style="color: #339933;">,</span><span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">conn</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
	<span style="color: #009900;">&#125;</span>
&nbsp;
	<span style="color: #000000; font-weight: bold;">public</span> <span style="color: #000000; font-weight: bold;">function</span> getList<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
		<span style="color: #000088;">$sql</span> <span style="color: #339933;">=</span> <span style="color: #0000ff;">&quot;SELECT * FROM categories ORDER BY orderid&quot;</span><span style="color: #339933;">;</span>
		<span style="color: #000088;">$recordSet</span> <span style="color: #339933;">=</span> <span style="color: #990000;">mysql_query</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$sql</span><span style="color: #339933;">,</span><span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">conn</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
		<span style="color: #000088;">$results</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;">while</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$row</span> <span style="color: #339933;">=</span> <span style="color: #990000;">mysql_fetch_assoc</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$recordSet</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
			<span style="color: #000088;">$results</span><span style="color: #009900;">&#91;</span><span style="color: #009900;">&#93;</span> <span style="color: #339933;">=</span> <span style="color: #000088;">$row</span><span style="color: #339933;">;</span>
		<span style="color: #009900;">&#125;</span>
		<span style="color: #b1b100;">return</span> <span style="color: #000088;">$results</span><span style="color: #339933;">;</span>
	<span style="color: #009900;">&#125;</span>
&nbsp;
	<span style="color: #000000; font-weight: bold;">public</span> <span style="color: #000000; font-weight: bold;">function</span> updateList<span style="color: #009900;">&#40;</span><span style="color: #000088;">$orderArray</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
		<span style="color: #000088;">$orderid</span> <span style="color: #339933;">=</span> <span style="color: #cc66cc;">1</span><span style="color: #339933;">;</span>
		<span style="color: #b1b100;">foreach</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$orderArray</span> <span style="color: #b1b100;">as</span> <span style="color: #000088;">$catid</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
			<span style="color: #000088;">$catid</span> <span style="color: #339933;">=</span> <span style="color: #009900;">&#40;</span>int<span style="color: #009900;">&#41;</span> <span style="color: #000088;">$catid</span><span style="color: #339933;">;</span>
			<span style="color: #000088;">$sql</span> <span style="color: #339933;">=</span> <span style="color: #0000ff;">&quot;UPDATE categories SET orderid=<span style="color: #006699; font-weight: bold;">{$orderid}</span> WHERE catid=<span style="color: #006699; font-weight: bold;">{$catid}</span>&quot;</span><span style="color: #339933;">;</span>
			<span style="color: #000088;">$recordSet</span> <span style="color: #339933;">=</span> <span style="color: #990000;">mysql_query</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$sql</span><span style="color: #339933;">,</span><span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">conn</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
			<span style="color: #000088;">$orderid</span><span style="color: #339933;">++;</span>
		<span style="color: #009900;">&#125;</span>
	<span style="color: #009900;">&#125;</span>
<span style="color: #009900;">&#125;</span>
<span style="color: #000000; font-weight: bold;">?&gt;</span></pre></td></tr></table></div>

<p>Important note &#8211; this file uses PHP 5 syntax in this object&#8230;you&#8217;d need some changes to get this to run in PHP 4.  I&#8217;ll skip talking about the constructor (which connects to the database) and the getList function (which&#8230;gets the list) in order to focus on the last method, &#8216;updateList&#8217;.  This function takes in an array of items, i.e. array(5,7,2), that come from the serialized list.  It loops through the list and generates SQL UPDATE queries for each item.  Each time it increments $orderid so that the first item has an orderid of 1, the 2nd an orderid of 2, etc.  This means that whenever we get the list, as long as the SQL &#8216;ORDER BY orderid&#8217; clause is used the list will show in the correct order.</p>
<h3>Summary</h3>
<p>That&#8217;s it&#8230;hope you enjoyed it.  The hopeful moral of the story is&#8230;Ajax is easy, and so is drag and drop&#8230;.especially if you&#8217;re using a good library.  Personally I think that Prototype is incredibly useful for JavaScript development and Scriptaculous is a good sidekick for effects and drag/drop.  I&#8217;ve also used the <a href="http://developer.yahoo.com/yui">Yahoo YUI widgets</a> at work where we needed to do some more dynamic widgets such as trees &#8211; it worked really well.  <a href="http://www.jackslocum.com">Jack Slocum&#8217;s YUI extension</a> is incredibly well done too&#8230;though it&#8217;s a heavy one in terms of file size!  In the end, it comes down to finding the right tool for the job&#8230;</p>
<p><a href="http://www.gregphoto.net/projects/scriptaculous17/scriptaculous_ajax.zip">Download </a>the sample application if you want to take a closer look&#8230;.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.gregphoto.net/index.php/2007/01/16/scriptaculous-sortables-with-ajax-callback/feed/</wfw:commentRss>
		<slash:comments>49</slash:comments>
		</item>
		<item>
		<title>gCards Forum Up!</title>
		<link>http://www.gregphoto.net/index.php/2006/07/03/gcards-forum-up/</link>
		<comments>http://www.gregphoto.net/index.php/2006/07/03/gcards-forum-up/#comments</comments>
		<pubDate>Mon, 03 Jul 2006 23:41:02 +0000</pubDate>
		<dc:creator>Greg</dc:creator>
				<category><![CDATA[gCards]]></category>
		<category><![CDATA[PHP]]></category>
		<category><![CDATA[Uncategorized]]></category>

		<guid isPermaLink="false">http://www.gregphoto.net/index.php/2006/07/03/gcards-forum-up/</guid>
		<description><![CDATA[Many folks have complained since I took down the forum that was up for the support of gCards. Now, I&#8217;ve got a new forum up, this one powered by Vanilla. Hopefully it&#8217;ll do a bit better than the last one. Check it out]]></description>
			<content:encoded><![CDATA[<p>Many folks have complained since I took down the forum that was up for the support of gCards.  Now, I&#8217;ve got a new forum up, this one powered by <a href="http://getvanilla.com/">Vanilla</a>.  Hopefully it&#8217;ll do a bit better than the last one.</p>
<p><a href="http://www.gregphoto.net/gcards/vanilla">Check it out</a></p>
]]></content:encoded>
			<wfw:commentRss>http://www.gregphoto.net/index.php/2006/07/03/gcards-forum-up/feed/</wfw:commentRss>
		<slash:comments>10</slash:comments>
		</item>
		<item>
		<title>Moved to new webhost</title>
		<link>http://www.gregphoto.net/index.php/2006/02/20/moved-to-new-webhost/</link>
		<comments>http://www.gregphoto.net/index.php/2006/02/20/moved-to-new-webhost/#comments</comments>
		<pubDate>Mon, 20 Feb 2006 23:04:24 +0000</pubDate>
		<dc:creator>Greg</dc:creator>
				<category><![CDATA[Uncategorized]]></category>

		<guid isPermaLink="false">http://www.gregphoto.net/index.php/2006/02/20/moved-to-new-webhost/</guid>
		<description><![CDATA[I moved this site to a new webhost &#8211; Dreamhost. Be on the lookout for links that don&#8217;t work and other broken stuff &#8211; if you find anything please add a comment to this post to let me know and I&#8217;ll take care of it. In the process of moving my stuff from my old [...]]]></description>
			<content:encoded><![CDATA[<p>I moved this site to a new webhost &#8211; <a href="http://www.dreamhost.com">Dreamhost</a>.  Be on the lookout for links that don&#8217;t work and other broken stuff &#8211; if you find anything please add a comment to this post to let me know and I&#8217;ll take care of it.  </p>
<p>In the process of moving my stuff from my old host to the new one, I came to learn that my forum for <a href="http://www.gregphoto.net/gcards">gcards</a> was somewhat hacked&#8230;so I&#8217;ve decided to take it down (i.e. not reinstall it) for the time being.  I may setup Media Wiki in its place or find another forum alternative&#8230;</p>
<p>Greg</p>
]]></content:encoded>
			<wfw:commentRss>http://www.gregphoto.net/index.php/2006/02/20/moved-to-new-webhost/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Nursing jokes&#8230;courtesy of Yenari</title>
		<link>http://www.gregphoto.net/index.php/2006/02/16/nursing-jokescourtesy-of-yenari/</link>
		<comments>http://www.gregphoto.net/index.php/2006/02/16/nursing-jokescourtesy-of-yenari/#comments</comments>
		<pubDate>Thu, 16 Feb 2006 07:17:17 +0000</pubDate>
		<dc:creator>Greg</dc:creator>
				<category><![CDATA[Uncategorized]]></category>

		<guid isPermaLink="false">http://www.gregphoto.net/index.php/2006/02/16/nursing-jokescourtesy-of-yenari/</guid>
		<description><![CDATA[&#8220;Top ten reasons to become a nurse&#8221; 1. Pays better than fast food, though the hours aren&#8217;t as good. 2. Fashionable shoes and cool uniforms 3. Needles: &#8220;Tis better to give than receive&#8221; 4. Reassure your patients that all bleeding stops&#8230;eventually 5. Expose yourself to rare, exciting new diseases 6. Interesting aromas 7. Courteous and [...]]]></description>
			<content:encoded><![CDATA[<p><strong>&#8220;Top ten reasons to become a nurse&#8221;</strong></p>
<p>1.  Pays better than fast food, though the hours aren&#8217;t as good.<br />
2.  Fashionable shoes and cool uniforms<br />
3.  Needles: &#8220;Tis better to give than receive&#8221;<br />
4.  Reassure your patients that all bleeding stops&#8230;eventually<br />
5.  Expose yourself to rare, exciting new diseases<br />
6.  Interesting aromas<br />
7.  Courteous and infallible doctors who always leave clear orders in legible handwriting<br />
8.  Do enough charting to navigate around the world<br />
9. Celebrate the holidays with your friends-at work<br />
10. Take comfort that most of your patients survive no matter what you do to them</p>
<p>Just for fun&#8230;<strong>pregnancy dictionary</strong></p>
<p>Artery&#8230;..the study of paintings<br />
Bacteria&#8230;..the back door to the cafeteria<br />
Benign&#8230;&#8230;what you be, after you be eight<br />
cauterize&#8230;&#8230;made eye contact with her<br />
Dilate&#8230;&#8230;live long<br />
enema&#8230;..not a friend<br />
Fester&#8230;&#8230;.qucker than someone else<br />
Morbid&#8230;&#8230;..a higher offer<br />
Nitrates&#8230;&#8230;&#8230;cheaper than day rates<br />
Outpatient&#8230;.. a person who has fainter<br />
Seizure&#8230;&#8230;&#8230;.roman emperor<br />
Terminal Illness&#8230;&#8230;.getting sick at the airport<br />
Tumor&#8230;&#8230;&#8230;.one plus one more<br />
Urine&#8230;&#8230;.opposite of your out</p>
]]></content:encoded>
			<wfw:commentRss>http://www.gregphoto.net/index.php/2006/02/16/nursing-jokescourtesy-of-yenari/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>Backing up delicious with PHP, mySQL, SimpleXML, and AJAX for Live Search</title>
		<link>http://www.gregphoto.net/index.php/2006/01/07/backing-up-delicious-with-php-mysql-simplexml-and-ajax-for-live-search/</link>
		<comments>http://www.gregphoto.net/index.php/2006/01/07/backing-up-delicious-with-php-mysql-simplexml-and-ajax-for-live-search/#comments</comments>
		<pubDate>Sat, 07 Jan 2006 21:49:48 +0000</pubDate>
		<dc:creator>Greg</dc:creator>
				<category><![CDATA[Uncategorized]]></category>

		<guid isPermaLink="false">http://www.gregphoto.net/index.php/2006/01/07/backing-up-delicious-with-php-mysql-simplexml-and-ajax-for-live-search/</guid>
		<description><![CDATA[I&#8217;m a constant user of the social bookmarking service delicious. I use it to store bookmarks for all of the interesting web sites I see, and I use it to find interesting sites other people have found. It&#8217;s a very useful service and I&#8217;ve grown to rely on it. They have, unfortunately, had some problems [...]]]></description>
			<content:encoded><![CDATA[<p>I&#8217;m a constant user of the social bookmarking service <a href="http://del.icio.us" target="_blank">delicious</a>.  I use it to store bookmarks for all of the interesting web sites I see, and I use it to find interesting sites other people have found.  It&#8217;s a very useful service and I&#8217;ve grown to rely on it.  They have, unfortunately, had some problems with downtime, slow service, and other unreliability.  I&#8217;m sure that this will be diminished greatly due to their <a href="http://blog.del.icio.us/blog/2005/12/yahoo.html" target="_blank">purchase by Yahoo!</a>, and I&#8217;m not really complaining, because it is a free service.</p>
<p>Because I rely on it so much, I decided that I needed a way to back up my bookmarks and still have access to them anywhere with an internet connection.  Exporting to an HTML file or to my Firefox bookmarks didn&#8217;t really have any appeal to me.  So my idea was to put together a simple PHP script to load all of my delicious links into a mySQL database and provide a simple interface to browse them.  Delicious provides a <a href="http://del.icio.us/doc/api" target="_blank">REST API</a> that has a call to export all of your posts to XML &#8211; if you load up <a href="http://del.icio.us/api/posts/all" target="_blank">http://del.icio.us/api/posts/all</a> in your web browser, provide your delicious username and password, you can get the full XML.  I also took this as an opportunity to play around with some technology that I haven&#8217;t used much yet &#8211; PHP5, SimpleXML, and AJAX.  </p>
<p>Some of this is spurred on by the fact that I got a new webhosting account at <a href="http://www.dreamhost.com" target="_blank">Dreamhost</a> &#8211; this supports PHP5 and has a ton of other great features.  As a side note, if you&#8217;re looking for a webhosting account, you can sign up for Dreamhost&#8217;s <a href="http://www.dreamhost.com/shared/comparison.html">Level 1 account</a> (20GB space, just about unlimited bandwidth, PHP5, PHP4, Ruby on Rails, SSH, unlimited domains/subdomains, and a free 1 year domain registration) for $30 if you use the code &#8216;<strong>GREGPHOTO</strong>&#8216; at checkout and sign up for a 1 year prepaid plan.  Ok, enough of the advertising &#8211; onto how I made the app and a bunch of code examples!</p>
<p><strong>Exporting delicious posts</strong></p>
<p>As mentioned above, I used the link <a href="http://del.icio.us/api/posts/all" target="_blank">http://del.icio.us/api/posts/all</a> through Firefox to download the XML file and save it as all.xml.  This has a very simple format, an example is shown below:</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="xml" style="font-family:monospace;"><span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;?xml</span> <span style="color: #000066;">version</span>=<span style="color: #ff0000;">&quot;1.0&quot;</span> <span style="color: #000066;">standalone</span>=<span style="color: #ff0000;">&quot;yes&quot;</span><span style="color: #000000; font-weight: bold;">?&gt;</span></span>
<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;posts</span> <span style="color: #000066;">update</span>=<span style="color: #ff0000;">&quot;2006-01-07T17:55:47Z&quot;</span> <span style="color: #000066;">user</span>=<span style="color: #ff0000;">&quot;gneustaetter&quot;</span><span style="color: #000000; font-weight: bold;">&gt;</span></span>
  <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;post</span> <span style="color: #000066;">href</span>=<span style="color: #ff0000;">&quot;http://www.subzane.com/projects.details.php?ID=12&quot;</span> <span style="color: #000066;">description</span>=<span style="color: #ff0000;">&quot;subzane.com - Free PHP Scripts and Classes&quot;</span> <span style="color: #000066;">hash</span>=<span style="color: #ff0000;">&quot;05d908f23adbb89ef3e97e5d3a6ffd9f&quot;</span> <span style="color: #000066;">tag</span>=<span style="color: #ff0000;">&quot;php&quot;</span> <span style="color: #000066;">time</span>=<span style="color: #ff0000;">&quot;2006-01-06T07:50:49Z&quot;</span><span style="color: #000000; font-weight: bold;">/&gt;</span></span>
  <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;post</span> <span style="color: #000066;">href</span>=<span style="color: #ff0000;">&quot;http://priyadi.net/archives/2005/09/27/wordpress-plugin-code-autoescape/&quot;</span> <span style="color: #000066;">description</span>=<span style="color: #ff0000;">&quot;Priyadi�s Place � Blog Archive � WordPress Plugin: Code Autoescape&quot;</span> <span style="color: #000066;">hash</span>=<span style="color: #ff0000;">&quot;502441799d404abcbe08a07186c32626&quot;</span> <span style="color: #000066;">tag</span>=<span style="color: #ff0000;">&quot;php wordpress&quot;</span> <span style="color: #000066;">time</span>=<span style="color: #ff0000;">&quot;2006-01-06T06:47:59Z&quot;</span><span style="color: #000000; font-weight: bold;">/&gt;</span></span>
   <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;post</span> <span style="color: #000066;">href</span>=<span style="color: #ff0000;">&quot;http://www.huddletogether.com/projects/lightbox/&quot;</span> <span style="color: #000066;">description</span>=<span style="color: #ff0000;">&quot;Lightbox JS: Fullsize Image Overlays&quot;</span> <span style="color: #000066;">hash</span>=<span style="color: #ff0000;">&quot;08a5a446ff39aeb04c5fdbc50d674765&quot;</span> <span style="color: #000066;">tag</span>=<span style="color: #ff0000;">&quot;javascript css design&quot;</span> <span style="color: #000066;">time</span>=<span style="color: #ff0000;">&quot;2005-12-30T17:58:44Z&quot;</span><span style="color: #000000; font-weight: bold;">/&gt;</span></span>
  <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;post</span> <span style="color: #000066;">href</span>=<span style="color: #ff0000;">&quot;http://www.kayak.com/h/buzz/flights&quot;</span> <span style="color: #000066;">description</span>=<span style="color: #ff0000;">&quot;Kayak Buzz popular flight searches&quot;</span> <span style="color: #000066;">hash</span>=<span style="color: #ff0000;">&quot;ea74f520caad38215201d839403fc61f&quot;</span> <span style="color: #000066;">tag</span>=<span style="color: #ff0000;">&quot;travel maps&quot;</span> <span style="color: #000066;">time</span>=<span style="color: #ff0000;">&quot;2005-12-21T17:37:50Z&quot;</span><span style="color: #000000; font-weight: bold;">/&gt;</span></span>
  <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;post</span> <span style="color: #000066;">href</span>=<span style="color: #ff0000;">&quot;http://wsfinder.jot.com/WikiHome&quot;</span> <span style="color: #000066;">description</span>=<span style="color: #ff0000;">&quot;WikiHome - wsfinder - JotSpot&quot;</span> <span style="color: #000066;">hash</span>=<span style="color: #ff0000;">&quot;0e85912cf399cb7469a00e8633d13a77&quot;</span> <span style="color: #000066;">tag</span>=<span style="color: #ff0000;">&quot;api reference tools&quot;</span> <span style="color: #000066;">time</span>=<span style="color: #ff0000;">&quot;2005-12-21T17:31:16Z&quot;</span><span style="color: #000000; font-weight: bold;">/&gt;</span></span>
<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/posts<span style="color: #000000; font-weight: bold;">&gt;</span></span></span></pre></td></tr></table></div>

<p>So basically it has a top level &#8216;posts&#8217; element and then &#8216;post&#8217; elements inside this that detail the link href, description, the tags applied to the link, the time posted, and a hash.  I&#8217;ll use all of the information except for the hash.</p>
<p><strong>Parsing the XML with PHP5&#8242;s SimpleXML</strong></p>
<p>One of the greatest features in PHP5 is <a href="www.php.net/simplexml" target="_blank">SimpleXML</a>, which really allows incredibly simple access to XML.  For tasks such as parsing the above XML, this is a great thing to use &#8211; you basically get to iterate through the XML as if it were an Array.  Let&#8217;s take a look at the parseXML function in my delicious import class:</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
</pre></td><td class="code"><pre class="php" style="font-family:monospace;"><span style="color: #000000; font-weight: bold;">function</span> parseXML<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
	<span style="color: #000088;">$xml</span> <span style="color: #339933;">=</span> <span style="color: #990000;">simplexml_load_file</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">xmlfile</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
	<span style="color: #b1b100;">foreach</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$xml</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">post</span> <span style="color: #b1b100;">as</span> <span style="color: #000088;">$post</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
		<span style="color: #000088;">$tags</span> <span style="color: #339933;">=</span> <span style="color: #000088;">$post</span><span style="color: #009900;">&#91;</span><span style="color: #0000ff;">'tag'</span><span style="color: #009900;">&#93;</span><span style="color: #339933;">;</span>
		<span style="color: #000088;">$tags</span> <span style="color: #339933;">=</span> <span style="color: #990000;">explode</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">' '</span><span style="color: #339933;">,</span><span style="color: #000088;">$tags</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
		<span style="color: #b1b100;">foreach</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$tags</span> <span style="color: #b1b100;">as</span> <span style="color: #000088;">$tag</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
			<span style="color: #000088;">$tag</span> <span style="color: #339933;">=</span> <span style="color: #990000;">trim</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$tag</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><span style="color: #990000;">in_array</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$tag</span><span style="color: #339933;">,</span> <span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">tags</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
				<span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">tags</span><span style="color: #009900;">&#91;</span><span style="color: #000088;">$tag</span><span style="color: #009900;">&#93;</span><span style="color: #009900;">&#91;</span><span style="color: #0000ff;">'name'</span><span style="color: #009900;">&#93;</span> <span style="color: #339933;">=</span> <span style="color: #000088;">$tag</span><span style="color: #339933;">;</span>
			<span style="color: #009900;">&#125;</span>
		<span style="color: #009900;">&#125;</span>
		<span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">posts</span><span style="color: #009900;">&#91;</span><span style="color: #009900;">&#93;</span> <span style="color: #339933;">=</span> <span style="color: #990000;">array</span><span style="color: #009900;">&#40;</span>
			<span style="color: #0000ff;">'href'</span> <span style="color: #339933;">=&gt;</span> <span style="color: #009900;">&#40;</span>string<span style="color: #009900;">&#41;</span><span style="color: #000088;">$post</span><span style="color: #009900;">&#91;</span><span style="color: #0000ff;">'href'</span><span style="color: #009900;">&#93;</span><span style="color: #339933;">,</span>
			<span style="color: #0000ff;">'description'</span> <span style="color: #339933;">=&gt;</span> <span style="color: #009900;">&#40;</span>string<span style="color: #009900;">&#41;</span><span style="color: #000088;">$post</span><span style="color: #009900;">&#91;</span><span style="color: #0000ff;">'description'</span><span style="color: #009900;">&#93;</span><span style="color: #339933;">,</span>
			<span style="color: #0000ff;">'tags'</span> <span style="color: #339933;">=&gt;</span> <span style="color: #000088;">$tags</span><span style="color: #339933;">,</span>
			<span style="color: #0000ff;">'time'</span> <span style="color: #339933;">=&gt;</span> <span style="color: #990000;">strtotime</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#40;</span>string<span style="color: #009900;">&#41;</span><span style="color: #000088;">$post</span><span style="color: #009900;">&#91;</span><span style="color: #0000ff;">'time'</span><span style="color: #009900;">&#93;</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: #009900;">&#125;</span></pre></td></tr></table></div>

<ol>
<li>The function takes no arguments and starts off (on line 2) by loading the all.xml file (path stored as $this->xmlfile) and creating a simplexml object called $xml</li>
<li>SimpleXML supports iteration, so we can loop through the XML file as if it were an array &#8211; using the foreach construct (line 3)</li>
<li>On lines 3 and 4, we get the tags from the tag attribute of the XML, and explode them into an array by splitting them wherever there are spaces &#8211; i.e. the tag &#8220;php5 simplexml&#8221; would turn into an array with two elements, &#8220;php5&#8243; and &#8220;simpleXML&#8221;</li>
<li>From here, we loop through the tags array I just created and push the tags into a class-level array if they aren&#8217;t already in there yet (lines 6-11)</li>
<li>Lastly, on lines 12-18, we populate information about the post into a class-level array that stores the information about all the posts</li>
</ol>
<p>So in this function we took the all.xml file that had all of the delicious links, loaded them into a simpleXML object, and populated two arrays &#8211; one holding a unique list of all the tags, another holding information about all of the posts.  </p>
<p><span id="more-23"></span></p>
<p><strong>Populating the database</strong></p>
<p>At this point, we insert all of the information into the database &#8211; none of that is too exciting, so I won&#8217;t publish that in this post, though you can look at the delicious.class.php file in the zip file that includes all of the files.  It&#8217;s in the inc/classes directory.  This class uses the incredibly popular <a href="http://adodb.sourceforge.net/" target="_blank">ADODB database abstraction library</a> to take care of inserting all of the data.  This is split into three tables:</p>
<ul>
<li>tags &#8211; holds a record for each unique tag</li>
<li>posts &#8211; holds a record for each tag, including all of it&#8217;s attributes such the href, description, space-separated list of tags (for easier searching later), and posting date</li>
<li>posttags &#8211; holds the relationships between posts and tags.  A record is created for each tag associated with a post</li>
</ul>
<p><strong>Building the interface</strong></p>
<p>Now that we have all of the information stored in the database, we can build the user interface and backend that are needed to display the bookmarks.  The final version of what we&#8217;re building can be seen <a href="http://www.pragmaticidealist.net/delicious" target="_blank">here</a>.  We start by creating a class to hold get all the information from the database.  I&#8217;ve called this class bookmarks.class.php and it can be found in the &#8216;inc/classes&#8217; directory.  Again, there really isn&#8217;t much exciting code here, so I&#8217;ll just list out the relevant functions provided by the class:</p>
<ul>
<li>__construct($conn) &#8211; takes an ADODB connection object and instantiates the bookmarks class</li>
<li>getAllBookmarks() &#8211; return an ADODB resultSet object (that implements iterator functions) that includes all of the posts and their details</li>
<li>getBookmarksByTag($tag) &#8211; takes a tagid a return as ADODB resultSet, as above, for the boomarks in the appropriate tag</li>
<li>searchBookmarks($criteria) &#8211; takes a search string and return an ADODB resultSet with bookmarks that match the search criteria</li>
<li>getTags() &#8211; returns an ADODB resultSet with all of the tags and their tagids</li>
</ul>
<p>All in all, a pretty simple class, weighing in just under 50 lines.  Next we need to build the user interface to display the bookmarks &#8211; I could have built a simple, standard application that rendered the bookmarks.  Instead, I decided that I&#8217;d use some AJAX in order to dynamically load information when searching and when choosing a tag.  We&#8217;ll get to the JavaScript once we show the two PHP pages I&#8217;m using for the application.</p>
<p>index.php</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
</pre></td><td class="code"><pre class="php" style="font-family:monospace;"><span style="color: #000000; font-weight: bold;">&lt;?</span>
<span style="color: #b1b100;">require</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'config.php'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
<span style="color: #b1b100;">require</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'inc/classes/bookmarks.class.php'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
<span style="color: #000088;">$bmarks</span> <span style="color: #339933;">=</span> <span style="color: #000000; font-weight: bold;">new</span> bookmarks<span style="color: #009900;">&#40;</span><span style="color: #000088;">$conn</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
<span style="color: #000088;">$tags</span> <span style="color: #339933;">=</span> <span style="color: #000088;">$bmarks</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">getTags</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;!DOCTYPE HTML PUBLIC &quot;-//W3C//DTD HTML 4.01 Transitional//EN&quot;&gt;
&nbsp;
&lt;html&gt;
&lt;head&gt;
&lt;title&gt;Delicious Backup&lt;/title&gt;
&lt;link rel=&quot;stylesheet&quot; type=&quot;text/css&quot; href=&quot;css/style.css&quot;&gt;
&lt;script language=&quot;JavaScript&quot; src=&quot;js/prototype.js&quot;&gt;&lt;/script&gt;
&lt;script language=&quot;JavaScript&quot; src=&quot;js/bookmarks.js&quot;&gt;&lt;/script&gt;
&lt;/head&gt;
&nbsp;
&lt;body&gt;
&lt;table cellspacing=&quot;0&quot; cellpadding=&quot;0&quot; width=&quot;100%&quot; id=&quot;outerTable&quot;&gt;
	&lt;tr&gt;
		&lt;td colspan=&quot;2&quot; align=&quot;center&quot; id=&quot;search&quot;&gt;
			Search &lt;input type=&quot;text&quot; id=&quot;searchbox&quot;&gt;
		&lt;/td&gt;
	&lt;/tr&gt;
	&lt;tr&gt;
		&lt;td id=&quot;bookmarks&quot;&gt;
			<span style="color: #000000; font-weight: bold;">&lt;?</span> <span style="color: #b1b100;">require</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'bookmarks.php'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><span style="color: #000000; font-weight: bold;">?&gt;</span>
		&lt;/td&gt;
		&lt;td id=&quot;tags&quot; align=&quot;right&quot;&gt;
			&lt;h3&gt;Tags&lt;/h3&gt;
			&lt;ul&gt;
			<span style="color: #000000; font-weight: bold;">&lt;?</span>
			<span style="color: #b1b100;">foreach</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$tags</span> <span style="color: #b1b100;">as</span> <span style="color: #000088;">$tag</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
				<span style="color: #000000; font-weight: bold;">?&gt;</span>&lt;li&gt;&lt;a href=&quot;#&quot; onClick=&quot;setTag(<span style="color: #000000; font-weight: bold;">&lt;?=</span><span style="color: #000088;">$tag</span><span style="color: #009900;">&#91;</span><span style="color: #0000ff;">'id'</span><span style="color: #009900;">&#93;</span><span style="color: #339933;">;</span><span style="color: #000000; font-weight: bold;">?&gt;</span>);&quot;&gt;<span style="color: #000000; font-weight: bold;">&lt;?=</span><span style="color: #000088;">$tag</span><span style="color: #009900;">&#91;</span><span style="color: #0000ff;">'tag'</span><span style="color: #009900;">&#93;</span><span style="color: #339933;">;</span><span style="color: #000000; font-weight: bold;">?&gt;</span>&lt;/a&gt;&lt;/li&gt;<span style="color: #000000; font-weight: bold;">&lt;?</span>
			<span style="color: #009900;">&#125;</span>
			<span style="color: #000000; font-weight: bold;">?&gt;</span>
			&lt;/ul&gt;
		&lt;/td&gt;
	&lt;/tr&gt;
&lt;/table&gt;
&lt;/body&gt;
&lt;/html&gt;</pre></td></tr></table></div>

<p>bookmarks.php</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
</pre></td><td class="code"><pre class="php" style="font-family:monospace;"><span style="color: #000000; font-weight: bold;">&lt;?</span>
<span style="color: #b1b100;">require_once</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'config.php'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
<span style="color: #b1b100;">require_once</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'inc/classes/bookmarks.class.php'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
<span style="color: #b1b100;">if</span><span style="color: #009900;">&#40;</span><span style="color: #339933;">!</span><span style="color: #990000;">isset</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$bmarks</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
	<span style="color: #000088;">$bmarks</span> <span style="color: #339933;">=</span> <span style="color: #000000; font-weight: bold;">new</span> bookmarks<span style="color: #009900;">&#40;</span><span style="color: #000088;">$conn</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
<span style="color: #009900;">&#125;</span>
&nbsp;
<span style="color: #b1b100;">if</span><span style="color: #009900;">&#40;</span><span style="color: #990000;">isset</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$_REQUEST</span><span style="color: #009900;">&#91;</span><span style="color: #0000ff;">'tag'</span><span style="color: #009900;">&#93;</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
	<span style="color: #000088;">$bookmarks</span> <span style="color: #339933;">=</span> <span style="color: #000088;">$bmarks</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">getBookmarksByTag</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$_REQUEST</span><span style="color: #009900;">&#91;</span><span style="color: #0000ff;">'tag'</span><span style="color: #009900;">&#93;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
<span style="color: #009900;">&#125;</span> <span style="color: #b1b100;">elseif</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$_REQUEST</span><span style="color: #009900;">&#91;</span><span style="color: #0000ff;">'criteria'</span><span style="color: #009900;">&#93;</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
	<span style="color: #000088;">$bookmarks</span> <span style="color: #339933;">=</span> <span style="color: #000088;">$bmarks</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">searchBookmarks</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$_REQUEST</span><span style="color: #009900;">&#91;</span><span style="color: #0000ff;">'criteria'</span><span style="color: #009900;">&#93;</span><span style="color: #009900;">&#41;</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: #000088;">$bookmarks</span> <span style="color: #339933;">=</span> <span style="color: #000088;">$bmarks</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">getAllBookmarks</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: #000000; font-weight: bold;">?&gt;</span>
&lt;h3&gt;Bookmarks (<span style="color: #000000; font-weight: bold;">&lt;?=</span><span style="color: #000088;">$bmarks</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">numRows</span><span style="color: #339933;">;</span><span style="color: #000000; font-weight: bold;">?&gt;</span> matching)&lt;/h3&gt;
<span style="color: #000000; font-weight: bold;">&lt;?</span>
<span style="color: #b1b100;">foreach</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$bookmarks</span> <span style="color: #b1b100;">as</span> <span style="color: #000088;">$bookmark</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
	<span style="color: #000000; font-weight: bold;">?&gt;</span>
	&lt;div class=&quot;bookmark&quot;&gt;
		&lt;a href=&quot;<span style="color: #000000; font-weight: bold;">&lt;?=</span><span style="color: #000088;">$bookmark</span><span style="color: #009900;">&#91;</span><span style="color: #0000ff;">'href'</span><span style="color: #009900;">&#93;</span><span style="color: #339933;">;</span><span style="color: #000000; font-weight: bold;">?&gt;</span>&quot;&gt;<span style="color: #000000; font-weight: bold;">&lt;?=</span><span style="color: #000088;">$bookmark</span><span style="color: #009900;">&#91;</span><span style="color: #0000ff;">'description'</span><span style="color: #009900;">&#93;</span><span style="color: #339933;">;</span><span style="color: #000000; font-weight: bold;">?&gt;</span>&lt;/a&gt; posted <span style="color: #000000; font-weight: bold;">&lt;?=</span><span style="color: #990000;">Date</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'m/d/y'</span><span style="color: #339933;">,</span> <span style="color: #000088;">$bookmark</span><span style="color: #009900;">&#91;</span><span style="color: #0000ff;">'posted'</span><span style="color: #009900;">&#93;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><span style="color: #000000; font-weight: bold;">?&gt;</span>&lt;br&gt;
		<span style="color: #000000; font-weight: bold;">&lt;?=</span><span style="color: #000088;">$bookmark</span><span style="color: #009900;">&#91;</span><span style="color: #0000ff;">'tags'</span><span style="color: #009900;">&#93;</span><span style="color: #339933;">;</span><span style="color: #000000; font-weight: bold;">?&gt;</span>
	&lt;/div&gt;
	<span style="color: #000000; font-weight: bold;">&lt;?</span>
<span style="color: #009900;">&#125;</span>
<span style="color: #000000; font-weight: bold;">?&gt;</span></pre></td></tr></table></div>

<p>The index.php requires a config file that creates a database connection object, requires the bookmarks.class.php file we just created, instantiates the bookmarks class, and then gets a list of the tags (lines 2-6).  From there, it&#8217;s mostly simple HTML work, requiring the bookmarks.php file (line 27), and finally looping through and displaying the tags &#8211; each with a link, when clicked, calls a javascript function &#8216;setTag&#8217; that we&#8217;ll get to later.</p>
<p>The bookmarks.php file requires the same files as the index.php page, with the slight difference of using require_once instead of require.  This page is going to be called within index.php on the first load, but then all other actions are going to call this page directly, not in the context on index.php.  For the same reason, lines 5-7 conditionally instantiate a bookmarks object if it doesn&#8217;t not yet exist.  From here on, the rest of the page is very simple &#8211; it determines whether it should be showing all of the bookmarks, bookmarks for a particular tag, or the search results.  Each case uses one of the functions we defined in the bookmarks class.  Lastly, it loops through the resultSet returned by the function and prints out each bookmark.</p>
<p><strong>Bring on the AJAX</strong></p>
<p>So we&#8217;ve built the basic structure of our pages and the backend, but I&#8217;ve put off talking about the JavaScript that&#8217;s needed to run this.  There&#8217;s been a revolution in the world of web design &#8211; and JavaScript is coming out as a big winner.  There are a number of incredibly useful JavaScript libraries that have been lowering the bar for creating compelling, dynamic websites.  The one that&#8217;s probably used the most is the <a href="http://prototype.conio.net/" target="_blank">Prototype library</a>.  This library makes simple AJAX work really simple.  Let&#8217;s walk through JavaScript, first with a refresher on the index.php page:</p>
<p>index.php</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;">&lt;!DOCTYPE HTML PUBLIC &quot;-//W3C//DTD HTML 4.01 Transitional//EN&quot;&gt;
&nbsp;
&lt;html&gt;
&lt;head&gt;
&lt;title&gt;Delicious Backup&lt;/title&gt;
&lt;link rel=&quot;stylesheet&quot; type=&quot;text/css&quot; href=&quot;css/style.css&quot;&gt;
&lt;script language=&quot;JavaScript&quot; src=&quot;js/prototype.js&quot;&gt;&lt;/script&gt;
&lt;script language=&quot;JavaScript&quot; src=&quot;js/bookmarks.js&quot;&gt;&lt;/script&gt;
&lt;/head&gt;
&nbsp;
&lt;body&gt;
&lt;table cellspacing=&quot;0&quot; cellpadding=&quot;0&quot; width=&quot;100%&quot; id=&quot;outerTable&quot;&gt;
	&lt;tr&gt;
		&lt;td colspan=&quot;2&quot; align=&quot;center&quot; id=&quot;search&quot;&gt;
			Search &lt;input type=&quot;text&quot; id=&quot;searchbox&quot;&gt;
		&lt;/td&gt;
	&lt;/tr&gt;
	&lt;tr&gt;
		&lt;td id=&quot;bookmarks&quot;&gt;
			<span style="color: #000000; font-weight: bold;">&lt;?</span> <span style="color: #b1b100;">require</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'bookmarks.php'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><span style="color: #000000; font-weight: bold;">?&gt;</span>
		&lt;/td&gt;</pre></td></tr></table></div>

<p>You can see on line 7 and 8 we&#8217;re linking to two external JavaScript files &#8211; the first is the prototype library, and the second is the logic used for this application.  Now for the contents of bookmarks.js:</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
</pre></td><td class="code"><pre class="javascript" style="font-family:monospace;">Event.<span style="color: #660066;">observe</span><span style="color: #009900;">&#40;</span>window<span style="color: #339933;">,</span> <span style="color: #3366CC;">'load'</span><span style="color: #339933;">,</span> init<span style="color: #339933;">,</span> <span style="color: #003366; font-weight: bold;">false</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
<span style="color: #003366; font-weight: bold;">function</span> init<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
	Field.<span style="color: #000066;">focus</span><span style="color: #009900;">&#40;</span><span style="color: #3366CC;">'searchbox'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
	Event.<span style="color: #660066;">observe</span><span style="color: #009900;">&#40;</span><span style="color: #3366CC;">'searchbox'</span><span style="color: #339933;">,</span> <span style="color: #3366CC;">'keyup'</span><span style="color: #339933;">,</span> doSearch<span style="color: #339933;">,</span> <span style="color: #003366; font-weight: bold;">false</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
<span style="color: #009900;">&#125;</span>
&nbsp;
<span style="color: #003366; font-weight: bold;">function</span> setTag<span style="color: #009900;">&#40;</span>tagid<span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
	<span style="color: #003366; font-weight: bold;">var</span> url <span style="color: #339933;">=</span> <span style="color: #3366CC;">'bookmarks.php'</span><span style="color: #339933;">;</span>
	<span style="color: #003366; font-weight: bold;">var</span> pars <span style="color: #339933;">=</span> <span style="color: #3366CC;">'tag='</span><span style="color: #339933;">+</span>tagid<span style="color: #339933;">;</span>
	<span style="color: #003366; font-weight: bold;">var</span> target <span style="color: #339933;">=</span> <span style="color: #3366CC;">'bookmarks'</span><span style="color: #339933;">;</span>
	<span style="color: #003366; font-weight: bold;">var</span> myAjax <span style="color: #339933;">=</span> <span style="color: #003366; font-weight: bold;">new</span> Ajax.<span style="color: #660066;">Updater</span><span style="color: #009900;">&#40;</span>target<span style="color: #339933;">,</span> url<span style="color: #339933;">,</span> <span style="color: #009900;">&#123;</span>method<span style="color: #339933;">:</span> <span style="color: #3366CC;">'get'</span><span style="color: #339933;">,</span> parameters<span style="color: #339933;">:</span> pars<span style="color: #009900;">&#125;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
<span style="color: #009900;">&#125;</span>
&nbsp;
<span style="color: #003366; font-weight: bold;">function</span> doSearch<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
	<span style="color: #003366; font-weight: bold;">var</span> url <span style="color: #339933;">=</span> <span style="color: #3366CC;">'bookmarks.php'</span><span style="color: #339933;">;</span>
	<span style="color: #003366; font-weight: bold;">var</span> pars <span style="color: #339933;">=</span> <span style="color: #3366CC;">'criteria='</span><span style="color: #339933;">+</span>$F<span style="color: #009900;">&#40;</span><span style="color: #3366CC;">'searchbox'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
	<span style="color: #003366; font-weight: bold;">var</span> target <span style="color: #339933;">=</span> <span style="color: #3366CC;">'bookmarks'</span><span style="color: #339933;">;</span>
	<span style="color: #003366; font-weight: bold;">var</span> myAjax <span style="color: #339933;">=</span> <span style="color: #003366; font-weight: bold;">new</span> Ajax.<span style="color: #660066;">Updater</span><span style="color: #009900;">&#40;</span>target<span style="color: #339933;">,</span> url<span style="color: #339933;">,</span> <span style="color: #009900;">&#123;</span>method<span style="color: #339933;">:</span> <span style="color: #3366CC;">'get'</span><span style="color: #339933;">,</span> parameters<span style="color: #339933;">:</span> pars<span style="color: #009900;">&#125;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
<span style="color: #009900;">&#125;</span></pre></td></tr></table></div>

<p>Line 1 starts off by using Prototype&#8217;s Event object to add an observer that will call the &#8216;init&#8217; function &#8216;onLoad&#8217; of the window.  The init function (lines 1-3), sets the field focus on the text box &#8216;searchbox&#8217;, that is defined on index.php.  It also sets an observer on this text box that will call the &#8216;doSearch&#8217; function whenever a character is entered (or cleared) from the search box element.</p>
<p>Skipping down to the doSearch function (lines 15-20), this just sets a couple variables &#8211; the page we want to request (bokmarks.php), the parameters that we want to send (this uses the prototype $F function to get the current value from the searchbox element), and the target element we want to update &#8211; in this case, a table cell with an ID of &#8216;bookmarks&#8217;.  Lastly, we use the Ajax.Updater provided by the Prototype library to send off a request to the page, get the resulting HTML, and replace the contents of the bookmarks table cell with the new contents &#8211; not too hard, huh?  The setTag function is almost identical except it takes a tagid as an input and sends that off to the bookmarks page.</p>
<p>Now when we open up the <a href="http://www.pragmaticidealist.net/delicious" target="_blank">final results</a>, we have a dynamic application that reloads boomarks when you click on a tag, and performs a live search on the bookmarks.  I&#8217;d didn&#8217;t spend any time to spruce up the pages, but that&#8217;s for another day.  I hope you enjoyed this walkthrough, and learned something you didn&#8217;t know yet.  You can download all of the project files below:</p>
<p><a href="http://www.pragmaticidealist.net/download/delicious_backup.zip">Download Delicious Backup Project Files</a> (135 KB)</p>
]]></content:encoded>
			<wfw:commentRss>http://www.gregphoto.net/index.php/2006/01/07/backing-up-delicious-with-php-mysql-simplexml-and-ajax-for-live-search/feed/</wfw:commentRss>
		<slash:comments>9</slash:comments>
		</item>
	</channel>
</rss>

