<?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>Dark Crimson Blog</title>
	<atom:link href="http://blog.darkcrimson.com/feed/" rel="self" type="application/rss+xml" />
	<link>http://blog.darkcrimson.com</link>
	<description>The Blog of Ben Lister</description>
	<lastBuildDate>Fri, 13 Aug 2010 02:18:06 +0000</lastBuildDate>
	<generator>http://wordpress.org/?v=2.8.6</generator>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
			<item>
		<title>HTML5 / jQuery Slideshow</title>
		<link>http://blog.darkcrimson.com/2010/08/html5-jquery-slideshow/</link>
		<comments>http://blog.darkcrimson.com/2010/08/html5-jquery-slideshow/#comments</comments>
		<pubDate>Fri, 13 Aug 2010 02:11:00 +0000</pubDate>
		<dc:creator>Ben Lister</dc:creator>
				<category><![CDATA[HTML5]]></category>
		<category><![CDATA[contenteditable]]></category>
		<category><![CDATA[CSS3]]></category>
		<category><![CDATA[localStorage]]></category>

		<guid isPermaLink="false">http://blog.darkcrimson.com/?p=377</guid>
		<description><![CDATA[A few weeks ago, I wrote a jQuery slideshow app for a personal project. The slideshow ended up being more useful than I originally expected and I realized that it could be re-used in a many different applications with a little more work. Several days later, A List Apart launched &#8220;10K Apart: A contest to [...]]]></description>
			<content:encoded><![CDATA[<p>A few weeks ago, I wrote a jQuery slideshow app for a personal project. The slideshow ended up being more useful than I originally expected and I realized that it could be re-used in a many different applications with a little more work. Several days later, <a href="http://alistapart.com" target="_blank">A List Apart</a> launched &#8220;<a href="http://10k.aneventapart.com/" target="_blank">10K Apart: A contest to inspire the web in under 10k.</a>&#8221; When I first read about the contest my slideshow app came to mind so I decided to look into ways to make it work for the concept.<span id="more-377"></span></p>
<p>Originally, the content of the slides were entered manually to the HTML file but with the help of HTML5&#8217;s very handy <code>localStorage</code> and <code>contentEditable</code> features, I added the ability to create the slide content within the browser, saving it as it&#8217;s typed. Most conventional desktop slideshows rely on the mouse to add content and navigate which is slow and often frustrating. To avoid this pitfall and improve the work flow, I added simple keyboard commands to easily navigate (up and down arrows) and add / remove slides (ctrl+A / ctrl+D).</p>
<p>I plan to release the full source of this project and do a code walk through soon but in the meantime, you can <em>view and vote for the project</em> on the 10K Apart website:</p>
<p><a href="http://10k.aneventapart.com/Entry/143" class="view_source" style="margin:0 auto;float: none;" target="_blank">View the Project</a></p>
<div style="clear:both"></div>
<h3 class="blog_ttl">Features</h3>
<dl class="arrows">
<dt>→</dt>
<dd>Fully editable slides</dd>
<dt>→</dt>
<dd>Ability to quickly and easily Add / Remove slides</dd>
<dt>→</dt>
<dd>Persistent content (saved &#8220;on the fly&#8221; with <code>localStorage</code>)</dd>
<dt>→</dt>
<dd>Arrow key navigation</dd>
<dt>→</dt>
<dd>Two themes</dd>
<dt>→</dt>
<dd>Light weight (under 10k not including jQuery)</dd>
</dl>
<p></p>
<h3 class="blog_ttl">Technologies used</h3>
<dl class="arrows">
<dt>→</dt>
<dd><code>localStorage</code></dd>
<dt>→</dt>
<dd><code>contentEditable</code></dd>
<dt>→</dt>
<dd>CSS3 Radial Gradients</dd>
<dt>→</dt>
<dd>RGBa</dd>
<dt>→</dt>
<dd>Border Radius</dd>
<dt>→</dt>
<dd>Box Shadow</dd>
<dt>→</dt>
<dd>Text shadow</dd>
</dl>
<div style="clear:both"></div>
<p><a href="http://10k.aneventapart.com/Entry/143" class="view_source" style="margin:0 auto;float: none;" target="_blank">View the Project</a></p>
<div style="clear:both"></div>
]]></content:encoded>
			<wfw:commentRss>http://blog.darkcrimson.com/2010/08/html5-jquery-slideshow/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Getting Started with HTML5 Local Databases</title>
		<link>http://blog.darkcrimson.com/2010/05/local-databases/</link>
		<comments>http://blog.darkcrimson.com/2010/05/local-databases/#comments</comments>
		<pubDate>Mon, 17 May 2010 02:00:57 +0000</pubDate>
		<dc:creator>Ben Lister</dc:creator>
				<category><![CDATA[HTML5]]></category>
		<category><![CDATA[Database]]></category>
		<category><![CDATA[JavaScript]]></category>
		<category><![CDATA[jQuery]]></category>
		<category><![CDATA[Safari]]></category>
		<category><![CDATA[Webkit]]></category>

		<guid isPermaLink="false">http://blog.darkcrimson.com/?p=217</guid>
		<description><![CDATA[Starting with Safari 4, iPhone/iPad OS3, Chrome 5,  and Opera 10.5 (Desktop), HTML5 Local Databases are now supported. I&#8217;ve been reading about local databases for quite some time and decided to do a write up with some basic examples on how to get started.
Setting up the Database

function initDatabase() {
	try {
	    if [...]]]></description>
			<content:encoded><![CDATA[<p>Starting with Safari 4, iPhone/iPad OS3, Chrome 5,  and Opera 10.5 (Desktop), HTML5 Local Databases are now supported. I&#8217;ve been <a href="http://webkit.org/blog/126/webkit-does-html5-client-side-database-storage/" target="_blank">reading about local databases for quite some time</a> and decided to do a write up with some basic examples on how to get started.<span id="more-217"></span></p>
<h3 class="blog_ttl">Setting up the Database</h3>
<pre name="code" class="javascript">
function initDatabase() {
	try {
	    if (!window.openDatabase) {
	        alert('Databases are not supported in this browser.');
	    } else {
	        var shortName = 'DEMODB';
	        var version = '1.0';
	        var displayName = 'DEMO Database';
	        var maxSize = 100000; //  bytes
	        DEMODB = openDatabase(shortName, version, displayName, maxSize);
			createTables();
			selectAll();
	    }
	} catch(e) {

	    if (e == 2) {
	        // Version number mismatch.
	        console.log("Invalid database version.");
	    } else {
	        console.log("Unknown error "+e+".");
	    }
	    return;
	}
}
</pre>
<p>First we check if the browser supports the openDatabase method, is so we continue and define the database parameters:</p>
<ul class="in_post">
<li><code>shortName</code> is the DB name as it will be referred to by the browser and SQL</li>
<li><code>version</code> openDatabase version. 1.0 for this (<a href="http://developer.apple.com/safari/library/documentation/iPhone/Conceptual/SafariJSDatabaseGuide/UsingtheJavascriptDatabase/UsingtheJavascriptDatabase.html#//apple_ref/doc/uid/TP40007256-CH3-XSW1" target="_blank">more on that here</a>) </li>
<li><code>displayName</code> The full display name / description of the database</li>
<li><code>maxSize</code> This is max size in bytes is the size you expect the database to reach. This is essential for memory management purposes.</li>
</ul>
<p>Next, we call the <code>createTables();</code> function where the table is defined and pre-populated with initial data (optional).</p>
<h3 class="blog_ttl">Building the Table</h3>
<pre name="code" class="javascript">
function createTables(){
	DEMODB.transaction(
        function (transaction) {
        	transaction.executeSql('CREATE TABLE IF NOT EXISTS page_settings(id INTEGER NOT NULL PRIMARY KEY, fname TEXT NOT NULL,bgcolor TEXT NOT NULL, font TEXT, favcar TEXT);', [], nullDataHandler, errorHandler);
        }
    );
	prePopulate();
}
</pre>
<p>This basic function executes the <code>executeSql</code> method which runs as the <code>CREATE TABLE</code> query. The SQL syntax is based on <a href="http://sqlite.org/" target="_blank">SQLite</a> so it should feel familiar to many Web &#038; Mobile developers. For this demo, we are going to pre-populate the newly created <code>page_settings</code> table with some initial data:</p>
<pre name="code" class="javascript">
function prePopulate(){
	DEMODB.transaction(
	    function (transaction) {
		//Optional Starter Data when page is initialized
		var data = ['1','none','#B3B4EF','Helvetica','Porsche 911 GT3'];
		transaction.executeSql("INSERT INTO page_settings(id, fname, bgcolor, font, favcar) VALUES (?, ?, ?, ?, ?)", [data[0], data[1], data[2], data[3], data[4]]);
	    }
	);
}
</pre>
<p><em>Note: although we don&#8217;t really need a <abbr title="Primary Key">PK</abbr> for such a basic demo it will be there for future extensions and advancements.</em></p>
<p>Now the database is initialized, a table has been created and we have a row of default data inserted. Since the data is stored, you can now reload or page or close and reopen it and the data will remain. To visualize this in Safari, go to <em> Develop > Show Web Inspector > Databases tab</em> where you can view the database and its contents as they are added or changed. </p>
<h3 class="blog_ttl">Select the data</h3>
<p>After the initial page load the data is stored and we run the <code>selectAll()</code> function to get the data:</p>
<pre name="code" class="javascript">
function selectAll(){
	DEMODB.transaction(
	    function (transaction) {
	        transaction.executeSql("SELECT * FROM page_settings;", [],
                dataSelectHandler, errorHandler);
	    }
	);
}
</pre>
<p><em>The demo consists of only one row so we use <code>*</code> to grab everything from the database but please optimize your queries if you decide to use this example for your own projects.<br />
</em></p>
<pre name="code" class="javascript">
function dataSelectHandler(transaction, results){

	// Handle the results
    for (var i=0; i<results.rows.length; i++) {

    	var row = results.rows.item(i);
        var newFeature = new Object();

    	newFeature.fname   = row['fname'];
        newFeature.bgcolor = row['bgcolor'];
        newFeature.font    = row['font'];
        newFeature.favcar  = row['favcar'];

        $('body').css('background-color',newFeature.bgcolor);
        $('body').css('font-family',newFeature.font);
        $('#content').html('
<h4 id="your_car">Your Favorite Car is a '+ newFeature.favcar +'</h4>

');

        if(newFeature.fname != 'none') {
       		$('#greeting').html('Howdy-ho, '+ newFeature.fname+'!');
       		$('#fname').val(newFeature.fname);
        } 

       $('select#font_selection').find('option[value='+newFeature.font+']').attr('selected','selected');
       $('select#bg_color').find('option[value='+newFeature.bgcolor+']').attr('selected','selected');
       $('select#fav_car').find('option[value='+newFeature.favcar+']').attr('selected','selected');
    }

}
</pre>
<p>This function loops through our data and uses a bit of jQuery to apply the specific values to CSS properties on the DOM. Going further, we set the HTML form defaults based on data with the help of jQuery. </p>
<h3 class="blog_ttl">Making updates</h3>
<p>This function reads the form values, validates the <code>text</code> input and updates the database</p>
<pre name="code" class="javascript">
function updateSetting(){
	DEMODB.transaction(
	    function (transaction) {
	    	if($('#fname').val() != '') {
	    		var fname = $('#fname').val();
	    	} else {
	    		var fname = 'none';
	    	}
			var bg    = $('#bg_color').val();
			var font  = $('#font_selection').val();
			var car   = $('#fav_car').val();
	    	transaction.executeSql("UPDATE page_settings SET fname=?, bgcolor=?, font=?, favcar=? WHERE id = 1", [fname, bg, font, car]);
	    }
	);
		selectAll();
}
</pre>
<h3 class="blog_ttl">Dropping the table</h3>
<p>We could simply remove the row with a <code>DELETE</code> query but since we already check for the presence of data, it makes more sense to <code>DROP</code> the table:</p>
<pre name="code" class="javascript">
function dropTables(){
	DEMODB.transaction(
	    function (transaction) {
	    	transaction.executeSql("DROP TABLE page_settings;", [], nullDataHandler, errorHandler);
	    }
	);
	location.reload();
}
</pre>
<p>After the table is dropped, the page is refreshed which triggers the initial database setup procedures defined earlier. </p>
<h3 class="blog_ttl">The demo:</h3>
<p><a href="http://blog.darkcrimson.com/samples/localdb/" class="view_demo ext">View Demo</a><a href="http://blog.darkcrimson.com/samples/localdb/darkcrimson_localdb_demo.zip" class="view_source">Download Source</a></p>
<div style="clear:both"></div>
<h3 class="blog_ttl">Why should you use Local Databases?</h3>
<dl class="arrows">
<dt>→</dt>
<dd> They are fast, flexible and never expire. Developers can define the maximum size of the database and since all of the queries are run via JavaScript, no external server calls are required and unlike cookies and sessions, they persist until manually removed.</dd>
<dt>→</dt>
<dd> Unlike cookies and sessions, which are created on the server side and then stored in the browser, the information stored in a local database is truly local. </dd>
<dt>→</dt>
<dd> Safari and Opera&#8217;s local databases are based on <a href="http://sqlite.org/" target="_blank">SQLite</a> and are <a href="http://www.sqlite.org/faq.html#q6">threadsafe</a> which prevents multiple instances of the data from being opened concurrently. </dd>
<dt>→</dt>
<dd> iPhone and iPad OS support local databases through their Mobile Safari browsers, making this storage platform ideal for mobile web apps.
</dd>
<dt>→</dt>
<dd> From the UX perspective, the possibility of storing user and page settings and options locally, instantly  and securely without the out the need to make external server or server side database calls is incredible. Since the HTML5 is <a href="http://www.findmebyip.com/litmus/#target-selector" target="_blank">widely supported</a> in Webkit and Opera, there are nearly limitless possibilities for HTML5-based games and web apps. <br class="clearall "><br class="clearall "><br class="clearall ">
</dd>
</dl>
<div style="clear:both"></div>
<h3 class="blog_ttl">Why should you NOT use Local Databases?</h3>
<p>Local databases are a great way for you to simplify and improve your projects but they have a few obvious drawbacks:</p>
<dl class="arrows">
<dt>→</dt>
<dd> Limited cross-browser support in the current form. At the time of this article, Safari 4, iPhone / iPad OS3, Chrome 5 and Opera 10.5 (Desktop) are the only mainstream browsers with support.</dd>
<dt>→</dt>
<dd> Not ideal for sensitive information. Sure, JavaScript can do <a href="http://www.webtoolkit.info/javascript-md5.html" target="_blank">MD5</a> and <a href="http://www.webtoolkit.info/javascript-sha1.html" target="_blank">SHA1</a> hashing but if <a href="http://www.youtube.com/watch?v=96fAX0beduE" target="_blank">these guys</a> can crack the code while listening to KoЯn, how safe do you feel?</dd>
<dt>→</dt>
<dd> Even though SQLite has been around for 10 years now, Webkit / Opera support is <a href="http://webkit.org/blog/126/webkit-does-html5-client-side-database-storage" target="_blank">much newer</a> and has consequently seen less vetting from those who would want to steal your data.<br class="clearall "><br class="clearall "><br class="clearall "></dd>
</dl>
<div style="clear:both"></div>
<h3 class="blog_ttl">What about FireFox, Chrome and IE? </h3>
<dl class="arrows">
<dt>→</dt>
<dd> <strong>Firefox</strong> introduced support for <a href="https://developer.mozilla.org/en/DOM/Storage#localStorage" target="_blank">localStorage</a> in version 3.5 in the <code>key-value</code> pair format (similar to cookies and sessions) but has so far (<a href="http://weblogs.mozillazine.org/roc/archives/2010/06/not_implementin.html" target="_blank">and for the foreseeable future</a>) stayed away from the  SQL Database Storage model. More about that  <a href="http://hacks.mozilla.org/2009/06/localstorage/" target="_blank">here</a>, <a href="http://hacks.mozilla.org/2010/01/offline-web-applications/#comments" target="_blank">here</a> and <a href="http://blog.vlad1.com/2009/04/06/html5-web-storage-and-sql/" target="_blank">here</a></dd>
<dt>→</dt>
<dd><strong>Internet Explorer</strong> has offered persistent storage support since IE5.5 which they&#8217;ve termed <a href="http://msdn.microsoft.com/en-us/library/ms531424%28VS.85%29.aspx" target="_blank">userData Behavior</a>. This technique is very limited in features and has a maximum storage size of 128k per page. IE local storage <a href="http://msdn.microsoft.com/en-us/library/cc197062%28VS.85%29.aspx#_global" target="_blank">improved in IE8 with the introduction of localStorage</a>. Both IE local storage formats are <code>key-value</code> and there is currently no native local database support in IE&mdash;maybe in <a href="http://ie.microsoft.com/testdrive/" target="_blank">IE9?</a><br class="clearall "><br class="clearall "><br class="clearall "></dd>
<dt>→</dt>
<dd><span style="color:#8F8F8F;opacity:0.6">Prior to version 4, local database storage support in <strong>Chrome</strong> was limited to implimentaiton via the <a href="http://code.google.com/apis/gears/upcoming/api_database.html" target="_blank">Google Gears API</a>. Gears offers a very similar SQLite-based local storage component that works across most browsers including IE6+, FireFox, Opera and Safari. The Gears platform was created to let developers create web applications that can be used offline and also offers support for other features such as  Canvas, Desktop support and Geolocation. The downside is that users must install the Google Gears browser extension on their machine before they can access these features. Additionally, Gears requires developers to include a JavaScript file in their application in order to use Gears which makes it a less than ideal choice for the low-bandwidth mobile web application world. More on the Google Gears Database API <a href="http://code.google.com/apis/gears/api_database.html" target="_blank">here</a>.</span> </p>
<p><em><strong>*UPDATE*</strong></em> As January 2010 <strong>Chrome</strong> now offers full local database storage support natively in effort to move to a more standards-based approach. Gears is still being supported in its current form (no new development or further platform compatibility, though) for the time being.  More information on this change can be found <a href="http://gearsblog.blogspot.com/2010/02/hello-html5.html" target="_blank">here</a>. <em>(Thanks for the correction, <a href="http://catcubed.com" target="_blank">Colin</a>)</em>  </dd>
</dl>
<div style="clear:both"></div>
<h3 class="blog_ttl">Resources</h3>
<ul class="in_post">
<li><a href="http://developer.apple.com/safari/library/documentation/iPhone/Conceptual/SafariJSDatabaseGuide/UsingtheJavascriptDatabase/UsingtheJavascriptDatabase.html" target="_blank">Safari Reference Library: Using the JavaScript Database</a></li>
<li><a href="http://webkit.org/blog/126/webkit-does-html5-client-side-database-storage" target="_blank">WebKit Does HTML5 Client-side Database Storage</a></li>
<li><a href="http://weblogs.mozillazine.org/roc/archives/2010/06/not_implementin.html" target="_blank">MozillaZine Weblog: Not Implementing Features Is Hard</a></li>
</ul>
<p></p>
<ul class="in_post">
<li><a href="http://my.opera.com/core/blog/2010/03/03/persistent-client-side-storage-for-your-persistent-needs" target="_blank">Opera: Persistent client side storage for your persistent needs</a></li>
<li><a href="http://dev.opera.com/forums/topic/433221" target="_blank">Opera Web Storage: easier, more powerful client-side data storage</a></li>
</ul>
<p></p>
<ul class="in_post">
<li><a href="http://unlock.edina.ac.uk/mobile.html" target="_blank">Unlock data &#8211; mobile example</a></li>
<li><a href="http://girliemac.com/blog/2009/09/03/webkit-css-3d-local-db-demo/" target="_blank">Webkit CSS 3D + Local DB Demo </a></li>
<li><a href="http://webkit.org/demos/sticky-notes/index.html" target="_blank">Storage Notes Demo</a>
</ul>
<p><br class="clearall "><br class="clearall "></p>
<h3 class="blog_ttl">The demo:</h3>
<p><a href="http://blog.darkcrimson.com/samples/localdb/" class="view_demo ext">View Demo</a><a href="http://blog.darkcrimson.com/samples/localdb/darkcrimson_localdb_demo.zip" class="view_source">Download Source</a><br />
<br class="clearall "></p>
<p><br class="clearall "><br class="clearall "></p>
]]></content:encoded>
			<wfw:commentRss>http://blog.darkcrimson.com/2010/05/local-databases/feed/</wfw:commentRss>
		<slash:comments>50</slash:comments>
		</item>
		<item>
		<title>Practical CSS3 for Web Designers</title>
		<link>http://blog.darkcrimson.com/2010/04/practical-css3/</link>
		<comments>http://blog.darkcrimson.com/2010/04/practical-css3/#comments</comments>
		<pubDate>Sun, 25 Apr 2010 21:31:11 +0000</pubDate>
		<dc:creator>Ben Lister</dc:creator>
				<category><![CDATA[CSS3]]></category>
		<category><![CDATA[CSS3 Border Image]]></category>
		<category><![CDATA[Tutorials]]></category>

		<guid isPermaLink="false">http://blog.darkcrimson.com/?p=196</guid>
		<description><![CDATA[Designers have been using basic CSS3 techniques to enhance their designs for several years now, but cross-browser incompatibilities and lack of practical examples have slowed its progression in the mainstream design world. In this tutorial, I explore and demonstrate some of the more practical aspects of CSS3 and provide realistic examples, resources, advise and a [...]]]></description>
			<content:encoded><![CDATA[<p>Designers have been using basic CSS3 techniques to enhance their designs for several years now, but cross-browser incompatibilities and lack of practical examples have slowed its progression in the mainstream design world. In this tutorial, I explore and demonstrate some of the more practical aspects of CSS3 and provide realistic examples, resources, advise and a compatibility guide.</p>
<p><span id="more-196"></span></p>
<h3 class="blog_ttl">The demo page showcases a number of CSS3 techniques including:</h3>
<ul class="in_post">
<li>Gradients (Radial and Linear)</li>
<li>&#8220;Rounded&#8221; Border Images</li>
<li>Border Radius</li>
<li>Drop Shadows (Box and Text)</li>
<li>Transforms</li>
<li>Keyframe Animations</li>
<li>Transitions</li>
<li>Image Masking</li>
<li>:target Pseudo Selector</li>
<li>Multiple Backgrounds</li>
<li>CSS Columns</li>
</ul>
<h3 class="blog_ttl">Examples in the demo include:</h3>
<ul class="in_post">
<li>Image gallery with randomized CSS transitions (supplemented with jQuery)</li>
<li>Image-less 3D Bar Chart</li>
<li>Pure HTML / CSS Accordion links</li>
<li>Navigation with  CSS animated hover effects</li>
<li>jQuery powered &#8220;View Mode&#8221; with CSS3 visual enhancements</li>
</ul>
<p>
<strong><br />
 After exploring the demo use the &#8220;CSS View Mode&#8221; feature to see example code, my comments and suggested resources / examples for each example.</strong>
</p>
<h3 class="blog_ttl">The demo:</h3>
<p><a href="http://blog.darkcrimson.com/samples/css3/" class="view_demo ext">View Demo</a><a href="http://blog.darkcrimson.com/samples/css3/darkcrimson_css3_demo.zip" class="view_source">Download Source</a><br />
<br class="clearall "></p>
<h3 class="blog_ttl">Final thoughts</h3>
<p>Although the upcoming FireFox <a href="http://www.downloadsquad.com/2010/05/11/firefox-3-7-will-become-4-0-firefox-4-with-updated-gecko-co/" target="_blank">3.7/ 4.0</a> is <a href="https://developer.mozilla.org/en/CSS/-moz-transition" target="_blank">said to include support for CSS transitions</a>, you will need to use a Webkit browser for now to see some of the advanced examples. I recommend updating to the latest version for full support.  I designed this demo for Webkit, Firefox 3.6+ and Opera 10.5.3 and have intentionally used browser vendor prefixes accordingly.  There are, of course, other browsers which offer (limited) support of CSS3 properties but this demo is geared towards mainstream browsers (that is my way of saying don&#8217;t use IE on this demo).</p>
<div style="text-align: center; margin: 20px auto; width: 75%; padding: 8px; background: none repeat scroll 0% 0% rgb(79, 0, 0);"><strong>UPDATE 5/28/10:</strong> Added Opera support to demo page, see my comment from 5/28 below.</div>
]]></content:encoded>
			<wfw:commentRss>http://blog.darkcrimson.com/2010/04/practical-css3/feed/</wfw:commentRss>
		<slash:comments>19</slash:comments>
		</item>
		<item>
		<title>Set a Dynamic Width / Height on Fancybox</title>
		<link>http://blog.darkcrimson.com/2010/03/set-a-dynamic-width-height-on-fancybox/</link>
		<comments>http://blog.darkcrimson.com/2010/03/set-a-dynamic-width-height-on-fancybox/#comments</comments>
		<pubDate>Wed, 10 Mar 2010 02:55:56 +0000</pubDate>
		<dc:creator>Ben Lister</dc:creator>
				<category><![CDATA[jQuery]]></category>
		<category><![CDATA[AJAX]]></category>
		<category><![CDATA[Fancybox]]></category>
		<category><![CDATA[JavaScript]]></category>
		<category><![CDATA[Tutorial]]></category>

		<guid isPermaLink="false">http://blog.darkcrimson.com/?p=182</guid>
		<description><![CDATA[Fancybox is a powerful, lightweight jQuery based lightbox script that offers developers an impressive variety of content display options. I&#8217;ve used this script many times in the past (including my portfolio) and have never run into any  limitations in terms of functionality until a recent project required many lightboxes with varying sizes. Since the site [...]]]></description>
			<content:encoded><![CDATA[<p><a href="http://fancybox.net/">Fancybox</a> is a powerful, lightweight jQuery based lightbox script that offers developers an impressive variety of content display options. I&#8217;ve used this script many times in the past (including <a href="http://darkcrimson.com/portfolio" target="_blank">my portfolio</a>) and have never run into any  limitations in terms of functionality until a recent project required many lightboxes with varying sizes. <span id="more-182"></span>Since the site used Fancybox&#8217;s <code>iframe</code> functionality to display articles with custom-sized graphics and Fancybox&#8217;s API does not offer a dynamic size option I created a simple DOM based jQuery solution:</p>
<pre name="code" class="javascript">
    $('a.fb_dynamic').each(function(){
           var dWidth 	= parseInt($(this).attr('href').match(/width=[0-9]+/i)[0].replace('width=',''));
           var dHeight 	=  parseInt($(this).attr('href').match(/height=[0-9]+/i)[0].replace('height=',''));
			$(this).fancybox({
				'width':dWidth,
				'height':dHeight,
				'autoScale'     	: false,
				'transitionIn'		: 'elastic',
				'transitionOut'		: 'elastic',
				'type'			: 'iframe'
			});
      });
</pre>
<p>With this code in place Fancybox can be called by simply adding the class <code>fb_dynamic</code> and then specifying the width and height in the URL&#8217;s parameters:</p>
<pre name="code" class="html">
<a class="fb_dynamic" href="http://darkcrimson.com/?width=400&#038;height=300">Free iPods!!!!</a>
</pre>
<p><strong>Going one step further</strong>, if you need to make the Fancybox call from Flash (another feature not in the API) you can create a simple JavaScript function and make the call from your <code>SWF</code> or <code>AS</code> file:</p>
<pre name="code" class="javascript">
	/**************************************************************
	Call Fancybox from Flash with a Dynamic width and Height
		@w = integer [width]
     @h = integer [height]
     @u = string [url]
      example funtion call: flashFancybox(500,600,'http://darkcrimson.com')
	***************************************************************/
			function flashFancybox(w,h,u) {
			    var fbflash = $('a#fbflash');
                                fbflash.attr('href', u+ '?width=' + w + '&#038;height=' + h );
				fbflash.trigger('click');
			}
          $(function () {
              // Create dynamic link, change append location to change FB animation start point
	      $('#body').append(' <a href="javascript:void(0)" id="fbflash" class="fb_dynamic">&nbsp;</a>');
          });
</pre>
]]></content:encoded>
			<wfw:commentRss>http://blog.darkcrimson.com/2010/03/set-a-dynamic-width-height-on-fancybox/feed/</wfw:commentRss>
		<slash:comments>15</slash:comments>
		</item>
		<item>
		<title>jQuery XML Parser with Sorting and Filtering</title>
		<link>http://blog.darkcrimson.com/2010/01/jquery-xml-parser/</link>
		<comments>http://blog.darkcrimson.com/2010/01/jquery-xml-parser/#comments</comments>
		<pubDate>Mon, 11 Jan 2010 06:45:11 +0000</pubDate>
		<dc:creator>Ben Lister</dc:creator>
				<category><![CDATA[jQuery]]></category>
		<category><![CDATA[AJAX]]></category>
		<category><![CDATA[JavaScript]]></category>
		<category><![CDATA[Tutorial]]></category>
		<category><![CDATA[XML]]></category>

		<guid isPermaLink="false">http://blog.darkcrimson.com/?p=115</guid>
		<description><![CDATA[In early 2009, I experimented with XML based iPhone / Safari Mobile web app which used jQuery to parse and traverse multiple levels of nodes in an XML file and display the data. While that project never panned out, the core code has become quite useful in a number of professional and personal projects. This [...]]]></description>
			<content:encoded><![CDATA[<p>In early 2009, I <a title="(example was built *specifically* for Safari mobile)" href="http://darkcrimson.com/lab/itunes" target="_blank">experimented with XML based iPhone / Safari Mobile web app</a> which used jQuery to parse and traverse multiple levels of nodes in an XML file and display the data. While that project never panned out, the core code has become quite useful in a number of professional and personal projects. This tutorial provides working examples and demonstrates the concept of parsing and traversing an XML file with jQuery using AJAX.<span id="more-115"></span></p>
<div style="text-align:center;margin: 20px auto;width:75%;padding:8px; background:#4F0000"><strong>UPDATE 4/25/10</strong><br />Moved the XML data append outside of the loop to increase performance</div>
<p><a class="view_demo ext" href="http://blog.darkcrimson.com/samples/jquery-xml-parser">View Demo</a><a class="view_source" href="http://blog.darkcrimson.com/samples/jquery-xml-parser/jq_xml_parser.zip">Download Source</a><br />
<br class="clearall "/></p>
<h3 class="blog_ttl">The XML</h3>
<p>First, lets take a look at the XML structure:</p>
<pre name="code" class="javascript">
<?xml version="1.0" encoding="UTF-8"?>
<data>
	<entry date="1/08/10" cost="27" category="Mobile Phone Accessories">
		<name>
			<![CDATA[ iPhone Case]]&gt;
		</name>
		<description>
			<![CDATA[ Black Matte Finish, fits all 3G and 3Gs models. ]]&gt;
		</description>
	</entry>

</data>
</pre>
<p>In it&#8217;s most basic form, the XML file contains the main <code>&lt;data&gt;</code> node with subsequent <code>&lt;entry&gt;</code> nodes. Within each entry we are defining the meta data such as <code>&lt;date&gt;</code>, <code>&lt;cost&gt;</code> and <code>&lt;category&gt;</code>. Also within the entry are a <code>&lt;name&gt;</code> and <code>&lt;description&gt;</code> field which are wrapped in <a href="http://en.wikipedia.org/wiki/CDATA" target="_blank">CDATA</a> blocks that will allow us to use special characters and punctuation without compromising the validity of the XML file.</p>
<h3 class="blog_ttl">AJAX</h3>
<p>Using jQuery&#8217;s wonderfully simple AJAX method to make an <code>XMLHttpRequest</code>. The basic code for making the AJAX request for the example XML file shown below:</p>
<pre name="code" class="javascript">
$.ajax({
type: 'GET',
url: 'xml/data.xml',
dataType: 'xml',
success: function(xml_list) {</code>

var xmlArr = [];

$(xml_list).find('entry').each(function() {

	var xml_date      	= $(this).attr('date');
	var xml_cost 	  	= $(this).attr('cost');
	var xml_category  	= $(this).attr('category');

	var xml_name  	  	= $(this).find('name').text();
	var xml_description = $(this).find('description').text();
					  // Add matched items to an array
	xmlArr += '&lt;tr filterCriteria="';
	xmlArr += xml_cost;
	xmlArr += '"&gt;&lt;td&gt;';
	xmlArr += xml_date;
	xmlArr += '&lt;/td&gt;&lt;td class="xml_name"&gt;';
	xmlArr += xml_name;
	xmlArr += '&lt;/td&gt;&lt;td&gt;';
	xmlArr += xml_description;
	xmlArr += '&lt;/td&gt;&lt;td&gt;';
	xmlArr += xml_category;
	xmlArr += '&lt;/td&gt;&lt;td class="xml_cost"&gt;$';
	xmlArr += xml_cost;
	xmlArr += '&lt;/td&gt;&lt;/tr&gt;';

}); // end each loop

 //Append array to table (this way is much faster than doing this individually for each item)

	$(xmlArr).appendTo(wrapper +' table tbody');
</pre>
<p>The first two things to note in the code are the <code>dataType</code> and <code>success</code> parameters. We use <code>dataType</code> to specify that we are requesting an XML fie and using a function in <code>success</code> to manipulate and display the XML data. Next, we use jQuery&#8217;s super handy <code>find()</code> method to search the XML document for entry nodes. We then chain the <code>each()</code> function to iterate through the data that is returned from the <code>find()</code>. Next, variables are created for each of the items we will be displaying. Using variables as opposed to the selector name caches the data so that it is not called in each iteration. Note that there are two methods of assigning the variables in this example; the first simply assigns available attributes to the variables while the second has to traverse one step deeper to return the values of the name and description nodes.</p>
<h3 class="blog_ttl">Making it work</h3>
<p>At this point we&#8217;ve covered the basic concepts but it is time to actually do something practical with the data. Displaying the results in HTML is easy but while we&#8217;re writing the markup, lets add some placeholders for filtering the data.</p>
<pre name="code" class="javascript">
<div id="xml_wrapper">
<ul id="xml_nav">
<li><a class="filter_10" href="javascript:void(0)"><span>&lt; $10</span></a></li>
<li><a class="filter_10_20" href="javascript:void(0)"><span>$10 – $20</span></a></li>
<li><a class="filter_20" href="javascript:void(0)"><span>$20 +</span></a></li>
<li class="xml_nav_hit"><a class="filter_0 hit" href="javascript:void(0)"><span>Any price</span></a></li>
</ul>
<table border="0">
<thead>
<tr>
<th class="header headerSortUp">Date</th>
<th class="header">Name</th>
<th class="header">Description</th>
<th class="header">Category</th>
<th class="header">$</th>
</tr>
</thead>
<tbody></tbody>
</table>
</div>
</pre>
<p>Ignore the <code>&lt;UL&gt;</code> for now and notice that we are adding elements to the the <code>&lt;thead&gt;</code> but not the <code>&lt;tbody&gt;</code>. Jump back to the JavaScript file and add this line below the var declaration for <code>description</code> and add:</p>
<pre name="code" class="javascript">
$('&lt;tr filterCriteria= "'+ xml_cost +'"&gt;&lt;/tr&gt;')
.html('
<td>'+ xml_date  +'</td>
<td class="xml_name">'+ xml_name  +'</td>
<td>'+ xml_description  +'</td>
<td>'+ xml_category +'</td>
<td class="xml_cost">$'+ xml_cost  +'</td>

')
.appendTo(wrapper +' table tbody');
</pre>
<p>This line is in our loop so it will iterate a populated <code>&lt;tr&gt;</code> for each <code>entry</code> in our XML and append it to the <code>&lt;tbody&gt;&lt;/tbody&gt;</code> of the table.</p>
<h3 class="blog_ttl">Making it useful</h3>
<p>The parser is now built and displays the data from our XML file but it lacks practicality. What if you want to sort by Computer Accessories? What if you want to show all items less than $20?  These start to become serious issues as the length of the XML document increases.</p>
<p>We will cheat a little bit and tie in Christian Bach&#8217;s incredibly useful <a href="http://tablesorter.com/docs/" target="_blank">tablesorter jQuery plugin</a> to do the sorting in this example. I won&#8217;t go into detail on the options and uses of this plugin because they are already covered thoroughly on the <a href="http://tablesorter.com/docs/#Configuration" target="_blank">tablesorter plugin site</a>.</p>
<p>Filtering is done by simply using jQuery&#8217;s <code>hide()</code> and <code>show()</code> on specifically tagged table rows. We&#8217;ve already created the HTML in previous steps so all that is left is to assign a <code>onClick</code> event and add a switch to create the filter. To add sorting to the table we&#8217;ve created add the following after the <code>each()</code> function inside the AJAX call:</p>
<pre name="code" class="javascript"> window.setTimeout('$("'+ wrapper +' table").tablesorter({sortList:[[0,0],[0,0]], widgets: [\'zebra\']});', 120);</pre>
<p>The selector is wrapped in an interval because both the tablesorter script call and our AJAX call happen concurrently on page load which causes the tablesorter to fire before the table is fully populated with or XML. The 120ms on the interval is somewhat arbitrary and it can be changed as needed. Additionally, if you prefer not to use the interval, you might be able to do so depending on your particular use and XML file size. Also, note the use of the &#8220;zebra widget&#8221; option; this will assign a &#8220;stripe&#8221; class to odd numbered rows which allows for alternate row background colors. </p>
<pre name="code" class="javascript">var nav_link = $('#xml_nav li a');
nav_link.click( function() {
var tr = wrapper +' table tbody tr';
$(tr).show(); //Show all rows
switch ($(this).attr("class")) {
case  "filter_10 hit" :
$(tr).filter(function (index) {
return parseFloat($(this).attr('filterCriteria')) &gt; 10;
}).hide();
break;

case  "filter_10_20 hit" :
$(tr).filter(function (index) {
return parseFloat($(this).attr('filterCriteria')) &lt; 10 || parseFloat($(this).attr("filterCriteria")) &gt; 20  ;
}).hide();
break;

case  "filter_20 hit" :
$(tr).filter(function (index) {
return parseFloat($(this).attr('filterCriteria')) &lt; 20;
}).hide();

break;

case  "filter_0 hit" :
$(tr).show();
break;

}
/* Remove all instances of the stripe (alternating row) class
   Then re-apply stripe class as to visible alternating rows
*/
$(tr).removeClass('stripe');
$(tr + ':visible:odd').addClass('stripe');
});
</pre>
<p>In a previous step we generated the HTML that is inserted into our table and you might have noticed an attribute was added to the <code>cost</code> <code>&lt;td&gt;</code> called <code>filterCriteria</code>. The code above uses the value of this attribute to determine which items to show / hide. Obviously, this will only work if the value of cost is an integer. Feel free to develop a more elegant solution.</p>
<h3 class="blog_ttl">Finishing up</h3>
<p>The last step that I will cover is adding a simple preloader to display as AJAX grabs the XML data. At the top of the function place the following line:</p>
<pre name="code" class="javascript">
     $('
<div id="preload_xml"></div>

').html('<img src="images/ajax-loader.gif" alt="loading data" />
<h3>Loading Data...</h3>

').prependTo($('body'));
</pre>
<p>Inside of the <code>xml_parser()</code> function in the AJAX call&#8217;s <code>success</code> parameter place these two lines:</p>
<pre name="code" class="javascript">
$('#preload_xml').remove();
$(wrapper).show();</pre>
<p>Thes four lines of code will first hide our wrapper div and then dynamically construct a div with a loading message and then remove the code from the page once everything is loaded and finally show the wrapper again.</p>
<p>We now have a parser that sorts and filters XML data. There are many other features that could be added such as a more complex content filter and code cleanup to make things even more re-usable. If you find this code useful and decide to use it in your projects, I encourage you to modify the code as you find necessary and please feel free to share your examples.</p>
<h3 class="blog_ttl">Other Considerations</h3>
<p>There is a great jQuery XML parser plugin called <a title="jParse" href="http://jparse.kylerush.net/demo" target="_blank">jParse</a> which can be used to grab display the contents of an XML file with little effort. Other than the reliance on AJAX to call the XML file, the approach used by jParse differs considerably from the approach that I took in this article. If you are looking strictly for XML display, I recommend looking into jParse.</p>
<p><a class="view_demo ext" href="http://blog.darkcrimson.com/samples/jquery-xml-parser">View Demo</a><a class="view_source" href="http://blog.darkcrimson.com/samples/jquery-xml-parser/jq_xml_parser.zip">Download Source</a><br />
<br class="clearall "/></p>
]]></content:encoded>
			<wfw:commentRss>http://blog.darkcrimson.com/2010/01/jquery-xml-parser/feed/</wfw:commentRss>
		<slash:comments>26</slash:comments>
		</item>
		<item>
		<title>Practical tips for securing your WordPress blog</title>
		<link>http://blog.darkcrimson.com/2009/12/tips-for-securing-wordpress/</link>
		<comments>http://blog.darkcrimson.com/2009/12/tips-for-securing-wordpress/#comments</comments>
		<pubDate>Fri, 04 Dec 2009 02:27:36 +0000</pubDate>
		<dc:creator>Ben Lister</dc:creator>
				<category><![CDATA[WordPress]]></category>
		<category><![CDATA[.htaccess]]></category>
		<category><![CDATA[PHP]]></category>
		<category><![CDATA[Security]]></category>
		<category><![CDATA[XSS]]></category>

		<guid isPermaLink="false">http://blog.darkcrimson.com/?p=81</guid>
		<description><![CDATA[Wordpress is one of the the most commonly used and talked about blogging platforms on the internet. Because of this, it has gained the interest of bloggers, hackers and corporate marketing douche bags who wear too much cologne alike. A simple Google search will yield numerous guides offering WordPress security tips and while there is [...]]]></description>
			<content:encoded><![CDATA[<p>Wordpress is one of the the most commonly used and talked about blogging platforms on the internet. Because of this, it has gained the interest of bloggers, hackers and corporate marketing douche bags who wear too much cologne alike. A simple Google search will yield numerous guides offering WordPress security tips and while there is a lot great information out there, I&#8217;ve found that most are either focused on a single topic or contain outdated information. That is why I&#8217;ve created this guide serving not only an overview of <strong>practical methods</strong> for securing <strong>modern versions</strong> of WordPress but will also a more detailed look at why these procedures are actually relevant and necessary.<span id="more-81"></span></p>
<h3 class="blog_ttl">Introduction</h3>
<p>The Wordpress platform is fairly secure &#8220;out of the box&#8221; but because the deployment script has been simplified for ease of use, many things such as default usernames and paths are predetermined. While this is convenient, it also creates potential for attacks by hackers who can easily find your default administration pages with a basic search on most search engines.  You can see for yourself by searching Google with the following query:  <a href="http://www.google.com/search?hl=en&amp;q=inurl%3Awp-admin%3A+site%3Aus" target="_blank"><code>inurl:wp-admin: site:us</code></a> .  With just this basic example, the admin path to nearly 20,000 blogs is at your fingertips.</p>
<p>While this information alone is not enough to gain access your site, a hacker who has an exploit or a basic script to guess your password can potentially access your blog&#8217;s administration area without ever viewing your site. Below I&#8217;ve outlined a few of the most essential tips and additionally provided some insight on how to clean WordPress if your site once its been hacked.</p>
<h3 class="blog_ttl">Use random names for your Database and tables</h3>
<p>Throw in some random numbers or letters; it is going to be a much more difficult attack your site with malicious queries or XSS if the attacker cannot identify your DB name.</p>
<p>I&#8217;ve been working in WordPress for several years now and have not noticed significant changes in the table structure. Hackers know this and can write queries on your default <code>wp_posts</code> and <code>wp_comments</code> tables in their sleep. Even if your Database has a strong name, it is  a wasted effort if you do not use a unique table prefix. I suggest something completely random and meaningless containing both a number and letter.</p>
<h3 class="blog_ttl">Don&#8217;t use &#8220;WP_&#8221; as a table prefix</h3>
<p>Throw in some random numbers or letters; it is going to be a much more difficult to use XSS attacks since the hacker will have to work a lot harder to target your DB.</p>
<h3 class="blog_ttl">Rename the &#8216;admin&#8217; user</h3>
<p>Having a strong password will certainly reduce the chances of unauthorized access but since hackers know that the default account login is <em>admin </em>, they are already 50% of the way in.  Renaming the <em>admin</em> account can be difficult if not impossible to change from WordPress itself, so I recommend doing this directly from the database. Access your users table and simply rename the admin account to something harder to guess. It probably goes without saying but after you change the username, <em>don&#8217;t make your Nickname the same as your login.</em></p>
<h3 class="blog_ttl">Server Configuration</h3>
<p>Some hackers attempt to access WordPress through the admin interface which allows them full control of the content of your blog but what about the hackers who want to steal your traffic or install a prominent ad for &#8220;v1@gr@&#8221; on every page of your site?</p>
<p>Many exploits are aimed at the internal WordPress files which can potentially give the hacker complete control of not only your blog content but your <em>entire server.</em> Fortunately, blocking most of these attacks can be done with a few simple <code>.htaccess</code> tricks.</p>
<p>The majority of WP&#8217;s &#8220;guts&#8221; are located in the <em>wp-includes</em> and<em> wp-content</em> folders. I recommend placing an <code>.htaccess</code> similar to the one below in both the  <em>wp-includes</em> and<em> wp-content </em>directories. <em>Note:you might need to customize the &lt;files&gt; section depending on your plug-in requirements and WP version</em>.</p>
<pre name="code" class="php">
Order Allow,Deny
Deny from all
<Files ~ "\.(js|css|png|gif|jpg|jpeg)$">
 Allow from all
</Files>
</pre>
<p>This code will deter XSS attacks on your core PHP files and make it more difficult for hackers who do get into run malicious files that they&#8217;ve left in these directories in the future.</p>
<p>Another area in need of some <code>.htaccess</code> fun <em>wp-admin</em> folder. For this folder, we will require server authentication before accessing anything in the admin folder. To do this, create a <code>.htpasswd</code> file and then add create a <code>.htaccess </code>file with the code below (change AuthName and Require user fields as desired):</p>
<pre name="code" class="php">AuthType Basic
AuthName "Please insert coins to ride the Pony"
AuthUserFile /path/to/your/.htpasswd
Require user barbiegrrrl45453</pre>
<p>This type of authentication can be confusing to less technical users, more information can found <a href="http://www.htaccesstools.com/htaccess-authentication/" target="_blank">here</a> and I also recommend checking with your host as I&#8217;ve found that many major hosting companies have a &#8220;protect a directory&#8221; feature in their admin panels.</p>
<p>As a final &#8220;sledgehammer&#8221; method, <code>.htaccess </code>makes it  easy to block geographical areas from accessing your site all together. The basic syntax is show below and should be placed in the <code>.htaccess</code> located in the blog&#8217;s root directory (this file already exists so be careful not to remove any of the existing code)</p>
<pre name="code" class="php">order allow,deny
deny from 000.867.530.9
allow from all</pre>
<p>To block a specific country you can refer to the aptly named <a href="http://www.blockacountry.com/" target="_blank">BlockACountry.com</a> for a list of specific IP addresses. <em>Please note that by doing this, you are, in theory, blocking _EVERYONE_ from the specified country. This method can also increase page load times if the list is too long.</em></p>
<h3 class="blog_ttl">Have you already been hacked?</h3>
<p>Issues such as inability to login to your account, mysterious ads and comments and random errors are obvious signs of that something is wrong. But what if your site has been hacked without any visual signs?  These types hacks are typically the most frustrating and most difficult to check. The usual signs are HTML comments or  hidden / broken code with spam keywords and / or links.</p>
<p>This type of attack is usually done when a hacker gains access to your server and then modifies your WP files to generate the malicious code. It is important to catch these types of attacks as early as possible (and to monitor your files occasionally) because Google&#8217;s bots typically can detect the malicious code which will often get you marked as a &#8220;Malicious / Spyware&#8221; site or in some cases get your site blacklisted altogether .</p>
<p>The specific files targeted vary depending on the purpose of the attack but after dealing with several types of attacks in the past, the most common files are custom<strong> JavaScript</strong> files linked in the header (usually hacked to show ads or deceive the user by creating invisible links), <strong>index.php</strong> ( typically injected an <code>eval()</code> statement that generates HTML) and through the<strong> .htaccess</strong> located in the root directory (typically used to generate traffic to malware / ad sites). These are the first three places that I check when I investigate a hacked site but there is also a good chance that the hacker will leave an innocently named file such as a .jpg or .swf which contains a &#8220;an all access pass&#8221; to your server.</p>
<p>The other type of attack wherein the hacker gains unauthorized access to your database can usually be resolved much easier. With this type of attack you will be able to tell if anything is out of place with the <em>posts</em> or <em>comments </em>tables since these are published on your site but it is also very important to check the <em>users </em>and <em>options </em>tables for un-authorized users and suspicious entries.</p>
<p>If all else fails, back up your database and files and start with a fresh install and then add your theme files and data in small batches once you deem them clean. <a href="http://ocaoimh.ie/exploit-scanner/" target="_blank">There is also a  great plugin to check if your code has been hacked</a>.</p>
<h3 class="blog_ttl">Common Sense Messures</h3>
<p>Regarding user accounts, I suggest using this feature with caution.  At very least, accounts should require administrator approval. For those who are paranoid, you can always rename or remove the wp-register.php file (after you set up all of your accounts) so that no additional accounts can be created.</p>
<p>One of the easiest things you can do is make sure that the version if WordPress your site is running is the most current.  It can be tedious but it is the <em>most effective and easiest</em> way to protect your site. &lt;soapbox&gt;While I am a fan of WordPress, I am usually wary of choosing it as a CMS solution for my clients because of the potential for vulnerabilities in older versions. I suggest to anyone reading this who uses WordPress as a CMS on client projects to consider the potential issues and plan for (and perform!) routine upgrades accordingly.&lt;/soapbox&gt;</p>
<p>My last recommendation is to create a secret key in your <em>wp-config.php. </em>The secret key is a hashing salt which makes it more difficult for a hacker running a password hacking script to gain unauthorized access. Wordpress has a<a href="https://api.wordpress.org/secret-key/1.1/" target="_blank"> secret key generator</a> which I highly recommend using for this operation. Below is a SAMPLE key,<em> </em>please make sure to change it if you use it on your blog! <em>Note: the exact  implementation of these keys depends on your WordPress version. Since you&#8217;ve read this far down, I assume you have already upgraded or will be shortly, but <a href="http://codex.wordpress.org/Editing_wp-config.php" target="_blank">visit the entry in WordPress&#8217; Codex </a> for more information.<br />
</em></p>
<pre name="code" class="php">define('AUTH_KEY', ':dr+%/5V4sAUG-gg%aS*v;&amp;xGhd%{YKC^Z7KKGh j&gt;k[.Nf$y7iGKdJ3c*[Kr5Bg');
define('SECURE_AUTH_KEY', 'TufWOuA _.t&gt;#+hA?^|3RfGTm&gt;@*+S=8\"\'+\"}]&lt;2V^$T])=8Xh2a:b:}U_E');
define('NONCE_KEY', 'k1+EOc-&amp;w?hG8j84&gt;6L9v\"6C89NH?ui{*3\\(t09mumL/fFP_!K$JCEkLuy ={x{0');</pre>
<p><strong> If you have any questions, suggestions or corrections feel free to add them in the comments.</strong></p>
]]></content:encoded>
			<wfw:commentRss>http://blog.darkcrimson.com/2009/12/tips-for-securing-wordpress/feed/</wfw:commentRss>
		<slash:comments>3</slash:comments>
		</item>
		<item>
		<title>Mastering the Flickr API with PHP and cURL</title>
		<link>http://blog.darkcrimson.com/2009/11/mastering-the-flickr-api-with-php-and-curl/</link>
		<comments>http://blog.darkcrimson.com/2009/11/mastering-the-flickr-api-with-php-and-curl/#comments</comments>
		<pubDate>Sat, 28 Nov 2009 04:48:55 +0000</pubDate>
		<dc:creator>Ben Lister</dc:creator>
				<category><![CDATA[PHP]]></category>
		<category><![CDATA[API]]></category>
		<category><![CDATA[CURL]]></category>
		<category><![CDATA[Flickr]]></category>
		<category><![CDATA[Tutorials]]></category>

		<guid isPermaLink="false">http://blog.darkcrimson.com/?p=34</guid>
		<description><![CDATA[The Flickr API is a very powerful and easy to use way to put photos on your website without having to worry about bandwidth or server performance issues. This tutorial will cover how to make an API call for a photoset and then format and display a list of ~100px thumbnail images in unordered list.
Getting [...]]]></description>
			<content:encoded><![CDATA[<p>The <a href="http://www.flickr.com/services/api/" class="ext">Flickr API</a> is a very powerful and easy to use way to put photos on your website without having to worry about bandwidth or server performance issues. This tutorial will cover how to make an API call for a photoset and then format and display a list of ~100px thumbnail images in unordered list.<span id="more-34"></span></p>
<h3 class="blog_ttl">Getting An API Key</h3>
<p>To get started with the Flickr API, you need to sign into Flickr and <a href="http://www.flickr.com/services/apps/create/apply/" class="ext">Apply for an API key</a>. After you register for the API Key, you should browse through <a href="http://www.flickr.com/services/api/" target="_self">Flickr&#8217;s API page</a> to see some examples of what is possible. As you will see, there are quite a few methods listed which might seem a bit daunting. The nice thing is all of the provided methods are well documented and after one successful implementation, working through the rest is fairly repetitious.</p>
<h3 class="blog_ttl">Hot, Steamy PHP Action</h3>
<p>We will be using <a href="http://php.net/manual/en/book.curl.php" class="ext"><code>cURL</code></a> to get the data from Flickr. Some might prefer another method such as PHP&#8217;s <a href="http://php.net/manual/en/function.file-get-contents.php" class="ext"><code>file_get_contents</code></a>, there are advantages to both but you can read a book (or <a href="http://www.google.com/search?q=curl+vs+file_get_contents" class="ext">Google</a>) for more information on this.</p>
<p>Getting started with the cURL request:</p>
<pre name="code" class="php">$params = array(
	'api_key'	=&gt; 'XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX',
	'method'	=&gt; 'flickr.photosets.getPhotos',
	'photoset_id'	=&gt; '72157622566216264',
	'extras'	=> 'original_format',
	'format'	=&gt; 'php_serial'
);
$encoded_params = array();
foreach ($params as $k => $v){ $encoded_params[] = urlencode($k).'='.urlencode($v); }
</pre>
<p>In the code above we first put the API key and then choose the Method (which is listed on the Flickr API page link listed earlier in the tutorial). Next we specify the photo set id which for this example is the set seen in <a href="http://darkcrimson.com/portfolio" class="ext">my Portfolio</a>. The parameters for &#8220;Extras&#8221; depend on the Method used and desired options and range from date uploaded to author to tags. For this example we will be calling &#8220;original_format&#8221; which will pull a link to the full size version of the image. Finally, we choose &#8220;php_serial&#8221; as the format which will return a <a href="http://php.net/manual/en/function.serialize.php" class="ext">serialized</a> PHP string with the data (Alternatively you could use JSON but we can save that fun for a JavaScript tutorial).</p>
<p><em>Please note: </em>to use the &#8220;original_format&#8221; parameter you will need to be a <a href="http://www.flickr.com/upgrade/" class="ext">Flickr Pro</a> member.</p>
<pre name="code" class="php">$ch = curl_init();
$timeout = 5; // set to zero for no timeout
curl_setopt ($ch, CURLOPT_URL, 'http://api.flickr.com/services/rest/?'.implode('&amp;', $encoded_params));
curl_setopt ($ch, CURLOPT_RETURNTRANSFER, 1);
curl_setopt ($ch, CURLOPT_CONNECTTIMEOUT, $timeout);
$file_contents = curl_exec($ch);
curl_close($ch);

 $rsp_obj = unserialize($file_contents);</pre>
<p>The code above makes the cURL call to Flickr&#8217;s API with the data we set in the previous code block, <code>unserializes</code> the <code>cURL</code> object&#8217;s returned data and creates a new Array called <code>$rsp_obj.</code></p>
<p>Let&#8217;s pause and take a look at some of the data that was returned with a little <code>print_r($_rsp_ojb)</code> action:</p>
<pre name="code" class="php">Array
(
    [photoset] =&gt; Array
        (
            [id] =&gt; 72157622566216264
            [primary] =&gt; 4003748546
            [owner] =&gt; 7332638@N08
            [ownername] =&gt; benlister
            [photo] =&gt; Array
                (
                    [0] =&gt; Array
                        (
                            [id] =&gt; 4003748546
                            [secret] =&gt; 69b188c174
                            [server] =&gt; 2643
                            [farm] =&gt; 3
                            [title] =&gt; Chicago (Montrose Harbor)
                            [isprimary] =&gt; 1
                            [originalsecret] =&gt; 728e01b6c1
                            [originalformat] =&gt; jpg
                        )

                    [1] =&gt; Array
                        (
                            [id] =&gt; 4052220478
                            [secret] =&gt; ec5e79cbbe
                            [server] =&gt; 2780
                            [farm] =&gt; 3
                            [title] =&gt; Seattle Sci-Fi Museum Exterior
                            [isprimary] =&gt; 0
                            [originalsecret] =&gt; 625519fc32
                            [originalformat] =&gt; jpg
                        )

..............</pre>
<p>The array output above tells us pretty  everything we will need to create links to all sizes of each photo in the set. To display each photo in the photo set we first need to step into the <code>[photo]</code> section of  the <code>[photoset]</code> array.</p>
<pre name="code" class="php">if ($rsp_obj['stat'] == 'ok') {

		$photos = $rsp_obj["photoset"]["photo"];

	echo "
<ul>";

	foreach($photos as $photo) {

               $farm              = $photo['farm'];
               $server            = $photo['server'];
               $photo_id          = $photo['id'];
               $secret            = $photo['secret'];
               $photo_title       = $photo['title'];
<li><img /*SEE CODE BLOCK BELOW/* /></li>

	}
	  echo "</li>
</ul>

";

	} else {
            echo "Error getting photos";
       }</pre>
<p>     [note: the codeblock is not displaying the following img src line correctly in the line above so it has been moved below]</p>
<pre name="code" class="php">src="http://farm'.$photo['farm'].'.static.flickr.com/'.$photo['server'].'/'.$photo['id'].'_'.$photo['secret'].'_t.jpg" alt="'.$photo['title'].'"</pre>
<p>The code above first checks to see if the data was returned ok before trying to iterate through the array. Once we have verified that we have the data, we name the <code>[photo]</code> array more intuitively.</p>
<h3 class="blog_ttl">Putting it all together</h3>
<p>Let&#8217;s break down the URL piece by piece to better understand whats going on: For example if the URL is as follows:</p>
<p>http://farm<strong>3</strong>.static.flickr.com/<strong>2421</strong>/<strong>4002906997</strong>_<strong>5e9de854c6</strong>_<strong>t</strong>.jpg</p>
<ul>
<li>$photo["farm"] = 3</li>
<li>$photo["server"] = 2421</li>
<li>$photo["id"] = 4002906997</li>
<li>$photo["secret"] = 5e9de854c6</li>
<li>_s = 75px square thumbnail</li>
<li>_t = 100px thumbnail</li>
<li>_m = 240px thumbnail</li>
</ul>
<p><strong>To get the &#8220;normal&#8221; 500px image, use the sequence above minus the &#8220;underscore letter&#8221; ending.</strong></p>
<p><strong>To get the full &#8220;original size&#8221; takes a bit more work:</strong></p>
<p><strong><br />
</strong></p>
<pre name="code" class="php">src="http://farm'.$photo['farm'].'.static.flickr.com/'.$photo['server'].'/'.$photo['id'].'_'.$photo['originalsecret'].'_o.jpg"</pre>
<p><strong>UPDATE 7/10:</strong> I realized that I haven&#8217;t updated this in a while and wanted to share a much easier way to get the original full-size image:</p>
<pre name="code" class="php">
	// In the params array, replace:
	'extras'	=> 'original_format',

	// With:
	'extras'	=> 'url_o',

	//And to call the image:

	src="'.$photo['url_o'].'"
</pre>
<p>You should now be able to create a sample image page from a photo set in all sizes. You can also apply these principles to almost any of Flickr&#8217;s API Methods to achieve more customized results. Enjoy!</p>
<p><a class="view_tutorial ext" href="http://darkcrimson.com/flickr_example.php">View thumbnail Sample Page</a></p>
]]></content:encoded>
			<wfw:commentRss>http://blog.darkcrimson.com/2009/11/mastering-the-flickr-api-with-php-and-curl/feed/</wfw:commentRss>
		<slash:comments>9</slash:comments>
		</item>
		<item>
		<title>Site Redesign</title>
		<link>http://blog.darkcrimson.com/2009/11/site-redesign/</link>
		<comments>http://blog.darkcrimson.com/2009/11/site-redesign/#comments</comments>
		<pubDate>Tue, 24 Nov 2009 12:30:55 +0000</pubDate>
		<dc:creator>Ben Lister</dc:creator>
				<category><![CDATA[Random]]></category>
		<category><![CDATA[DCP]]></category>
		<category><![CDATA[jQuery]]></category>
		<category><![CDATA[Redesign]]></category>

		<guid isPermaLink="false">http://blog.darkcrimson.com/?p=75</guid>
		<description><![CDATA[After 14 months with the previous version of DCP, I&#8217;ve launched a full site re-design. This version is a complete code overhaul including completely re-written back end PHP using Codeigniter MVC framework. In this version I&#8217;ve also made the switch from Prototype JS to jQuery which has been my library of choice in my professional [...]]]></description>
			<content:encoded><![CDATA[<p>After 14 months with the previous version of DCP, I&#8217;ve launched a full site re-design. This version is a complete code overhaul including completely re-written back end PHP using Codeigniter MVC framework. In this version I&#8217;ve also made the switch from Prototype JS to jQuery which has been my library of choice in my professional work for the last years.<span id="more-75"></span></p>
<p>This overhaul has been an extremely long process and has convinced me that I am without a doubt the <a href="http://www.alistapart.com/articles/redesigning-your-own-site/" target="_blank">most difficult to please client</a>. Although I&#8217;ve been involved in well over a dozen freelance projects so far this year, I am glad that the nearly 9 month process of brainstorming, trial an error, redesigns and coding for this project is now over.</p>
<p>Apart from the design  face lift, my <a href="http://darkcrimson.com/portfolio" target="_blank">Portfolio</a> has been completely re-designed and programmed with some custom jQuery and Flickr API magic.</p>
<p>The Blog has also been reconfigured and is now considerably easier to navigate through than the previous version. I have a number of tech tutorials and random topics that I plan to write about over the next few <del>days</del> <del>weeks</del> months so make sure to  <a href="http://blog.darkcrimson.com/feed/" target="_blank">subscribe to my RSS feed</a>.</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.darkcrimson.com/2009/11/site-redesign/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Drupal Clean URLs on MediaTemple</title>
		<link>http://blog.darkcrimson.com/2008/11/drupal-clean-urls-on-mediatemple/</link>
		<comments>http://blog.darkcrimson.com/2008/11/drupal-clean-urls-on-mediatemple/#comments</comments>
		<pubDate>Sun, 09 Nov 2008 00:22:33 +0000</pubDate>
		<dc:creator>Ben Lister</dc:creator>
				<category><![CDATA[Tutorials]]></category>
		<category><![CDATA[.htaccess]]></category>
		<category><![CDATA[Drupal]]></category>
		<category><![CDATA[Media Temple]]></category>

		<guid isPermaLink="false">http://blog.darkcrimson.com/?p=6</guid>
		<description><![CDATA[I spent the last hour or so searching for the correct .htaccess file for installing Drupal Clean URLs (Drupal 6.xx) on MediaTemple's server without any luck. Finally, I was able to piece something together that worked and I thought it would be worth sharing]]></description>
			<content:encoded><![CDATA[<p>I spent the last hour or so searching for the correct .htaccess file for installing Drupal Clean URLs (Drupal 6.xx) on MediaTemple&#8217;s server without any luck. Finally, I was able to piece something together that worked and I thought it would be worth sharing <span id="more-6"></span>:</p>
<pre name="code" class="php">< IfModule mod_php5.c>
  php_value magic_quotes_gpc 0
  php_value register_globals 0
  php_value session.auto_start 0
  php_value mbstring.http_input pass
  php_value mbstring.http_output pass
  php_value mbstring.encoding_translation 0
< /IfModule>
< IfModule mod_rewrite.c>
  RewriteEngine on
  RewriteBase /YOUR-SUBDIRECTORY-NAME-HERE
  RewriteCond %{REQUEST_FILENAME} !-f
  RewriteCond %{REQUEST_FILENAME} !-d
  RewriteRule ^(.*)$ index.php?q=$1 [L,QSA]
< /IfModule></pre>
<p>I hope that this helps someone in the future.</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.darkcrimson.com/2008/11/drupal-clean-urls-on-mediatemple/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Modal Kombat! A Lightbox Comparison</title>
		<link>http://blog.darkcrimson.com/2008/04/modal-kombat-a-lightbox-comparison/</link>
		<comments>http://blog.darkcrimson.com/2008/04/modal-kombat-a-lightbox-comparison/#comments</comments>
		<pubDate>Tue, 08 Apr 2008 18:10:20 +0000</pubDate>
		<dc:creator>Ben Lister</dc:creator>
				<category><![CDATA[JavaScript]]></category>
		<category><![CDATA[jQuery]]></category>
		<category><![CDATA[Lightbox]]></category>
		<category><![CDATA[Modal]]></category>
		<category><![CDATA[Prototype]]></category>

		<guid isPermaLink="false">http://blog.darkcrimson.com/?p=3</guid>
		<description><![CDATA[JavaScript Frameworks have gained  wide acceptance among developers since the &#34;Web 2.0&#34; movement and have, in many ways, changed how we use the web.  One of the greatest outcomes of this has been the reduction in external popup  windows in favor of unobtrusive, JavaScript-based &#34;Modal Window&#34; and  &#34;Lightbox&#34; solutions. At work, [...]]]></description>
			<content:encoded><![CDATA[<p>JavaScript Frameworks have gained  wide acceptance among developers since the &quot;Web 2.0&quot; movement and have, in many ways, changed how we use the web.  One of the greatest outcomes of this has been the reduction in external popup  windows in favor of unobtrusive, JavaScript-based &quot;Modal Window&quot; and  &quot;Lightbox&quot; solutions. At work,  clients frequently ask us to incorporate content and image overlay solutions into their  projects and after experimenting with, and customizing a wide variety of  different scripts, I decided to write a comparison of several of the most popular Light Box  solutions. <span id="more-3"></span></p>
<p>For this comparison, I have evaluated the Light Boxes based on coding  techniques, ease of use / customization, community support and frequency of  updates. Additionally, I have listed specifications for file size and framework  dependency / version for each along with my rating on a 1-10 scale.</p>
<p><strong>The Scripts chosen for this comparison are as follows:</strong></p>
<ul class="in_post">
<li><a href="#lb2">Lightbox 2 </a>&nbsp;&nbsp;</li>
<li><a href="#lv">Lightview</a>&nbsp;&nbsp;</li>
<li><a href="#lb">Litebox</a>&nbsp;&nbsp;</li>
<li><a href="#tb">Thickbox</a>&nbsp;&nbsp;</li>
<li><a href="#mb">Modalbox</a>&nbsp;&nbsp;</li>
<li><a href="#sb">Slimbox</a>&nbsp;&nbsp;</li>
<li><a href="#mb2">Multibox</a>&nbsp;&nbsp;</li>
<li><a href="#be">jQuery Lightbox Plugin (balupton edition)</a>&nbsp;&nbsp;
  </li>
</ul>
<p>&nbsp;</p>
<h3 class="blog_ttl" ><a href="http://www.huddletogether.com/projects/lightbox2/" name="lb2" target="_blank">Lightbox 2</a></h3>
<hr />
<p>The original Lightbox is considered by many to be the first  modal window widely available to developers. The latest release, version 2 ,  like its predecessors, is based on the Prototype framework and uses  Scriptaculous effects. This script is very stable, has seen frequent bug fixes  and off-shoots throughout its existence and has a very active user-driven  support forum. The JavaScript file itself is very nicely documented and offers  many configurable options.</p>
<p>Although Lightbox 2 offers the advantage of a large following and easy to configure (and understand) code it does have limitations. The script is called by using the <a href="http://www.utoronto.ca/webdocs/HTMLdocs/NewHTML/a_rel.html" target="_blank"><em>rel</em></a> attribute which limits its functionality for non-basic methods such as Flash and image maps. Additionally, this script, unlike most others in this comparison, is only capable of displaying images. <strong>Update:</strong> after some poking around, I found a lightbox clone which appears to be nearily identical to Lightbox 2, but with the ability to display Flash movies natively. For more information, <a href="http://www.codefidelity.com/blog/?page_id=7" target="_blank">visit this link. </a></p>
<table width="500" cellspacing="0" cellpadding="0" border="0">
<tr style="background: #000;color:#fff;">
<td style="padding: 4px; width: 185px"><strong>Framework Dependency: </strong></td>
<td style="padding: 4px; width: 240px">Prototype  v1.6.0.2+ / Scriptaculous</td>
</tr>
<tr style="background: #444;color:#fff;">
<td style="padding: 4px; width: 185px"><strong>Total package size: </strong></td>
<td style="padding: 4px; width: 240px">26k</td>
</tr>
<tr style="background: #777;color:#fff;">
<td style="padding: 4px; width: 185px"><strong>License: </strong></td>
<td style="padding: 4px; width: 240px">Creative Commons Attribution 2.5 </td>
</tr>
<tr>
<tr style="background: #999;color:#fff;">
<td style="padding: 4px; width: 185px"><strong>My Rating:</strong></td>
<td style="padding: 4px; width: 240px">7/10</td>
</tr>
</table>
<div style="padding:8px;background:#000;color:#fff; width:90%; border:1px dotted #777; font-size:14px;margin-top:20px;"><strong>Summary: </strong>A well-developed and document script; useful for smaller applications, can only be used for images. Has led the way for many developer off-shoots.</div>
<p>&nbsp;</p>
<h3 class="blog_ttl" ><a href="http://www.nickstakenburg.com/projects/lightview/" name="lv" target="_blank">Lightview</a></h3>
<hr />
<p>Lightview is a somewhat unique take on the standard  Lightbox. Smartly written, with an image-free, fully adjustable, rounded corner  solution (which works on browsers across the board), Lightbox is a very  aesthetically pleasing and also very powerful solution. Unlike the standard  Lightbox, and many of it&#8217;s clones, Lightview&#8217;s content box scrolls with the  page so that you are never left wondering where the content is. In addition to  images, Lightview also offers the ability to display Flash, Quicktime, AJAX calls, inline  content and even full web sites in an i-frame. Lightview features a very neat  image gallery option which can be used as a timed (configurable) slide show,  which resizes the content box to the dimensions of each image. Another great  thing, which I consider a big advantage over most of the competition, is that  the Lightview window is called through the class attribute. </p>
<p>One major issue that I have found with Lightview is that, beyond the configuration settings, the script comes pre-compressed with no original source code attached. This causes major headaches when trying to change anything not in the settings or CSS. I encountered this limitation when developing the <a href="http://www.darkcrimson.com" target="_blank">new version of my site</a> in the portfolio section when I wanted to add two simple hyperlinks to the Lightview window. Although I was able to add the links, I had to place the links in the <em>title </em>attribute, which does not validate as XHTML.</p>
<table width="500" cellspacing="0" cellpadding="0" border="0">
<tr style="background: #000;color:#fff;">
<td style="padding: 4px; width: 185px"><strong>Framework Dependency: </strong></td>
<td style="padding: 4px; width: 240px">Prototype 1.6+ / Scriptaculous</td>
</tr>
<tr style="background: #444;color:#fff;">
<td style="padding: 4px; width: 185px"><strong>Total package size: </strong></td>
<td style="padding: 4px; width: 240px">~43k</td>
</tr>
<tr style="background: #777;color:#fff;">
<td style="padding: 4px; width: 185px"><strong>License:</strong></td>
<td style="padding: 4px; width: 240px">Creative Commons Attribution-Noncommercial-No Derivative Works </td>
</tr>
<tr>
<tr style="background: #999;color:#fff;">
<td style="padding: 4px; width: 185px"><strong>My Rating:</strong></td>
<td style="padding: 4px; width: 240px">9/10</td>
</tr>
</table>
<div style="padding:8px;background:#000;color:#fff; width:90%; border:1px dotted #777; font-size:14px;margin-top:20px;"><strong>Summary: </strong>Tons of features: Flash, Quicktime, Inline, AJAX, Images. Cool slide show feature. No uncompressed JS distributed which limits or prevents major customizations.</div>
<p>&nbsp;</p>
<h3 class="blog_ttl" ><a href="http://www.doknowevil.net/litebox/" name="lb" target="_blank">Litebox</a></h3>
<hr />
<p>Litebox is basically a compact version of Lightbox. Although listed below as ~23k, which is a mere 3k less than the original Lightbox, the true saving is with the compact, 4k Prototype.lite and moo fx libraries used instead of the conventional 120k+ standard Prototype library and somewhat bulky Scriptaculous files. Litebox is a great, lightweight solution but unlike its older, and slightly pudgy sibling, Lightbox 2, this script does not seem to be frequently updated. The last updated date from the Litebox JS file is July, 2006 compared to March 2008 (at the time of this comparison) with Lightbox 2.</p>
<table width="500" cellspacing="0" cellpadding="0" border="0">
<tr style="background: #000;color:#fff;">
<td style="padding: 4px; width: 185px"><strong>Framework Dependency: </strong></td>
<td style="padding: 4px; width: 240px">Prototype.lite/ moo fx</td>
</tr>
<tr style="background: #444;color:#fff;">
<td style="padding: 4px; width: 185px"><strong>Total package size: </strong></td>
<td style="padding: 4px; width: 240px">~23k</td>
</tr>
<tr style="background: #777;color:#fff;">
<td style="padding: 4px; width: 185px"><strong>License:</strong></td>
<td style="padding: 4px; width: 240px">Creative Commons Attribution 2.5 </td>
</tr>
<tr>
<tr style="background: #999;color:#fff;">
<td style="padding: 4px; width: 185px"><strong>My Rating:</strong></td>
<td style="padding: 4px; width: 240px">7.5/10</td>
</tr>
</table>
<div style="padding:8px;background:#000;color:#fff; width:90%; border:1px dotted #777; font-size:14px;margin-top:20px;"><strong>Summary: </strong>Very lightweight solution. Suitable for sites where load time is essential. Suffers from lack of updates and like Lightbox2, can only be used for images. </div>
<p>&nbsp;</p>
<h3 class="blog_ttl" ><a href="http://jquery.com/demo/thickbox/" name="tb" target="_blank">Thickbox</a></h3>
<hr />
<p>Thickbox was written in the lightweight jQuery framework and  weighs in at an amazing 10k compressed and only 15k uncompressed. Additionally,  the developer wrote the script to run with the compressed version of jQuery  which only adds 20k instead of the 120k+ with Prototype. The script does not  have the community-driven support forums that the previous three scripts have  but the author states that you may email him with detailed questions or bugs.  Thickbox does not offer a lot of the customization options seen in Lightbox,  Lightview etc&#8230; But does provide both an uncompressed and compressed version  for developers to extend at will. The &quot;out of the box&quot; appearance for  Thickbox is not as aesthetically pleasing as some of it&#8217;s alternatives but  keeping with its easily extendable theme, images and CSS can be added as  desired to alter the look. One annoyance that I found was, when activated, the  mouse scroll wheel becomes inoperative which requires you to use the browser&#8217;s  side scroll bar.</p>
<p>Thickbox offers quite a few features for such a small package including inline content, i-frame as well as both single and multiple image support. The author claims that both Flash and PDF files can work with this script but notes that these media types are untested. </p>
<table width="500" cellspacing="0" cellpadding="0" border="0">
<tr style="background: #000;color:#fff;">
<td style="padding: 4px; width: 185px"><strong>Framework Dependency: </strong></td>
<td style="padding: 4px; width: 240px">jQuery 1.1.2</td>
</tr>
<tr style="background: #444;color:#fff;">
<td style="padding: 4px; width: 185px"><strong>Total package size: </strong></td>
<td style="padding: 4px; width: 240px">~15k/~10k</td>
</tr>
<tr style="background: #777;color:#fff;">
<td style="padding: 4px; width: 185px"><strong>License:</strong></td>
<td style="padding: 4px; width: 240px">MIT/GNU </td>
</tr>
<tr>
<tr style="background: #999;color:#fff;">
<td style="padding: 4px; width: 185px"><strong>My Rating:</strong></td>
<td style="padding: 4px; width: 240px">8.5/10</td>
</tr>
</table>
<div style="padding:8px;background:#000;color:#fff; width:90%; border:1px dotted #777; font-size:14px;margin-top:20px;"><strong>Summary: </strong>Extremely small, has compressed / uncompressed, easy to extend, lots of features for such a small package, smooth </div>
<p>&nbsp;</p>
<h3 class="blog_ttl" ><a href="http://www.wildbit.com/labs/modalbox/" name="mb" target="_blank">Modalbox </a></h3>
<hr />
<p>Modalbox is a very powerful tool which allows the developer to not only show single page content or images like many other modal windows but perform complex tasks with AJAX call backs which allows the end user to perform multiple tasks with few clicks and no browser refreshes. Unlike similar scripts, Modalbox uses AJAX instead of deprecated i-frames and even supports scrolling. The project is supported in <a href="http://code.google.com/" target="_blank">Google Code</a> and has a Wiki as well as detailed information about uses, bugs, etc&#8230;</p>
<p>I have used this for multiple client projects and  have  have received positive feedback with not hitches during the development process. One potential issue with Modbalbox is that it relies on Prototype and Scriptaculous which can be a little heavy for large scale projects but for those cases, there is a mootools clone called <a href="http://www.e-magine.ro/web-dev-and-design/36/moodalbox/" target="_blank">MOOdalBox</a> which has the same Google Code backing and support. </p>
<table width="500" cellspacing="0" cellpadding="0" border="0">
<tr style="background: #000;color:#fff;">
<td style="padding: 4px; width: 185px"><strong>Framework Dependency: </strong></td>
<td style="padding: 4px; width: 240px">Prototype / Scriptaculous (or mootools)</td>
</tr>
<tr style="background: #444;color:#fff;">
<td style="padding: 4px; width: 185px"><strong>Total package size: </strong></td>
<td style="padding: 4px; width: 240px">~32k</td>
</tr>
<tr style="background: #777;color:#fff;">
<td style="padding: 4px; width: 185px"><strong>License:</strong></td>
<td style="padding: 4px; width: 240px">MIT </td>
</tr>
<tr>
<tr style="background: #999;color:#fff;">
<td style="padding: 4px; width: 185px"><strong>My Rating:</strong></td>
<td style="padding: 4px; width: 240px">9.5/10</td>
</tr>
</table>
<div style="padding:8px;background:#000;color:#fff; width:90%; border:1px dotted #777; font-size:14px;margin-top:20px;"><strong>Summary:</strong>Summary: Easy to use and customize very powerful and well-written code. Versions for Prototype and Mootools. Lots of cool AJAX stuff. </div>
<p>&nbsp;</p>
<h3 class="blog_ttl" ><a href="http://www.digitalia.be/software/slimbox" name="sb" target="_blank">Slimbox</a></h3>
<hr />
<p>Slimbox is a mootools clone of Lightbox 2. The entire script plus images and CSS is amazingly only 13k uncompressed. This project has support forums and the homepage for the project allows visitors to post comments in which the author often responds to questions. After playing around with this script, I was impressed with the small file size but found the overall package to be somewhat buggy, particularly with the dark page cover when scrolling.</p>
<table width="500" cellspacing="0" cellpadding="0" border="0">
<tr style="background: #000;color:#fff;">
<td style="padding: 4px; width: 185px"><strong>Framework Dependency: </strong></td>
<td style="padding: 4px; width: 240px">Mootools 1.1+</td>
</tr>
<tr style="background: #444;color:#fff;">
<td style="padding: 4px; width: 185px"><strong>Total package size: </strong></td>
<td style="padding: 4px; width: 240px">~13k</td>
</tr>
<tr style="background: #777;color:#fff;">
<td style="padding: 4px; width: 185px"><strong>License:</strong></td>
<td style="padding: 4px; width: 240px">MIT</td>
</tr>
<tr>
<tr style="background: #999;color:#fff;">
<td style="padding: 4px; width: 185px"><strong>My Rating:</strong></td>
<td style="padding: 4px; width: 240px">6/10</td>
</tr>
</table>
<div style="padding:8px;background:#000;color:#fff; width:90%; border:1px dotted #777; font-size:14px;margin-top:20px;"><strong>Summary: </strong>A big punch in a small package. Buggy when scrolling but at 13k, this is the IKEA of Lightboxes; nice looking but has </div>
<p>&nbsp;</p>
<h3 class="blog_ttl" ><a href="http://www.phatfusion.net/multibox/" name="mb2" target="_blank">Multibox</a></h3>
<hr />
<p>Multibox is a versatile Lightbox that is able to display a  large variety of different media types including images, audio (Real Player,  MP3), video (Windows Media Player and QuickTime, FLV), as well as the standard  image and content (AJAX  and inline). The default design is pleasant enough that most developers won&#8217;t  need to do aesthetic modifications but doing so would be fairly easy due to the  way the script was written. </p>
<p>The code is fairly straightforward but is not as well  structured as some of the other options; one thing that caught my eye was the  use of JavaScript to print the actual HTML code for the box. In other scripts,  this is done dynamically at the savings of dozens of lines of code. It also  appears that there is no form of support (or update log) for this script so it  looks like bug fixes could be an issue.</p>
<table width="500" cellspacing="0" cellpadding="0" border="0">
<tr style="background: #000;color:#fff;">
<td style="padding: 4px; width: 185px"><strong>Framework Dependency: </strong></td>
<td style="padding: 4px; width: 240px">Mootools 1.1+</td>
</tr>
<tr style="background: #444;color:#fff;">
<td style="padding: 4px; width: 185px"><strong>Total package size: </strong></td>
<td style="padding: 4px; width: 240px">~30k</td>
</tr>
<tr style="background: #777;color:#fff;">
<td style="padding: 4px; width: 185px"><strong>License:</strong></td>
<td style="padding: 4px; width: 240px">MIT</td>
</tr>
<tr>
<tr style="background: #999;color:#fff;">
<td style="padding: 4px; width: 185px"><strong>My Rating:</strong></td>
<td style="padding: 4px; width: 240px">9/10</td>
</tr>
</table>
<div style="padding:8px;background:#000;color:#fff; width:90%; border:1px dotted #777; font-size:14px;margin-top:20px;"><strong>Summary: </strong>One of the best looking and smoothest working in the comparison. Lacks support, suffers from inefficient code, large file size. If file size doesn&#8217;t matter and you know that your users have up to date browsers, go for it!</div>
<p>&nbsp;</p>
<h3 class="blog_ttl" ><a href="http://plugins.jquery.com/project/jquerylightbox_bal" name="be" target="_blank">jQuery Lightbox Plugin (balupton edition) 1.0</a></h3>
<hr />
<p>This jQuery plugin, based on Lightbox2 delivers unusually  smooth scrolling (far better than Lightbox2) as well as many efficiency  benefits and a small file size. Unlike many of the other scripts in this  comparison, this plugin requires no configuration and a smart automatic URL  detection which means that only one file has to be included in the display  file. The jQuery Lightbox Plugin can be used manually or automatically to  generate Lightboxes which means that it can be set, like many others with the  <em>rel</em> attribute or with on event such as <em>onclick</em>.  This is a huge advantage and makes The jQuery Lightbox Plugin potentially the  most versatile in this comparison. Additionally, most media types can be used  without modification including Qucktime, Flash and other embedded content  types.</p>
<p>The only real downside that I found with this script was the lack of clear documentation. Although the instructions are fairly clear, it takes some digging around to find the information you are looking for. Luckily, this script is listed on the <a href="http://plugins.jquery.com/" target="_blank">jQuery plugin site</a> which includes support request and bug report sections as well as a log of changes.</p>
<table width="500" cellspacing="0" cellpadding="0" border="0">
<tr style="background: #000;color:#fff;">
<td style="padding: 4px; width: 185px"><strong>Framework Dependency: </strong></td>
<td style="padding: 4px; width: 240px">jQuery 1.2.1+</td>
</tr>
<tr style="background: #444;color:#fff;">
<td style="padding: 4px; width: 185px"><strong>Total package size: </strong></td>
<td style="padding: 4px; width: 240px">~15k</td>
</tr>
<tr style="background: #777;color:#fff;">
<td style="padding: 4px; width: 185px"><strong>License:</strong></td>
<td style="padding: 4px; width: 240px">GNU Affero General Public License</td>
</tr>
<tr>
<tr style="background: #999;color:#fff;">
<td style="padding: 4px; width: 185px"><strong>My Rating:</strong></td>
<td style="padding: 4px; width: 240px">9.5/10</td>
</tr>
</table>
<div style="padding:8px;background:#000;color:#fff; width:90%; border:1px dotted #777; font-size:14px;margin-top:20px;">
 Summary: The smoothest and best overall Lightbox clone in  the comparison. Could benefit from more documentation on the site, but it&rsquo;s so  easy to use, that its hard to complain.
</div>
<p>&nbsp;</p>
<p>&nbsp;</p>
<h3 class="blog_ttl" >Other considerations and Conclusions</h3>
<p class="blog_ttl" >One additional script that was too task specific to include in this comparison but I wanted to include a link. <a href="http://dev.visualdrugs.net/mootools/gmapsoverlay/" target="_blank">GMapsOverlay</a> is a moo-tools based Lightbox that is used specificially to display configurable Google Maps. </p>
<p>Although I have listed the file sizes for the scripts evaluated in this comparison, some of which are more attractive than others, further compression can be applied to most of these scripts using applications such as: <a href="http://www.dojotoolkit.org/docs/shrinksafe" target="_blank">DoJo Toolkit&#8217;s ShrinkSafe</a> or <a href="http://dean.edwards.name/packer/" target="_blank">Packer.</a></p>
<p>So, after reading all of this, which one of these Lightboxes is right for you? That depends&mdash;I typically use Prototype because I have worked with it in the past quite often&mdash;but, there are many alternatives and clones using other JavaScript Frameworks or none at all so it depends on your specific need. Keeping that in mind, it is possible to <a href="http://docs.jquery.com/Using_jQuery_with_Other_Libraries" target="_blank">use multiple frameworks together</a>. </p></p>
]]></content:encoded>
			<wfw:commentRss>http://blog.darkcrimson.com/2008/04/modal-kombat-a-lightbox-comparison/feed/</wfw:commentRss>
		<slash:comments>6</slash:comments>
		</item>
	</channel>
</rss>

