<?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>mdgArt</title>
	<atom:link href="http://www.mdgart.com/feed/" rel="self" type="application/rss+xml" />
	<link>http://www.mdgart.com</link>
	<description>Art &#38; Programming</description>
	<lastBuildDate>Thu, 12 Jan 2012 11:56:28 +0000</lastBuildDate>
	<generator>http://wordpress.org/?v=2.8.5</generator>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
			<item>
		<title>Django Auth behind proxy server</title>
		<link>http://www.mdgart.com/2011/01/15/django-auth-behind-proxy-server/</link>
		<comments>http://www.mdgart.com/2011/01/15/django-auth-behind-proxy-server/#comments</comments>
		<pubDate>Sat, 15 Jan 2011 17:35:44 +0000</pubDate>
		<dc:creator>Mauro</dc:creator>
				<category><![CDATA[Django]]></category>
		<category><![CDATA[Programming]]></category>
		<category><![CDATA[Python]]></category>
		<category><![CDATA[Auth]]></category>
		<category><![CDATA[django admin]]></category>
		<category><![CDATA[Proxy]]></category>
		<category><![CDATA[SESSION]]></category>

		<guid isPermaLink="false">http://www.mdgart.com/?p=136</guid>
		<description><![CDATA[Yesterday I had a weird problem with a Django application that should primarily work on computer behind a proxy server: for some reason that I didn&#8217;t understand yet, the proxy lost the session&#8217;s cookie, but only when a form send data (via POST) to a view that is visible only to logged users (=O).
The other [...]]]></description>
			<content:encoded><![CDATA[<p>Yesterday I had a weird problem with a Django application that should primarily work on computer behind a proxy server: for some reason that I didn&#8217;t understand yet, the proxy lost the session&#8217;s cookie, but only when a form send data (via POST) to a view that is visible only to logged users (=O).<br />
The other views works well, but that particular views lost the cookie! What to do in this case?<br />
A simple workaround helped me: I sent the session id via GET to the view. I know, django never use this for security reason, but I didn&#8217;t find a &#8220;official&#8221; solution, so this is what I did:</p>
<p>I create this middleware that use the query string session id if it doesn&#8217;t find the session&#8217;s cookies in the request:</p>

<div class="wp_syntax"><div class="code"><pre class="python" style="font-family:monospace;"><span style="color: #ff7700;font-weight:bold;">from</span> django.<span style="color: black;">conf</span> <span style="color: #ff7700;font-weight:bold;">import</span> settings
&nbsp;
<span style="color: #ff7700;font-weight:bold;">class</span> FakeSessionCookieMiddleware<span style="color: black;">&#40;</span><span style="color: #008000;">object</span><span style="color: black;">&#41;</span>:
&nbsp;
    <span style="color: #ff7700;font-weight:bold;">def</span> process_request<span style="color: black;">&#40;</span><span style="color: #008000;">self</span>, request<span style="color: black;">&#41;</span>:
        <span style="color: #ff7700;font-weight:bold;">if</span> <span style="color: #ff7700;font-weight:bold;">not</span> request.<span style="color: black;">COOKIES</span>.<span style="color: black;">has_key</span><span style="color: black;">&#40;</span>settings.<span style="color: black;">SESSION_COOKIE_NAME</span><span style="color: black;">&#41;</span> <span style="color: #ff7700;font-weight:bold;">and</span> request.<span style="color: black;">GET</span>.<span style="color: black;">has_key</span><span style="color: black;">&#40;</span>settings.<span style="color: black;">SESSION_COOKIE_NAME</span><span style="color: black;">&#41;</span>:
            request.<span style="color: black;">COOKIES</span><span style="color: black;">&#91;</span>settings.<span style="color: black;">SESSION_COOKIE_NAME</span><span style="color: black;">&#93;</span> = request.<span style="color: black;">GET</span><span style="color: black;">&#91;</span>settings.<span style="color: black;">SESSION_COOKIE_NAME</span><span style="color: black;">&#93;</span></pre></div></div>

<p>You have to add this middleware to your settings.py <strong>before</strong> django.contrib.sessions.middleware.SessionMiddleware:</p>

<div class="wp_syntax"><div class="code"><pre class="python" style="font-family:monospace;">MIDDLEWARE_CLASSES = <span style="color: black;">&#40;</span>
    ...
    <span style="color: #483d8b;">'myapp.middleware.FakeSessionCookieMiddleware'</span>,
    <span style="color: #483d8b;">'django.contrib.sessions.middleware.SessionMiddleware'</span>,
    <span style="color: #483d8b;">'django.contrib.auth.middleware.AuthenticationMiddleware'</span>,
    ...
<span style="color: black;">&#41;</span></pre></div></div>

<p>In this case the middleware class is inside the <strong>middleware.py</strong> file in <strong>myapp</strong> application.<br />
Then you can add SESSION_COOKIE_NAME in your context like this:</p>

<div class="wp_syntax"><div class="code"><pre class="python" style="font-family:monospace;">context = <span style="color: black;">&#123;</span>
    <span style="color: #483d8b;">'session_cookie_name'</span>: settings.<span style="color: black;">SESSION_COOKIE_NAME</span>,
    <span style="color: #483d8b;">'session_cookie_value'</span>: request.<span style="color: black;">COOKIES</span><span style="color: black;">&#91;</span>settings.<span style="color: black;">SESSION_COOKIE_NAME</span><span style="color: black;">&#93;</span>, 
<span style="color: black;">&#125;</span> 
    template = <span style="color: #483d8b;">'yourtemplate.html'</span> 	
    <span style="color: #ff7700;font-weight:bold;">return</span> render_to_response<span style="color: black;">&#40;</span>template, context, context_instance=RequestContext<span style="color: black;">&#40;</span>request<span style="color: black;">&#41;</span><span style="color: black;">&#41;</span></pre></div></div>

<p>and pass &#8220;session_cookie_name&#8221; and &#8220;session_cookie_value&#8221; in your URL:</p>

<div class="wp_syntax"><div class="code"><pre class="html" style="font-family:monospace;">&lt;a href=&quot;/your/url/?{{session_cookie_name}}={{session_cookie_value}}&quot;&gt;</pre></div></div>

<p>Is ugly and potentially dangerous, but it&#8217;s an extreme solution in case you REALLY have this problem that can&#8217;t be solved in other ways. Hope this can help someone with the same issue.</p>
<p class="buymebeer"><form action="https://www.paypal.com/cgi-bin/webscr" target="paypal" method="post"><input type="hidden" name="cmd" value="_xclick" /><input type="hidden" name="business" value="mauro@ondadiluce.com" /><input type="hidden" name="return" value="" /><input type="hidden" name="item_name" value="Buy me a coffe for Django Auth behind proxy server" /><input type="hidden" name="currency_code" value="EUR" /><input type="hidden" name="amount" value="1" /><input type="image" src="http://www.mdgart.com/wp-content/plugins/buy-me-beer/icon_cafe.gif" align="left" alt="Buy me a coffe" title="Buy me a coffe" hspace="3" style="border:0;" /></form><a href="https://www.paypal.com/cgi-bin/webscr?cmd=_xclick&amp;business=mauro@ondadiluce.com&amp;currency_code=EUR&amp;amount=1&amp;return=&amp;item_name=Buy+me+a+coffe+for+Django+Auth+behind+proxy+server" target="paypal">Donate 1 euro, buy me a coffee, I need it to write more posts! Thanks ;)</a></p>]]></content:encoded>
			<wfw:commentRss>http://www.mdgart.com/2011/01/15/django-auth-behind-proxy-server/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Django Tip: Cross Domain Cookies</title>
		<link>http://www.mdgart.com/2011/01/15/django-tip-cross-domain-cookies/</link>
		<comments>http://www.mdgart.com/2011/01/15/django-tip-cross-domain-cookies/#comments</comments>
		<pubDate>Sat, 15 Jan 2011 17:32:03 +0000</pubDate>
		<dc:creator>Mauro</dc:creator>
				<category><![CDATA[Django]]></category>
		<category><![CDATA[Python]]></category>
		<category><![CDATA[Auth]]></category>
		<category><![CDATA[django admin]]></category>
		<category><![CDATA[SESSION]]></category>
		<category><![CDATA[subdomain]]></category>

		<guid isPermaLink="false">http://www.mdgart.com/?p=142</guid>
		<description><![CDATA[If you use the Django Auth Framework you may need to know the existence of this constant that you can set in the settings.py of your project:

SESSION_COOKIE_DOMAIN = &#34;.yourdomain.com&#34;

when you login, your cookies session will be set to be valid on every subdomain, so you will be still logged in www.yourdomain.com, yourdomain.com, and any every [...]]]></description>
			<content:encoded><![CDATA[<p>If you use the Django Auth Framework you may need to know the existence of this constant that you can set in the settings.py of your project:</p>

<div class="wp_syntax"><div class="code"><pre class="python" style="font-family:monospace;">SESSION_COOKIE_DOMAIN = <span style="color: #483d8b;">&quot;.yourdomain.com&quot;</span></pre></div></div>

<p>when you login, your cookies session will be set to be valid on every subdomain, so you will be still logged in www.yourdomain.com, yourdomain.com, and any every subdomains.yourdomain.com.</p>
<p class="buymebeer"><form action="https://www.paypal.com/cgi-bin/webscr" target="paypal" method="post"><input type="hidden" name="cmd" value="_xclick" /><input type="hidden" name="business" value="mauro@ondadiluce.com" /><input type="hidden" name="return" value="" /><input type="hidden" name="item_name" value="Buy me a coffe for Django Tip: Cross Domain Cookies" /><input type="hidden" name="currency_code" value="EUR" /><input type="hidden" name="amount" value="1" /><input type="image" src="http://www.mdgart.com/wp-content/plugins/buy-me-beer/icon_cafe.gif" align="left" alt="Buy me a coffe" title="Buy me a coffe" hspace="3" style="border:0;" /></form><a href="https://www.paypal.com/cgi-bin/webscr?cmd=_xclick&amp;business=mauro@ondadiluce.com&amp;currency_code=EUR&amp;amount=1&amp;return=&amp;item_name=Buy+me+a+coffe+for+Django+Tip:+Cross+Domain+Cookies" target="paypal">Donate 1 euro, buy me a coffee, I need it to write more posts! Thanks ;)</a></p>]]></content:encoded>
			<wfw:commentRss>http://www.mdgart.com/2011/01/15/django-tip-cross-domain-cookies/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Django admin: how to hide fields for certain users (that are not superusers)</title>
		<link>http://www.mdgart.com/2010/04/08/django-admin-how-to-hide-fields-in-a-form-for-certain-users-that-are-not-superusers/</link>
		<comments>http://www.mdgart.com/2010/04/08/django-admin-how-to-hide-fields-in-a-form-for-certain-users-that-are-not-superusers/#comments</comments>
		<pubDate>Thu, 08 Apr 2010 17:56:57 +0000</pubDate>
		<dc:creator>Mauro</dc:creator>
				<category><![CDATA[Django]]></category>
		<category><![CDATA[Programming]]></category>
		<category><![CDATA[Python]]></category>
		<category><![CDATA[django admin]]></category>
		<category><![CDATA[ModelAdmin]]></category>
		<category><![CDATA[webdev]]></category>

		<guid isPermaLink="false">http://www.mdgart.com/?p=102</guid>
		<description><![CDATA[I&#8217;m working on a project and I&#8217;m using the incredible django admin. So, yesterday I needed a way to hide some fields in a model for user that didn&#8217;t have superuser permissions. After some googling, I found a method in the ModelAdmin class that was perfect (well, I think that it&#8217;s perfect) for my needs: [...]]]></description>
			<content:encoded><![CDATA[<p>I&#8217;m working on a project and I&#8217;m using the incredible django admin. So, yesterday I needed a way to hide some fields in a model for user that didn&#8217;t have superuser permissions. After some googling, I found a method in the ModelAdmin class that was perfect (well, I think that it&#8217;s perfect) for my needs: <code><strong>get_form</strong></code>.<br />
The method is not really mentioned in the official django documentation except in the <a href="http://docs.djangoproject.com/en/dev/ref/contrib/comments/custom/#django.contrib.comments.get_form">comment framework</a>, but you can use it in your ModelAdmin subclass as well. It&#8217;s called before the &#8220;change form&#8221; is created, so we can dynamically change it before it&#8217;s displayed.<br />
The principle is very simple: I dynamically populate the <a href="http://docs.djangoproject.com/en/dev/ref/contrib/admin/#django.contrib.admin.ModelAdmin.exclude">exclude</a> attribute so that if a user is not a superuser I can exclude a field (or more that one field). Let&#8217;s see an example:</p>

<div class="wp_syntax"><div class="code"><pre class="python" style="font-family:monospace;"><span style="color: #ff7700;font-weight:bold;">class</span> MyModelAdmin<span style="color: black;">&#40;</span>admin.<span style="color: black;">ModelAdmin</span><span style="color: black;">&#41;</span>:
	<span style="color: #ff7700;font-weight:bold;">def</span> get_form<span style="color: black;">&#40;</span><span style="color: #008000;">self</span>, request, obj=<span style="color: #008000;">None</span>, <span style="color: #66cc66;">**</span>kwargs<span style="color: black;">&#41;</span>:
		<span style="color: #008000;">self</span>.<span style="color: black;">exclude</span> = <span style="color: black;">&#91;</span><span style="color: black;">&#93;</span>	
		<span style="color: #ff7700;font-weight:bold;">if</span> <span style="color: #ff7700;font-weight:bold;">not</span> request.<span style="color: #dc143c;">user</span>.<span style="color: black;">is_superuser</span>:
			<span style="color: #008000;">self</span>.<span style="color: black;">exclude</span>.<span style="color: black;">append</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">'field_to_hide'</span><span style="color: black;">&#41;</span>
		<span style="color: #ff7700;font-weight:bold;">return</span> <span style="color: #008000;">super</span><span style="color: black;">&#40;</span>MyModelAdmin, <span style="color: #008000;">self</span><span style="color: black;">&#41;</span>.<span style="color: black;">get_form</span><span style="color: black;">&#40;</span>request, obj, <span style="color: #66cc66;">**</span>kwargs<span style="color: black;">&#41;</span></pre></div></div>

<p>What it does is simply add the <code><strong>field_to_hide</strong></code> to the <code><strong>exclude</strong></code> list of MyModelAdmin. In this case, the field will be visible only to superusers, checking  the <code><strong>request.user.is_superuser attribute</strong></code>. Pretty simple!</p>
<p class="buymebeer"><form action="https://www.paypal.com/cgi-bin/webscr" target="paypal" method="post"><input type="hidden" name="cmd" value="_xclick" /><input type="hidden" name="business" value="mauro@ondadiluce.com" /><input type="hidden" name="return" value="" /><input type="hidden" name="item_name" value="Buy me a coffe for Django admin: how to hide fields for certain users (that are not superusers)" /><input type="hidden" name="currency_code" value="EUR" /><input type="hidden" name="amount" value="1" /><input type="image" src="http://www.mdgart.com/wp-content/plugins/buy-me-beer/icon_cafe.gif" align="left" alt="Buy me a coffe" title="Buy me a coffe" hspace="3" style="border:0;" /></form><a href="https://www.paypal.com/cgi-bin/webscr?cmd=_xclick&amp;business=mauro@ondadiluce.com&amp;currency_code=EUR&amp;amount=1&amp;return=&amp;item_name=Buy+me+a+coffe+for+Django+admin:+how+to+hide+fields+for+certain+users+(that+are+not+superusers)" target="paypal">Donate 1 euro, buy me a coffee, I need it to write more posts! Thanks ;)</a></p>]]></content:encoded>
			<wfw:commentRss>http://www.mdgart.com/2010/04/08/django-admin-how-to-hide-fields-in-a-form-for-certain-users-that-are-not-superusers/feed/</wfw:commentRss>
		<slash:comments>9</slash:comments>
		</item>
		<item>
		<title>Time to change</title>
		<link>http://www.mdgart.com/2010/04/06/time-to-change/</link>
		<comments>http://www.mdgart.com/2010/04/06/time-to-change/#comments</comments>
		<pubDate>Tue, 06 Apr 2010 13:27:27 +0000</pubDate>
		<dc:creator>Mauro</dc:creator>
				<category><![CDATA[Programming]]></category>
		<category><![CDATA[browser]]></category>
		<category><![CDATA[css]]></category>
		<category><![CDATA[ie6]]></category>
		<category><![CDATA[statistics]]></category>

		<guid isPermaLink="false">http://www.mdgart.com/?p=100</guid>
		<description><![CDATA[According to w3c browser statistics ie6 is less then 10% of the market today, and ie7 is 11%. IE8 is growing (about 15%) and, although it is not the best browser on earth it is a big step forward. A preview release of IE9 has been unveiled, and it seems that something is really changing. [...]]]></description>
			<content:encoded><![CDATA[<p>According to <a href="http://www.w3schools.com/browsers/browsers_stats.asp" target="_blank">w3c browser statistics</a> ie6 is less then 10% of the market today, and ie7 is 11%. IE8 is growing (about 15%) and, although it is not the best browser on earth it is a big step forward. A <a href="http://ie.microsoft.com/testdrive/Default.html" target="_blank">preview release of IE9</a> has been unveiled, and it seems that something is really changing. So we (web designers in this case) should seriously start to think about saying goodbye to the horrible and heated ie6 right now, serving a specific <a href="http://forabeautifulweb.com/blog/about/universal_internet_explorer_6_css" target="_blank">universal CSS</a> for that browser: <br /><a href="http://forabeautifulweb.com/blog/about/universal_internet_explorer_6_css" target="_blank">http://forabeautifulweb.com/blog/about/universal_internet_explorer_6_css</a>.</p>
<p class="buymebeer"><form action="https://www.paypal.com/cgi-bin/webscr" target="paypal" method="post"><input type="hidden" name="cmd" value="_xclick" /><input type="hidden" name="business" value="mauro@ondadiluce.com" /><input type="hidden" name="return" value="" /><input type="hidden" name="item_name" value="Buy me a coffe for Time to change" /><input type="hidden" name="currency_code" value="EUR" /><input type="hidden" name="amount" value="1" /><input type="image" src="http://www.mdgart.com/wp-content/plugins/buy-me-beer/icon_cafe.gif" align="left" alt="Buy me a coffe" title="Buy me a coffe" hspace="3" style="border:0;" /></form><a href="https://www.paypal.com/cgi-bin/webscr?cmd=_xclick&amp;business=mauro@ondadiluce.com&amp;currency_code=EUR&amp;amount=1&amp;return=&amp;item_name=Buy+me+a+coffe+for+Time+to+change" target="paypal">Donate 1 euro, buy me a coffee, I need it to write more posts! Thanks ;)</a></p>]]></content:encoded>
			<wfw:commentRss>http://www.mdgart.com/2010/04/06/time-to-change/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Persistent drag and drop tree with jQuery, PHP and MySQL &#8211; CRUD</title>
		<link>http://www.mdgart.com/2009/08/04/persistent-drag-and-drop-tree-with-jquery-php-and-mysql-crud/</link>
		<comments>http://www.mdgart.com/2009/08/04/persistent-drag-and-drop-tree-with-jquery-php-and-mysql-crud/#comments</comments>
		<pubDate>Tue, 04 Aug 2009 11:07:24 +0000</pubDate>
		<dc:creator>Mauro</dc:creator>
				<category><![CDATA[Javascript]]></category>
		<category><![CDATA[MySQL]]></category>
		<category><![CDATA[PHP]]></category>
		<category><![CDATA[Programming]]></category>
		<category><![CDATA[jQuery]]></category>
		<category><![CDATA[tree]]></category>

		<guid isPermaLink="false">http://www.mdgart.com/?p=89</guid>
		<description><![CDATA[Many people asked me how to implement the basic CRUD functionalities for the D&#038;D Tree, so here it is:

 Download persistentTreeCRUD.zip

I use the simpletree callback function afterDblClick for the modify functionality, and a simple jQuery click for add and delete. I also used nyroModal for the popup windows.
In this example i reload the page when [...]]]></description>
			<content:encoded><![CDATA[<p>Many people asked me how to implement the basic CRUD functionalities for the D&#038;D Tree, so here it is:</p>
<p><a href="http://www.mdgart.com/jQuery/Simple-Persistent-TreeCRUD/persistentTreeCRUD.zip"><br />
<img src="../../additional_icons/download.png" alt="download" width="48" height="48" border="0"/> Download persistentTreeCRUD.zip<br />
</a></p>
<p>I use the simpletree callback function afterDblClick for the modify functionality, and a simple jQuery click for add and delete. I also used <a href="http://nyromodal.nyrodev.com/">nyroModal</a> for the popup windows.<br />
In this example i reload the page when a CRUD operation is performed, a better implementation should use ajax to modify the tree on the fly.<br />
Is not perfect but it works <img src='http://www.mdgart.com/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' />  Enjoy!</p>
<p class="buymebeer"><form action="https://www.paypal.com/cgi-bin/webscr" target="paypal" method="post"><input type="hidden" name="cmd" value="_xclick" /><input type="hidden" name="business" value="mauro@ondadiluce.com" /><input type="hidden" name="return" value="" /><input type="hidden" name="item_name" value="Buy me a coffe for Persistent drag and drop tree with jQuery, PHP and MySQL - CRUD" /><input type="hidden" name="currency_code" value="EUR" /><input type="hidden" name="amount" value="1" /><input type="image" src="http://www.mdgart.com/wp-content/plugins/buy-me-beer/icon_cafe.gif" align="left" alt="Buy me a coffe" title="Buy me a coffe" hspace="3" style="border:0;" /></form><a href="https://www.paypal.com/cgi-bin/webscr?cmd=_xclick&amp;business=mauro@ondadiluce.com&amp;currency_code=EUR&amp;amount=1&amp;return=&amp;item_name=Buy+me+a+coffe+for+Persistent+drag+and+drop+tree+with+jQuery,+PHP+and+MySQL+-+CRUD" target="paypal">Donate 1 euro, buy me a coffee, I need it to write more posts! Thanks ;)</a></p>]]></content:encoded>
			<wfw:commentRss>http://www.mdgart.com/2009/08/04/persistent-drag-and-drop-tree-with-jquery-php-and-mysql-crud/feed/</wfw:commentRss>
		<slash:comments>27</slash:comments>
		</item>
		<item>
		<title>How to develop a Plug-in for Panic Coda with Python</title>
		<link>http://www.mdgart.com/2009/03/31/how-to-develop-a-plug-in-for-panic-coda-with-python/</link>
		<comments>http://www.mdgart.com/2009/03/31/how-to-develop-a-plug-in-for-panic-coda-with-python/#comments</comments>
		<pubDate>Tue, 31 Mar 2009 09:09:33 +0000</pubDate>
		<dc:creator>Mauro</dc:creator>
				<category><![CDATA[Programming]]></category>
		<category><![CDATA[Python]]></category>
		<category><![CDATA[Coda]]></category>
		<category><![CDATA[mac]]></category>
		<category><![CDATA[osx]]></category>
		<category><![CDATA[panic]]></category>
		<category><![CDATA[plugin]]></category>
		<category><![CDATA[tutorial]]></category>
		<category><![CDATA[webdev]]></category>

		<guid isPermaLink="false">http://www.mdgart.com/?p=72</guid>
		<description><![CDATA[If you are (like me) a mac fan and you use the excellent Panic Coda to develop, you should know that is now possible to write plugins with every languages you want (if you have the interpreter installed on your system).
Python is bundled on every mac, and is also a beautiful and simple language, so [...]]]></description>
			<content:encoded><![CDATA[<p>If you are (like me) a mac fan and you use the excellent <a href="http://www.panic.com/coda/" target="_blank">Panic Coda</a> to develop, you should know that is now possible to write plugins with every languages you want (if you have the interpreter installed on your system).<br />
Python is bundled on every mac, and is also a beautiful and simple language, so i want to show how to develop a simple plugin for Coda with Python!<br />
First of all you need to download the <a href="http://www.panic.com/coda/developer/howto/plugins.php" target="_blank">Coda Plug-in Creator</a> that is the application that will convert your python script into a brand new plugin.<br />
<span id="more-72"></span><br />
The plugin that we are going to create is simple but useful; it will convert the selected rows in the current document into a html unordered list:</p>
<p>Remember the milk<br />
Build a Coda Plugin<br />
Clean the house<br />
Feed the cats</p>
<p>will become</p>

<div class="wp_syntax"><div class="code"><pre class="html4strict" style="font-family:monospace;"><span style="color: #009900;">&lt;<span style="color: #000000; font-weight: bold;">ul</span>&gt;</span>
	<span style="color: #009900;">&lt;<span style="color: #000000; font-weight: bold;">li</span>&gt;</span>Remember the milk<span style="color: #009900;">&lt;<span style="color: #66cc66;">/</span><span style="color: #000000; font-weight: bold;">li</span>&gt;</span>
	<span style="color: #009900;">&lt;<span style="color: #000000; font-weight: bold;">li</span>&gt;</span>Build a Coda Plugin<span style="color: #009900;">&lt;<span style="color: #66cc66;">/</span><span style="color: #000000; font-weight: bold;">li</span>&gt;</span>
	<span style="color: #009900;">&lt;<span style="color: #000000; font-weight: bold;">li</span>&gt;</span>Clean the house<span style="color: #009900;">&lt;<span style="color: #66cc66;">/</span><span style="color: #000000; font-weight: bold;">li</span>&gt;</span>
	<span style="color: #009900;">&lt;<span style="color: #000000; font-weight: bold;">li</span>&gt;</span>Feed the cats<span style="color: #009900;">&lt;<span style="color: #66cc66;">/</span><span style="color: #000000; font-weight: bold;">li</span>&gt;</span>
<span style="color: #009900;">&lt;<span style="color: #66cc66;">/</span><span style="color: #000000; font-weight: bold;">ul</span>&gt;</span></pre></div></div>

<p>Simple but enough to understand the principle of making a pulgin,  however it can be useful in some situations when you need a &#8220;raw list&#8221; on your page.<br />
So, let&#8217;s get started! Fire up your text editor and enter this python code:</p>

<div class="wp_syntax"><div class="code"><pre class="python" style="font-family:monospace;"><span style="color: #808080; font-style: italic;">#!/sw/bin/python</span>
<span style="color: #ff7700;font-weight:bold;">import</span>	<span style="color: #dc143c;">sys</span>
&nbsp;
text = <span style="color: #dc143c;">sys</span>.<span style="color: black;">stdin</span>.<span style="color: black;">read</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>
&nbsp;
unorderedlist = <span style="color: #483d8b;">&quot;&lt;ul&gt;<span style="color: #000099; font-weight: bold;">\n</span>&quot;</span> 
<span style="color: #ff7700;font-weight:bold;">for</span> line <span style="color: #ff7700;font-weight:bold;">in</span> text.<span style="color: black;">splitlines</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>:
	unorderedlist = unorderedlist + <span style="color: #483d8b;">&quot;<span style="color: #000099; font-weight: bold;">\t</span>&lt;li&gt;&quot;</span> + line + <span style="color: #483d8b;">&quot;&lt;/li&gt;<span style="color: #000099; font-weight: bold;">\n</span>&quot;</span>
&nbsp;
unorderedlist = unorderedlist + <span style="color: #483d8b;">&quot;&lt;/ul&gt;<span style="color: #000099; font-weight: bold;">\n</span>&quot;</span>
&nbsp;
<span style="color: #dc143c;">sys</span>.<span style="color: black;">stdout</span>.<span style="color: black;">write</span><span style="color: black;">&#40;</span>unorderedlist<span style="color: black;">&#41;</span></pre></div></div>

<p>Save it as textToList.py. The code is very simple: after importing the sys module, we read the standard input with sys.stdin.read() and we put it on the variable <i>text</i>.<br />
Next we initialize a string called <i>unorderedlist</i> with the first html element we need to build the structure, and then we read every single line of the selection, using splitlines() method on the text string, to create every single list entry.<br />
Finally, we pass the complete unorderedlist string to the standard output with sys.stdout.write().</p>
<p>Now open the Coda plug-in creator, click on <strong>Add Command</strong> button and name it textToList (or what you want) drag and drop the <code>textToList.py</code> in the <strong>Script</strong> input field, choose <i>Selection</i> in the <strong>STDIN</strong> popup menu and <i>Replace Selection</i> in the <strong>STDOUT</strong> popup menu (to know how to use this settings please refear to the <a href="http://www.panic.com/coda/developer/howto/plugins.php" target="_blank">Coda developer documentations</a>) and save the plugin with a nice name (like textToList for example, lol). </p>
<p>That&#8217;s it! Our brand new plugin is ready to be installed! Double click on it and you will find it in the <strong>plugin</strong> menu. To test it write some line of text, select the lines, and then choose textToList from the plugin menu.</p>
<div id="attachment_66" class="wp-caption alignnone" style="width: 160px"><a href="http://www.mdgart.com/python/CodaPlugin/textToList.py"><img src="http://www.mdgart.com/wp-content/uploads/2009/03/download.png" alt="Download the code of this article" title="download" width="48" height="48" class="size-full wp-image-66" /></a><p class="wp-caption-text">Download the code of this article</p></div>
<p>Enjoy!</p>
<p>If you like this article, please write a comment and share it! Thanks <img src='http://www.mdgart.com/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' /> </p>
<p class="buymebeer"><form action="https://www.paypal.com/cgi-bin/webscr" target="paypal" method="post"><input type="hidden" name="cmd" value="_xclick" /><input type="hidden" name="business" value="mauro@ondadiluce.com" /><input type="hidden" name="return" value="" /><input type="hidden" name="item_name" value="Buy me a coffe for How to develop a Plug-in for Panic Coda with Python" /><input type="hidden" name="currency_code" value="EUR" /><input type="hidden" name="amount" value="1" /><input type="image" src="http://www.mdgart.com/wp-content/plugins/buy-me-beer/icon_cafe.gif" align="left" alt="Buy me a coffe" title="Buy me a coffe" hspace="3" style="border:0;" /></form><a href="https://www.paypal.com/cgi-bin/webscr?cmd=_xclick&amp;business=mauro@ondadiluce.com&amp;currency_code=EUR&amp;amount=1&amp;return=&amp;item_name=Buy+me+a+coffe+for+How+to+develop+a+Plug-in+for+Panic+Coda+with+Python" target="paypal">Donate 1 euro, buy me a coffee, I need it to write more posts! Thanks ;)</a></p>]]></content:encoded>
			<wfw:commentRss>http://www.mdgart.com/2009/03/31/how-to-develop-a-plug-in-for-panic-coda-with-python/feed/</wfw:commentRss>
		<slash:comments>8</slash:comments>
		</item>
		<item>
		<title>Persistent drag and drop tree with jQuery, PHP and MySQL &#8211; part 2</title>
		<link>http://www.mdgart.com/2009/03/29/persistent-drag-and-drop-tree-with-jquery-php-and-mysql-part-2/</link>
		<comments>http://www.mdgart.com/2009/03/29/persistent-drag-and-drop-tree-with-jquery-php-and-mysql-part-2/#comments</comments>
		<pubDate>Sun, 29 Mar 2009 19:51:24 +0000</pubDate>
		<dc:creator>Mauro</dc:creator>
				<category><![CDATA[Javascript]]></category>
		<category><![CDATA[MySQL]]></category>
		<category><![CDATA[PHP]]></category>
		<category><![CDATA[Programming]]></category>
		<category><![CDATA[jQuery]]></category>
		<category><![CDATA[algorithm]]></category>
		<category><![CDATA[how to]]></category>
		<category><![CDATA[tutorial]]></category>
		<category><![CDATA[webdev]]></category>

		<guid isPermaLink="false">http://www.mdgart.com/?p=59</guid>
		<description><![CDATA[In this second part of this article (this is the first part) i&#8217;m going to show you how to retreive and serialize the tree structure using jQuery and sent the serialized data to a php script (using ajax) that saves it on the database. In this way, we can have the persistence of any change [...]]]></description>
			<content:encoded><![CDATA[<p>In this second part of this article (<a href="http://www.mdgart.com/2009/03/15/persistent-drag-and-drop-tree-with-jquery-php-and-mysql-part-1/">this is the first part</a>) i&#8217;m going to show you how to retreive and serialize the tree structure using jQuery and sent the serialized data to a php script (using ajax) that saves it on the database. In this way, we can have the persistence of any change made on the tree.<br />
<span id="more-59"></span><br />
Let&#8217;s start with the serializzation problem, that is simply this: how can i retreive the structure of the tree in a form that can be sent to a php script via POST or GET? To do that i have to read every single branch of the tree and save, for every single category, three values: category_id, parent_id and orderby:</p>
<p>0:1:1|0:2:2|2:3:1|2:5:2|2:4:3|0:6:3|6:7:1|</p>
<p>The group category_id, parent_id and orderby are separated by a pipe. To do that we need a function that reads every single branch of the tree and it&#8217;s relative information. The function will call a php file to save the serialized in the mysql database.<br />
This is the jQuery function that perform this operation:</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
</pre></td><td class="code"><pre class="javascript" style="font-family:monospace;"><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: #003366; font-weight: bold;">var</span> serialStr <span style="color: #339933;">=</span> <span style="color: #3366CC;">&quot;&quot;</span><span style="color: #339933;">;</span>
	<span style="color: #003366; font-weight: bold;">var</span> order <span style="color: #339933;">=</span> <span style="color: #3366CC;">&quot;&quot;</span><span style="color: #339933;">;</span>
&nbsp;
	$<span style="color: #009900;">&#40;</span><span style="color: #3366CC;">&quot;ul.simpleTree li span&quot;</span><span style="color: #009900;">&#41;</span>.<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><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#123;</span>			
		parentId <span style="color: #339933;">=</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: #660066;">parent</span><span style="color: #009900;">&#40;</span><span style="color: #3366CC;">&quot;li&quot;</span><span style="color: #009900;">&#41;</span>.<span style="color: #660066;">parent</span><span style="color: #009900;">&#40;</span><span style="color: #3366CC;">&quot;ul&quot;</span><span style="color: #009900;">&#41;</span>.<span style="color: #660066;">parent</span><span style="color: #009900;">&#40;</span><span style="color: #3366CC;">&quot;li&quot;</span><span style="color: #009900;">&#41;</span>.<span style="color: #660066;">attr</span><span style="color: #009900;">&#40;</span><span style="color: #3366CC;">&quot;id&quot;</span><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>parentId <span style="color: #339933;">==</span> undefined<span style="color: #009900;">&#41;</span> parentId <span style="color: #339933;">=</span> <span style="color: #3366CC;">&quot;root&quot;</span><span style="color: #339933;">;</span>
		order <span style="color: #339933;">=</span> <span style="color: #009900;">&#40;</span><span style="color: #009900;">&#40;</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: #660066;">parent</span><span style="color: #009900;">&#40;</span><span style="color: #3366CC;">&quot;li&quot;</span><span style="color: #009900;">&#41;</span>.<span style="color: #660066;">prevAll</span><span style="color: #009900;">&#40;</span><span style="color: #3366CC;">&quot;li&quot;</span><span style="color: #009900;">&#41;</span>.<span style="color: #660066;">size</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">+</span><span style="color: #CC0000;">1</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">/</span><span style="color: #CC0000;">2</span><span style="color: #339933;">;</span> 
		<span style="color: #000066; font-weight: bold;">if</span> <span style="color: #009900;">&#40;</span> parentId <span style="color: #339933;">!=</span> <span style="color: #3366CC;">&quot;root&quot;</span><span style="color: #009900;">&#41;</span> serialStr <span style="color: #339933;">+=</span> <span style="color: #3366CC;">&quot;&quot;</span><span style="color: #339933;">+</span>parentId<span style="color: #339933;">+</span><span style="color: #3366CC;">&quot;:&quot;</span><span style="color: #339933;">+</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: #660066;">parent</span><span style="color: #009900;">&#40;</span><span style="color: #3366CC;">&quot;li&quot;</span><span style="color: #009900;">&#41;</span>.<span style="color: #660066;">attr</span><span style="color: #009900;">&#40;</span><span style="color: #3366CC;">&quot;id&quot;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">+</span><span style="color: #3366CC;">&quot;:&quot;</span><span style="color: #339933;">+</span>order<span style="color: #339933;">+</span><span style="color: #3366CC;">&quot;|&quot;</span><span style="color: #339933;">;</span>
	<span style="color: #009900;">&#125;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
	$.<span style="color: #660066;">ajax</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#123;</span>
	   type<span style="color: #339933;">:</span> <span style="color: #3366CC;">&quot;POST&quot;</span><span style="color: #339933;">,</span>
	   url<span style="color: #339933;">:</span> <span style="color: #3366CC;">&quot;saveData.php&quot;</span><span style="color: #339933;">,</span>
	   data<span style="color: #339933;">:</span> <span style="color: #3366CC;">&quot;serialized=&quot;</span><span style="color: #339933;">+</span>serialStr<span style="color: #339933;">,</span>
	   success<span style="color: #339933;">:</span> <span style="color: #003366; font-weight: bold;">function</span><span style="color: #009900;">&#40;</span>msg<span style="color: #009900;">&#41;</span><span style="color: #009900;">&#123;</span>
	   	 $<span style="color: #009900;">&#40;</span><span style="color: #3366CC;">&quot;#serializedList&quot;</span><span style="color: #009900;">&#41;</span>.<span style="color: #660066;">html</span><span style="color: #009900;">&#40;</span>msg<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;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
	<span style="color: #000066; font-weight: bold;">return</span> <span style="color: #003366; font-weight: bold;">false</span><span style="color: #339933;">;</span>
&nbsp;
<span style="color: #009900;">&#125;</span></pre></td></tr></table></div>

<p>Let me explain a bit how the jQuery function work: it loops through each <i>span</i> of the tree, read the current id of the <i>li</i> and the id of the parent <i>li</i>, and finally it calculates the position of the current element to use as orderby value in the category table.<br />
When the string is created, i passed to a php script with an ajax call. The php file that saves the serialized data on the server is 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
</pre></td><td class="code"><pre class="php" style="font-family:monospace;"><span style="color: #b1b100;">include_once</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">&quot;connection.php&quot;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span> <span style="color: #666666; font-style: italic;">// the connection to the database</span>
<span style="color: #b1b100;">if</span> <span style="color: #009900;">&#40;</span><span style="color: #000088;">$_POST</span><span style="color: #009900;">&#91;</span><span style="color: #0000ff;">'serialized'</span><span style="color: #009900;">&#93;</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
&nbsp;
	<span style="color: #666666; font-style: italic;">// create an array from the string $_POST['serialized'] </span>
	<span style="color: #666666; font-style: italic;">// with the group category_id:parent_id:orderby for each array member </span>
	<span style="color: #666666; font-style: italic;">// i strip the last pipe, so i will not have an array with a empty member at the end</span>
	<span style="color: #000088;">$categories</span> <span style="color: #339933;">=</span> <span style="color: #990000;">explode</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">&quot;|&quot;</span><span style="color: #339933;">,</span> <span style="color: #990000;">substr</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$_POST</span><span style="color: #009900;">&#91;</span><span style="color: #0000ff;">'serialized'</span><span style="color: #009900;">&#93;</span><span style="color: #339933;">,</span><span style="color: #cc66cc;">0</span><span style="color: #339933;">,-</span><span style="color: #cc66cc;">1</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
	<span style="color: #000088;">$error</span> <span style="color: #339933;">=</span>  <span style="color: #009900; font-weight: bold;">false</span><span style="color: #339933;">;</span>
&nbsp;
 	<span style="color: #666666; font-style: italic;">// loop through each array member</span>
	<span style="color: #b1b100;">foreach</span> <span style="color: #009900;">&#40;</span><span style="color: #000088;">$categories</span> <span style="color: #b1b100;">as</span> <span style="color: #000088;">$category</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
		<span style="color: #666666; font-style: italic;">// split the group by the colon and put the three value is separated variable</span>
 		<span style="color: #990000;">list</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$parentId</span><span style="color: #339933;">,</span> <span style="color: #000088;">$categoryId</span><span style="color: #339933;">,</span> <span style="color: #000088;">$order</span><span style="color: #009900;">&#41;</span> <span style="color: #339933;">=</span> <span style="color: #990000;">split</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">&quot;:&quot;</span><span style="color: #339933;">,</span> <span style="color: #000088;">$category</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
		<span style="color: #666666; font-style: italic;">// update the database</span>
&nbsp;
 		<span style="color: #000088;">$result</span> <span style="color: #339933;">=</span> <span style="color: #990000;">mysql_query</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">&quot;UPDATE category SET parent_id = &quot;</span><span style="color: #339933;">.</span><span style="color: #000088;">$parentId</span><span style="color: #339933;">.</span><span style="color: #0000ff;">&quot;, orderby = &quot;</span><span style="color: #339933;">.</span><span style="color: #000088;">$order</span><span style="color: #339933;">.</span><span style="color: #0000ff;">&quot; 
 						    WHERE category_id = &quot;</span><span style="color: #339933;">.</span><span style="color: #000088;">$categoryId</span> <span style="color: #009900;">&#41;</span> or <span style="color: #990000;">die</span><span style="color: #009900;">&#40;</span><span style="color: #990000;">mysql_error</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
 	<span style="color: #009900;">&#125;</span>	
&nbsp;
	<span style="color: #b1b100;">echo</span> <span style="color: #0000ff;">&quot;Tree updated.&quot;</span><span style="color: #339933;">;</span>
&nbsp;
<span style="color: #009900;">&#125;</span>
<span style="color: #b1b100;">echo</span> <span style="color: #0000ff;">&quot;&lt;br /&gt;&quot;</span><span style="color: #339933;">.</span><span style="color: #000088;">$_POST</span><span style="color: #009900;">&#91;</span><span style="color: #0000ff;">'serialized'</span><span style="color: #009900;">&#93;</span><span style="color: #339933;">;</span></pre></td></tr></table></div>

<p>The php is straight forward and i commented every step. The output of the php script is output inside a div called <i>serializedList</i>, so we can see the result of the operation. At the end of the script, i print also the serialized string to debug and test purpose.</p>
<p>You can see a working example of the tree at <a href="http://www.mdgart.com/jQuery/Simple-Persistent-Tree/final_test.php" target="_blank">this page</a>.<br />
As you can see, the jQuery function is fired every time a branch is moved, thanks to the <i>afterMove:</i> callback of simpleTree.</p>
<p>In my real word applications, to create a new category and delete a category i use 2 small buttons, while to update a category i use the double click callback functionality of simpleTree. This is a how it looks: <a href="http://www.mdgart.com/jQuery/Simple-Persistent-Tree/persistentTree.php" target="_blank">persistent tree final result</a>.<br />
If you are interested to know how i do it please let me know, i will be glad to help you <img src='http://www.mdgart.com/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' /> </p>
<p>You can download all the scripts of this article here:</p>
<div id="attachment_66" class="wp-caption alignnone" style="width: 160px"><a href="http://www.mdgart.com/jQuery/Simple-Persistent-Tree/persistentTree.zip"><img src="http://www.mdgart.com/wp-content/uploads/2009/03/download.png" alt="Download persistentTree.zip" title="download persistentTree.zip" width="48" height="48" class="size-full wp-image-66" /></a><p class="wp-caption-text">Download persistentTree.zip</p></div>
<p>Please leave a comment if you like this article, thanks!</p>
<p>That&#8217;s all folks!</p>
<p class="buymebeer"><form action="https://www.paypal.com/cgi-bin/webscr" target="paypal" method="post"><input type="hidden" name="cmd" value="_xclick" /><input type="hidden" name="business" value="mauro@ondadiluce.com" /><input type="hidden" name="return" value="" /><input type="hidden" name="item_name" value="Buy me a coffe for Persistent drag and drop tree with jQuery, PHP and MySQL - part 2" /><input type="hidden" name="currency_code" value="EUR" /><input type="hidden" name="amount" value="1" /><input type="image" src="http://www.mdgart.com/wp-content/plugins/buy-me-beer/icon_cafe.gif" align="left" alt="Buy me a coffe" title="Buy me a coffe" hspace="3" style="border:0;" /></form><a href="https://www.paypal.com/cgi-bin/webscr?cmd=_xclick&amp;business=mauro@ondadiluce.com&amp;currency_code=EUR&amp;amount=1&amp;return=&amp;item_name=Buy+me+a+coffe+for+Persistent+drag+and+drop+tree+with+jQuery,+PHP+and+MySQL+-+part+2" target="paypal">Donate 1 euro, buy me a coffee, I need it to write more posts! Thanks ;)</a></p>]]></content:encoded>
			<wfw:commentRss>http://www.mdgart.com/2009/03/29/persistent-drag-and-drop-tree-with-jquery-php-and-mysql-part-2/feed/</wfw:commentRss>
		<slash:comments>26</slash:comments>
		</item>
		<item>
		<title>Persistent drag and drop tree with jQuery, PHP and MySQL &#8211; part 1</title>
		<link>http://www.mdgart.com/2009/03/15/persistent-drag-and-drop-tree-with-jquery-php-and-mysql-part-1/</link>
		<comments>http://www.mdgart.com/2009/03/15/persistent-drag-and-drop-tree-with-jquery-php-and-mysql-part-1/#comments</comments>
		<pubDate>Sun, 15 Mar 2009 21:18:38 +0000</pubDate>
		<dc:creator>Mauro</dc:creator>
				<category><![CDATA[Javascript]]></category>
		<category><![CDATA[MySQL]]></category>
		<category><![CDATA[PHP]]></category>
		<category><![CDATA[Programming]]></category>
		<category><![CDATA[jQuery]]></category>
		<category><![CDATA[algorithm]]></category>
		<category><![CDATA[how to]]></category>
		<category><![CDATA[tutorial]]></category>
		<category><![CDATA[webdev]]></category>

		<guid isPermaLink="false">http://www.mdgart.com/?p=13</guid>
		<description><![CDATA[I&#8217;m developing a website that have a catalog with nested categories; this categories are also ordered and with a not predefined depth levels. I needed to find a way to manage with category in a fast and intuitive way for the user, so i decided to use a directory like tree allowing the users to [...]]]></description>
			<content:encoded><![CDATA[<p>I&#8217;m developing a website that have a catalog with nested categories; this categories are also ordered and with a not predefined depth levels. I needed to find a way to manage with category in a fast and intuitive way for the user, so i decided to use a directory like tree allowing the users to drag and drop the categories to change the order and even the position on the tree: of course i use <a title="jQuery website" href="http://jquery.com/" target="_blank">jQuery</a> to do this, and PHP/MySQL to save the structure of the tree in a database.<br />
I found a nice tree jQuery plugin on the web, that i used as a starting point for my project: <a href="http://news.kg/wp-content/uploads/tree/">http://news.kg/wp-content/uploads/tree/</a>. The plugin work well on all browser i tested (FF3, Safari 3, IE6, IE7). It provide the drag and drop funcionality and some interesting callback, like afterClick and afterDblClick.<br />
But let&#8217;s start from the beginning. <span id="more-13"></span> First of all the structure if the categories table is the follow:</p>
<ul>
<li><strong>category_id</strong> &#8211; the id of the category</li>
<li><strong>parent_id</strong> &#8211; the id of the parent category (or 0 if is a main category)</li>
<li><strong>category_label </strong>- the name of the category</li>
<li><strong>order</strong> &#8211; the order of the category. This order is local to the branch (more later&#8230;).</li>
</ul>
<p>This information are enough to build a ordered tree like this:</p>
<div id="attachment_16" class="wp-caption alignnone" style="width: 207px"><a href="http://www.mdgart.com/wp-content/uploads/2009/03/treeexample.png"><img src="http://www.mdgart.com/wp-content/uploads/2009/03/treeexample-197x300.png" alt="Example of a categories tree, click to enlarge" title="Example of a categories tree" width="197" height="300" class="size-medium wp-image-16" /></a><p class="wp-caption-text">Example of a categories tree, click to enlarge</p></div>
<p>As you can see every branch have is own progressive counter number, to indicate the order of the category inside the branch.<br />
The tree will be rendered in a unordered list 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
</pre></td><td class="code"><pre class="html4strict" style="font-family:monospace;"><span style="color: #009900;">&lt;<span style="color: #000000; font-weight: bold;">ul</span> <span style="color: #000066;">class</span><span style="color: #66cc66;">=</span><span style="color: #ff0000;">&quot;simpleTree&quot;</span>&gt;</span>
 <span style="color: #009900;">&lt;<span style="color: #000000; font-weight: bold;">li</span> <span style="color: #000066;">id</span><span style="color: #66cc66;">=</span><span style="color: #ff0000;">&quot;0&quot;</span> <span style="color: #000066;">class</span><span style="color: #66cc66;">=</span><span style="color: #ff0000;">&quot;root&quot;</span>&gt;&lt;<span style="color: #000000; font-weight: bold;">span</span>&gt;</span>Categories<span style="color: #009900;">&lt;<span style="color: #66cc66;">/</span><span style="color: #000000; font-weight: bold;">span</span>&gt;</span>
  <span style="color: #009900;">&lt;<span style="color: #000000; font-weight: bold;">ul</span>&gt;</span>
   <span style="color: #009900;">&lt;<span style="color: #000000; font-weight: bold;">li</span> <span style="color: #000066;">id</span><span style="color: #66cc66;">=</span><span style="color: #ff0000;">&quot;1&quot;</span>&gt;&lt;<span style="color: #000000; font-weight: bold;">span</span>&gt;</span>Category one<span style="color: #009900;">&lt;<span style="color: #66cc66;">/</span><span style="color: #000000; font-weight: bold;">li</span>&gt;</span>
   <span style="color: #009900;">&lt;<span style="color: #000000; font-weight: bold;">li</span> <span style="color: #000066;">id</span><span style="color: #66cc66;">=</span><span style="color: #ff0000;">&quot;2&quot;</span>&gt;&lt;<span style="color: #000000; font-weight: bold;">span</span>&gt;</span>Category two<span style="color: #009900;">&lt;<span style="color: #66cc66;">/</span><span style="color: #000000; font-weight: bold;">span</span>&gt;</span>
    <span style="color: #009900;">&lt;<span style="color: #000000; font-weight: bold;">ul</span>&gt;</span>
     <span style="color: #009900;">&lt;<span style="color: #000000; font-weight: bold;">li</span> <span style="color: #000066;">id</span><span style="color: #66cc66;">=</span><span style="color: #ff0000;">&quot;3&quot;</span>&gt;&lt;<span style="color: #000000; font-weight: bold;">span</span>&gt;</span>Category three<span style="color: #009900;">&lt;<span style="color: #66cc66;">/</span><span style="color: #000000; font-weight: bold;">span</span>&gt;&lt;<span style="color: #66cc66;">/</span><span style="color: #000000; font-weight: bold;">li</span>&gt;</span>
     <span style="color: #009900;">&lt;<span style="color: #000000; font-weight: bold;">li</span> <span style="color: #000066;">id</span><span style="color: #66cc66;">=</span><span style="color: #ff0000;">&quot;4&quot;</span>&gt;&lt;<span style="color: #000000; font-weight: bold;">span</span>&gt;</span>Category four<span style="color: #009900;">&lt;<span style="color: #66cc66;">/</span><span style="color: #000000; font-weight: bold;">span</span>&gt;</span>
      <span style="color: #009900;">&lt;<span style="color: #000000; font-weight: bold;">ul</span>&gt;</span>
       <span style="color: #009900;">&lt;<span style="color: #000000; font-weight: bold;">li</span> <span style="color: #000066;">id</span><span style="color: #66cc66;">=</span><span style="color: #ff0000;">&quot;5&quot;</span>&gt;&lt;<span style="color: #000000; font-weight: bold;">span</span>&gt;</span>Category five<span style="color: #009900;">&lt;<span style="color: #66cc66;">/</span><span style="color: #000000; font-weight: bold;">span</span>&gt;&lt;<span style="color: #66cc66;">/</span><span style="color: #000000; font-weight: bold;">li</span>&gt;</span>  
      <span style="color: #009900;">&lt;<span style="color: #66cc66;">/</span><span style="color: #000000; font-weight: bold;">ul</span>&gt;</span>
    <span style="color: #009900;">&lt;<span style="color: #66cc66;">/</span><span style="color: #000000; font-weight: bold;">li</span>&gt;</span>
   <span style="color: #009900;">&lt;<span style="color: #66cc66;">/</span><span style="color: #000000; font-weight: bold;">ul</span>&gt;</span>
   <span style="color: #009900;">&lt;<span style="color: #000000; font-weight: bold;">li</span> <span style="color: #000066;">id</span><span style="color: #66cc66;">=</span><span style="color: #ff0000;">&quot;6&quot;</span>&gt;&lt;<span style="color: #000000; font-weight: bold;">span</span>&gt;</span>Category six<span style="color: #009900;">&lt;<span style="color: #66cc66;">/</span><span style="color: #000000; font-weight: bold;">span</span>&gt;</span>
    <span style="color: #009900;">&lt;<span style="color: #000000; font-weight: bold;">ul</span>&gt;</span>
     <span style="color: #009900;">&lt;<span style="color: #000000; font-weight: bold;">li</span> <span style="color: #000066;">id</span><span style="color: #66cc66;">=</span><span style="color: #ff0000;">&quot;7&quot;</span>&gt;&lt;<span style="color: #000000; font-weight: bold;">span</span>&gt;</span>Category seven<span style="color: #009900;">&lt;<span style="color: #66cc66;">/</span><span style="color: #000000; font-weight: bold;">span</span>&gt;&lt;<span style="color: #66cc66;">/</span><span style="color: #000000; font-weight: bold;">li</span>&gt;</span>
    <span style="color: #009900;">&lt;<span style="color: #66cc66;">/</span><span style="color: #000000; font-weight: bold;">ul</span>&gt;</span>
   <span style="color: #009900;">&lt;<span style="color: #66cc66;">/</span><span style="color: #000000; font-weight: bold;">li</span>&gt;</span>
  <span style="color: #009900;">&lt;<span style="color: #66cc66;">/</span><span style="color: #000000; font-weight: bold;">ul</span>&gt;</span>
 <span style="color: #009900;">&lt;<span style="color: #66cc66;">/</span><span style="color: #000000; font-weight: bold;">li</span>&gt;</span>
<span style="color: #009900;">&lt;<span style="color: #66cc66;">/</span><span style="color: #000000; font-weight: bold;">ul</span>&gt;</span></pre></td></tr></table></div>

<p>With jQuery and simple tree correctly included in the page, you should see <a href="http://www.mdgart.com/jQuery/Simple-Persistent-Tree/initial_test.php" target="_blank">someting like this</a>.</p>
<p>As you can see i already added a class simpleTree to the first ul and a main category with at the beginning with a class root, that wrap the whole tree of mine categories. I do that because i&#8217;m going to use the simpleTree plugin to manage the drag and drop. Please refer to <a href="http://news.kg/wp-content/uploads/tree/">the plugin documentation</a> for further information.</p>
<h3>The database</h3>
<p>Let&#8217;s create the database table, that is very simple:</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="sql" style="font-family:monospace;"><span style="color: #993333; font-weight: bold;">CREATE</span> <span style="color: #993333; font-weight: bold;">TABLE</span> <span style="color: #ff0000;">`category`</span> <span style="color: #66cc66;">&#40;</span>
  <span style="color: #ff0000;">`category_id`</span> int<span style="color: #66cc66;">&#40;</span><span style="color: #cc66cc;">11</span><span style="color: #66cc66;">&#41;</span> <span style="color: #993333; font-weight: bold;">NOT</span> <span style="color: #993333; font-weight: bold;">NULL</span> <span style="color: #993333; font-weight: bold;">AUTO_INCREMENT</span><span style="color: #66cc66;">,</span>
  <span style="color: #ff0000;">`parent_id`</span> int<span style="color: #66cc66;">&#40;</span><span style="color: #cc66cc;">11</span><span style="color: #66cc66;">&#41;</span> <span style="color: #993333; font-weight: bold;">DEFAULT</span> <span style="color: #ff0000;">'0'</span><span style="color: #66cc66;">,</span>
  <span style="color: #ff0000;">`category_label`</span> varchar<span style="color: #66cc66;">&#40;</span><span style="color: #cc66cc;">100</span><span style="color: #66cc66;">&#41;</span> <span style="color: #993333; font-weight: bold;">DEFAULT</span> <span style="color: #993333; font-weight: bold;">NULL</span><span style="color: #66cc66;">,</span>
  <span style="color: #ff0000;">`orderby`</span> int<span style="color: #66cc66;">&#40;</span><span style="color: #cc66cc;">11</span><span style="color: #66cc66;">&#41;</span> <span style="color: #993333; font-weight: bold;">DEFAULT</span> <span style="color: #993333; font-weight: bold;">NULL</span><span style="color: #66cc66;">,</span>
  <span style="color: #993333; font-weight: bold;">PRIMARY</span> <span style="color: #993333; font-weight: bold;">KEY</span>  <span style="color: #66cc66;">&#40;</span><span style="color: #ff0000;">`category_id`</span><span style="color: #66cc66;">&#41;</span>
<span style="color: #66cc66;">&#41;</span> ENGINE<span style="color: #66cc66;">=</span>MyISAM <span style="color: #993333; font-weight: bold;">DEFAULT</span> CHARSET<span style="color: #66cc66;">=</span>utf8;</pre></td></tr></table></div>

<p>for the initial tests i also prepopulated the category table with the follow data:</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="sql" style="font-family:monospace;"><span style="color: #993333; font-weight: bold;">INSERT</span> <span style="color: #993333; font-weight: bold;">INTO</span> <span style="color: #ff0000;">`category`</span> <span style="color: #66cc66;">&#40;</span><span style="color: #ff0000;">`category_id`</span><span style="color: #66cc66;">,</span><span style="color: #ff0000;">`parent_id`</span><span style="color: #66cc66;">,</span><span style="color: #ff0000;">`category_label`</span><span style="color: #66cc66;">,</span><span style="color: #ff0000;">`orderby`</span><span style="color: #66cc66;">&#41;</span> <span style="color: #993333; font-weight: bold;">VALUES</span> <span style="color: #66cc66;">&#40;</span><span style="color: #ff0000;">'1'</span><span style="color: #66cc66;">,</span><span style="color: #ff0000;">'0'</span><span style="color: #66cc66;">,</span><span style="color: #ff0000;">'category one'</span><span style="color: #66cc66;">,</span><span style="color: #ff0000;">'1'</span><span style="color: #66cc66;">&#41;</span>;
<span style="color: #993333; font-weight: bold;">INSERT</span> <span style="color: #993333; font-weight: bold;">INTO</span> <span style="color: #ff0000;">`category`</span> <span style="color: #66cc66;">&#40;</span><span style="color: #ff0000;">`category_id`</span><span style="color: #66cc66;">,</span><span style="color: #ff0000;">`parent_id`</span><span style="color: #66cc66;">,</span><span style="color: #ff0000;">`category_label`</span><span style="color: #66cc66;">,</span><span style="color: #ff0000;">`orderby`</span><span style="color: #66cc66;">&#41;</span> <span style="color: #993333; font-weight: bold;">VALUES</span> <span style="color: #66cc66;">&#40;</span><span style="color: #ff0000;">'2'</span><span style="color: #66cc66;">,</span><span style="color: #ff0000;">'0'</span><span style="color: #66cc66;">,</span><span style="color: #ff0000;">'category two'</span><span style="color: #66cc66;">,</span><span style="color: #ff0000;">'2'</span><span style="color: #66cc66;">&#41;</span>;
<span style="color: #993333; font-weight: bold;">INSERT</span> <span style="color: #993333; font-weight: bold;">INTO</span> <span style="color: #ff0000;">`category`</span> <span style="color: #66cc66;">&#40;</span><span style="color: #ff0000;">`category_id`</span><span style="color: #66cc66;">,</span><span style="color: #ff0000;">`parent_id`</span><span style="color: #66cc66;">,</span><span style="color: #ff0000;">`category_label`</span><span style="color: #66cc66;">,</span><span style="color: #ff0000;">`orderby`</span><span style="color: #66cc66;">&#41;</span> <span style="color: #993333; font-weight: bold;">VALUES</span> <span style="color: #66cc66;">&#40;</span><span style="color: #ff0000;">'3'</span><span style="color: #66cc66;">,</span><span style="color: #ff0000;">'2'</span><span style="color: #66cc66;">,</span><span style="color: #ff0000;">'category three'</span><span style="color: #66cc66;">,</span><span style="color: #ff0000;">'1'</span><span style="color: #66cc66;">&#41;</span>;
<span style="color: #993333; font-weight: bold;">INSERT</span> <span style="color: #993333; font-weight: bold;">INTO</span> <span style="color: #ff0000;">`category`</span> <span style="color: #66cc66;">&#40;</span><span style="color: #ff0000;">`category_id`</span><span style="color: #66cc66;">,</span><span style="color: #ff0000;">`parent_id`</span><span style="color: #66cc66;">,</span><span style="color: #ff0000;">`category_label`</span><span style="color: #66cc66;">,</span><span style="color: #ff0000;">`orderby`</span><span style="color: #66cc66;">&#41;</span> <span style="color: #993333; font-weight: bold;">VALUES</span> <span style="color: #66cc66;">&#40;</span><span style="color: #ff0000;">'4'</span><span style="color: #66cc66;">,</span><span style="color: #ff0000;">'2'</span><span style="color: #66cc66;">,</span><span style="color: #ff0000;">'category four'</span><span style="color: #66cc66;">,</span><span style="color: #ff0000;">'2'</span><span style="color: #66cc66;">&#41;</span>;
<span style="color: #993333; font-weight: bold;">INSERT</span> <span style="color: #993333; font-weight: bold;">INTO</span> <span style="color: #ff0000;">`category`</span> <span style="color: #66cc66;">&#40;</span><span style="color: #ff0000;">`category_id`</span><span style="color: #66cc66;">,</span><span style="color: #ff0000;">`parent_id`</span><span style="color: #66cc66;">,</span><span style="color: #ff0000;">`category_label`</span><span style="color: #66cc66;">,</span><span style="color: #ff0000;">`orderby`</span><span style="color: #66cc66;">&#41;</span> <span style="color: #993333; font-weight: bold;">VALUES</span> <span style="color: #66cc66;">&#40;</span><span style="color: #ff0000;">'5'</span><span style="color: #66cc66;">,</span><span style="color: #ff0000;">'4'</span><span style="color: #66cc66;">,</span><span style="color: #ff0000;">'category fine'</span><span style="color: #66cc66;">,</span><span style="color: #ff0000;">'1'</span><span style="color: #66cc66;">&#41;</span>;
<span style="color: #993333; font-weight: bold;">INSERT</span> <span style="color: #993333; font-weight: bold;">INTO</span> <span style="color: #ff0000;">`category`</span> <span style="color: #66cc66;">&#40;</span><span style="color: #ff0000;">`category_id`</span><span style="color: #66cc66;">,</span><span style="color: #ff0000;">`parent_id`</span><span style="color: #66cc66;">,</span><span style="color: #ff0000;">`category_label`</span><span style="color: #66cc66;">,</span><span style="color: #ff0000;">`orderby`</span><span style="color: #66cc66;">&#41;</span> <span style="color: #993333; font-weight: bold;">VALUES</span> <span style="color: #66cc66;">&#40;</span><span style="color: #ff0000;">'6'</span><span style="color: #66cc66;">,</span><span style="color: #ff0000;">'0'</span><span style="color: #66cc66;">,</span><span style="color: #ff0000;">'category six'</span><span style="color: #66cc66;">,</span><span style="color: #ff0000;">'3'</span><span style="color: #66cc66;">&#41;</span>;
<span style="color: #993333; font-weight: bold;">INSERT</span> <span style="color: #993333; font-weight: bold;">INTO</span> <span style="color: #ff0000;">`category`</span> <span style="color: #66cc66;">&#40;</span><span style="color: #ff0000;">`category_id`</span><span style="color: #66cc66;">,</span><span style="color: #ff0000;">`parent_id`</span><span style="color: #66cc66;">,</span><span style="color: #ff0000;">`category_label`</span><span style="color: #66cc66;">,</span><span style="color: #ff0000;">`orderby`</span><span style="color: #66cc66;">&#41;</span> <span style="color: #993333; font-weight: bold;">VALUES</span> <span style="color: #66cc66;">&#40;</span><span style="color: #ff0000;">'7'</span><span style="color: #66cc66;">,</span><span style="color: #ff0000;">'6'</span><span style="color: #66cc66;">,</span><span style="color: #ff0000;">'category seven'</span><span style="color: #66cc66;">,</span><span style="color: #ff0000;">'1'</span><span style="color: #66cc66;">&#41;</span>;</pre></td></tr></table></div>

<p>You can start with an empty database if you want, but i strongly reccomend that you to put some data inside the table to test the tree.</p>
<h3>Retrieve the data and create the tree with PHP</h3>
<p>To retrieve the data from the database i use this sql:</p>

<div class="wp_syntax"><table><tr><td class="line_numbers"><pre>1
</pre></td><td class="code"><pre class="sql" style="font-family:monospace;"><span style="color: #993333; font-weight: bold;">SELECT</span> <span style="color: #66cc66;">*</span> <span style="color: #993333; font-weight: bold;">FROM</span> category <span style="color: #993333; font-weight: bold;">ORDER</span> <span style="color: #993333; font-weight: bold;">BY</span> parent_id<span style="color: #66cc66;">,</span> orderby</pre></td></tr></table></div>

<p>Notice the order by statement: what i have is a list of categories preordered by <b>parent_id</b> (so i have the 0 parent at the beginning) and also by <b>orderby</b>, so i will have every group of category that are related with the same parent ordered by <b>orderby</b>.</p>
<p>At this point i put the results of the query inside an array, so i can manage it inside the function that will create the tree. The complete code to retrieve the data and put it in an array is the follows:</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="php" style="font-family:monospace;"><span style="color: #990000;">mysql_connect</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">&quot;&lt;b&gt;host&lt;/b&gt;&quot;</span><span style="color: #339933;">,</span> <span style="color: #0000ff;">&quot;&lt;b&gt;user&lt;/b&gt;&quot;</span><span style="color: #339933;">,</span> <span style="color: #0000ff;">&quot;&lt;b&gt;password&lt;/b&gt;&quot;</span><span style="color: #009900;">&#41;</span> or <span style="color: #990000;">die</span><span style="color: #009900;">&#40;</span><span style="color: #990000;">mysql_error</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: #990000;">mysql_select_db</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">&quot;&lt;b&gt;database&lt;/b&gt;&quot;</span><span style="color: #009900;">&#41;</span> or <span style="color: #990000;">die</span><span style="color: #009900;">&#40;</span><span style="color: #990000;">mysql_error</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
<span style="color: #000088;">$rsCategories</span> <span style="color: #339933;">=</span> <span style="color: #990000;">mysql_query</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">&quot;SELECT * FROM category ORDER BY parent_id, orderby&quot;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
<span style="color: #666666; font-style: italic;">// create the empty array</span>
<span style="color: #000088;">$arrayCategories</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>
&nbsp;
<span style="color: #666666; font-style: italic;">// put the results inside the array</span>
<span style="color: #666666; font-style: italic;">// i use the category id as key for the array, and i store the parent_id </span>
<span style="color: #666666; font-style: italic;">// and the name of the category in a hash with the keys parent_id and name (of course)  </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;">$rsCategories</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#123;</span> 
	<span style="color: #000088;">$arrayCategories</span><span style="color: #009900;">&#91;</span><span style="color: #000088;">$row</span><span style="color: #009900;">&#91;</span><span style="color: #0000ff;">'category_id'</span><span style="color: #009900;">&#93;</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;">&quot;parent_id&quot;</span> <span style="color: #339933;">=&gt;</span> <span style="color: #000088;">$row</span><span style="color: #009900;">&#91;</span><span style="color: #0000ff;">'parent_id'</span><span style="color: #009900;">&#93;</span><span style="color: #339933;">,</span> <span style="color: #0000ff;">&quot;name&quot;</span> <span style="color: #339933;">=&gt;</span> <span style="color: #000088;">$row</span><span style="color: #009900;">&#91;</span><span style="color: #0000ff;">'category_label'</span><span style="color: #009900;">&#93;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>	
<span style="color: #009900;">&#125;</span></pre></td></tr></table></div>

<p>The code is straightforward, read the comments if you dont understand how the array is created.</p>
<h3>How to build the tree structure from the array</h3>
<p>At this point i have to create the tree based on the information that i put inside the array.<br />
Because I don&#8217;t know prior how may level I will have in the category tree (i dont know the deepest of the branches), to recreate the tree i use a <a href="http://en.wikipedia.org/wiki/Recursion_(computer_science)" target="_blank">recursive function</a>, which is a function that call itself.<br />
This is the bare naked function, that print the ordered list of categories, but without the html markup. Instead, i use asterisks to indicate the level of nesting.<br />
The final function will render a complete unordered list.</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: #666666; font-style: italic;">// function to create a tree based on a unordered array</span>
<span style="color: #000000; font-weight: bold;">function</span> createTreeT<span style="color: #009900;">&#40;</span><span style="color: #000088;">$array</span><span style="color: #339933;">,</span> <span style="color: #000088;">$currentParent</span><span style="color: #339933;">,</span> <span style="color: #000088;">$currLevel</span> <span style="color: #339933;">=</span> <span style="color: #339933;">-</span><span style="color: #cc66cc;">1</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
	<span style="color: #b1b100;">foreach</span> <span style="color: #009900;">&#40;</span><span style="color: #000088;">$array</span> <span style="color: #b1b100;">as</span> <span style="color: #000088;">$categoryId</span> <span style="color: #339933;">=&gt;</span> <span style="color: #000088;">$category</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
		<span style="color: #b1b100;">if</span> <span style="color: #009900;">&#40;</span><span style="color: #000088;">$currentParent</span> <span style="color: #339933;">==</span> <span style="color: #000088;">$category</span><span style="color: #009900;">&#91;</span><span style="color: #0000ff;">'parent_id'</span><span style="color: #009900;">&#93;</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
&nbsp;
			<span style="color: #666666; font-style: italic;">// print the asterisks based on the current level of nesting		</span>
			<span style="color: #b1b100;">for</span> <span style="color: #009900;">&#40;</span><span style="color: #000088;">$i</span><span style="color: #339933;">=</span><span style="color: #cc66cc;">0</span><span style="color: #339933;">;</span><span style="color: #000088;">$i</span><span style="color: #339933;">&lt;</span><span style="color: #000088;">$currLevel</span><span style="color: #339933;">;</span><span style="color: #000088;">$i</span><span style="color: #339933;">++</span><span style="color: #009900;">&#41;</span> <span style="color: #b1b100;">echo</span> <span style="color: #0000ff;">&quot;*&quot;</span><span style="color: #339933;">;</span>			
&nbsp;
			<span style="color: #b1b100;">echo</span> <span style="color: #000088;">$category</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: #0000ff;">&quot;&lt;br /&gt;&quot;</span><span style="color: #339933;">;</span> <span style="color: #666666; font-style: italic;">// print the category name</span>
&nbsp;
			<span style="color: #000088;">$currLevel</span><span style="color: #339933;">++;</span>
		 	createTreeT <span style="color: #009900;">&#40;</span><span style="color: #000088;">$array</span><span style="color: #339933;">,</span> <span style="color: #000088;">$categoryId</span><span style="color: #339933;">,</span> <span style="color: #000088;">$currLevel</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
		 	<span style="color: #000088;">$currLevel</span><span style="color: #339933;">--;</span>
		<span style="color: #009900;">&#125;</span>	
	<span style="color: #009900;">&#125;</span>
<span style="color: #009900;">&#125;</span>
&nbsp;
<span style="color: #666666; font-style: italic;">// create the tree starting from the root (parent_id = 0)</span>
createTree<span style="color: #009900;">&#40;</span><span style="color: #000088;">$arrayCategories</span><span style="color: #339933;">,</span> <span style="color: #cc66cc;">0</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span></pre></td></tr></table></div>

<p>If you used the data that i provided you sould have something like this:</p>
<p>category one<br />
category two<br />
*category three<br />
*category four<br />
**category fine<br />
category six<br />
*category seven</p>
<p>Let me explain how it works. As you can see the function accepts 3 arguments: the first is the array with the category that we build with the category in the database, the second is the parent_id of the current level of category, and the third is the current level of nesting. I know that this seems confusing now, i will try to make it more clear.</p>
<p>Inside the <i>foreach</i> statement (that simply extract all the category one by one form the array), the <i>if</i> compare the current parent value, that is initially 0, with the whole array again, the value of the parent_id of the category extracted: if the value match it print the category name (with eventually the asterisks in front of it) and then call itself with the value of the id of the current category as new $currentParent, and the current level increased by 1.</p>
<p>The new call start the <i>foreach</i> again, but with the new values, and search for the category that have the parent_id that match the category_id passed. If it finds something, the process start again, but with a new category_id and a new level of nesting.<br />
If nothing is found the function exit, and the process is passed to the calling function, the current level is decreased and the next for each is processed.<br />
I know, is not so simple to understand, but when you got it you have a very powerful thing in your hands. In<a href="http://www.freenetpages.co.uk/hp/alan.gauld/tutrecur.htm"  target="_blank">this article, you can find a simple example of recursive function in python to calculate the factorial of a number</a>.<br />
Notice that you can retrieve only a branch of the tree by passing a different value as second parameter. For example when i calls the function like this:</p>
<p>createTree($arrayCategories, 2);</p>
<p>I will have the branches with the categories that have the parent_id set to 2, with all the subcategories. Cool!!</p>
<p>Now that we have (hopefully) understand how the function works, let&#8217;s see how to print the tree with all the necessary markups. The function is the same, but i introduced a new variable to keep track of the level of nesting of the calling function:</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;">function</span> createTree<span style="color: #009900;">&#40;</span><span style="color: #000088;">$array</span><span style="color: #339933;">,</span> <span style="color: #000088;">$currentParent</span><span style="color: #339933;">,</span> <span style="color: #000088;">$currLevel</span> <span style="color: #339933;">=</span> <span style="color: #cc66cc;">0</span><span style="color: #339933;">,</span> <span style="color: #000088;">$prevLevel</span> <span style="color: #339933;">=</span> <span style="color: #339933;">-</span><span style="color: #cc66cc;">1</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
&nbsp;
	<span style="color: #b1b100;">foreach</span> <span style="color: #009900;">&#40;</span><span style="color: #000088;">$array</span> <span style="color: #b1b100;">as</span> <span style="color: #000088;">$categoryId</span> <span style="color: #339933;">=&gt;</span> <span style="color: #000088;">$category</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
&nbsp;
		<span style="color: #b1b100;">if</span> <span style="color: #009900;">&#40;</span><span style="color: #000088;">$currentParent</span> <span style="color: #339933;">==</span> <span style="color: #000088;">$category</span><span style="color: #009900;">&#91;</span><span style="color: #0000ff;">'parent_id'</span><span style="color: #009900;">&#93;</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>						
&nbsp;
			<span style="color: #b1b100;">if</span> <span style="color: #009900;">&#40;</span><span style="color: #000088;">$currLevel</span> <span style="color: #339933;">&gt;</span> <span style="color: #000088;">$prevLevel</span><span style="color: #009900;">&#41;</span> <span style="color: #b1b100;">echo</span> <span style="color: #0000ff;">&quot; &lt;ul&gt; &quot;</span><span style="color: #339933;">;</span> 
&nbsp;
			<span style="color: #b1b100;">if</span> <span style="color: #009900;">&#40;</span><span style="color: #000088;">$currLevel</span> <span style="color: #339933;">==</span> <span style="color: #000088;">$prevLevel</span><span style="color: #009900;">&#41;</span> <span style="color: #b1b100;">echo</span> <span style="color: #0000ff;">&quot; &lt;/li&gt; &quot;</span><span style="color: #339933;">;</span>
&nbsp;
			<span style="color: #b1b100;">echo</span> <span style="color: #0000ff;">'&lt;li id=&quot;'</span><span style="color: #339933;">.</span><span style="color: #000088;">$categoryId</span><span style="color: #339933;">.</span><span style="color: #0000ff;">'&quot;&gt;&lt;span&gt;'</span><span style="color: #339933;">.</span><span style="color: #000088;">$category</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: #0000ff;">'&lt;/span&gt;'</span><span style="color: #339933;">;</span>
&nbsp;
			<span style="color: #b1b100;">if</span> <span style="color: #009900;">&#40;</span><span style="color: #000088;">$currLevel</span> <span style="color: #339933;">&gt;</span> <span style="color: #000088;">$prevLevel</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span> <span style="color: #000088;">$prevLevel</span> <span style="color: #339933;">=</span> <span style="color: #000088;">$currLevel</span><span style="color: #339933;">;</span> <span style="color: #009900;">&#125;</span>
&nbsp;
			<span style="color: #000088;">$currLevel</span><span style="color: #339933;">++;</span> 
&nbsp;
		 	createTree <span style="color: #009900;">&#40;</span><span style="color: #000088;">$array</span><span style="color: #339933;">,</span> <span style="color: #000088;">$categoryId</span><span style="color: #339933;">,</span> <span style="color: #000088;">$currLevel</span><span style="color: #339933;">,</span> <span style="color: #000088;">$prevLevel</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
		 	<span style="color: #000088;">$currLevel</span><span style="color: #339933;">--;</span>	 		 	
		<span style="color: #009900;">&#125;</span>	
&nbsp;
	<span style="color: #009900;">&#125;</span>
&nbsp;
	<span style="color: #b1b100;">if</span> <span style="color: #009900;">&#40;</span><span style="color: #000088;">$currLevel</span> <span style="color: #339933;">==</span> <span style="color: #000088;">$prevLevel</span><span style="color: #009900;">&#41;</span> <span style="color: #b1b100;">echo</span> <span style="color: #0000ff;">&quot; &lt;/li&gt;  &lt;/ul&gt; &quot;</span><span style="color: #339933;">;</span>
&nbsp;
<span style="color: #009900;">&#125;</span></pre></td></tr></table></div>

<p>Essentially, it uses the variables $prevLevel and $currLevel to know what to print in order to render a correct unordered list structure: if $currLevel > $prevLevel this means that we are at the beginning of a new level, so it prints a ul, that prints the category name with the open li element and assigns the same value to $prevLevel and $currLevel, because we are currently in the same level.<br />
When the foreach ends, it prints the li and ul to close the structure correctly.</p>
<p>At this point we must call this function inside our html page:</p>

<div class="wp_syntax"><table><tr><td class="line_numbers"><pre>1
2
3
4
5
</pre></td><td class="code"><pre class="html4strict" style="font-family:monospace;"><span style="color: #009900;">&lt;<span style="color: #000000; font-weight: bold;">ul</span> <span style="color: #000066;">class</span><span style="color: #66cc66;">=</span><span style="color: #ff0000;">&quot;simpleTree&quot;</span>&gt;</span>
	<span style="color: #009900;">&lt;<span style="color: #000000; font-weight: bold;">li</span> <span style="color: #000066;">id</span><span style="color: #66cc66;">=</span><span style="color: #ff0000;">&quot;0&quot;</span> <span style="color: #000066;">class</span><span style="color: #66cc66;">=</span><span style="color: #ff0000;">&quot;root&quot;</span>&gt;&lt;<span style="color: #000000; font-weight: bold;">span</span>&gt;</span>Categories<span style="color: #009900;">&lt;<span style="color: #66cc66;">/</span><span style="color: #000000; font-weight: bold;">span</span>&gt;</span>
		<span style="color: #009900;">&lt;?php createTree<span style="color: #66cc66;">&#40;</span>$arrayCategories, <span style="color: #cc66cc;">0</span><span style="color: #66cc66;">&#41;</span>; ?&gt;</span>
	<span style="color: #009900;">&lt;<span style="color: #66cc66;">/</span><span style="color: #000000; font-weight: bold;">li</span>&gt;</span>
<span style="color: #009900;">&lt;<span style="color: #66cc66;">/</span><span style="color: #000000; font-weight: bold;">ul</span>&gt;</span></pre></td></tr></table></div>

<p>And you will have a a nicely formatted tree, similar to the one I showed you, but created with the category retrieved from the database.</p>
<p>In the next (and last) part of the article, i will show you how to save the state of the tree in the database when you drag and drop the category to reorder it. Of course, I will do it with jQuery!</p>
<p class="buymebeer"><form action="https://www.paypal.com/cgi-bin/webscr" target="paypal" method="post"><input type="hidden" name="cmd" value="_xclick" /><input type="hidden" name="business" value="mauro@ondadiluce.com" /><input type="hidden" name="return" value="" /><input type="hidden" name="item_name" value="Buy me a coffe for Persistent drag and drop tree with jQuery, PHP and MySQL - part 1" /><input type="hidden" name="currency_code" value="EUR" /><input type="hidden" name="amount" value="1" /><input type="image" src="http://www.mdgart.com/wp-content/plugins/buy-me-beer/icon_cafe.gif" align="left" alt="Buy me a coffe" title="Buy me a coffe" hspace="3" style="border:0;" /></form><a href="https://www.paypal.com/cgi-bin/webscr?cmd=_xclick&amp;business=mauro@ondadiluce.com&amp;currency_code=EUR&amp;amount=1&amp;return=&amp;item_name=Buy+me+a+coffe+for+Persistent+drag+and+drop+tree+with+jQuery,+PHP+and+MySQL+-+part+1" target="paypal">Donate 1 euro, buy me a coffee, I need it to write more posts! Thanks ;)</a></p>]]></content:encoded>
			<wfw:commentRss>http://www.mdgart.com/2009/03/15/persistent-drag-and-drop-tree-with-jquery-php-and-mysql-part-1/feed/</wfw:commentRss>
		<slash:comments>35</slash:comments>
		</item>
		<item>
		<title>RegEx: Link not beginning with http://</title>
		<link>http://www.mdgart.com/2009/01/23/regex-link-not-beginning-with-http/</link>
		<comments>http://www.mdgart.com/2009/01/23/regex-link-not-beginning-with-http/#comments</comments>
		<pubDate>Fri, 23 Jan 2009 16:54:01 +0000</pubDate>
		<dc:creator>Mauro</dc:creator>
				<category><![CDATA[PHP]]></category>
		<category><![CDATA[pcre]]></category>
		<category><![CDATA[regex]]></category>
		<category><![CDATA[regexp]]></category>
		<category><![CDATA[regular expression]]></category>
		<category><![CDATA[tutorial]]></category>

		<guid isPermaLink="false">http://www.mdgart.com/?p=3</guid>
		<description><![CDATA[I had to find a regex to match not a string that contain something, but a string that not contain something, and in particular i had to check that a link entered in a form does not begin with http://. I needed to use a regex for this that work with PHP and, i have to admin, it was not so simple. ]]></description>
			<content:encoded><![CDATA[<p>I had to find a regex to match not a string that contain something, but a string that not contain something, and in particular i had to check that a link entered in a form does not begin with http://. I needed to use a regex for this that work with PHP and, i have to admin, it was not so simple.<br />
The method that i found is based on lookahead technique, but seem to work only with preg_match() and not with ereg(). Is not perfect, because it don&#8217;t match any string that contain http://, not only that begin with.<br />
This is the regex:</p>
<p><code><br />
(^((?!.*http\://).)*$)<br />
</code></p>
<p>This match www.ciao.com, but not http://www.ciao.com and also not www.ciao.com/http:// and any string that contain http://. It work for my needs, but is not what really wanted to achieve.<br />
If you know a method to correct the regex, please tell me.</p>
<p class="buymebeer"><form action="https://www.paypal.com/cgi-bin/webscr" target="paypal" method="post"><input type="hidden" name="cmd" value="_xclick" /><input type="hidden" name="business" value="mauro@ondadiluce.com" /><input type="hidden" name="return" value="" /><input type="hidden" name="item_name" value="Buy me a coffe for RegEx: Link not beginning with http://" /><input type="hidden" name="currency_code" value="EUR" /><input type="hidden" name="amount" value="1" /><input type="image" src="http://www.mdgart.com/wp-content/plugins/buy-me-beer/icon_cafe.gif" align="left" alt="Buy me a coffe" title="Buy me a coffe" hspace="3" style="border:0;" /></form><a href="https://www.paypal.com/cgi-bin/webscr?cmd=_xclick&amp;business=mauro@ondadiluce.com&amp;currency_code=EUR&amp;amount=1&amp;return=&amp;item_name=Buy+me+a+coffe+for+RegEx:+Link+not+beginning+with+http://" target="paypal">Donate 1 euro, buy me a coffee, I need it to write more posts! Thanks ;)</a></p>]]></content:encoded>
			<wfw:commentRss>http://www.mdgart.com/2009/01/23/regex-link-not-beginning-with-http/feed/</wfw:commentRss>
		<slash:comments>5</slash:comments>
		</item>
	</channel>
</rss>
