<?xml version="1.0" encoding="UTF-8"?>
<?xml-stylesheet type="text/xsl" media="screen" href="/~d/styles/rss2full.xsl"?><?xml-stylesheet type="text/css" media="screen" href="http://feeds.feedburner.com/~d/styles/itemcontent.css"?><rss 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/" xmlns:feedburner="http://rssnamespace.org/feedburner/ext/1.0" version="2.0">

<channel>
	<title>Pixel Acres</title>
	
	<link>http://f6design.com/journal</link>
	<description>Adventures in web and graphic design</description>
	<lastBuildDate>Wed, 16 May 2012 06:50:42 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.3.1</generator>
		<atom10:link xmlns:atom10="http://www.w3.org/2005/Atom" rel="self" type="application/rss+xml" href="http://feeds.feedburner.com/PixelAcres" /><feedburner:info uri="pixelacres" /><atom10:link xmlns:atom10="http://www.w3.org/2005/Atom" rel="hub" href="http://pubsubhubbub.appspot.com/" /><feedburner:emailServiceId>PixelAcres</feedburner:emailServiceId><feedburner:feedburnerHostname>http://feedburner.google.com</feedburner:feedburnerHostname><item>
		<title>A jQuery plugin boilerplate</title>
		<link>http://feedproxy.google.com/~r/PixelAcres/~3/9GIBPqPX504/</link>
		<comments>http://f6design.com/journal/2012/05/06/a-jquery-plugin-boilerplate/#comments</comments>
		<pubDate>Sun, 06 May 2012 14:17:46 +0000</pubDate>
		<dc:creator>Jonathan</dc:creator>
				<category><![CDATA[jQuery]]></category>
		<category><![CDATA[Programming]]></category>
		<category><![CDATA[Toolbox]]></category>

		<guid isPermaLink="false">http://f6design.com/journal/?p=2430</guid>
		<description><![CDATA[I created this boilerplate for a jQuery plugin I&#8217;m working on, and you can use it to kick start your own jQuery plugin development. The features of my boilerplate are: Plugin can be customised using options Setters/Getters for options Private and public methods Callback hooks Plugin instances can be destroyed The boilerplate Here is the [...]]]></description>
			<content:encoded><![CDATA[<p>I created this boilerplate for a jQuery plugin I&#8217;m working on, and you can use it to kick start your own jQuery plugin development. The features of my boilerplate are:</p>
<ul>
<li>Plugin can be customised using options</li>
<li>Setters/Getters for options</li>
<li>Private and public methods</li>
<li>Callback hooks</li>
<li>Plugin instances can be destroyed</li>
</ul>
<h2>The boilerplate</h2>
<p>Here is the bare bones, uncommented boilerplate source code:</p>
<pre class="brush: jscript; title: ; notranslate">/**
 * A jQuery plugin boilerplate.
 * Author: Jonathan Nicol @f6design
 */
;(function($) {
  var pluginName = 'demoplugin';

  function Plugin(element, options) {
    var el = element;
    var $el = $(element);

    options = $.extend({}, $.fn[pluginName].defaults, options);

    function init() {
      // Add any initialization logic here...

      hook('onInit');
    }

    function fooPublic() {
      // Code goes here...
    }

    function option (key, val) {
      if (val) {
        options[key] = val;
      } else {
        return options[key];
      }
    }

    function destroy() {
      $el.each(function() {
        var el = this;
        var $el = $(this);

        // Add code to restore the element to its original state...

        hook('onDestroy');
        $el.removeData('plugin_' + pluginName);
      });
    }

    function hook(hookName) {
      if (options[hookName] !== undefined) {
        options[hookName].call(el);
      }
    }

    init();

    return {
      option: option,
      destroy: destroy,
      fooPublic: fooPublic
    };
  }

  $.fn[pluginName] = function(options) {
    if (typeof arguments[0] === 'string') {
      var methodName = arguments[0];
      var args = Array.prototype.slice.call(arguments, 1);
      var returnVal;
      this.each(function() {
        if ($.data(this, 'plugin_' + pluginName) &amp;&amp; typeof $.data(this, 'plugin_' + pluginName)[methodName] === 'function') {
          returnVal = $.data(this, 'plugin_' + pluginName)[methodName].apply(this, args);
        } else {
          throw new Error('Method ' +  methodName + ' does not exist on jQuery.' + pluginName);
        }
      });
      if (returnVal !== undefined){
        return returnVal;
      } else {
        return this;
      }
    } else if (typeof options === &quot;object&quot; || !options) {
      return this.each(function() {
        if (!$.data(this, 'plugin_' + pluginName)) {
          $.data(this, 'plugin_' + pluginName, new Plugin(this, options));
        }
      });
    }
  };

  $.fn[pluginName].defaults = {
    onInit: function() {},
    onDestroy: function() {}
  };

})(jQuery);</pre>
<p>&#8230;and with liberal comments:</p>
<pre class="brush: jscript; title: ; notranslate">/**
 * A jQuery plugin boilerplate.
 * Author: Jonathan Nicol @f6design
 */
;(function($) {
  // Change this to your plugin name.
  var pluginName = 'demoplugin';

  /**
   * Plugin object constructor.
   * Implements the Revealing Module Pattern.
   */
  function Plugin(element, options) {
    // References to DOM and jQuery versions of element.
    var el = element;
    var $el = $(element);

    // Extend default options with those supplied by user.
    options = $.extend({}, $.fn[pluginName].defaults, options);

    /**
     * Initialize plugin.
     */
    function init() {
      // Add any initialization logic here...

      hook('onInit');
    }

    /**
     * Example Public Method
     */
    function fooPublic() {
      // Code goes here...
    }

    /**
     * Get/set a plugin option.
     * Get usage: $('#el').demoplugin('option', 'key');
     * Set usage: $('#el').demoplugin('option', 'key', value);
     */
    function option (key, val) {
      if (val) {
        options[key] = val;
      } else {
        return options[key];
      }
    }

    /**
     * Destroy plugin.
     * Usage: $('#el').demoplugin('destroy');
     */
    function destroy() {
      // Iterate over each matching element.
      $el.each(function() {
        var el = this;
        var $el = $(this);

        // Add code to restore the element to its original state...

        hook('onDestroy');
        // Remove Plugin instance from the element.
        $el.removeData('plugin_' + pluginName);
      });
    }

    /**
     * Callback hooks.
     * Usage: In the defaults object specify a callback function:
     * hookName: function() {}
     * Then somewhere in the plugin trigger the callback:
     * hook('hookName');
     */
    function hook(hookName) {
      if (options[hookName] !== undefined) {
        // Call the user defined function.
        // Scope is set to the jQuery element we are operating on.
        options[hookName].call(el);
      }
    }

    // Initialize the plugin instance.
    init();

    // Expose methods of Plugin we wish to be public.
    return {
      option: option,
      destroy: destroy,
      fooPublic: fooPublic
    };
  }

  /**
   * Plugin definition.
   */
  $.fn[pluginName] = function(options) {
    // If the first parameter is a string, treat this as a call to
    // a public method.
    if (typeof arguments[0] === 'string') {
      var methodName = arguments[0];
      var args = Array.prototype.slice.call(arguments, 1);
      var returnVal;
      this.each(function() {
        // Check that the element has a plugin instance, and that
        // the requested public method exists.
        if ($.data(this, 'plugin_' + pluginName) &amp;&amp; typeof $.data(this, 'plugin_' + pluginName)[methodName] === 'function') {
          // Call the method of the Plugin instance, and Pass it
          // the supplied arguments.
          returnVal = $.data(this, 'plugin_' + pluginName)[methodName].apply(this, args);
        } else {
          throw new Error('Method ' +  methodName + ' does not exist on jQuery.' + pluginName);
        }
      });
      if (returnVal !== undefined){
        // If the method returned a value, return the value.
        return returnVal;
      } else {
        // Otherwise, returning 'this' preserves chainability.
        return this;
      }
    // If the first parameter is an object (options), or was omitted,
    // instantiate a new instance of the plugin.
    } else if (typeof options === &quot;object&quot; || !options) {
      return this.each(function() {
        // Only allow the plugin to be instantiated once.
        if (!$.data(this, 'plugin_' + pluginName)) {
          // Pass options to Plugin constructor, and store Plugin
          // instance in the elements jQuery data object.
          $.data(this, 'plugin_' + pluginName, new Plugin(this, options));
        }
      });
    }
  };

  // Default plugin options.
  // Options can be overwritten when initializing plugin, by
  // passing an object literal, or after initialization:
  // $('#el').demoplugin('option', 'key', value);
  $.fn[pluginName].defaults = {
    onInit: function() {},
    onDestroy: function() {}
  };

})(jQuery);</pre>
<h2>Usage</h2>
<p>The first thing you&#8217;ll need to do is change the name of the plugin, which is hardcoded as &#8216;demoplugin&#8217;, to something a little more descriptive. After that you should be able to follow the comments in the source code to customise the plugin.</p>
<p>Here are examples of how an end-user would interact with the plugin:</p>
<pre class="brush: jscript; title: ; notranslate">// Initialize plugin with default options.
$('#element').demoplugin();

// Initialize plugin with user defined options.
$('#element').demoplugin({
  option1: 2000,
  option2: 'value',
  callback1: function () { ... }
});

// Call a public method, no arguments.
$('#element').demoplugin('publicFunctionName');

// Call a public method with arguments.
$('#element').demoplugin('publicFunctionName', 'arg1', 'arg2');

// Get a plugin option.
$('#element').demoplugin('option', 'key');

// Set a plugin option after plugin initialization.
$('#element').demoplugin('option', 'key', value);

// Destroy plugin.
$('#element').demoplugin('destroy');</pre>
<h2>Setup options</h2>
<p>It is very useful to be able to customise jQuery plugins on a per instance basis. The boilerplate implements default settings which can be overwritten when the plugin is initialized:</p>
<pre class="brush: jscript; title: ; notranslate">// Default plugin options.
$.fn[pluginName].defaults = {
  color: '#ff0000',
  height: 200
};</pre>
<pre class="brush: jscript; title: ; notranslate">$('#element').demoplugin({
  color: '#0000ff',
  height: 400
});</pre>
<p>Options can also be overwritten after the plugin is initialized, using the <code>option</code> method:</p>
<pre class="brush: jscript; title: ; notranslate">$('#element').demoplugin('option', 'color', '#00ff00');</pre>
<p>An option value can be fetched using the same method by simply omitting the third parameter:</p>
<pre class="brush: jscript; title: ; notranslate">var color = $('#element').demoplugin('option', 'color');</pre>
<h2>Public and private methods</h2>
<p>Private functions reduce the chance of your users inadvertently calling the plugin&#8217;s utility methods. I&#8217;m a fan of the <a href="http://addyosmani.com/resources/essentialjsdesignpatterns/book/#revealingmodulepatternjavascript">Revealing Module pattern</a>, so that&#8217;s how I chose to implement private/public functionality in my boilerplate.</p>
<pre class="brush: jscript; title: ; notranslate">function Plugin(element, options) {
  // This method is public.
  function fooPublic(param1, param2) {
    // ...
  }

  // This method is private.
  function fooPrivate() {
    // ...
  }

  // Expose methods of Plugin we wish to be public.
  return {
    fooPublic: fooPublic
  };
}</pre>
<p>Public functions can be called by your users like so:</p>
<pre class="brush: jscript; title: ; notranslate">$('#element').demoplugin('fooPublic', 'val1', 'val2');</pre>
<h2>Callback hooks</h2>
<p>Callback hooks are incredibly powerful. They allow your users to listen for events in your plugin&#8217;s behaviour and respond accordingly. Hooks are implemented as functions in the default options object:</p>
<pre class="brush: jscript; title: ; notranslate">$.fn[pluginName].defaults = {
  onSlideshowFinished: function() {}
};</pre>
<p>Each function is empty to begin with, since the callback&#8217;s behaviour will be defined by the user. This is done by overwriting the callback function when setting the plugin&#8217;s options. The scope of the callback is the DOM element the plugin is attached to, so in the following example the DOM element would be hidden.</p>
<pre class="brush: jscript; title: ; notranslate">$('#element').demoplugin({
  onSlideshowFinished: function() {
    $(this).hide();
  }
});</pre>
<p>To trigger a hook, call the plugin&#8217;s <code>hook</code> method:</p>
<pre class="brush: jscript; title: ; notranslate">hook('onSlideshowFinished');</pre>
<p>There are two callbacks implemented by default in the boilerplate: <code>onInit</code> and <code>onDestroy</code>.</p>
<h2>Destroying a plugin instance</h2>
<p>Your users can remove an instance of the plugin by calling its <code>destroy</code> method:</p>
<pre class="brush: jscript; title: ; notranslate">$('#element').demoplugin('destroy');</pre>
<p>The plugin stores all its functionality in its DOM element&#8217;s <code>data</code> object. By default the <code>destroy</code> method simply removes the stored <code>data</code> values. You will probably need to customise <code>destroy</code> to restore the DOM element to its original state and remove any event handlers your plugin has created.</p>
<h2>Credit</h2>
<p>My boilerplate takes inspiration from a number of sources, most notably the jQuery <a href="http://docs.jquery.com/Plugins/Authoring">plugin authoring guidelines</a>, Stefan Gabos&#8217; <a href="http://stefangabos.ro/jquery/jquery-plugin-boilerplate-oop/">boilerplate</a>, and Zeno Rocha and Addy Osmani&#8217;s <a href="http://jqueryboilerplate.com/">jQuery Boilerplate</a>.</p>
<img src="http://feeds.feedburner.com/~r/PixelAcres/~4/9GIBPqPX504" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://f6design.com/journal/2012/05/06/a-jquery-plugin-boilerplate/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		<feedburner:origLink>http://f6design.com/journal/2012/05/06/a-jquery-plugin-boilerplate/</feedburner:origLink></item>
		<item>
		<title>Test your JavaScript skills with js-assessment</title>
		<link>http://feedproxy.google.com/~r/PixelAcres/~3/4LvIuZyxhuw/</link>
		<comments>http://f6design.com/journal/2012/04/15/test-your-javascript-skills-with-js-assessment/#comments</comments>
		<pubDate>Sun, 15 Apr 2012 09:47:52 +0000</pubDate>
		<dc:creator>Jonathan</dc:creator>
				<category><![CDATA[News & Reviews]]></category>
		<category><![CDATA[Programming]]></category>

		<guid isPermaLink="false">http://f6design.com/journal/?p=2365</guid>
		<description><![CDATA[I recently discovered js-assessment, a &#8220;test-driven approach to assessing JavaScript skills&#8221; created by Rebecca Murphey. The js-assessment application contains a series of tests designed to assess a job candidate&#8217;s grasp of JavaScript, but it can also be used to gauge your own knowledge of the language. Think of it as a mini Project Euler for [...]]]></description>
			<content:encoded><![CDATA[<p>I recently discovered <a href="https://github.com/rmurphey/js-assessment">js-assessment</a>, a &#8220;test-driven approach to assessing JavaScript skills&#8221; created by <a href="http://rmurphey.com/">Rebecca Murphey</a>. The js-assessment application contains a series of tests designed to assess a job candidate&#8217;s grasp of JavaScript, but it can also be used to gauge your own knowledge of the language. Think of it as a mini <a href="http://projecteuler.net/">Project Euler</a> for JavaScript.</p>
<p>The questions are divided into five topics covering different aspects of the language: arrays, objects and context, functions, asynchronous behavior and <a href="http://documentcloud.github.com/backbone/">Backbone</a> views. If, like me, you have a decent grasp of JavaScript, but wouldn&#8217;t feel confident writing &#8220;JavaScript programmer&#8221; on your curriculum vitae, then I think you&#8217;ll find the tests an enjoyable challenge. None of the questions are super difficult, though I confess to needing help from <a href="https://developer.mozilla.org/en-US/">MDN</a> to arrive at a few of the solutions. I definitely learned a thing or two about JavaScript along the way.</p>
<p>Because Rebecca&#8217;s application is built in Node, you&#8217;ll need to have <a href="http://nodejs.org">Node</a> and <a href="http://npmjs.org/">NPM</a> installed before you can run it. That&#8217;s a shortcoming I think, since it throws up a fairly large barrier-to-entry, but if you&#8217;re serious about JavaScript then you really ought to delve into Node anyway. I won&#8217;t bore you with instructions for installing Node &#8211; you can do it using <a href="http://mxcl.github.com/homebrew/">Homebrew</a> or download an installer from the official <a href="http://nodejs.org/#download">Node website</a>. After that, just follow the steps on the <a href="https://github.com/rmurphey/js-assessment">js-assessment github</a> and you&#8217;ll be up and running.</p>
<p>Rebecca seems undecided about whether to publish solutions to the tests, but in the name of sharing the knowledge (and at the risk of exposing my own shortcomings as a programmer), you&#8217;ll find my answers below. My solutions won&#8217;t make much sense taken out of context like this, but once your start working your way through js-assessment things will become a lot clearer.</p>
<p>Although my solutions pass Rebecca&#8217;s tests I&#8217;m sure some of them could be improved, so if you have suggestions for optimizing my code please leave a comment below.</p>
<h2>Arrays</h2>
<h4>1. You should be able to determine the location of an item in an array</h4>
<pre class="brush: jscript; title: ; notranslate">fn = function (arr, targ) {
  for (var pos=0; pos &lt; arr.length; pos++){
    if (arr[pos] == targ){
      return pos;
    }
  }
};</pre>
<h4>2. You should be able to add the values of an array</h4>
<pre class="brush: jscript; title: ; notranslate">fn = function (arr) {
  var total = 0;
  for (var pos=0; pos &lt; arr.length; pos++) {
    total += arr[pos];
  }
  return total;
};</pre>
<h4>3. You should be able to remove an item from an array</h4>
<pre class="brush: jscript; title: ; notranslate">fn = function (arr, itemToRemove) {
  for (var pos=0; pos &lt; arr.length; pos++){
    if (arr[pos] == itemToRemove){
      var removedItem = arr.splice(pos,1);
    }
  }
  return arr;
};</pre>
<h4>4. You should be able to add an item to the end of an array</h4>
<pre class="brush: jscript; title: ; notranslate">fn = function (arr, itemToAdd) {
  arr.push(itemToAdd);
  return arr;
};</pre>
<h4>5. You should be able to create an array from two arrays</h4>
<pre class="brush: jscript; title: ; notranslate">fn = function (arr1, arr2) {
  var arr = arr1.concat(arr2);
  return arr;
};</pre>
<h4>6. You should be able to add an item anywhere in an array</h4>
<pre class="brush: jscript; title: ; notranslate">fn = function (arr, itemToAdd, pos) {
  arr.splice(pos, 0, itemToAdd);
  return arr;
};</pre>
<h2>Objects and context</h2>
<h4>1. You should be able to alter the context in which a method runs</h4>
<pre class="brush: jscript; title: ; notranslate">fn = function () {
  // Call the sayIt() function and pass it the
  // 'b' object as its context.
  return a.sayIt.call(b);
};</pre>
<h4>2. You should be able to alter multiple objects at once</h4>
<pre class="brush: jscript; title: ; notranslate">fn = function (greeting) {
  C.prototype.greeting = greeting;
};</pre>
<h4>3. You should be able to iterate over an object&#8217;s &#8216;own&#8217; properties</h4>
<pre class="brush: jscript; title: ; notranslate">fn = function (obj) {
  var ownProperties = [];
  for (var prop in obj) {
    // hasOwnProperty returns true if the property
    // belongs to the object, not its prototype chain.
    if (obj.hasOwnProperty(prop)) {
      ownProperties.push(prop + ': ' + obj[prop]);
    }
  }
  return ownProperties;
};</pre>
<h2>Functions</h2>
<h4>1. You should be able to use an array as arguments when calling a function</h4>
<pre class="brush: jscript; title: ; notranslate">fn = function (opts) {
  // Call the sayIt() function in the context of 'this'
  // and pass it the 'opts' array.
  return sayIt.apply(this, opts);
};</pre>
<h4>2. You should be able to change the context in which a function is called</h4>
<pre class="brush: jscript; title: ; notranslate">fn = function (opts){
  // Call the speak() function in the context of 'obj'.
  return speak.call(obj);
};</pre>
<h4>3. You should be able to return a function from a function</h4>
<pre class="brush: jscript; title: ; notranslate">fn = function (prefix) {
  var concatFn = function(suffix) {
    return prefix + ', ' + suffix;
  };
  return concatFn;
};</pre>
<h4>4. You should be able to create a &#8216;partial&#8217; function</h4>
<pre class="brush: jscript; title: ; notranslate">fn = function (func, greeting, name) {
  var partialFn = function(punctuation) {
    return func(greeting, name, punctuation);
  };
  return partialFn;
};</pre>
<h2>Async behavior</h2>
<h4>1. You should understand how to uses &#8216;promises&#8217;</h4>
<p>As far as I know promises are not part of the JavaScript language, and need to be implemented using a third party library. In my solution I used jQuery&#8217;s <a href="http://api.jquery.com/deferred.promise/">deferred object</a> to return a promise.</p>
<pre class="brush: jscript; title: ; notranslate">fn = function () {
  // This is a contrived example to demonstrate that the promise
  // is returned asynchronously after a 1sec timeout.
  var dfd = $.Deferred();
  var timeoutID = window.setTimeout(function(){
    dfd.resolve(true);
  }, 1000);
  return dfd.promise();
};</pre>
<h4>2. You should be able to receive data from the server and manipulate it</h4>
<pre class="brush: jscript; title: ; notranslate">var get = $.ajax({
  url: url
});

// Since jQuery's $.ajax returns a promise, we can use
// .done and .fail callbacks.
get.done(function(response){
  peopleArray = [];
    for (var person in response.people){
      peopleArray.push(response.people[person].name);
    }
    peopleArray.sort(); // Not required in this case.
    tests();
});

get.fail(function(){
  console.log('Load failed');
});</pre>
<h2>Backbone views</h2>
<p>This section of the test relies on knowledge of the <a href="http://documentcloud.github.com/backbone/">Backbone</a> framework. Personally that doesn&#8217;t bother me since I have used Backbone before, but I&#8217;m not sure that Backbone knowledge should be considered mandatory for a JavaScript professional.</p>
<h4>1. You should be able to render a view using a template</h4>
<pre class="brush: jscript; title: ; notranslate">var MyView = Backbone.View.extend({
  template : tpl,
  render : function() {
    // This could be written on a single line, but I've
    // split across 3 lines for readability:
    var compiledTemplate = _.template(this.template);
    var viewHTML = compiledTemplate(this.model.toJSON());
    $('body').append(viewHTML);
  }
});</pre>
<h4>2. You should be able to update the view when the model changes</h4>
<pre class="brush: jscript; title: ; notranslate">var MyView = Backbone.View.extend({
  initialize : function() {
    this.model.bind('change:greeting', this.render, this);
    this.model.set({greeting: 'Goodbye, world'});
  },
  template : tpl,
  render : function() {
    $('#my-view').html(this.model.get('greeting'));
  }
});</pre>
<img src="http://feeds.feedburner.com/~r/PixelAcres/~4/4LvIuZyxhuw" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://f6design.com/journal/2012/04/15/test-your-javascript-skills-with-js-assessment/feed/</wfw:commentRss>
		<slash:comments>6</slash:comments>
		<feedburner:origLink>http://f6design.com/journal/2012/04/15/test-your-javascript-skills-with-js-assessment/</feedburner:origLink></item>
		<item>
		<title>Don’t believe the hype</title>
		<link>http://feedproxy.google.com/~r/PixelAcres/~3/Ixz2_qbGCGs/</link>
		<comments>http://f6design.com/journal/2012/04/12/dont-believe-the-hype/#comments</comments>
		<pubDate>Fri, 13 Apr 2012 03:17:27 +0000</pubDate>
		<dc:creator>Jonathan</dc:creator>
				<category><![CDATA[Business]]></category>
		<category><![CDATA[Programming]]></category>

		<guid isPermaLink="false">http://f6design.com/journal/?p=2329</guid>
		<description><![CDATA[This week I came across a new JavaScript framework, called Meteor, which promises to simplify the process of developing web applications. It looks like an interesting project, run by some very smart and talented people, but something about the Meteor marketing pitch rubbed me the wrong way. The Meteor website is full of claims about [...]]]></description>
			<content:encoded><![CDATA[<p>This week I came across a new JavaScript framework, called <a href="http://meteor.com">Meteor</a>, which promises to simplify the process of developing web applications. It looks like an interesting project, run by some very smart and talented people, but something about the Meteor marketing pitch rubbed me the wrong way.</p>
<p>The Meteor website is full of claims about how amazingly easy the framework will make web developer&#8217;s lives. It will allow us to build &#8220;top-quality web apps in a fraction of the time.&#8221; Its demo applications require &#8220;no programming knowledge.&#8221; What &#8220;once took weeks, even with the best tools, now takes hours.&#8221; In fact, you can &#8220;build a complete application in a weekend.&#8221;</p>
<p>If building Facebook or Twitter was really something that could be done in a weekend, wouldn&#8217;t everyone and their dog be CEO of their own Internet startup? If the barrier to entry was as low as the Meteor team would have us believe, then business owners would have no need for developers at all &#8211; a few hours of training and they&#8217;d have all the skills required to build their own app or website.</p>
<p>Obviously that&#8217;s not the case. Success in any field is hard earned, and it bugs me that some of our industry&#8217;s leaders perpetuate the idea that there are short cuts to becoming an accomplished web developer. Sure, it&#8217;s <em>possible</em> to build a killer app in a weekend, but to do so requires years of experience and a deep knowledge of your tools, and many more days, weeks, or months are required to turn that prototype into a robust website or application.</p>
<p>It may sound as if my gripe is with Meteor specifically, but that isn&#8217;t the case. I see similarly hyperbolic claims wherever I look. Publishers hawk their technical reference books with promises to convert novice coders into &#8220;ninjas&#8221;. The sales pitch for a commercial iOS design tutorial implies that it can &#8220;make you tons of money, and elevate your status within the design community&#8221;. An advertisement for <a href="http://teamtreehouse.com/">Treehouse</a> suggests that after joining their service you&#8217;ll soon be rubbing shoulders with Mark Zuckerberg. If you take these claims at face value you could be forgiven for thinking that all that is required to excel as a developer is a few hours of your time, a couple of hundred bucks to spend on training, and the right JavaScript framework.</p>
<p>In reality, web design and development are highly specialised disciplines that take years of practice to master, and require ongoing training to stay abreast of the near-constant advances in the field. I don&#8217;t think it does our industry any favours to pretend that mastery can be achieved in a weekend. If we don&#8217;t take our own professional expertise seriously, why should anyone else?</p>
<img src="http://feeds.feedburner.com/~r/PixelAcres/~4/Ixz2_qbGCGs" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://f6design.com/journal/2012/04/12/dont-believe-the-hype/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		<feedburner:origLink>http://f6design.com/journal/2012/04/12/dont-believe-the-hype/</feedburner:origLink></item>
		<item>
		<title>Launching XAMPP at OSX startup</title>
		<link>http://feedproxy.google.com/~r/PixelAcres/~3/7_qZgAVd3Ss/</link>
		<comments>http://f6design.com/journal/2012/03/12/launching-xampp-at-osx-startup/#comments</comments>
		<pubDate>Mon, 12 Mar 2012 21:42:14 +0000</pubDate>
		<dc:creator>Jonathan</dc:creator>
				<category><![CDATA[Programming]]></category>
		<category><![CDATA[Technology]]></category>

		<guid isPermaLink="false">http://f6design.com/journal/?p=2298</guid>
		<description><![CDATA[A few days ago I posted about my experiences setting up XAMPP on OSX. Here&#8217;s another little XAMPP tip&#8230; By default XAMPP won&#8217;t start the Apache and MySQL services at system startup, so every time you reboot your computer you&#8217;ll need to restart them. Wouldn&#8217;t it be nice if those services started automatically? One way [...]]]></description>
			<content:encoded><![CDATA[<p>A few days ago I posted about my experiences setting up XAMPP on OSX. Here&#8217;s another little XAMPP tip&#8230;</p>
<p>By default XAMPP won&#8217;t start the Apache and MySQL services at system startup, so every time you reboot your computer you&#8217;ll need to restart them. Wouldn&#8217;t it be nice if those services started automatically? One way of doing that is to create a Launch Daemon that runs at system startup and have it start XAMPP for us.</p>
<p>Fire up Terminal, and run the following command:</p>
<pre class="brush: bash; title: ; notranslate">cd /Library/LaunchDaemons
sudo nano apachefriends.xampp.apache.start.plist</pre>
<p>Enter your OSX password when prompted, then in <a href="http://en.wikipedia.org/wiki/GNU_nano">nano</a> paste the following into your new plist:</p>
<pre class="brush: xml; title: ; notranslate">&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot;?&gt;
&lt;!DOCTYPE plist PUBLIC &quot;-//Apple//DTD PLIST 1.0//EN&quot; &quot;http://www.apple.com/DTDs/PropertyList-1.0.dtd&quot;&gt;
&lt;plist version=&quot;1.0&quot;&gt;
&lt;dict&gt;
&lt;key&gt;EnableTransactions&lt;/key&gt;
&lt;true/&gt;
&lt;key&gt;Label&lt;/key&gt;
&lt;string&gt;apachefriends.xampp.apache.start&lt;/string&gt;
&lt;key&gt;ProgramArguments&lt;/key&gt;
&lt;array&gt;
&lt;string&gt;/Applications/XAMPP/xamppfiles/xampp&lt;/string&gt;
&lt;string&gt;startapache&lt;/string&gt;
&lt;/array&gt;
&lt;key&gt;RunAtLoad&lt;/key&gt;
&lt;true/&gt;
&lt;key&gt;WorkingDirectory&lt;/key&gt;
&lt;string&gt;/Applications/XAMPP/xamppfiles&lt;/string&gt;
&lt;key&gt;KeepAlive&lt;/key&gt;
&lt;false/&gt;
&lt;key&gt;AbandonProcessGroup&lt;/key&gt;
&lt;true/&gt;
&lt;/dict&gt;
&lt;/plist&gt;</pre>
<p>Save the file and exit nano (<code>control+o</code>, <code>return</code>, <code>control+x</code>).</p>
<p>Now run the following terminal command:</p>
<pre class="brush: bash; title: ; notranslate">sudo nano apachefriends.xampp.mysql.start.plist</pre>
<p>And into this new file paste:</p>
<pre class="brush: xml; title: ; notranslate">&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot;?&gt;
&lt;!DOCTYPE plist PUBLIC &quot;-//Apple//DTD PLIST 1.0//EN&quot; &quot;http://www.apple.com/DTDs/PropertyList-1.0.dtd&quot;&gt;
&lt;plist version=&quot;1.0&quot;&gt;
&lt;dict&gt;
&lt;key&gt;EnableTransactions&lt;/key&gt;
&lt;true/&gt;
&lt;key&gt;Label&lt;/key&gt;
&lt;string&gt;apachefriends.xampp.mysql.start&lt;/string&gt;
&lt;key&gt;ProgramArguments&lt;/key&gt;
&lt;array&gt;
&lt;string&gt;/Applications/XAMPP/xamppfiles/xampp&lt;/string&gt;
&lt;string&gt;startmysql&lt;/string&gt;
&lt;/array&gt;
&lt;key&gt;RunAtLoad&lt;/key&gt;
&lt;true/&gt;
&lt;key&gt;WorkingDirectory&lt;/key&gt;
&lt;string&gt;/Applications/XAMPP/xamppfiles&lt;/string&gt;
&lt;key&gt;KeepAlive&lt;/key&gt;
&lt;false/&gt;
&lt;key&gt;AbandonProcessGroup&lt;/key&gt;
&lt;true/&gt;
&lt;/dict&gt;
&lt;/plist&gt;</pre>
<p>Save the file and exit nano (<code>control+o</code>, <code>return</code>, <code>control+x</code>).</p>
<p>When you restart your computer the XAMPP Apache and MySQL services should start automatically. You can check this by launching XAMPP Control and checking that Apache and MySQL have green lights displayed next to them.</p>
<h3>A note about security</h3>
<p>If you&#8217;re concerned about the security of your system while running XAMPP, the safest approach is not to run Apache or MySQL at all, in which case you might not want to have those services running while you&#8217;re not using them. However, I&#8217;m fairly certain that unless you intentionally open up port 80 in your hardware/software firewall your XAMPP server should be invisible outside your local network.</p>
<h3>Credit</h3>
<p>A hat tip to &#8216;cwd&#8217;, who <a href="http://superuser.com/questions/243606/i-cant-get-xampp-to-start-automatically-in-os-x">posted this solution</a> on Superuser. I tried a couple of other approaches before I stumbled upon this one which actually works.</p>
<img src="http://feeds.feedburner.com/~r/PixelAcres/~4/7_qZgAVd3Ss" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://f6design.com/journal/2012/03/12/launching-xampp-at-osx-startup/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		<feedburner:origLink>http://f6design.com/journal/2012/03/12/launching-xampp-at-osx-startup/</feedburner:origLink></item>
		<item>
		<title>Configuring VirtualHosts in XAMPP on Mac</title>
		<link>http://feedproxy.google.com/~r/PixelAcres/~3/XssLSnzBkKg/</link>
		<comments>http://f6design.com/journal/2012/03/11/configuring-virtualhosts-in-xampp-on-mac/#comments</comments>
		<pubDate>Sun, 11 Mar 2012 12:02:51 +0000</pubDate>
		<dc:creator>Jonathan</dc:creator>
				<category><![CDATA[Programming]]></category>
		<category><![CDATA[Technology]]></category>

		<guid isPermaLink="false">http://f6design.com/journal/?p=2242</guid>
		<description><![CDATA[A few weeks back I rejoined the &#8220;Cult of Mac&#8221; when I replaced my old Asus notebook with a MacBook Pro, and since then I&#8217;ve been busy settling into my new OSX workflow. I do all my development locally, so one of the first applications I installed was XAMPP, a cross platform Apache/MySQL/PHP stack. While [...]]]></description>
			<content:encoded><![CDATA[<p>A few weeks back I rejoined the &#8220;Cult of Mac&#8221; when I replaced my old Asus notebook with a MacBook Pro, and since then I&#8217;ve been busy settling into my new OSX workflow. I do all my development locally, so one of the first applications I installed was <a href="http://www.apachefriends.org/en/xampp-macosx.html">XAMPP</a>, a cross platform Apache/MySQL/PHP stack. While I know that <a href="http://www.mamp.info/">MAMP</a> is very popular on Mac, I have been using XAMPP for many years so I thought I&#8217;d stick with what I know.</p>
<p>Installing XAMPP was a snap, but when I came to create my own <a href="http://httpd.apache.org/docs/2.0/vhosts/">Apache VirtualHosts</a> things started getting fiddly. Here are the steps I followed to get everything running smoothly.</p>
<h3>What are VirtualHosts?</h3>
<p>First, some quick background on what we&#8217;re trying to achieve.</p>
<p>VirtualHosts allow Apache to map a hostname to a directory on the filesystem. You can set up as many VirtualHosts as you need, so that each website operates under its own hostname. For example, you might want to map <code>mysite.local</code> to <code>/Users/yourusername/mysite</code>. To test your development site all you would need to do is plug &#8220;http://mysite.local&#8221; into your browser&#8217;s address bar.</p>
<h3>Enable VirtualHosts</h3>
<p>The first thing you&#8217;ll need to do is open the file <code>/Applications/XAMPP/xamppfile/etc/httpd.conf</code> in your favourite text editor. Look for the following lines:</p>
<pre class="brush: plain; title: ; notranslate"># Virtual hosts
#Include /Applications/XAMPP/etc/extra/httpd-vhosts.conf</pre>
<p>Uncomment the second line by removing the hash (<code>#</code>), so that Apache loads your custom VirtualHosts configuration file:</p>
<pre class="brush: plain; title: ; notranslate"># Virtual hosts
Include /Applications/XAMPP/etc/extra/httpd-vhosts.conf</pre>
<h3>Create your VirtualHosts</h3>
<p>Open the file <code>/Applications/XAMPP/xamppfile/etc/extra/httpd-vhosts.conf</code>. Towards the bottom of the file you will see some example VirtualHosts, which you should comment out or delete.</p>
<p>At the bottom of the file, add &#8216;localhost&#8217; as the default named VirtualHost:</p>
<pre class="brush: plain; title: ; notranslate"># localhost
&lt;VirtualHost *:80&gt;
    ServerName localhost
    DocumentRoot &quot;/Applications/XAMPP/htdocs&quot;
    &lt;Directory &quot;/Applications/XAMPP/htdocs&quot;&gt;
        Options Indexes FollowSymLinks Includes execCGI
        AllowOverride None
        Order Allow,Deny
        Allow From All
    &lt;/Directory&gt;
&lt;/VirtualHost&gt;</pre>
<p>This step is necessary to ensure that http://localhost still points at XAMPP&#8217;s <code>htdocs</code> directory once we&#8217;ve created our custom VirtualHosts. Personally I don&#8217;t use the <code>htdocs</code> directory a lot, but occasionally it&#8217;s useful to have somewhere to perform quick tests.</p>
<p>Now you are ready to create your own VirtualHosts. After the default localhost that you just created, add:</p>
<pre class="brush: plain; title: ; notranslate"># My custom host
&lt;VirtualHost *:80&gt;
    ServerName mysite.local
    DocumentRoot &quot;/Users/yourusername/path/to/your/site&quot;
    &lt;Directory &quot;/Users/yourusername/path/to/your/site&quot;&gt;
        Options Indexes FollowSymLinks Includes ExecCGI
        AllowOverride None
        Order Allow,Deny
        Allow From All
    &lt;/Directory&gt;
    ErrorLog &quot;logs/mysite.local-error_log&quot;
&lt;/VirtualHost&gt;</pre>
<p>In the above example you should replace &#8220;mysite.local&#8221; with your own hostname. This can be anything you wish, but make sure you choose a hostname that won&#8217;t conflict with a real domain name. Using a .local extension makes it obvious that the site is hosted locally rather than on a public web server.</p>
<p>The path to your website can point at any folder in your OSX user directory. I store most of my sites inside of <a href="https://www.dropbox.com/">Dropbox</a> so that I can access them on both my home and work machines. If your path includes spaces, make sure you enclose it in quotes, like in my example.</p>
<h3>Edit your hosts file</h3>
<p>Once you&#8217;ve saved your <code>httpd.conf</code> and <code>httpd-vhosts.conf</code> files, the next step is to edit your OSX <a href="http://en.wikipedia.org/wiki/Hosts_(file)">hosts file</a> so it knows how to handle your new <code>ServerName</code>. The hosts file is used by OSX to map hostnames to IP addresses. In this case we want to map your new <code>ServerName</code> to the IP address 127.0.0.1, which is your localhost.</p>
<p>Fire up a Terminal instance, and at the prompt type the following command:</p>
<pre class="brush: bash; title: ; notranslate">sudo nano /etc/hosts</pre>
<p>Enter your OSX password when prompted, and the hosts file will be opened in the <a href="http://en.wikipedia.org/wiki/GNU_nano">nano</a> text editor. You&#8217;ll see that the hosts file already contains some default hostname mappings (e.g. &#8220;127.0.0.1 localhost&#8221;). Use your keyboard&#8217;s arrow keys to navigate to the bottom of the file and add your own mapping:</p>
<pre class="brush: plain; title: ; notranslate"># XAMPP VirtualHost mappings
127.0.0.1 mysite.local</pre>
<p>Save the host file using the key combo <code>control+o</code>, and pressing return when prompted to choose the filename. Close the file using <code>control+x</code>.</p>
<h3>Restart Apache</h3>
<p>So that your changes take effect, restart Apache. This can be done using XAMPP Control, which is found at <code>/Applications/XAMPP/XAMPP Control.app</code>.</p>
<p>Point your browser at http://mysite.local (or whatever ServerName you chose) and you should see your website. However, there&#8217;s a chance that instead you&#8217;ll be faced with a&#8230;</p>
<h3>403 error</h3>
<p>Because Apache runs as the &#8216;nobody&#8217; user by default, it may not have adequate permission to browse your OSX user directory or some of its subdirectories, in which case you&#8217;ll see a 403 &#8216;access forbidden&#8217; error when you try and view your development site. Similarly, you may find that although you can view your dev site, PHP throws errors when you attempt to write files or make directories on the filesystem.</p>
<p>To fix this you can configure Apache to run as your OSX user. Open <code>/Applications/XAMPP/xamppfile/etc/httpd.conf</code> and look for the following lines:</p>
<pre class="brush: plain; title: ; notranslate"># User/Group: The name (or #number) of the user/group to run httpd as.
# It is usually good practice to create a dedicated user and group for
# running httpd, as with most system services.
#
User nobody
Group nogroup</pre>
<p>Change <code>User</code> to your OSX username, and save the file:</p>
<pre class="brush: plain; title: ; notranslate">User yourusername</pre>
<p>Restart Apache and you should now be able to navigate your site without any issues, including manipulating files and folders using PHP.</p>
<p>Making the change I&#8217;ve described above carries certain security risks, and if you choose to run Apache as your OSX user then you&#8217;ll need to be quite certain that XAMPP is not accessible from outside your local network. From what I understand, XAMPP&#8217;s built in security features ensure that <a href="http://bravo.newnetenterprises.com/wordpress/xampp/the-basics-of-xampp-security/">this is the case</a> out-of-the-box, and it is straightforward to <a href="http://www.apachefriends.org/en/xampp-macosx.html#873">beef up security</a> for additional piece of mind.</p>
<p>If you&#8217;re not convinced that it&#8217;s safe to let Apache run as your OSX user, another option is to <a href="http://stackoverflow.com/questions/2001881/correct-owner-group-permissions-for-apache-2-site-files-folders-under-mac-os-x">change the permissions</a> of your dev directories so that the &#8216;nobody&#8217; or &#8216;_www&#8217; user can read/write to them.I suspect that I would quickly tire of setting folder permissions, which is why I have opted to take the path of least resistance!</p>
<h3>Conclusion</h3>
<p>Hopefully this post helps someone else to get XAMPP up and running on OSX. I imagine that MAMP Pro streamlines this process somewhat (I know it has a wizard for creating VirtualHosts), but as long as you don&#8217;t mind getting your hands dirty XAMPP is a fantastic way to learn how Apache actually works.</p>
<img src="http://feeds.feedburner.com/~r/PixelAcres/~4/XssLSnzBkKg" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://f6design.com/journal/2012/03/11/configuring-virtualhosts-in-xampp-on-mac/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		<feedburner:origLink>http://f6design.com/journal/2012/03/11/configuring-virtualhosts-in-xampp-on-mac/</feedburner:origLink></item>
		<item>
		<title>Responsive elements that retain their aspect ratio</title>
		<link>http://feedproxy.google.com/~r/PixelAcres/~3/abnbmtfbr7Y/</link>
		<comments>http://f6design.com/journal/2011/10/18/responsive-elements-that-retain-their-aspect-ratio/#comments</comments>
		<pubDate>Tue, 18 Oct 2011 22:56:57 +0000</pubDate>
		<dc:creator>Jonathan</dc:creator>
				<category><![CDATA[CSS]]></category>

		<guid isPermaLink="false">http://f6design.com/journal/?p=2194</guid>
		<description><![CDATA[Here is a quick tip for creating responsive elements that retain their aspect ratio as they scale. The problem In a fixed width layout it is simple to specify both the width and the height of an element: .rect &#123; width: 800px; height: 400px; &#125; When creating a responsive layout things get trickier, since (to [...]]]></description>
			<content:encoded><![CDATA[<p>Here is a quick tip for creating responsive elements that retain their aspect ratio as they scale.</p>
<h3>The problem</h3>
<p>In a fixed width layout it is simple to specify both the width and the height of an element:</p>

<div class="wp_syntax"><div class="code"><pre class="css" style="font-family:monospace;"><span style="color: #6666ff;">.rect</span> <span style="color: #00AA00;">&#123;</span>
    <span style="color: #000000; font-weight: bold;">width</span><span style="color: #00AA00;">:</span> <span style="color: #933;">800px</span><span style="color: #00AA00;">;</span>
    <span style="color: #000000; font-weight: bold;">height</span><span style="color: #00AA00;">:</span> <span style="color: #933;">400px</span><span style="color: #00AA00;">;</span>
<span style="color: #00AA00;">&#125;</span></pre></div></div>

<p>When creating a responsive layout things get trickier, since (to the best of my knowledge) it isn&#8217;t possible to specify a percentage based height that is relative to an element&#8217;s width. For example the following CSS rule won&#8217;t have the desired result, since the <code>height</code> value will be ignored:</p>

<div class="wp_syntax"><div class="code"><pre class="css" style="font-family:monospace;"><span style="color: #6666ff;">.rect</span> <span style="color: #00AA00;">&#123;</span>
    <span style="color: #000000; font-weight: bold;">width</span><span style="color: #00AA00;">:</span> <span style="color: #933;">100%</span><span style="color: #00AA00;">;</span>
    <span style="color: #000000; font-weight: bold;">height</span><span style="color: #00AA00;">:</span> <span style="color: #933;">50%</span><span style="color: #00AA00;">;</span>
<span style="color: #00AA00;">&#125;</span></pre></div></div>

<p><img src="http://f6design.com/journal/wp-content/uploads/2011/10/ar-broken-578w.png" alt="Broken aspect ratio" width="578" height="56" class="contentImg" /></p>
<h3>A solution</h3>
<p>However, when we specify a <code>padding-bottom</code> value for the same element, the padding measurement <em>is</em> calculated relative to the element&#8217;s width:</p>

<div class="wp_syntax"><div class="code"><pre class="css" style="font-family:monospace;"><span style="color: #6666ff;">.rect</span> <span style="color: #00AA00;">&#123;</span>
    <span style="color: #000000; font-weight: bold;">width</span><span style="color: #00AA00;">:</span> <span style="color: #933;">100%</span><span style="color: #00AA00;">;</span>
    <span style="color: #000000; font-weight: bold;">height</span><span style="color: #00AA00;">:</span> <span style="color: #cc66cc;">0</span><span style="color: #00AA00;">;</span>
    <span style="color: #000000; font-weight: bold;">padding-bottom</span><span style="color: #00AA00;">:</span> <span style="color: #933;">50%</span><span style="color: #00AA00;">;</span>
<span style="color: #00AA00;">&#125;</span></pre></div></div>

<p><img src="http://f6design.com/journal/wp-content/uploads/2011/10/ar-working-578w.png" alt="Correct aspect ratio" width="578" height="308" class="contentImg" /></p>
<p><a href="http://f6design.com/projects/responsive-aspect-ratio/">View a demo</a></p>
<p>You will notice that I have set the element&#8217;s <code>height</code> property to <code>0</code>, to ensure that the height of any child elements will not be added to the padding value when the visible height is calculated. </p>
<h3>A note about child elements</h3>
<p>If you also want to specify percentage based heights for a child element, you will need to assign an <code>absolute</code> or <code>relative</code> <code>position</code> value to both the parent and the child:</p>

<div class="wp_syntax"><div class="code"><pre class="css" style="font-family:monospace;"><span style="color: #6666ff;">.rect</span> <span style="color: #00AA00;">&#123;</span>
    <span style="color: #000000; font-weight: bold;">position</span><span style="color: #00AA00;">:</span> <span style="color: #993333;">relative</span><span style="color: #00AA00;">;</span>
    <span style="color: #000000; font-weight: bold;">width</span><span style="color: #00AA00;">:</span> <span style="color: #933;">100%</span><span style="color: #00AA00;">;</span>
    <span style="color: #000000; font-weight: bold;">height</span><span style="color: #00AA00;">:</span> <span style="color: #cc66cc;">0</span><span style="color: #00AA00;">;</span>
    <span style="color: #000000; font-weight: bold;">padding-bottom</span><span style="color: #00AA00;">:</span> <span style="color: #933;">50%</span><span style="color: #00AA00;">;</span>
    <span style="color: #00AA00;">&#125;</span>
    <span style="color: #6666ff;">.rect</span> p <span style="color: #00AA00;">&#123;</span>
        <span style="color: #000000; font-weight: bold;">position</span><span style="color: #00AA00;">:</span> <span style="color: #993333;">absolute</span><span style="color: #00AA00;">;</span>
        <span style="color: #000000; font-weight: bold;">margin</span><span style="color: #00AA00;">:</span> <span style="color: #cc66cc;">0</span><span style="color: #00AA00;">;</span>
        <span style="color: #000000; font-weight: bold;">height</span><span style="color: #00AA00;">:</span> <span style="color: #933;">100%</span><span style="color: #00AA00;">;</span>
        <span style="color: #00AA00;">&#125;</span></pre></div></div>

<p><a href="http://f6design.com/projects/responsive-aspect-ratio/absolute.html">View a demo</a></p>
<img src="http://feeds.feedburner.com/~r/PixelAcres/~4/abnbmtfbr7Y" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://f6design.com/journal/2011/10/18/responsive-elements-that-retain-their-aspect-ratio/feed/</wfw:commentRss>
		<slash:comments>5</slash:comments>
		<feedburner:origLink>http://f6design.com/journal/2011/10/18/responsive-elements-that-retain-their-aspect-ratio/</feedburner:origLink></item>
		<item>
		<title>Build a parallax scrolling website interface with jQuery and CSS</title>
		<link>http://feedproxy.google.com/~r/PixelAcres/~3/Ac87-s3Q-Yc/</link>
		<comments>http://f6design.com/journal/2011/08/06/build-a-parallax-scrolling-website-interface-with-jquery-and-css/#comments</comments>
		<pubDate>Sun, 07 Aug 2011 02:36:52 +0000</pubDate>
		<dc:creator>Jonathan</dc:creator>
				<category><![CDATA[CSS]]></category>
		<category><![CDATA[HTML/XHTML]]></category>
		<category><![CDATA[Programming]]></category>
		<category><![CDATA[Web Design]]></category>

		<guid isPermaLink="false">http://f6design.com/journal/?p=2141</guid>
		<description><![CDATA[Parallax scrolling website interfaces have been popping up all over the place recently. I didn&#8217;t want to miss out on the fun, so I have put together a parallax scrolling demo built using jQuery and CSS. Parallax what? Even if you&#8217;re not familiar with the term &#8220;parallax scrolling&#8221; you will certainly be familiar with the [...]]]></description>
			<content:encoded><![CDATA[<p>Parallax scrolling website interfaces have been popping up all over the place recently. I didn&#8217;t want to miss out on the fun, so I have put together a parallax scrolling demo built using jQuery and CSS.</p>
<p><a href="http://f6design.com/projects/parallax-scrolling/"><img src="http://f6design.com/journal/wp-content/uploads/2011/08/parallax-screenshot-578w.jpg" alt="Parallax scrolling interface" width="578" height="423" class="contentImg" /></a></p>
<h3>Parallax what?</h3>
<p>Even if you&#8217;re not familiar with the term &#8220;parallax scrolling&#8221; you will certainly be familiar with the technique. <a href="http://en.wikipedia.org/wiki/Parallax_scrolling">Parallax scrolling</a> is a 2d animation process that creates an illusion of depth by animating foreground layers faster than background layers. When you observe the landscape from a moving car, objects closer to the car appear to pass you faster than scenery further away. Parallax scrolling uses the same principle to trick the viewer into thinking they are observing a 3d scene.</p>
<h3>Demo and Download</h3>
<p>My demo web page shows one approach to building a vertical parallax scrolling interface:</p>
<p><a href="http://f6design.com/projects/parallax-scrolling/">View demo</a><br />
<a href="http://f6design.com/projects/parallax-scrolling/parallax-scrolling-demo.zip">Download source</a></p>
<p>You can scroll in the usual fashion, use the navigation menu at the right-hand side of the page, or the next/prev buttons that appear underneath each article. As you scroll, the page&#8217;s four content layers are animated independently of one another to create an illusion of depth.</p>
<p>The scrolling looks smoothest in Safari (at least that&#8217;s the case on my PC), but my demo should work in any modern browser.</p>
<p><em><strong>Disclaimer 1:</strong> Because this is just an experiment I&#8217;ve not spent any time optimising the demo to work on mobile devices. I wanted to keep the demo lean &#8216;n&#8217; mean, and not clutter it by sniffing mobile browsers and forking my code. On a production site you&#8217;d want to ensure that the site degrades gracefully on mobile devices, where scroll events and fixed positioning might work in unexpected ways.</em></p>
<p><em><strong>Disclaimer 2:</strong> The navigation menu in my demo is inspired by the menu on the Nike <a href="http://www.nikebetterworld.com/">Better World</a> website. If you plan on implementing a similar menu on a production site, please be aware of its origin.</em></p>
<h3>How it works</h3>
<p>The articles and background layers are given a fixed positioned with CSS, and assigned a <code>z-index</code> so that the foreground layers appear above the background layers. The four layers are: small clouds, large clouds, balloon/landscape images, articles.</p>

<div class="wp_syntax"><div class="code"><pre class="css" style="font-family:monospace;"><span style="color: #808080; font-style: italic;">/* foreground (ballons/landscape) */</span>
<span style="color: #cc00cc;">#parallax-bg3</span> <span style="color: #00AA00;">&#123;</span>
    <span style="color: #000000; font-weight: bold;">z-index</span><span style="color: #00AA00;">:</span> <span style="color: #cc66cc;">3</span><span style="color: #00AA00;">;</span>
    <span style="color: #000000; font-weight: bold;">position</span><span style="color: #00AA00;">:</span> <span style="color: #993333;">fixed</span><span style="color: #00AA00;">;</span>
    <span style="color: #000000; font-weight: bold;">left</span><span style="color: #00AA00;">:</span> <span style="color: #933;">50%</span><span style="color: #00AA00;">;</span> <span style="color: #808080; font-style: italic;">/* align left edge with center of viewport */</span>
    <span style="color: #000000; font-weight: bold;">top</span><span style="color: #00AA00;">:</span> <span style="color: #cc66cc;">0</span><span style="color: #00AA00;">;</span>
    <span style="color: #000000; font-weight: bold;">width</span><span style="color: #00AA00;">:</span> <span style="color: #933;">940px</span><span style="color: #00AA00;">;</span>
    <span style="color: #000000; font-weight: bold;">margin-left</span><span style="color: #00AA00;">:</span> <span style="color: #933;">-470px</span><span style="color: #00AA00;">;</span> <span style="color: #808080; font-style: italic;">/* move left by half element's width */</span>
<span style="color: #00AA00;">&#125;</span></pre></div></div>

<p>Within each layer individual content elements are absolutely positioned. This was the most fiddly part of the process, since the elements need to positioned in such a way that they align in a pleasing manner when the user scrolls to any of the four articles. In this case it was really just a process of trial and error.</p>

<div class="wp_syntax"><div class="code"><pre class="css" style="font-family:monospace;"><span style="color: #cc00cc;">#bg3-1</span> <span style="color: #00AA00;">&#123;</span>
    <span style="color: #000000; font-weight: bold;">position</span><span style="color: #00AA00;">:</span> <span style="color: #993333;">absolute</span><span style="color: #00AA00;">;</span>
    <span style="color: #000000; font-weight: bold;">top</span><span style="color: #00AA00;">:</span> <span style="color: #933;">-111px</span><span style="color: #00AA00;">;</span>
    <span style="color: #000000; font-weight: bold;">left</span><span style="color: #00AA00;">:</span> <span style="color: #933;">355px</span><span style="color: #00AA00;">;</span>
<span style="color: #00AA00;">&#125;</span>
<span style="color: #cc00cc;">#bg3-2</span> <span style="color: #00AA00;">&#123;</span>
    <span style="color: #000000; font-weight: bold;">position</span><span style="color: #00AA00;">:</span> <span style="color: #993333;">absolute</span><span style="color: #00AA00;">;</span>
    <span style="color: #000000; font-weight: bold;">top</span><span style="color: #00AA00;">:</span> <span style="color: #933;">812px</span><span style="color: #00AA00;">;</span>
    <span style="color: #000000; font-weight: bold;">left</span><span style="color: #00AA00;">:</span> <span style="color: #933;">321px</span><span style="color: #00AA00;">;</span>
<span style="color: #00AA00;">&#125;</span>
<span style="color: #808080; font-style: italic;">/* etc... */</span></pre></div></div>

<p>A few lines of jQuery control the parallax effect, triggered by a scroll event. I was surprised how easy this was to achieve, it is literally just a handful of lines of code.</p>

<div class="wp_syntax"><div class="code"><pre class="javascript" style="font-family:monospace;">$<span style="color: #009900;">&#40;</span>window<span style="color: #009900;">&#41;</span>.<span style="color: #660066;">bind</span><span style="color: #009900;">&#40;</span><span style="color: #3366CC;">'scroll'</span><span style="color: #339933;">,</span><span style="color: #003366; font-weight: bold;">function</span><span style="color: #009900;">&#40;</span>e<span style="color: #009900;">&#41;</span><span style="color: #009900;">&#123;</span>
    parallaxScroll<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
<span style="color: #009900;">&#125;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
<span style="color: #003366; font-weight: bold;">function</span> parallaxScroll<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#123;</span>
    <span style="color: #003366; font-weight: bold;">var</span> scrolled <span style="color: #339933;">=</span> $<span style="color: #009900;">&#40;</span>window<span style="color: #009900;">&#41;</span>.<span style="color: #660066;">scrollTop</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
    $<span style="color: #009900;">&#40;</span><span style="color: #3366CC;">'#parallax-bg1'</span><span style="color: #009900;">&#41;</span>.<span style="color: #660066;">css</span><span style="color: #009900;">&#40;</span><span style="color: #3366CC;">'top'</span><span style="color: #339933;">,</span><span style="color: #009900;">&#40;</span><span style="color: #CC0000;">0</span><span style="color: #339933;">-</span><span style="color: #009900;">&#40;</span>scrolled<span style="color: #339933;">*</span>.25<span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">+</span><span style="color: #3366CC;">'px'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
    $<span style="color: #009900;">&#40;</span><span style="color: #3366CC;">'#parallax-bg2'</span><span style="color: #009900;">&#41;</span>.<span style="color: #660066;">css</span><span style="color: #009900;">&#40;</span><span style="color: #3366CC;">'top'</span><span style="color: #339933;">,</span><span style="color: #009900;">&#40;</span><span style="color: #CC0000;">0</span><span style="color: #339933;">-</span><span style="color: #009900;">&#40;</span>scrolled<span style="color: #339933;">*</span>.5<span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">+</span><span style="color: #3366CC;">'px'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
    $<span style="color: #009900;">&#40;</span><span style="color: #3366CC;">'#parallax-bg3'</span><span style="color: #009900;">&#41;</span>.<span style="color: #660066;">css</span><span style="color: #009900;">&#40;</span><span style="color: #3366CC;">'top'</span><span style="color: #339933;">,</span><span style="color: #009900;">&#40;</span><span style="color: #CC0000;">0</span><span style="color: #339933;">-</span><span style="color: #009900;">&#40;</span>scrolled<span style="color: #339933;">*</span>.75<span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">+</span><span style="color: #3366CC;">'px'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
<span style="color: #009900;">&#125;</span></pre></div></div>

<p>As you can see the CSS <code>top</code> property is used to move each layer as the user scrolls. The foreground layer is always aligned to the top of the document, while the movement of other layers is adjusted according to their depth. The lower a layer sits in the stack, the less distance it is moved.</p>
<p>The rest of the jQuery is concerned with controlling the navigation menus. When the user clicks a navigation button the page scrolls to the top of the associated article. In the event that the user has JavaScript disabled, regular HTML anchor links still allow the page to be navigated, but without any fancy pants animations.</p>
<h3>Next steps</h3>
<p>I&#8217;m sure there are plenty of other approaches to parallax scrolling, and hopefully my experiment provides a starting point for your own explorations of the technique.</p>
<h3>Update</h3>
<p>I have updated the demo so that each parallax layer is given a fixed, rather than absolute, position. This approach gives a smoother scrolling effect.</p>
<img src="http://feeds.feedburner.com/~r/PixelAcres/~4/Ac87-s3Q-Yc" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://f6design.com/journal/2011/08/06/build-a-parallax-scrolling-website-interface-with-jquery-and-css/feed/</wfw:commentRss>
		<slash:comments>70</slash:comments>
		<feedburner:origLink>http://f6design.com/journal/2011/08/06/build-a-parallax-scrolling-website-interface-with-jquery-and-css/</feedburner:origLink></item>
		<item>
		<title>Book Review: Dig Deal</title>
		<link>http://feedproxy.google.com/~r/PixelAcres/~3/9O2SkqjBeZk/</link>
		<comments>http://f6design.com/journal/2011/08/05/book-review-dig-deal/#comments</comments>
		<pubDate>Sat, 06 Aug 2011 05:36:01 +0000</pubDate>
		<dc:creator>Jonathan</dc:creator>
				<category><![CDATA[News & Reviews]]></category>
		<category><![CDATA[Web Design]]></category>

		<guid isPermaLink="false">http://f6design.com/journal/?p=2090</guid>
		<description><![CDATA[Robert Hoekman, Jr is a user experience designer and consultant who is best known for his books about interface design, Designing the Obvious and Designing the Moment. His self-published book Big Deal: On Being Famous to Almost No One tackles a far more personal subject. In Big Deal Hoekman, Jr recounts his rise to the [...]]]></description>
			<content:encoded><![CDATA[<div class="align-right border"><img src="http://f6design.com/journal/wp-content/uploads/2011/08/big-deal-218w.png" alt="Big Deal book cover"  width="218" height="309" class="contentImg" /></div>
<p><a href="http://rhjr.net/">Robert Hoekman, Jr</a> is a user experience designer and consultant who is best known for his books about interface design, <a href="http://www.amazon.com/Designing-Obvious-Common-Approach-Application/dp/032145345X"><i>Designing the Obvious</i></a> and <a href="http://www.amazon.com/Designing-Moment-Interface-Design-Concepts/dp/0321535081"><i>Designing the Moment</i></a>. His self-published book <a href="http://www.goodreads.com/book/show/12254276-big-deal"><i>Big Deal: On Being Famous to Almost No One</i></a> tackles a far more personal subject. In <i>Big Deal</i> Hoekman, Jr recounts his rise to the top of the web design field, and describes how his craving for professional notoriety eventually devastated his personal friendships, marriage, and sense of self worth.</p>
<p>The form of celebrity Hoekman Jr discusses in <i>Big Deal</i> has been dubbed &#8220;micro-fame&#8221;:</p>
<blockquote><p>My name is Robert Hoekman, Jr, and in certain rooms, under certain circumstances, at certain moments, surrounded by certain people, and when all these very certain things come together, I am a big fucking deal.</p></blockquote>
<p>In other words, Hoekman, Jr might be unknown to the general public, but within the web design industry he is a bona fide rock star.</p>
<p>From the unique perspective that this notoriety affords, he takes the reader on a whirlwind tour of the conference rooms, hotel bars, book signings, photo opportunities and corporate retreats that consumed his attention as he rose the ranks of his profession. Along the way we rub shoulders with a veritable who&#8217;s who of the web industry: Matt Mullenweg, Jeff Veen, Jeffrey Zeldman, Caterina Fake, Luke Wroblewski, to name but a few.</p>
<p>Ultimately Hoekman, Jr&#8217;s craving for recognition and approval forces a crisis in his professional and personal life, and he has to face up to the root causes of his obsession with fame, and deal with the fallout.</p>
<p>This makes for fascinating reading, especially for a web design nerd such as myself, but I was left with the nagging feeling that Hoekman, Jr has &#8211; perhaps unwittingly &#8211; used his book about the pitfalls of fame as a platform to reinforce his cool kid credentials.</p>
<p>The nonstop cataloging of his professional achievements came across at times like bragging, and I wish he had dialed the self promotion back a notch. Even in the book&#8217;s later chapters, where he describes a dawning awareness that his obsession with fame is destroying his marriage, the laundry list of book signings and speaking engagements barely slows down. It is as if he wants to remind the reader that even though he no longer <em>cares</em> about being famous, he still <em>is</em> famous. </p>
<p>It is said that that pride comes before a fall, and in <i>Big Deal</i> Hoekman, Jr talks candidly about the flipside of his micro-fame: spiraling self doubt, professional rejection by Apple and Yahoo, isolation from friends, and the collapse of his marriage. It takes guts for a writer to expose their weaknesses so openly, but it feels a little like sitting in on someone else&#8217;s therapy session (in a psychotherapy cliché he lays much of the blame for his low self esteem at the feet of his mother). I imagine the process of writing <i>Big Deal</i> was extremely cathartic, but I question whether the experience of reading the book is  equally enlightening. </p>
<p>The problem is that <i>Big Deal</i> is all about Hoekman, Jr, and frankly I&#8217;m not sure that his personal experiences provide enough material to do the book&#8217;s topic justice. If more of <i>Big Deal</i> had been devoted to examining the impact of micro-fame in a broader context &#8211; the cult of celebrity engendered by social networking services like Twitter, say &#8211; the book might be better rounded, and have a broader appeal.</p>
<p>Despite the reservations I have outlined above, I still found <i>Big Deal</i> very enjoyable. There is no doubt that Hoekman, Jr is a talented writer, and has penned a book that can accurately be described as a page turner. I finished the book in one day, and certainly wasn&#8217;t left unsatisfied. Hoekman, Jr paints a very human picture of his life as a web industry A-Lister, and in a field where technical manuals are the norm <i>Big Deal</i> is quite unlike any other web design book I have read.</p>
<p><i>Big Deal: On Being Famous to Almost No One</i> will be released as an ebook through Amazon and iBooks later this year. <a href="http://rhjr.tumblr.com/post/5173363304/big-deal-on-being-famous-to-almost-no-one">Learn more about the book</a> on Robert Hoekman, Jr&#8217;s website.</p>
<img src="http://feeds.feedburner.com/~r/PixelAcres/~4/9O2SkqjBeZk" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://f6design.com/journal/2011/08/05/book-review-dig-deal/feed/</wfw:commentRss>
		<slash:comments>3</slash:comments>
		<feedburner:origLink>http://f6design.com/journal/2011/08/05/book-review-dig-deal/</feedburner:origLink></item>
		<item>
		<title>FormBuilder updated to v1.5</title>
		<link>http://feedproxy.google.com/~r/PixelAcres/~3/IX2GQPla7x0/</link>
		<comments>http://f6design.com/journal/2011/07/18/formbuilder-updated-to-v1-5/#comments</comments>
		<pubDate>Tue, 19 Jul 2011 07:10:26 +0000</pubDate>
		<dc:creator>Jonathan</dc:creator>
				<category><![CDATA[Programming]]></category>
		<category><![CDATA[Toolbox]]></category>

		<guid isPermaLink="false">http://f6design.com/journal/?p=2079</guid>
		<description><![CDATA[It&#8217;s been almost exactly four years since I updated my FormBuilder PHP class, but believe it or not I have been slowly modifying and improving the class during the intervening years. I figured it was high time I rolled those improvements into the public version of the class, so here&#8217;s what&#8217;s new in version 1.5 [...]]]></description>
			<content:encoded><![CDATA[<p>It&#8217;s been almost exactly four years since I updated my <a href="http://f6design.com/journal/2007/04/27/formbuilder-html-forms-made-simple/">FormBuilder</a> PHP class, but believe it or not I have been slowly modifying and improving the class during the intervening years. I figured it was high time I rolled those improvements into the public version of the class, so here&#8217;s what&#8217;s new in version 1.5 of FormBuilder:</p>
<ul>
<li>Better handling of checkbox results in the <code>emailResults</code> method.</li>
<li>A custom form submit URL can be passed to the FormBuilder constructor. Useful when using FormBuilder in an environment that is performing URL rewriting.</li>
<li>Replaced deprecated <code>ergei</code> functions with <code>preg_match</code>.</li>
<li>Checkbox field types are correctly processed when field is not mandatory, and the user didn&#8217;t check any of the available options.</li>
<li>Added new field type: file (for file uploads). Note that files are currently <em>not</em> emailed when using the <code>emailResults</code> method. Any handling of the uploaded files should be accomplished manually by accessing PHP&#8217;s <code>$_Files</code> array.</li>
<li>The textbox and textarea field types now accept an optional <code>defaultvalue</code> parameter.</li>
<li>Fixed a bug that meant checkboxes had a CSS class of &#8216;fbheckbox&#8217; instead of &#8216;fbcheckbox&#8217;.</li>
</ul>
<p>If you encounter any problems with the new version please let me know.</p>
<img src="http://feeds.feedburner.com/~r/PixelAcres/~4/IX2GQPla7x0" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://f6design.com/journal/2011/07/18/formbuilder-updated-to-v1-5/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		<feedburner:origLink>http://f6design.com/journal/2011/07/18/formbuilder-updated-to-v1-5/</feedburner:origLink></item>
		<item>
		<title>How to tell if you’re a web design OG</title>
		<link>http://feedproxy.google.com/~r/PixelAcres/~3/pqoUPGYmxC0/</link>
		<comments>http://f6design.com/journal/2011/07/12/how-to-tell-if-youre-a-web-design-og/#comments</comments>
		<pubDate>Wed, 13 Jul 2011 00:16:02 +0000</pubDate>
		<dc:creator>Jonathan</dc:creator>
				<category><![CDATA[Web Design]]></category>

		<guid isPermaLink="false">http://f6design.com/journal/?p=2061</guid>
		<description><![CDATA[This morning I&#8217;ve been following the hilarious (and cringe inducing) web design OG Twitter meme started by Jeff Croft (if you&#8217;re wondering, OG stands for Original Gangster). Here are a few of my favourites: If you created a website that had &#8220;Works best with Netscape Navigator&#8221; you may be a #design_og @_j12 If you remember [...]]]></description>
			<content:encoded><![CDATA[<p>This morning I&#8217;ve been following the hilarious (and cringe inducing) <a href="http://search.twitter.com/search?had_popular=true&#038;q=%23design_og&#038;result_type=recent">web design OG</a> Twitter meme started by <a href="http://twitter.com/jcroft">Jeff Croft</a> (if you&#8217;re wondering, OG stands for Original Gangster). Here are a few of my favourites:</p>
<blockquote><p>If you created a website that had &#8220;Works best with Netscape Navigator&#8221; you may be a #design_og<br />
<a href="http://twitter.com/#!/_j12/status/90876432359763968">@_j12</a></p></blockquote>
<blockquote><p>If you remember Adobe PageMill, you may be a web design OG. #design_og<br />
<a href="http://twitter.com/#!/meyerweb/status/90876524101767168">@meyerweb</a></p></blockquote>
<blockquote><p>If you&#8217;ve ever said that your &#8220;site looks better in Netscape Navigator&#8221; you may just be a web design OG! #design_og<br />
<a href="http://twitter.com/#!/hudsonperalta/status/90886392565080064">@hudsonperalta</a></p></blockquote>
<blockquote><p>If you remember cleaning up bad Word-to-HTML markup by hand in a text editor, you might be a web design OG #design_og<br />
<a href="http://twitter.com/#!/DataG/status/90890989388054528">@DataG</a></p></blockquote>
<blockquote><p>If u ever designed an interactive CD-ROM you&#8217;re a #design_og<br />
<a href="http://twitter.com/#!/daveixd/status/90895527880818688">@daveixd</a></p></blockquote>
<blockquote><p>If you remember having to make sure that your hex colour codes were &#8220;web safe&#8221; you might be web design OG #design_og<br />
<a href="http://twitter.com/#!/stevecomrie/status/90907148007124993">@stevecomrie</a></p></blockquote>
<blockquote><p>If you used .midi files for audio on your webpage, maybe you are a #design_og<br />
<a href="http://twitter.com/#!/blueocto/status/90915850357444608">@blueocto</a></p></blockquote>
<blockquote><p>If you&#8217;ve ever optimized a website for 14.4, 28.8 and/or 33.6 baud rate modems, you might be a web design OG #design_og<br />
<a href="http://twitter.com/#!/digitaljhelms/status/90915860784480256">@digitaljhelms</a></p></blockquote>
<blockquote><p>If you still have some old business cards laying around where ur title was Webmistress, you&#8217;re a web #design_og (or OL as case may be)<br />
<a href="http://twitter.com/#!/flynine/status/90915862684516352">@flynine</a></p></blockquote>
<blockquote><p>If you used 1&#215;1 spacer gifs you may be a web design OG #design_og<br />
<a href="http://twitter.com/#!/trafnar/status/90920386878898176">@trafnar</a></p></blockquote>
<blockquote><p>If you ever thought while reading @alistapart article, &#8220;That&#8217;s great, but I&#8217;m still supporting IE3,&#8221; you might be a #design_og.<br />
<a href="http://twitter.com/#!/dylanw/statuses/90936282552860673">@dylanw</a></p></blockquote>
<p>And here are my contributions:</p>
<blockquote><p>If you ever designed a website that was hosted on Geocities, you may be a web design OG #design_og<br />
<a href="http://twitter.com/#!/f6design/status/90906731160403968">@f6design</a></p></blockquote>
<blockquote><p>If you ever designed a website for 640&#215;480 resolution, you may be a web design OG #design_og<br />
<a href="http://twitter.com/#!/f6design/status/90905962172514304">@f6design</a></p></blockquote>
<p>There are still plenty of goodies pouring in, so keep an eye on <a href="http://search.twitter.com/search?had_popular=true&#038;q=%23design_og&#038;result_type=recent">the meme</a>&#8230;</p>
<img src="http://feeds.feedburner.com/~r/PixelAcres/~4/pqoUPGYmxC0" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://f6design.com/journal/2011/07/12/how-to-tell-if-youre-a-web-design-og/feed/</wfw:commentRss>
		<slash:comments>4</slash:comments>
		<feedburner:origLink>http://f6design.com/journal/2011/07/12/how-to-tell-if-youre-a-web-design-og/</feedburner:origLink></item>
	</channel>
</rss>

