<?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>James Padolsey&#187; PHP category &#8211; James Padolsey</title>
	<atom:link href="http://james.padolsey.com/category/php/feed/" rel="self" type="application/rss+xml" />
	<link>http://james.padolsey.com</link>
	<description>Just another WordPress weblog</description>
	<lastBuildDate>Sun, 22 Jan 2012 17:04:26 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.2</generator>
		<item>
		<title>Isara&#8217;s new management system</title>
		<link>http://james.padolsey.com/general/isaras-new-management-system/</link>
		<comments>http://james.padolsey.com/general/isaras-new-management-system/#comments</comments>
		<pubDate>Sun, 20 Feb 2011 13:46:13 +0000</pubDate>
		<dc:creator>James</dc:creator>
				<category><![CDATA[General]]></category>
		<category><![CDATA[PHP]]></category>
		<category><![CDATA[isara]]></category>
		<category><![CDATA[project]]></category>

		<guid isPermaLink="false">http://james.padolsey.com/?p=1731</guid>
		<description><![CDATA[The <a href="http://www.isara.org">Isara Foundation</a> runs a learning centre in Nong Khai, Thailand. It&#8217;s known as the <abbr title="Isara Learning Center">ILC</abbr>. Here volunteers from around the world teach English, IT and Art to local people. There are classes for both children and adults, and within those bounds students are separated according&#8230;]]></description>
			<content:encoded><![CDATA[<p>The <a href="http://www.isara.org">Isara Foundation</a> runs a learning centre in Nong Khai, Thailand. It&#8217;s known as the <abbr title="Isara Learning Center">ILC</abbr>. Here volunteers from around the world teach English, IT and Art to local people. There are classes for both children and adults, and within those bounds students are separated according to capability, which is judged using a reading system (e.g. <em>phonics -> fables -> free-reading</em>).</p>

<h3>The current system</h3>

<p>I arrived at the ILC at the beginning of December. I started off just watching and admiring the work of other volunteers but eventually had to take a class on for myself. The then current system of record-keeping and proficiency-recording was paper-based. There were folders for each class and within each folder, booklets for each student.</p>

<p>Each booklet recorded a single student&#8217;s reading level, their strengths, their weaknesses and any concerns previous teachers had. These booklets would inevitably become full of volunteers&#8217; notes. So many volunteers&#8230; so many notes.</p>

<p>Many of the scribblings were not dated and not particularly tidy. Lesson plans were recorded on paper too, but only as a single bullet point per lesson.</p>

<p>Don&#8217;t let me paint a bad picture though. The work being done here is and was always fantastic! The typical volunteer would plan a lesson the day before and record the plan on their own stationary, whether that be a notebook or a scrap of paper. Despite my reservations about it being paper-based the lesson&#8217;s still got planned and the students still picked up valuable language skills.</p>

<p>The problem, as I saw it, was merely one of efficiency. The case for a computer-based alternative was, I felt, rock-solid. I begun.</p>

<span id="more-1731"></span>

<h3>The new system</h3>

<p>So, for the last few weeks I&#8217;ve been working on a new web application for the Isara Foundation which holds student records, lesson plans, teacher profiles and makes all this data accessible through an intuitive interface. Current volunteers can leave their lesson plans, student notes and class notes on a centralised system. New volunteers come along and don&#8217;t need to worry about digging through masses of paper to get the 101 on their assigned class. They can see all the data they could possibly want before even stepping into the classroom:</p>

<p class="video">
    <a href="http://james.padolsey.com/wp-content/uploads/isara_tms_s1.png"><img width="600" src="http://james.padolsey.com/wp-content/uploads/isara_tms_s1.png" alt="A typical student profile" /></a>
</p>

<p>The new system, which is already being used (I guess it&#8217;s <em>beta</em>), has the following features:</p>

<ul>
    <li>Stores basic data about students. Their names, ages, addresses, etc.</li>
    <li>Stores photos for all students. Great for learning your students&#8217; names!</li>
    <li>Stores teacher profiles and allows teachers to be assigned to classes and vice-versa.</li>
    <li>Allows teachers to leave notes on student profiles (individual strengths/weaknesses/comments) and class profiles (comments about class in general).</li>
    <li>Allows teachers to enter their lesson plans, and look over previous lesson plans.</li>
    <li>All students&#8217; skill levels recorded, which will eventually enable us to draw some interesting statistics about teaching techniques and skill acquisition.</li>
    <li>Makes it possible to receive notifications about student birthdays! (my favourite feature)</li>
</ul>

<p>In essence, it is a primitive system. Nothing too fancy is going on, but I definitely enjoyed building it!</p>

<p>As some of you will know, I used <a href="http://codeigniter.com">CodeIgniter</a> for this project, simply for its insistence on MVC and the fact that I was familiar with its API.</p>

<p>I don&#8217;t regret my decision to use CI. It has worked perfectly.</p>

<h3>Implementation notes</h3>

<p>The database schema seemed simple at first, but then came normalisation &#8212; and with that, apparent complexity. <a href="http://bit.ly/f1QiCK"><strong>Here&#8217;s the schema</strong></a>! (<em>not including audit tables</em>)</p>

<p>As one is supposed to, I created separate models for every table, except the auditing ones. I created <code>MY_Model</code> which took care of the auditing and added a few useful methods. All of my actual models inherited from this.</p>

<p>The models were originally used for creating, reading, updating and deleting, but I eventually moved over to a structure which delegated to regular models for creating, updating and deleting, but utilised a specialised query model for the reading. I did this because I originally found that I was duplicating a lot of code within models, and decided to abstract the whole querying business to its own model. This has worked remarkably well and has facilitated a much simpler querying syntax and interface.</p>

<p>Within <code>Query_model</code> I can specify what needs to be selected and from where within an associative array:</p>


<div class="wp_syntax"><div class="code"><pre class="php" style="font-family:monospace;"><span class="co1">// ...</span>
<span class="st_h">'classes'</span> <span class="sy0">=&gt;</span> <span class="kw3">array</span><span class="br0">&#40;</span>
    <span class="st_h">'select'</span> <span class="sy0">=&gt;</span> <span class="st0">&quot;
        classes.*,
        class_slots.name as slot_name,
        classes.name as class_name,
        class_slots.days as class_days,
        class_slots.time as class_time,
        rooms.id as room_id,
        rooms.name as room_name,
        rooms.photo as room_photo,
        COUNT(DISTINCT students.id) as student_count,
        GROUP_CONCAT(DISTINCT CONVERT(teacher_assignments.teacher_id, CHAR(8)) SEPARATOR ',') AS teacher_ids,
        GROUP_CONCAT(DISTINCT teachers.name SEPARATOR ',') AS teacher_names		
    &quot;</span><span class="sy0">,</span>
    <span class="st_h">'from'</span> <span class="sy0">=&gt;</span> <span class="st0">&quot;
        classes
            LEFT JOIN teacher_assignments
                ON classes.id = teacher_assignments.class_id
                AND teacher_assignments.active = TRUE
            LEFT JOIN class_slots
                ON class_slots.id = classes.slot_id
            LEFT JOIN teachers
                ON teachers.id = teacher_assignments.teacher_id
            LEFT JOIN student_assignments
                ON student_assignments.class_id = classes.id
            LEFT JOIN students
                ON students.id = student_assignments.student_id
            LEFT JOIN rooms
                ON classes.assigned_room_id = rooms.id
    &quot;</span><span class="sy0">,</span> 
    <span class="st_h">'where'</span> <span class="sy0">=&gt;</span> <span class="st0">&quot;&quot;</span><span class="sy0">,</span>
    <span class="st_h">'groupBy'</span> <span class="sy0">=&gt;</span> <span class="st_h">'classes.id'</span>
<span class="br0">&#41;</span><span class="sy0">,</span>
<span class="co1">// ...</span></pre></div></div>




<p>And of course, I store the the fields that one would want to query <em>by</em> in a separate array:</p>


<div class="wp_syntax"><div class="code"><pre class="php" style="font-family:monospace;"><span class="co1">// ...</span>
<span class="st_h">'classes'</span> <span class="sy0">=&gt;</span> <span class="kw3">array</span><span class="br0">&#40;</span>
    <span class="st_h">'teacher_id'</span> <span class="sy0">=&gt;</span> <span class="st0">&quot;teachers.id <span class="es6">%c</span> AND teacher_assignments.active = TRUE&quot;</span><span class="sy0">,</span>
    <span class="st_h">'student_id'</span> <span class="sy0">=&gt;</span> <span class="st0">&quot;students.id <span class="es6">%c</span> AND student_assignments.active = TRUE&quot;</span><span class="sy0">,</span>
    <span class="st_h">'id'</span> <span class="sy0">=&gt;</span> <span class="st0">&quot;classes.id <span class="es6">%c</span>&quot;</span><span class="sy0">,</span>
    <span class="st_h">'room_id'</span> <span class="sy0">=&gt;</span> <span class="st0">&quot;rooms.id <span class="es6">%c</span>&quot;</span><span class="sy0">,</span>
    <span class="st_h">'has_note_id'</span> <span class="sy0">=&gt;</span> <span class="st0">&quot;notes.id <span class="es6">%c</span>&quot;</span><span class="sy0">,</span>
    <span class="st_h">'slot_id'</span> <span class="sy0">=&gt;</span> <span class="st0">&quot;class_slots.id <span class="es6">%c</span>&quot;</span>
<span class="br0">&#41;</span><span class="sy0">,</span>
<span class="co1">// ...</span></pre></div></div>




<p>I love this kind of low-level control!</p>

<p>The <code>%c</code> token you see above is replaced with an operator and the value to be searched. Operators are stored like so:</p>


<div class="wp_syntax"><div class="code"><pre class="php" style="font-family:monospace;"><span class="kw2">var</span> <span class="re0">$operators</span> <span class="sy0">=</span> <span class="kw3">array</span><span class="br0">&#40;</span>
    <span class="st_h">'gt'</span> <span class="sy0">=&gt;</span> <span class="st_h">'&gt;&quot;%v&quot;'</span><span class="sy0">,</span>
    <span class="st_h">'lt'</span> <span class="sy0">=&gt;</span> <span class="st_h">'&lt;&quot;%v&quot;'</span><span class="sy0">,</span>
    <span class="st_h">'gte'</span> <span class="sy0">=&gt;</span> <span class="st_h">'&gt;=&quot;%v&quot;'</span><span class="sy0">,</span>
    <span class="st_h">'lte'</span> <span class="sy0">=&gt;</span> <span class="st_h">'&lt;=&quot;%v&quot;'</span><span class="sy0">,</span>
    <span class="st_h">'e'</span> <span class="sy0">=&gt;</span> <span class="st_h">'=&quot;%v&quot;'</span><span class="sy0">,</span>
    <span class="st_h">'ne'</span> <span class="sy0">=&gt;</span> <span class="st_h">'!=&quot;%v&quot;'</span><span class="sy0">,</span>
    <span class="st_h">'c'</span> <span class="sy0">=&gt;</span> <span class="st_h">'LIKE &quot;%%v%&quot;'</span><span class="sy0">,</span>
    <span class="st_h">'&gt;'</span> <span class="sy0">=&gt;</span> <span class="st_h">'&gt;&quot;%v&quot;'</span><span class="sy0">,</span>
    <span class="st_h">'&lt;'</span> <span class="sy0">=&gt;</span> <span class="st_h">'&lt;&quot;%v&quot;'</span><span class="sy0">,</span>
    <span class="st_h">'&gt;='</span> <span class="sy0">=&gt;</span> <span class="st_h">'&gt;=&quot;%v&quot;'</span><span class="sy0">,</span>
    <span class="st_h">'&lt;='</span> <span class="sy0">=&gt;</span> <span class="st_h">'&lt;=&quot;%v&quot;'</span><span class="sy0">,</span>
    <span class="st_h">'='</span> <span class="sy0">=&gt;</span> <span class="st_h">'=&quot;%v&quot;'</span><span class="sy0">,</span>
    <span class="st_h">'!='</span> <span class="sy0">=&gt;</span> <span class="st_h">'!=&quot;%v&quot;'</span><span class="sy0">,</span>
    <span class="st_h">'contains'</span> <span class="sy0">=&gt;</span> <span class="st_h">'LIKE &quot;%%v%&quot;'</span><span class="sy0">,</span>
<span class="br0">&#41;</span><span class="sy0">;</span></pre></div></div>




<p>The first bulk of operators you see there (<em>gt</em>, <em>lte</em> etc.) are utilised within query strings. E.g.</p>


<div class="wp_syntax"><div class="code"><pre class="text" style="font-family:monospace;">/query?ret=students&amp;k=age&amp;c=gte&amp;v=16
(get all students with an age &gt;= 16)</pre></div></div>




<p>Don&#8217;t worry though! This seemingly low-level access isn&#8217;t actually that revealing. In order for a query to execute, the field that you want to query by must be specified, in the query-model, as must the operator. Values are escaped also.</p>

<p>I want to share more about the implementation but it turns out everything else is quite boring and basic. The query-model thing was really the only point worth nothing. That said, I am trying out an action-managing idea which allows delayed database actions such as deletion or flagging. Each action has a UUID and can be activated via a URL (this would also work well for email-activation links). Anyway, maybe next time&#8230;</p>

<h3>It works!</h3>

<p>We&#8217;ve been entering data and testing it for about two weeks and today saw a mass adoption by all volunteers at Isara. Hopefully this system will last, at least until a <em>more efficient</em> alternative comes along.</p>]]></content:encoded>
			<wfw:commentRss>http://james.padolsey.com/general/isaras-new-management-system/feed/</wfw:commentRss>
		<slash:comments>9</slash:comments>
		</item>
		<item>
		<title>Isara + CodeIgniter = ?</title>
		<link>http://james.padolsey.com/general/isara-codeigniter/</link>
		<comments>http://james.padolsey.com/general/isara-codeigniter/#comments</comments>
		<pubDate>Mon, 03 Jan 2011 18:14:20 +0000</pubDate>
		<dc:creator>James</dc:creator>
				<category><![CDATA[General]]></category>
		<category><![CDATA[My Life]]></category>
		<category><![CDATA[PHP]]></category>
		<category><![CDATA[isara]]></category>
		<category><![CDATA[teaching]]></category>
		<category><![CDATA[volunteering]]></category>

		<guid isPermaLink="false">http://james.padolsey.com/?p=1715</guid>
		<description><![CDATA[I&#8217;ve been taking a bit of a holiday away from the web-scene recently. It isn&#8217;t something I regret though. I&#8217;ve done things that have given me new perspectives and insights into the world. I am still &#8220;away&#8221;, and if truth be told, I cannot envisage&#8230;]]></description>
			<content:encoded><![CDATA[<p>I&#8217;ve been taking a bit of a holiday away from the web-scene recently. It isn&#8217;t something I regret though. I&#8217;ve done things that have given me new perspectives and insights into the world. I am still &#8220;away&#8221;, and if truth be told, I cannot envisage myself wanting a regular job ever again, although I imagine in some unfortunate way that I will be driven to such lengths by financial limitations.</p>

<p>Anyway, as should be well known by anyone who frequents this blog, I am currently volunteering in Thailand. Specifically, I am working with <a href="http://www.isara.org">Isara</a>, an awesome non-profit foundation based in Nong Khai.</p>

<p>Let me try and shatter what you think you know about Thailand and put across what I know thus far in a paragraph. There are no blanket statements I can make such as &#8220;the food is delicious&#8221; or &#8220;the people are kind, generous and beautiful&#8221; because such things would only be as true as if said of any other country in the world.</p>

<span id="more-1715"></span>

<p>Isaan is Thailand&#8217;s poorest province &#8212; this is where Nong Khai is situated. The average farmer makes around 140 Baht each day, which is about £3 ($5), and considering everything, people from this area seem contented with their lives. <em>Farang</em>s (foreigners, specifically white ones) are almost revered for just being white. The locals find novelty in our white skin, our coloured hair and eyes, our height and our language. Children here are demotivated by the government education system which seems to attract dispassionate teachers because of it being one of few jobs with social security benefits. The children, albeit demotivated, are enthusiastic when inspired and willing to learn when shown what they can become. There are struggles. Uneducated people pollute and abuse the environment and each other. Health, safety and true education come second to saving face and appearing calm and subdued. The people here cover every spec of the spectrum &#8212; there are all kinds. There are many <em>farang</em> here too&#8230; some older folk, some younger. Some looking for their Thai brides, some travelling, and some staying to help. Life here is cheap for a westerner. Life here is hard for a local. Learning English is a way out, an opportunity to become something more, an opportunity to take the world by the horns and do what you will!</p>

<p>I&#8217;m currently working on developing a computer-based system for Isara&#8217;s learning center, where local people are invited to learn English for free three times a week. Currently all student records are kept in a paper-based system &#8212; this includes details about their progress in class. Moving it to a computer-based system will waste less paper, provide a centralised store of student details and progress, enable querying of the data to determine which students are behind and what topics have been taught, and it will provide a wealth of query-able, filter-able, process-able data that could save many man-hours of paper-fiddling and printing!</p>

<p>It&#8217;s still a plan in progress, but the DB schema looks <a href="http://bit.ly/gdL3TS">like this</a> thus far (all &#8216;_log&#8217; tables are for auditing). I am going to be using <a href="http://codeigniter.com/">CodeIgniter</a>, just because I remember how ridiculously simple it made a previous project. If you haven&#8217;t, you should try it out!</p>

<p>It insists upon separating your concerns into the traditional M-V-C pattern (Model, View, Controller) and has a bunch of auto-load-able helper classes and libraries. It&#8217;s very widely used, so finding help online is rarely a problem (Google is your friend).</p>

<p>Got any tips or stories to share about CI? Please share.</p>]]></content:encoded>
			<wfw:commentRss>http://james.padolsey.com/general/isara-codeigniter/feed/</wfw:commentRss>
		<slash:comments>12</slash:comments>
		</item>
		<item>
		<title>&#8220;wordwrap&#8221; for JavaScript</title>
		<link>http://james.padolsey.com/javascript/wordwrap-for-javascript/</link>
		<comments>http://james.padolsey.com/javascript/wordwrap-for-javascript/#comments</comments>
		<pubDate>Fri, 26 Jun 2009 08:17:01 +0000</pubDate>
		<dc:creator>James</dc:creator>
				<category><![CDATA[Code Snippets]]></category>
		<category><![CDATA[JavaScript]]></category>
		<category><![CDATA[PHP]]></category>
		<category><![CDATA[Strings]]></category>

		<guid isPermaLink="false">http://james.padolsey.com/?p=968</guid>
		<description><![CDATA[This function emulates PHP's <code>wordwrap</code>. It takes four arguments]]></description>
			<content:encoded><![CDATA[<p>This function emulates PHP&#8217;s <code><a href="http://us3.php.net/manual/en/function.wordwrap.php">wordwrap</a></code>. It takes four arguments:</p>

<ul>
    <li>The string to be wrapped.</li>
    <li>The column width (a number, default: 75)</li>
    <li>The character(s) to be inserted at every break. (default: &#8216;\n&#8217;)</li>
    <li>The cut: a Boolean value (false by default). See <a href="http://us3.php.net/manual/en/function.wordwrap.php">PHP docs</a> for more info.</li>
</ul>

<h2>The code</h2>


<div class="wp_syntax"><div class="code"><pre class="javascript" style="font-family:monospace;"><span class="kw2">function</span> wordwrap<span class="br0">&#40;</span> str<span class="sy0">,</span> width<span class="sy0">,</span> brk<span class="sy0">,</span> cut <span class="br0">&#41;</span> <span class="br0">&#123;</span>
&nbsp;
    brk <span class="sy0">=</span> brk <span class="sy0">||</span> <span class="st0">'<span class="es0">\n</span>'</span><span class="sy0">;</span>
    width <span class="sy0">=</span> width <span class="sy0">||</span> <span class="nu0">75</span><span class="sy0">;</span>
    cut <span class="sy0">=</span> cut <span class="sy0">||</span> <span class="kw2">false</span><span class="sy0">;</span>
&nbsp;
    <span class="kw1">if</span> <span class="br0">&#40;</span><span class="sy0">!</span>str<span class="br0">&#41;</span> <span class="br0">&#123;</span> <span class="kw1">return</span> str<span class="sy0">;</span> <span class="br0">&#125;</span>
&nbsp;
    <span class="kw2">var</span> regex <span class="sy0">=</span> <span class="st0">'.{1,'</span> <span class="sy0">+</span>width<span class="sy0">+</span> <span class="st0">'}(<span class="es0">\\</span>s|$)'</span> <span class="sy0">+</span> <span class="br0">&#40;</span>cut <span class="sy0">?</span> <span class="st0">'|.{'</span> <span class="sy0">+</span>width<span class="sy0">+</span> <span class="st0">'}|.+$'</span> <span class="sy0">:</span> <span class="st0">'|<span class="es0">\\</span>S+?(<span class="es0">\\</span>s|$)'</span><span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp;
    <span class="kw1">return</span> str.<span class="me1">match</span><span class="br0">&#40;</span> RegExp<span class="br0">&#40;</span>regex<span class="sy0">,</span> <span class="st0">'g'</span><span class="br0">&#41;</span> <span class="br0">&#41;</span>.<span class="me1">join</span><span class="br0">&#40;</span> brk <span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp;
<span class="br0">&#125;</span></pre></div></div>




<h2>Usage</h2>


<div class="wp_syntax"><div class="code"><pre class="javascript" style="font-family:monospace;">wordwrap<span class="br0">&#40;</span><span class="st0">'The quick brown fox jumped over the lazy dog.'</span><span class="sy0">,</span> <span class="nu0">20</span><span class="sy0">,</span> <span class="st0">'&lt;br/&gt;<span class="es0">\n</span>'</span><span class="br0">&#41;</span><span class="sy0">;</span></pre></div></div>





<div class="wp_syntax"><div class="code"><pre class="text" style="font-family:monospace;">The quick brown fox &lt;br/&gt;
jumped over the lazy &lt;br/&gt;
dog.</pre></div></div>




<p>I know there are other solutions out there; the ones I saw seemed a bit slow though, not to mention unnecessarily complicated/bloated&#8230;</p>
]]></content:encoded>
			<wfw:commentRss>http://james.padolsey.com/javascript/wordwrap-for-javascript/feed/</wfw:commentRss>
		<slash:comments>6</slash:comments>
		</item>
		<item>
		<title>&#8216;tweetFromFile&#8217; PHP Class</title>
		<link>http://james.padolsey.com/twitter/tweetfromfile-php-class/</link>
		<comments>http://james.padolsey.com/twitter/tweetfromfile-php-class/#comments</comments>
		<pubDate>Mon, 02 Mar 2009 21:45:04 +0000</pubDate>
		<dc:creator>James</dc:creator>
				<category><![CDATA[Code Snippets]]></category>
		<category><![CDATA[PHP]]></category>
		<category><![CDATA[Twitter]]></category>
		<category><![CDATA[Automation]]></category>
		<category><![CDATA[Class]]></category>

		<guid isPermaLink="false">http://james.padolsey.com/?p=612</guid>
		<description><![CDATA[This recently created PHP class is part of today's ongoing struggle of trying to create a Twitter 'drip' that will automatically update Twitter at pre-defined intervals with status updates specified in a text file]]></description>
			<content:encoded><![CDATA[<p>This recently created PHP class is part of today&#8217;s ongoing struggle of trying to create a Twitter &#8216;drip&#8217; that will automatically update Twitter at pre-defined intervals with status updates specified in a text file.</p>


<div class="wp_syntax"><div class="code"><pre class="php" style="font-family:monospace;"><span class="co1">// (C) Copyright JAMES PADOLSEY</span>
<span class="kw2">class</span> tweetFromFile <span class="br0">&#123;</span>
&nbsp;
    <span class="kw2">private</span> <span class="re0">$curlHandle</span><span class="sy0">;</span>
    <span class="kw2">private</span> <span class="re0">$updateFile</span><span class="sy0">;</span>
    <span class="kw2">private</span> <span class="re0">$archiveFile</span><span class="sy0">;</span>
&nbsp;
    <span class="kw2">private</span> <span class="kw2">function</span> getNewStatus<span class="br0">&#40;</span><span class="br0">&#41;</span> <span class="br0">&#123;</span>
&nbsp;
        <span class="re0">$upcomingTweetsFile</span> <span class="sy0">=</span> <span class="re0">$this</span><span class="sy0">-&gt;</span><span class="me1">files</span><span class="br0">&#91;</span><span class="st_h">'upcoming'</span><span class="br0">&#93;</span><span class="sy0">;</span>
        <span class="re0">$archivedTweetsFile</span> <span class="sy0">=</span> <span class="re0">$this</span><span class="sy0">-&gt;</span><span class="me1">files</span><span class="br0">&#91;</span><span class="st_h">'archive'</span><span class="br0">&#93;</span><span class="sy0">;</span>
&nbsp;
        <span class="re0">$upcomingTweets_R</span> <span class="sy0">=</span> <span class="kw3">fopen</span><span class="br0">&#40;</span><span class="re0">$upcomingTweetsFile</span><span class="sy0">,</span> <span class="st0">&quot;r&quot;</span><span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp;
        <span class="co1">// Get upcoming Tweets:</span>
        <span class="re0">$contents</span> <span class="sy0">=</span> <span class="kw3">fread</span><span class="br0">&#40;</span><span class="re0">$upcomingTweets_R</span><span class="sy0">,</span> <span class="kw3">filesize</span><span class="br0">&#40;</span><span class="re0">$upcomingTweetsFile</span><span class="br0">&#41;</span><span class="br0">&#41;</span><span class="sy0">;</span>
        <span class="re0">$splitContents</span> <span class="sy0">=</span> <span class="kw3">preg_split</span><span class="br0">&#40;</span><span class="st_h">'/\n/'</span><span class="sy0">,</span> <span class="re0">$contents</span><span class="sy0">,</span> <span class="nu0">2</span><span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp;
        <span class="co1">// ARCHIVE OLD POSTS:</span>
        <span class="re0">$archive</span> <span class="sy0">=</span> <span class="kw3">fopen</span><span class="br0">&#40;</span><span class="re0">$archivedTweetsFile</span><span class="sy0">,</span> <span class="st0">&quot;a&quot;</span><span class="br0">&#41;</span><span class="sy0">;</span>
        <span class="kw3">fwrite</span><span class="br0">&#40;</span><span class="re0">$archive</span><span class="sy0">,</span> <span class="re0">$splitContents</span><span class="br0">&#91;</span><span class="nu0">0</span><span class="br0">&#93;</span><span class="sy0">.</span><span class="st0">&quot;<span class="es1">\n</span>&quot;</span><span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp;
        <span class="co1">// Remove top line from upcoming:</span>
        <span class="re0">$upcomingTweets_W</span> <span class="sy0">=</span> <span class="kw3">fopen</span><span class="br0">&#40;</span><span class="re0">$upcomingTweetsFile</span><span class="sy0">,</span> <span class="st0">&quot;w&quot;</span><span class="br0">&#41;</span><span class="sy0">;</span>
        <span class="kw3">fwrite</span><span class="br0">&#40;</span><span class="re0">$upcomingTweets_W</span><span class="sy0">,</span> <span class="re0">$splitContents</span><span class="br0">&#91;</span><span class="nu0">1</span><span class="br0">&#93;</span><span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp;
        <span class="co1">// Clean up</span>
        <span class="kw3">fclose</span><span class="br0">&#40;</span><span class="re0">$upcomingTweets_W</span><span class="br0">&#41;</span><span class="sy0">;</span>
        <span class="kw3">fclose</span><span class="br0">&#40;</span><span class="re0">$upcomingTweets_R</span><span class="br0">&#41;</span><span class="sy0">;</span>
        <span class="kw3">fclose</span><span class="br0">&#40;</span><span class="re0">$archive</span><span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp;
        <span class="kw1">return</span> <span class="re0">$splitContents</span><span class="br0">&#91;</span><span class="nu0">0</span><span class="br0">&#93;</span><span class="sy0">;</span>
    <span class="br0">&#125;</span>
&nbsp;
    <span class="kw2">public</span> <span class="re0">$files</span> <span class="sy0">=</span> <span class="kw3">array</span><span class="br0">&#40;</span><span class="st_h">'upcoming'</span> <span class="sy0">=&gt;</span> <span class="st_h">''</span><span class="sy0">,</span> <span class="st_h">'archive'</span> <span class="sy0">=&gt;</span> <span class="st_h">''</span><span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp;
    <span class="kw2">public</span> <span class="kw2">function</span> __construct<span class="br0">&#40;</span><span class="re0">$username</span><span class="sy0">,</span> <span class="re0">$password</span><span class="sy0">,</span> <span class="re0">$filename</span><span class="br0">&#41;</span> <span class="br0">&#123;</span>
&nbsp;
        <span class="re0">$this</span><span class="sy0">-&gt;</span><span class="me1">curlHandle</span> <span class="sy0">=</span> curl_init<span class="br0">&#40;</span><span class="br0">&#41;</span><span class="sy0">;</span>
        <span class="re0">$this</span><span class="sy0">-&gt;</span><span class="me1">files</span><span class="br0">&#91;</span><span class="st_h">'upcoming'</span><span class="br0">&#93;</span> <span class="sy0">=</span> <span class="re0">$filename</span><span class="sy0">;</span>
        <span class="re0">$this</span><span class="sy0">-&gt;</span><span class="me1">files</span><span class="br0">&#91;</span><span class="st_h">'archive'</span><span class="br0">&#93;</span> <span class="sy0">=</span> <span class="st_h">'ARCHIVE_'</span> <span class="sy0">.</span> <span class="re0">$filename</span><span class="sy0">;</span>
&nbsp;
        <span class="co1">// Shortcut:</span>
        <span class="re0">$ch</span> <span class="sy0">=</span> <span class="re0">$this</span><span class="sy0">-&gt;</span><span class="me1">curlHandle</span><span class="sy0">;</span>
&nbsp;
        curl_setopt<span class="br0">&#40;</span><span class="re0">$ch</span><span class="sy0">,</span> CURLOPT_URL<span class="sy0">,</span> <span class="st0">&quot;http://twitter.com/statuses/update.xml&quot;</span><span class="br0">&#41;</span><span class="sy0">;</span>
        curl_setopt<span class="br0">&#40;</span><span class="re0">$ch</span><span class="sy0">,</span> CURLOPT_CONNECTTIMEOUT<span class="sy0">,</span> <span class="nu0">2</span><span class="br0">&#41;</span><span class="sy0">;</span>
        curl_setopt<span class="br0">&#40;</span><span class="re0">$ch</span><span class="sy0">,</span> CURLOPT_RETURNTRANSFER<span class="sy0">,</span> <span class="nu0">1</span><span class="br0">&#41;</span><span class="sy0">;</span>
        curl_setopt<span class="br0">&#40;</span><span class="re0">$ch</span><span class="sy0">,</span> CURLOPT_POST<span class="sy0">,</span> <span class="nu0">1</span><span class="br0">&#41;</span><span class="sy0">;</span>
        curl_setopt<span class="br0">&#40;</span><span class="re0">$ch</span><span class="sy0">,</span> CURLOPT_USERPWD<span class="sy0">,</span> <span class="st0">&quot;<span class="es4">$username</span>:<span class="es4">$password</span>&quot;</span><span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp;
    <span class="br0">&#125;</span>
&nbsp;
    <span class="kw2">public</span> <span class="kw2">function</span> __destruct<span class="br0">&#40;</span><span class="br0">&#41;</span> <span class="br0">&#123;</span>
        curl_close<span class="br0">&#40;</span><span class="re0">$this</span><span class="sy0">-&gt;</span><span class="me1">curlHandle</span><span class="br0">&#41;</span><span class="sy0">;</span>
    <span class="br0">&#125;</span>
&nbsp;
    <span class="kw2">public</span> <span class="kw2">function</span> updateStatus<span class="br0">&#40;</span><span class="br0">&#41;</span> <span class="br0">&#123;</span>
&nbsp;
        <span class="re0">$status</span> <span class="sy0">=</span> <span class="re0">$this</span><span class="sy0">-&gt;</span><span class="me1">getNewStatus</span><span class="br0">&#40;</span><span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp;
        curl_setopt<span class="br0">&#40;</span><span class="re0">$this</span><span class="sy0">-&gt;</span><span class="me1">curlHandle</span><span class="sy0">,</span> CURLOPT_POSTFIELDS<span class="sy0">,</span> <span class="st0">&quot;status=<span class="es4">$status</span>&quot;</span><span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp;
        <span class="re0">$result</span> <span class="sy0">=</span> curl_exec<span class="br0">&#40;</span><span class="re0">$this</span><span class="sy0">-&gt;</span><span class="me1">curlHandle</span><span class="br0">&#41;</span><span class="sy0">;</span>	
	<span class="re0">$resultArray</span> <span class="sy0">=</span> curl_getinfo<span class="br0">&#40;</span><span class="re0">$this</span><span class="sy0">-&gt;</span><span class="me1">curlHandle</span><span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp;
        <span class="kw1">if</span> <span class="br0">&#40;</span><span class="re0">$resultArray</span><span class="br0">&#91;</span><span class="st_h">'http_code'</span><span class="br0">&#93;</span> <span class="sy0">==</span> <span class="nu0">200</span><span class="br0">&#41;</span> <span class="kw1">return</span> <span class="kw2">true</span><span class="sy0">;</span>
&nbsp;
        <span class="kw1">return</span> <span class="kw2">false</span><span class="sy0">;</span>
&nbsp;
    <span class="br0">&#125;</span>
&nbsp;
<span class="br0">&#125;</span>
&nbsp;
<span class="co1">// ==================</span>
<span class="co1">// ===== USAGE ======</span>
<span class="co1">// ==================</span>
&nbsp;
<span class="re0">$tweet</span> <span class="sy0">=</span> <span class="kw2">new</span> tweetFromFile<span class="br0">&#40;</span><span class="st_h">'twitterUsername'</span><span class="sy0">,</span> <span class="st_h">'password'</span><span class="sy0">,</span> <span class="st_h">'textfile.txt'</span><span class="br0">&#41;</span><span class="sy0">;</span>
<span class="re0">$success</span> <span class="sy0">=</span> <span class="re0">$tweet</span><span class="sy0">-&gt;</span><span class="me1">updateStatus</span><span class="br0">&#40;</span><span class="br0">&#41;</span><span class="sy0">;</span>
<span class="kw1">if</span> <span class="br0">&#40;</span><span class="re0">$success</span><span class="br0">&#41;</span> <span class="br0">&#123;</span>
    <span class="kw3">echo</span> <span class="st_h">'Twitter updated!'</span><span class="sy0">;</span>
<span class="br0">&#125;</span> <span class="kw1">else</span> <span class="br0">&#123;</span>
    <span class="kw3">echo</span> <span class="st_h">'Hmm, an error...'</span><span class="sy0">;</span>
<span class="br0">&#125;</span></pre></div></div>




<p>The class will retrieve each new update from the specified text file. Each update needs to be on a new line; an example text file:</p>


<div class="wp_syntax"><div class="code"><pre class="text" style="font-family:monospace;">Blah blah blah, this is the first update...
And another update!
Third and last update!!! ARGH!</pre></div></div>




<p>The PHP class will remove each update from this file when it&#8217;s added to Twitter so all you need to do is keep adding to the bottom of the file&#8230;</p>

<p>This won&#8217;t do the dripping automatically. You&#8217;ll need to setup a &#8216;cron job&#8217; to request the script at selected intervals (e.g. every two hours). I&#8217;m rubbish at Apache and anything to do with the command line so I haven&#8217;t quite accomplished this part yet&#8230; maybe someone else wants to give it a go? <img src='http://james.padolsey.com/wp-includes/images/smilies/icon_wink.gif' alt=';)' class='wp-smiley' /> </p>]]></content:encoded>
			<wfw:commentRss>http://james.padolsey.com/twitter/tweetfromfile-php-class/feed/</wfw:commentRss>
		<slash:comments>5</slash:comments>
		</item>
		<item>
		<title>Getting the real time in JavaScript</title>
		<link>http://james.padolsey.com/javascript/getting-the-real-time-in-javascript/</link>
		<comments>http://james.padolsey.com/javascript/getting-the-real-time-in-javascript/#comments</comments>
		<pubDate>Thu, 29 Jan 2009 00:03:51 +0000</pubDate>
		<dc:creator>James</dc:creator>
				<category><![CDATA[Code Snippets]]></category>
		<category><![CDATA[JavaScript]]></category>
		<category><![CDATA[News]]></category>
		<category><![CDATA[PHP]]></category>
		<category><![CDATA[Usability]]></category>
		<category><![CDATA[jQuery]]></category>
		<category><![CDATA[Mootools]]></category>
		<category><![CDATA[Time]]></category>

		<guid isPermaLink="false">http://james.padolsey.com/?p=477</guid>
		<description><![CDATA[Getting the time in JavaScript is pretty simple. Using the <a href="https://developer.mozilla.org/en/Core_JavaScript_1.5_Reference/Global_Objects/Date">Date</a> constructor will give us the time as set on the user's computer, but what if we want the accurate time, or the time in a different timezone?]]></description>
			<content:encoded><![CDATA[<p>Getting the time in JavaScript is pretty simple. Using the <a href="https://developer.mozilla.org/en/Core_JavaScript_1.5_Reference/Global_Objects/Date">Date</a> constructor will give us the time as set on the user&#8217;s computer, but what if we want the accurate time, or the time in a different timezone?</p>

<p>Even with <a href="https://developer.mozilla.org/en/Core_JavaScript_1.5_Reference/Global_Objects/Date/getTimezoneOffset"><code>getTimezoneOffset()</code></a> you&#8217;re still relying on the client!</p>

<p>It turns out that the only way of getting a complete and accurate time from any timezone requires a little bit of server interaction. Luckily there are a few APIs out there that offer this service (actually, there&#8217;s only one; well I couldn&#8217;t find any others)! </p>

<p>Here we&#8217;re using the <a href="http://simonwillison.net/2008/Jun/21/jsontime/">&#8216;json-time&#8217; API developed by Simon Willson</a>:</p>


<h2>JSON-time</h2>


<div class="wp_syntax"><div class="code"><pre class="javascript" style="font-family:monospace;"><span class="kw2">function</span> getTime<span class="br0">&#40;</span>zone<span class="sy0">,</span> success<span class="br0">&#41;</span> <span class="br0">&#123;</span>
    <span class="kw2">var</span> url <span class="sy0">=</span> <span class="st0">'http://json-time.appspot.com/time.json?tz='</span> <span class="sy0">+</span> zone<span class="sy0">,</span>
        ud <span class="sy0">=</span> <span class="st0">'json'</span> <span class="sy0">+</span> <span class="br0">&#40;</span><span class="sy0">+</span><span class="kw2">new</span> Date<span class="br0">&#40;</span><span class="br0">&#41;</span><span class="br0">&#41;</span><span class="sy0">;</span>
    window<span class="br0">&#91;</span>ud<span class="br0">&#93;</span><span class="sy0">=</span> <span class="kw2">function</span><span class="br0">&#40;</span>o<span class="br0">&#41;</span><span class="br0">&#123;</span>
        success <span class="sy0">&amp;&amp;</span> success<span class="br0">&#40;</span><span class="kw2">new</span> Date<span class="br0">&#40;</span>o.<span class="me1">datetime</span><span class="br0">&#41;</span><span class="sy0">,</span> o<span class="br0">&#41;</span><span class="sy0">;</span>
    <span class="br0">&#125;</span><span class="sy0">;</span>
    document.<span class="me1">getElementsByTagName</span><span class="br0">&#40;</span><span class="st0">'head'</span><span class="br0">&#41;</span><span class="br0">&#91;</span><span class="nu0">0</span><span class="br0">&#93;</span>.<span class="me1">appendChild</span><span class="br0">&#40;</span><span class="br0">&#40;</span><span class="kw2">function</span><span class="br0">&#40;</span><span class="br0">&#41;</span><span class="br0">&#123;</span>
        <span class="kw2">var</span> s <span class="sy0">=</span> document.<span class="me1">createElement</span><span class="br0">&#40;</span><span class="st0">'script'</span><span class="br0">&#41;</span><span class="sy0">;</span>
        s.<span class="me1">type</span> <span class="sy0">=</span> <span class="st0">'text/javascript'</span><span class="sy0">;</span>
        s.<span class="me1">src</span> <span class="sy0">=</span> url <span class="sy0">+</span> <span class="st0">'&amp;callback='</span> <span class="sy0">+</span> ud<span class="sy0">;</span>
        <span class="kw1">return</span> s<span class="sy0">;</span>
    <span class="br0">&#125;</span><span class="br0">&#41;</span><span class="br0">&#40;</span><span class="br0">&#41;</span><span class="br0">&#41;</span><span class="sy0">;</span>
<span class="br0">&#125;</span></pre></div></div>




<h2>Usage</h2>

<p>The first parameter of the callback function is the time (having been passed through the Date constructor), so you can use <a href="https://developer.mozilla.org/en/Core_JavaScript_1.5_Reference/Global_Objects/Date#Methods_2">Date methods</a> such as <code>getSeconds()</code> etc. The second parameter is the entire object returned from the JSON request.</p>


<div class="wp_syntax"><div class="code"><pre class="javascript" style="font-family:monospace;"><span class="co1">// Alert GMT:</span>
getTime<span class="br0">&#40;</span><span class="st0">'GMT'</span><span class="sy0">,</span> <span class="kw2">function</span><span class="br0">&#40;</span>time<span class="br0">&#41;</span><span class="br0">&#123;</span>
    <span class="kw3">alert</span><span class="br0">&#40;</span>time<span class="br0">&#41;</span><span class="sy0">;</span>
<span class="br0">&#125;</span><span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp;
<span class="co1">// Get London time, and format it:</span>
getTime<span class="br0">&#40;</span><span class="st0">'Europe/London'</span><span class="sy0">,</span> <span class="kw2">function</span><span class="br0">&#40;</span>time<span class="br0">&#41;</span><span class="br0">&#123;</span>
    <span class="kw2">var</span> formatted <span class="sy0">=</span> time.<span class="me1">getHours</span><span class="br0">&#40;</span><span class="br0">&#41;</span> <span class="sy0">+</span> <span class="st0">':'</span> 
                  <span class="sy0">+</span> time.<span class="me1">getMinutes</span><span class="br0">&#40;</span><span class="br0">&#41;</span> <span class="sy0">+</span> <span class="st0">':'</span>
                  <span class="sy0">+</span> time.<span class="me1">getSeconds</span><span class="br0">&#40;</span><span class="br0">&#41;</span><span class="sy0">;</span>
    <span class="kw3">alert</span><span class="br0">&#40;</span> <span class="st0">'The time in London is '</span> <span class="sy0">+</span> formatted <span class="br0">&#41;</span><span class="sy0">;</span>
<span class="br0">&#125;</span><span class="br0">&#41;</span><span class="sy0">;</span></pre></div></div>




<p>For reference, here&#8217;s <a href="http://json-time.appspot.com/timezones.json">a list of all the available timezones</a> (to use one, remove the backslash).</p>

<h2>jQuery version</h2>


<div class="wp_syntax"><div class="code"><pre class="javascript" style="font-family:monospace;">$.<span class="me1">getTime</span> <span class="sy0">=</span> <span class="kw2">function</span><span class="br0">&#40;</span>zone<span class="sy0">,</span> success<span class="br0">&#41;</span> <span class="br0">&#123;</span>
    <span class="kw2">var</span> url <span class="sy0">=</span> <span class="st0">'http://json-time.appspot.com/time.json?tz='</span>
            <span class="sy0">+</span> zone <span class="sy0">+</span> <span class="st0">'&amp;callback=?'</span><span class="sy0">;</span>
    $.<span class="me1">getJSON</span><span class="br0">&#40;</span>url<span class="sy0">,</span> <span class="kw2">function</span><span class="br0">&#40;</span>o<span class="br0">&#41;</span><span class="br0">&#123;</span>
        success <span class="sy0">&amp;&amp;</span> success<span class="br0">&#40;</span><span class="kw2">new</span> Date<span class="br0">&#40;</span>o.<span class="me1">datetime</span><span class="br0">&#41;</span><span class="sy0">,</span> o<span class="br0">&#41;</span><span class="sy0">;</span>
    <span class="br0">&#125;</span><span class="br0">&#41;</span><span class="sy0">;</span>
<span class="br0">&#125;</span><span class="sy0">;</span>
&nbsp;
<span class="co1">// Usage:</span>
$.<span class="me1">getTime</span><span class="br0">&#40;</span><span class="st0">'GMT'</span><span class="sy0">,</span> <span class="kw2">function</span><span class="br0">&#40;</span>time<span class="br0">&#41;</span><span class="br0">&#123;</span>
    <span class="kw3">alert</span><span class="br0">&#40;</span>time<span class="br0">&#41;</span><span class="sy0">;</span>
<span class="br0">&#125;</span><span class="br0">&#41;</span><span class="sy0">;</span></pre></div></div>




<h2>MooTools version</h2>

<p>You&#8217;ll need to download the <a href="http://www.clientcide.com/docs/Request/JsonP">JsonP class</a>.</p>


<div class="wp_syntax"><div class="code"><pre class="javascript" style="font-family:monospace;"><span class="kw2">function</span> getTime<span class="br0">&#40;</span>zone<span class="sy0">,</span> success<span class="br0">&#41;</span> <span class="br0">&#123;</span>
    <span class="kw2">var</span> url <span class="sy0">=</span> <span class="st0">'http://json-time.appspot.com/time.json'</span><span class="sy0">;</span>
    <span class="kw2">new</span> JsonP<span class="br0">&#40;</span>url<span class="sy0">,</span> <span class="br0">&#123;</span>
        data<span class="sy0">:</span> <span class="br0">&#123;</span> tz<span class="sy0">:</span> zone <span class="br0">&#125;</span><span class="sy0">,</span>
        onComplete<span class="sy0">:</span> <span class="kw2">function</span><span class="br0">&#40;</span>o<span class="br0">&#41;</span><span class="br0">&#123;</span>
            success <span class="sy0">&amp;&amp;</span> success<span class="br0">&#40;</span><span class="kw2">new</span> Date<span class="br0">&#40;</span>o.<span class="me1">datetime</span><span class="br0">&#41;</span><span class="sy0">,</span> o<span class="br0">&#41;</span><span class="sy0">;</span>
        <span class="br0">&#125;</span>
    <span class="br0">&#125;</span><span class="br0">&#41;</span>.<span class="me1">request</span><span class="br0">&#40;</span><span class="br0">&#41;</span><span class="sy0">;</span>
<span class="br0">&#125;</span>
&nbsp;
<span class="co1">// Usage:</span>
getTime<span class="br0">&#40;</span><span class="st0">'GMT'</span><span class="sy0">,</span> <span class="kw2">function</span><span class="br0">&#40;</span>time<span class="br0">&#41;</span><span class="br0">&#123;</span>
    <span class="kw3">alert</span><span class="br0">&#40;</span>time<span class="br0">&#41;</span><span class="sy0">;</span>
<span class="br0">&#125;</span><span class="br0">&#41;</span><span class="sy0">;</span></pre></div></div>




<p>Thank you <a href="http://simonwillison.net/">Simon Willison</a> for making this API; seriously, I searched around the entire internets just for one damn API and I almost lost hope!</p>]]></content:encoded>
			<wfw:commentRss>http://james.padolsey.com/javascript/getting-the-real-time-in-javascript/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>Preloading images from a directory</title>
		<link>http://james.padolsey.com/javascript/preloading-images-from-a-directory/</link>
		<comments>http://james.padolsey.com/javascript/preloading-images-from-a-directory/#comments</comments>
		<pubDate>Wed, 07 Jan 2009 00:23:42 +0000</pubDate>
		<dc:creator>James</dc:creator>
				<category><![CDATA[Code Snippets]]></category>
		<category><![CDATA[JavaScript]]></category>
		<category><![CDATA[PHP]]></category>
		<category><![CDATA[Images]]></category>
		<category><![CDATA[JSON]]></category>
		<category><![CDATA[JSONP]]></category>
		<category><![CDATA[Preloading]]></category>

		<guid isPermaLink="false">http://james.padolsey.com/?p=374</guid>
		<description><![CDATA[Here's a very handy script which will scan through a directory of images, form an array of the contents of that directory and then return the array in JSON format to the client-side where the images will be preloaded into the user's cache. (Basically, it's a fancy preloader)]]></description>
			<content:encoded><![CDATA[<p>Here&#8217;s a very handy script which will scan through a directory of images, form an array of the contents of that directory and then return the array in JSON format to the client-side where the images will be preloaded into the user&#8217;s cache.</p>

<p>There are two components to this: the PHP script and some simple JavaScript:</p>

<span id="more-374"></span>

<h2>The Code (PHP):</h2>


<div class="wp_syntax"><div class="code"><pre class="php" style="font-family:monospace;"><span class="coMULTI">/* PHP file, e.g. scanImageDirectory.json.php */</span>
&nbsp;
<span class="co1">// Check that a callback function has been specified:</span>
<span class="kw1">if</span> <span class="br0">&#40;</span><span class="sy0">!</span><span class="kw3">isset</span><span class="br0">&#40;</span><span class="re0">$_GET</span><span class="br0">&#91;</span><span class="st_h">'callback'</span><span class="br0">&#93;</span><span class="br0">&#41;</span> <span class="sy0">||</span> <span class="sy0">!</span><span class="kw3">isset</span><span class="br0">&#40;</span><span class="re0">$_GET</span><span class="br0">&#91;</span><span class="st_h">'directory'</span><span class="br0">&#93;</span><span class="br0">&#41;</span><span class="br0">&#41;</span> <span class="kw3">exit</span><span class="sy0">;</span>
&nbsp;
<span class="co1">// Use PHP5's scandir function to scan all</span>
<span class="co1">// of images directory:</span>
<span class="re0">$dirContents</span> <span class="sy0">=</span> scandir<span class="br0">&#40;</span><span class="re0">$_GET</span><span class="br0">&#91;</span><span class="st_h">'directory'</span><span class="br0">&#93;</span><span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp;
<span class="co1">// Define function to confirm each</span>
<span class="co1">// filename is a valid image name/extension:</span>
<span class="kw2">function</span> isImageFile<span class="br0">&#40;</span><span class="re0">$src</span><span class="br0">&#41;</span> <span class="br0">&#123;</span>
    <span class="kw1">return</span> <span class="kw3">preg_match</span><span class="br0">&#40;</span><span class="st_h">'/^.+\.(gif|png|jpe?g|bmp|tif)$/i'</span><span class="sy0">,</span> <span class="re0">$src</span><span class="br0">&#41;</span><span class="sy0">;</span>
<span class="br0">&#125;</span>
&nbsp;
<span class="co1">// Loop through directory files and add to</span>
<span class="co1">// $arrayContents on each iteration:</span>
<span class="re0">$arrayContents</span> <span class="sy0">=</span> <span class="st_h">''</span><span class="sy0">;</span>
<span class="kw1">foreach</span><span class="br0">&#40;</span><span class="re0">$dirContents</span> <span class="kw1">as</span> <span class="re0">$image</span><span class="br0">&#41;</span> <span class="br0">&#123;</span>
    <span class="kw1">if</span> <span class="br0">&#40;</span>isImageFile<span class="br0">&#40;</span><span class="re0">$image</span><span class="br0">&#41;</span><span class="br0">&#41;</span> <span class="br0">&#123;</span>
        <span class="re0">$arrayContents</span> <span class="sy0">.=</span> <span class="sy0">!</span><span class="kw3">empty</span><span class="br0">&#40;</span><span class="re0">$arrayContents</span><span class="br0">&#41;</span> ? <span class="st_h">','</span> <span class="sy0">:</span> <span class="st_h">''</span><span class="sy0">;</span>
        <span class="re0">$arrayContents</span> <span class="sy0">.=</span> <span class="st_h">'&quot;'</span> <span class="sy0">.</span> <span class="st_h">'images/'</span> <span class="sy0">.</span> <span class="re0">$image</span> <span class="sy0">.</span> <span class="st_h">'&quot;'</span><span class="sy0">;</span>
    <span class="br0">&#125;</span>
<span class="br0">&#125;</span>
&nbsp;
<span class="co1">// Prepate JSON(P) output</span>
<span class="re0">$output</span> <span class="sy0">=</span> <span class="re0">$_GET</span><span class="br0">&#91;</span><span class="st_h">'callback'</span><span class="br0">&#93;</span> <span class="sy0">.</span> <span class="st_h">'({\'</span>images\<span class="st_h">':['</span> <span class="sy0">.</span> <span class="re0">$arrayContents</span> <span class="sy0">.</span> <span class="st_h">']});'</span><span class="sy0">;</span>
&nbsp;
<span class="co1">// Output the output:</span>
<span class="kw3">echo</span> <span class="re0">$output</span><span class="sy0">;</span></pre></div></div>




<p>The above PHP script will use PHP5&#8242;s <code><a href="http://uk3.php.net/scandir">scandir</a></code> to scan the &#8216;images&#8217; directory and it outputs a list of all images in JSON format. (so it can be used by our JavaScript). The JavaScript is below:</p>


<h2>The Code (JavaScript):</h2>


<div class="wp_syntax"><div class="code"><pre class="javascript" style="font-family:monospace;"><span class="coMULTI">/* JavaScript Component */</span>
&nbsp;
<span class="kw2">function</span> preloadImagesFromDirectory<span class="br0">&#40;</span>dir<span class="br0">&#41;</span> <span class="br0">&#123;</span>
&nbsp;
    <span class="kw1">if</span><span class="br0">&#40;</span><span class="sy0">!</span>dir<span class="br0">&#41;</span> <span class="kw1">return</span><span class="sy0">;</span>
&nbsp;
    <span class="kw2">function</span> getJSON<span class="br0">&#40;</span>URL<span class="sy0">,</span>success<span class="br0">&#41;</span><span class="br0">&#123;</span>
&nbsp;
        <span class="co1">// Create new function (within global namespace)</span>
        <span class="co1">// (With unique name):</span>
        <span class="kw2">var</span> uniqueID <span class="sy0">=</span> <span class="st0">'json'</span><span class="sy0">+</span><span class="br0">&#40;</span><span class="sy0">+</span><span class="br0">&#40;</span><span class="kw2">new</span> Date<span class="br0">&#40;</span><span class="br0">&#41;</span><span class="br0">&#41;</span><span class="br0">&#41;</span><span class="sy0">;</span>
            window<span class="br0">&#91;</span>uniqueID<span class="br0">&#93;</span> <span class="sy0">=</span> <span class="kw2">function</span><span class="br0">&#40;</span>data<span class="br0">&#41;</span><span class="br0">&#123;</span>
                success <span class="sy0">&amp;&amp;</span> success<span class="br0">&#40;</span>data<span class="br0">&#41;</span><span class="sy0">;</span>
            <span class="br0">&#125;</span><span class="sy0">;</span>
&nbsp;
        <span class="co1">// Append new SCRIPT element to DOM:</span>
        document.<span class="me1">getElementsByTagName</span><span class="br0">&#40;</span><span class="st0">'body'</span><span class="br0">&#41;</span><span class="br0">&#91;</span><span class="nu0">0</span><span class="br0">&#93;</span>.<span class="me1">appendChild</span><span class="br0">&#40;</span><span class="br0">&#40;</span><span class="kw2">function</span><span class="br0">&#40;</span><span class="br0">&#41;</span><span class="br0">&#123;</span>
            <span class="kw2">var</span> script <span class="sy0">=</span> document.<span class="me1">createElement</span><span class="br0">&#40;</span><span class="st0">'script'</span><span class="br0">&#41;</span><span class="sy0">;</span>
            script.<span class="me1">type</span> <span class="sy0">=</span> <span class="st0">'text/javascript'</span><span class="sy0">;</span>
            script.<span class="me1">src</span> <span class="sy0">=</span> URL.<span class="me1">replace</span><span class="br0">&#40;</span><span class="st0">'callback=?'</span><span class="sy0">,</span><span class="st0">'callback='</span> <span class="sy0">+</span> uniqueID<span class="br0">&#41;</span><span class="sy0">;</span>
            <span class="kw1">return</span> script<span class="sy0">;</span>
        <span class="br0">&#125;</span><span class="br0">&#41;</span><span class="br0">&#40;</span><span class="br0">&#41;</span><span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp;
    <span class="br0">&#125;</span>
&nbsp;
    <span class="kw2">function</span> preload<span class="br0">&#40;</span>srcArray<span class="br0">&#41;</span> <span class="br0">&#123;</span>
        <span class="kw1">for</span><span class="br0">&#40;</span><span class="kw2">var</span> i <span class="sy0">=</span> <span class="nu0">0</span><span class="sy0">;</span> i <span class="sy0">&lt;</span> srcArray.<span class="me1">length</span><span class="sy0">;</span> i<span class="sy0">++</span><span class="br0">&#41;</span> <span class="br0">&#123;</span>
            <span class="br0">&#40;</span><span class="kw2">new</span> Image<span class="br0">&#40;</span><span class="br0">&#41;</span><span class="br0">&#41;</span>.<span class="me1">src</span> <span class="sy0">=</span> srcArray<span class="br0">&#91;</span>i<span class="br0">&#93;</span><span class="sy0">;</span>
        <span class="br0">&#125;</span>
    <span class="br0">&#125;</span>
&nbsp;
    <span class="co1">// Get that JSON data:</span>
    getJSON<span class="br0">&#40;</span><span class="st0">'scanImageDirectory.php?directory='</span> <span class="sy0">+</span> encodeURIComponent<span class="br0">&#40;</span>dir<span class="br0">&#41;</span> <span class="sy0">+</span> <span class="st0">'&amp;callback=?'</span><span class="sy0">,</span> <span class="kw2">function</span><span class="br0">&#40;</span>data<span class="br0">&#41;</span><span class="br0">&#123;</span>
        <span class="kw1">return</span> data.<span class="me1">images</span> <span class="sy0">?</span> preload<span class="br0">&#40;</span> data.<span class="me1">images</span> <span class="br0">&#41;</span> <span class="sy0">:</span> <span class="kw2">false</span><span class="sy0">;</span>
    <span class="br0">&#125;</span><span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp;
<span class="br0">&#125;</span></pre></div></div>




<p>The above JavaScript uses JSONP to load the PHP file into a SCRIPT element as if it were a JavaScript file itself, then the automatically generated function is fired which then executes the specified callback (&#8216;success&#8217;) function which is specified when calling <code>getJSON</code>. The callback then preloads the passed data (i.e. the array of images).</p>

<h2>Usage:</h2>


<div class="wp_syntax"><div class="code"><pre class="javascript" style="font-family:monospace;"><span class="co1">// We don't want to disturb anything so we'll wait</span>
<span class="co1">// until everything's done loading before preloading:</span>
window.<span class="kw3">onload</span> <span class="sy0">=</span> <span class="kw2">function</span><span class="br0">&#40;</span><span class="br0">&#41;</span><span class="br0">&#123;</span>
    preloadImagesFromDirectory<span class="br0">&#40;</span><span class="st0">'images/'</span><span class="br0">&#41;</span><span class="sy0">;</span>
<span class="br0">&#125;</span></pre></div></div>




<h2>Security concerns:</h2>

<p>Since the directory to be scanned is specified in a query string it would be VERY easy for ANYONE to gain information on your file structure/nomenclature. The regular expression used to validate the image names on the server-side (the PHP script) will stop any files from being listed that do not end in gif, png, jpg, jpeg, bmp or tif. If you&#8217;re still concerned then simply specify the directory to be scanned from within the PHP script instead of having it passed through the query string.</p>]]></content:encoded>
			<wfw:commentRss>http://james.padolsey.com/javascript/preloading-images-from-a-directory/feed/</wfw:commentRss>
		<slash:comments>9</slash:comments>
		</item>
	</channel>
</rss>

