<?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>The World of Curtis Gibby - My Blog</title>
	<atom:link href="http://www.curtisgibby.com/blog/feed/" rel="self" type="application/rss+xml" />
	<link>http://www.curtisgibby.com/blog</link>
	<description></description>
	<lastBuildDate>Thu, 28 Jul 2011 21:40:13 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.3.2</generator>
		<item>
		<title>HTML5 form inputs in CakePHP 1.2</title>
		<link>http://www.curtisgibby.com/blog/2011/07/html5-form-inputs-in-cakephp-1-2/</link>
		<comments>http://www.curtisgibby.com/blog/2011/07/html5-form-inputs-in-cakephp-1-2/#comments</comments>
		<pubDate>Thu, 28 Jul 2011 21:40:13 +0000</pubDate>
		<dc:creator>Curtis Gibby</dc:creator>
				<category><![CDATA[Programming]]></category>
		<category><![CDATA[Work]]></category>
		<category><![CDATA[CakePHP]]></category>
		<category><![CDATA[form inputs]]></category>
		<category><![CDATA[HTML5]]></category>
		<category><![CDATA[mobile]]></category>
		<category><![CDATA[PHP]]></category>

		<guid isPermaLink="false">http://www.curtisgibby.com/blog/?p=749</guid>
		<description><![CDATA[At work, we&#8217;re building out a mobile version of our replicated sites.  As anyone who&#8217;s used an iPhone or Android browser to fill out a web form knows&#8230; using an iPhone or Android browser to fill out a web form is really annoying, and it&#8217;s best to make things as user-friendly as possible.  That&#8217;s why [...]]]></description>
			<content:encoded><![CDATA[<p>At work, we&#8217;re building out a mobile version of our replicated sites.  As anyone who&#8217;s used an iPhone or Android browser to fill out a web form knows&#8230; using an iPhone or Android browser to fill out a web form is really annoying, and it&#8217;s best to make things as user-friendly as possible.  That&#8217;s why I wanted to leverage the power of <a href="http://diveintohtml5.org/forms.html" target="_blank">HTML5 form elements</a> to minimize that annoyance.</p>
<p>On the iPhone, Mobile Safari renders its on-screen keyboard differently for &#8220;email,&#8221; &#8220;tel&#8221; and &#8220;url&#8221; form fields &#8212; you automatically get the keys that make the most sense for each specific situation.</p>
<div id="attachment_753" class="wp-caption aligncenter" style="width: 330px"><a href="http://www.curtisgibby.com/blog/wp-content/uploads/2011/07/iphone-email1.png"><img class="size-full wp-image-753" title="iphone email" src="http://www.curtisgibby.com/blog/wp-content/uploads/2011/07/iphone-email1.png" alt="HTML5 email form input rendered on an iPhone" width="320" height="480" /></a><p class="wp-caption-text">HTML5 email form input rendered on an iPhone</p></div>
<div id="attachment_751" class="wp-caption aligncenter" style="width: 330px"><a href="http://www.curtisgibby.com/blog/wp-content/uploads/2011/07/iphone-tel.png"><img class="size-full wp-image-751" title="iphone tel" src="http://www.curtisgibby.com/blog/wp-content/uploads/2011/07/iphone-tel.png" alt="HTML5 tel form input rendered on an iPhone" width="320" height="480" /></a><p class="wp-caption-text">HTML5 tel form input rendered on an iPhone</p></div>
<div id="attachment_752" class="wp-caption aligncenter" style="width: 330px"><a href="http://www.curtisgibby.com/blog/wp-content/uploads/2011/07/iphone-url.png"><img class="size-full wp-image-752" title="iphone url" src="http://www.curtisgibby.com/blog/wp-content/uploads/2011/07/iphone-url.png" alt="HTML5 url form input rendered on an iPhone" width="320" height="480" /></a><p class="wp-caption-text">HTML5 url form input rendered on an iPhone</p></div>
<p>However, the version of CakePHP that we&#8217;re running our replicated sites on (1.2.5) doesn&#8217;t have support for these awesome HTML5 inputs &#8212; any unknown input type is automatically rendered as a textarea.  (What kind of weird default is that?)</p>
<p>The HTML5 inputs <a href="http://cakephp.lighthouseapp.com/projects/42648/tickets/598-support-for-html5-input-types-in-formhelper" target="_blank"><em>are</em> supported</a> in CakePHP 2.0 (currently in beta), but we&#8217;re stuck with 1.2.5 for the time being.  <a href="http://lennaert.nu/2010/12/04/html5-form-elements-in-cakephp-formhelper" target="_blank">Lennaert Ekelmans back-ported that support</a> to 1.3.6, but his solution didn&#8217;t work for me out of the box either &#8212; apparently there were a couple of changes in the Form helper between 1.2.5 and 1.3.6.  So I back-back-ported his code to work with 1.2.5.  Here it is:</p>
<pre class="brush:php"> &lt;?php
# app/views/helpers/html5_form.php
App::import('Helper', 'Form');
class Html5FormHelper extends FormHelper {
    /**
     * Generates a form input element complete with label and wrapper div
     *
     * Options - See each field type method for more information. Any options that are part of
     * $attributes or $options for the different type methods can be included in $options for input().
     *
     * - 'type' - Force the type of widget you want. e.g. ```type =&gt; 'select'```
     * - 'label' - control the label
     * - 'div' - control the wrapping div element
     * - 'options' - for widgets that take options e.g. radio, select
     * - 'error' - control the error message that is produced
     *
     * @param string $fieldName This should be "Modelname.fieldname"
     * @param array $options Each type of input takes different options.
     * @return string Completed form widget
     *
     * different from regular form helper only in the textarea/default case -- adds support for HTML5 form types and attributes like placeholder
     *
     */
    function input($fieldName, $options = array()) {
        $view =&amp; ClassRegistry::getObject('view');
        $this-&gt;setEntity($fieldName);
        $entity = join('.', $view-&gt;entity());

        $defaults = array('before' =&gt; null, 'between' =&gt; null, 'after' =&gt; null);
        $options = array_merge($defaults, $options);

        if (!isset($options['type'])) {
            $options['type'] = 'text';

            if (isset($options['options'])) {
                $options['type'] = 'select';
            } elseif (in_array($this-&gt;field(), array('psword', 'passwd', 'password'))) {
                $options['type'] = 'password';
            } elseif (isset($this-&gt;fieldset['fields'][$entity])) {
                $fieldDef = $this-&gt;fieldset['fields'][$entity];
                $type = $fieldDef['type'];
                $primaryKey = $this-&gt;fieldset['key'];
            } elseif (ClassRegistry::isKeySet($this-&gt;model())) {
                $model =&amp; ClassRegistry::getObject($this-&gt;model());
                $type = $model-&gt;getColumnType($this-&gt;field());
                $fieldDef = $model-&gt;schema();

                if (isset($fieldDef[$this-&gt;field()])) {
                    $fieldDef = $fieldDef[$this-&gt;field()];
                } else {
                    $fieldDef = array();
                }
                $primaryKey = $model-&gt;primaryKey;
            }

            if (isset($type)) {
                $map = array(
                    'string'  =&gt; 'text',     'datetime'  =&gt; 'datetime',
                    'boolean' =&gt; 'checkbox', 'timestamp' =&gt; 'datetime',
                    'text'    =&gt; 'textarea', 'time'      =&gt; 'time',
                    'date'    =&gt; 'date',     'float'     =&gt; 'text'
                );

                if (isset($this-&gt;map[$type])) {
                    $options['type'] = $this-&gt;map[$type];
                } elseif (isset($map[$type])) {
                    $options['type'] = $map[$type];
                }
                if ($this-&gt;field() == $primaryKey) {
                    $options['type'] = 'hidden';
                }
            }

            if ($this-&gt;model() === $this-&gt;field()) {
                $options['type'] = 'select';
                if (!isset($options['multiple'])) {
                    $options['multiple'] = 'multiple';
                }
            }
        }
        $types = array('text', 'checkbox', 'radio', 'select');

        if (!isset($options['options']) &amp;&amp; in_array($options['type'], $types)) {
            $view =&amp; ClassRegistry::getObject('view');
            $varName = Inflector::variable(
                Inflector::pluralize(preg_replace('/_id$/', '', $this-&gt;field()))
            );
            $varOptions = $view-&gt;getVar($varName);
            if (is_array($varOptions)) {
                if ($options['type'] !== 'radio') {
                    $options['type'] = 'select';
                }
                $options['options'] = $varOptions;
            }
        }

        $autoLength = (!array_key_exists('maxlength', $options) &amp;&amp; isset($fieldDef['length']));
        if ($autoLength &amp;&amp; $options['type'] == 'text') {
            $options['maxlength'] = $fieldDef['length'];
        }
        if ($autoLength &amp;&amp; $fieldDef['type'] == 'float') {
            $options['maxlength'] = array_sum(explode(',', $fieldDef['length']))+1;
        }

        $out = '';
        $div = true;
        $divOptions = array();

        if (array_key_exists('div', $options)) {
            $div = $options['div'];
            unset($options['div']);
        }

        if (!empty($div)) {
            $divOptions['class'] = 'input';
            $divOptions = $this-&gt;addClass($divOptions, $options['type']);
            if (is_string($div)) {
                $divOptions['class'] = $div;
            } elseif (is_array($div)) {
                $divOptions = array_merge($divOptions, $div);
            }
            if (in_array($this-&gt;field(), $this-&gt;fieldset['validates'])) {
                $divOptions = $this-&gt;addClass($divOptions, 'required');
            }
            if (!isset($divOptions['tag'])) {
                $divOptions['tag'] = 'div';
            }
        }

        $label = null;
        if (isset($options['label']) &amp;&amp; $options['type'] !== 'radio') {
            $label = $options['label'];
            unset($options['label']);
        }

        if ($options['type'] === 'radio') {
            $label = false;
            if (isset($options['options'])) {
                if (is_array($options['options'])) {
                    $radioOptions = $options['options'];
                } else {
                    $radioOptions = array($options['options']);
                }
                unset($options['options']);
            }
        }

        if ($label !== false) {
            $labelAttributes = $this-&gt;domId(array(), 'for');
            if (in_array($options['type'], array('date', 'datetime'))) {
                $labelAttributes['for'] .= 'Month';
            } else if ($options['type'] === 'time') {
                $labelAttributes['for'] .= 'Hour';
            }

            if (is_array($label)) {
                $labelText = null;
                if (isset($label['text'])) {
                    $labelText = $label['text'];
                    unset($label['text']);
                }
                $labelAttributes = array_merge($labelAttributes, $label);
            } else {
                $labelText = $label;
            }

            if (isset($options['id'])) {
                $labelAttributes = array_merge($labelAttributes, array('for' =&gt; $options['id']));
            }
            $out = $this-&gt;label($fieldName, $labelText, $labelAttributes);
        }

        $error = null;
        if (isset($options['error'])) {
            $error = $options['error'];
            unset($options['error']);
        }

        $selected = null;
        if (array_key_exists('selected', $options)) {
            $selected = $options['selected'];
            unset($options['selected']);
        }
        if (isset($options['rows']) || isset($options['cols'])) {
            $options['type'] = 'textarea';
        }

        $empty = false;
        if (isset($options['empty'])) {
            $empty = $options['empty'];
            unset($options['empty']);
        }

        $timeFormat = 12;
        if (isset($options['timeFormat'])) {
            $timeFormat = $options['timeFormat'];
            unset($options['timeFormat']);
        }

        $dateFormat = 'MDY';
        if (isset($options['dateFormat'])) {
            $dateFormat = $options['dateFormat'];
            unset($options['dateFormat']);
        }

        $type     = $options['type'];
        $before     = $options['before'];
        $between = $options['between'];
        $after     = $options['after'];
        unset($options['type'], $options['before'], $options['between'], $options['after']);

        switch ($type) {
            case 'hidden':
                $out = $this-&gt;hidden($fieldName, $options);
                unset($divOptions);
            break;
            case 'checkbox':
                $out = $before . $this-&gt;checkbox($fieldName, $options) . $between . $out;
            break;
            case 'radio':
                $out = $before . $out . $this-&gt;radio($fieldName, $radioOptions, $options) . $between;
            break;
            case 'text':
            case 'password':
                $out = $before . $out . $between . $this-&gt;{$type}($fieldName, $options);
            break;
            case 'file':
                $out = $before . $out . $between . $this-&gt;file($fieldName, $options);
            break;
            case 'select':
                $options = array_merge(array('options' =&gt; array()), $options);
                $list = $options['options'];
                unset($options['options']);
                $out = $before . $out . $between . $this-&gt;select(
                    $fieldName, $list, $selected, $options, $empty
                );
            break;
            case 'time':
                $out = $before . $out . $between . $this-&gt;dateTime(
                    $fieldName, null, $timeFormat, $selected, $options, $empty
                );
            break;
            case 'date':
                $out = $before . $out . $between . $this-&gt;dateTime(
                    $fieldName, $dateFormat, null, $selected, $options, $empty
                );
            break;
            case 'datetime':
                $out = $before . $out . $between . $this-&gt;dateTime(
                    $fieldName, $dateFormat, $timeFormat, $selected, $options, $empty
                );
            break;
            case 'textarea':
                $out = $before . $out . $between . $this-&gt;textarea($fieldName, $options + array('cols' =&gt; 30, 'rows' =&gt; 6));
            break;
            default:
                $out = $before . $out . $between . $this-&gt;defaultInput($type, $fieldName, $options);
            break;
        }

        if ($type != 'hidden') {
            $out .= $after;
            if ($error !== false) {
                $errMsg = $this-&gt;error($fieldName, $error);
                if ($errMsg) {
                    $out .= $errMsg;
                    $divOptions = $this-&gt;addClass($divOptions, 'error');
                }
            }
        }
        if (isset($divOptions) &amp;&amp; isset($divOptions['tag'])) {
            $tag = $divOptions['tag'];
            unset($divOptions['tag']);
            $out = $this-&gt;Html-&gt;tag($tag, $out, $divOptions);
        }
        return $out;
    }

    /**
    * Creates a default input widget, whose type is determined by $options['type'].
    *
    * @param string $fieldName Name of a field, in the form "Modelname.fieldname"
    * @param array $options Array of HTML attributes.
    * @return string A generated HTML input element
    * @access public
    */
    function defaultInput($type, $fieldName, $options = array()) {
            $options = $this-&gt;_initInputField($fieldName, array_merge(
                    array('type' =&gt; $type), $options
            ));
            return sprintf(
                    $this-&gt;Html-&gt;tags['input'],
                    $options['name'],
                    $this-&gt;_parseAttributes($options, array('name'), null, ' ')
            );
    }
}    
?&gt;</pre>
<p>Unlike Lennaert, I chose to extend the regular form helper by creating my own helper class instead of adding the necessary code to Cake&#8217;s own form helper. Now I can get good HTML5 form inputs by adding the Html5Form helper to my controller and then calling the following code in my view:</p>
<pre class="brush:php">echo $html5Form-&gt;input('email',
    array(
        'autofocus' =&gt; 'autofocus',
        'placeholder' =&gt; 'email@example.com',
        'type' =&gt; 'email',
        'label' =&gt; __('Email address', true),
        'required' =&gt; 'required',
        'div' =&gt; 'required'
    )
);
echo $html5Form-&gt;input('phone',
    array(
        'placeholder' =&gt; '801-867-5309',
        'type' =&gt; 'tel',
        'label' =&gt; __('Phone', true),
        'required' =&gt; 'required',
        'div' =&gt; 'required'
    )
);
echo $html5Form-&gt;input('phone',
    array(
        'placeholder' =&gt; 'http://www.curtisgibby.com',
        'type' =&gt; 'url',
        'label' =&gt; __('Web site', true),
        'required' =&gt; 'required',
        'div' =&gt; 'required'
    )
);</pre>
<p>That results in the following HTML:</p>
<pre class="brush:html">&lt;div&gt;
    &lt;label for="ContactEmail"&gt;Email address&lt;/label&gt;
    &lt;input name="data[Contact][email]" type="email" autofocus="autofocus" placeholder="email@example.com" required="required" value="" id="ContactEmail" /&gt;
&lt;/div&gt;
&lt;div&gt;
    &lt;label for="ContactPhone"&gt;Phone&lt;/label&gt;
    &lt;input name="data[Contact][phone]" type="tel" placeholder="801-867-5309" required="required" value="" id="ContactPhone" /&gt;
&lt;/div&gt;
&lt;div&gt;
    &lt;label for="ContactPhone"&gt;Web site&lt;/label&gt;
    &lt;input name="data[Contact][phone]" type="url" placeholder="http://www.curtisgibby.com" required="required" value="" id="ContactPhone" /&gt;
&lt;/div&gt;</pre>
<p>(There doesn&#8217;t seem to be an easy way to output HTML5&#8242;s standalone attributes as simply <em>autofocus</em> or <em>required</em> rather than the more verbose XHTML-ish <em>autofocus = &#8216;autofocus&#8217;</em> or <em>required = &#8216;true&#8217;</em> &#8212; without hacking the CakePHP base helper class. I&#8217;m okay with this slightly lengthier version for now though.)</p>
<p>If you find this code useful, let me know in the comments.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.curtisgibby.com/blog/2011/07/html5-form-inputs-in-cakephp-1-2/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>The breakdown: WIRED magazine, June 2011</title>
		<link>http://www.curtisgibby.com/blog/2011/06/the-breakdown-wired-magazine-june-2011/</link>
		<comments>http://www.curtisgibby.com/blog/2011/06/the-breakdown-wired-magazine-june-2011/#comments</comments>
		<pubDate>Fri, 03 Jun 2011 13:31:29 +0000</pubDate>
		<dc:creator>Curtis Gibby</dc:creator>
				<category><![CDATA[The Breakdown]]></category>
		<category><![CDATA[advertising]]></category>
		<category><![CDATA[journalism]]></category>
		<category><![CDATA[the breakdown]]></category>
		<category><![CDATA[wired magazine]]></category>

		<guid isPermaLink="false">http://www.curtisgibby.com/blog/?p=724</guid>
		<description><![CDATA[I tear apart (literally!) the June 2011 issue of WIRED magazine to get to the bottom of how much advertising content there is versus how much actual editorial content.]]></description>
			<content:encoded><![CDATA[<p>This year, I got a subscription to WIRED magazine for Christmas.  It&#8217;s been a couple of years since I had a magazine to read every month, and I noticed something this time around that seemed indicative of a wider change in the journalism industry: more ads.  It appeared that every other page in this magazine was advertising content rather than editorial content.  No longer was I the consumer and the magazine the product.  Instead, I was the product and advertisers were the consumers.</p>
<p>By the time the May issue came in the mail, I was annoyed enough that I started ripping the all-ad pages out of the magazine and <a href="http://www.facebook.com/permalink.php?story_fbid=10150165360110866&amp;id=558170865" target="_blank">complaining about it</a> on Facebook: &#8220;Curtis Gibby just ripped out 10 of the first 16 pages in my new WIRED magazine because they were useless ads on both sides. Who says print journalism is dying?&#8221;  A couple of people took notice of my post, and I thought it would be interesting to expand on the subject when the June issue rolled around.</p>
<h2><em><a href="http://www.youtube.com/watch?v=Xpugp6DIb3I#t=03m05s" target="_blank">And now it&#8217;s time for a breakdown</a>&#8230;</em></h2>
<div id="attachment_725" class="wp-caption aligncenter" style="width: 245px"><a href="http://www.curtisgibby.com/blog/wp-content/uploads/2011/05/5-Wired-Breakdown-001.jpg"><img class="size-medium wp-image-725 " title="The magazine in its wrapper, before I started ripping it apart" src="http://www.curtisgibby.com/blog/wp-content/uploads/2011/05/5-Wired-Breakdown-001-235x300.jpg" alt="The magazine in its wrapper, before I started ripping it apart" width="235" height="300" /></a><p class="wp-caption-text">The magazine in its wrapper, before I started ripping it apart</p></div>
<p>It came in a little plastic bag and had a subscription card for the New Yorker behind it.</p>
<div id="attachment_726" class="wp-caption aligncenter" style="width: 236px"><a href="http://www.curtisgibby.com/blog/wp-content/uploads/2011/05/5-Wired-Breakdown-002.jpg"><img class="size-medium wp-image-726 " title="The back cover, immediately after opening the wrapper" src="http://www.curtisgibby.com/blog/wp-content/uploads/2011/05/5-Wired-Breakdown-002-226x300.jpg" alt="The back cover, immediately after opening the wrapper" width="226" height="300" /></a><p class="wp-caption-text">The back cover, immediately after opening the wrapper</p></div>
<p>I immediately noticed that both sides of the back cover were actually ads. I had decided to tear out any sheet that was advertising on both sides,  but I didn&#8217;t want to destroy the physical integrity of the magazine by  ripping off the cover.  Curse you, Conde Nast editors!</p>
<div id="attachment_727" class="wp-caption aligncenter" style="width: 235px"><a href="http://www.curtisgibby.com/blog/wp-content/uploads/2011/05/5-Wired-Breakdown-003.jpg"><img class="size-medium wp-image-727" title="The back cover - an ad" src="http://www.curtisgibby.com/blog/wp-content/uploads/2011/05/5-Wired-Breakdown-003-225x300.jpg" alt="The back cover - an ad" width="225" height="300" /></a><p class="wp-caption-text">The back cover - an ad</p></div>
<div id="attachment_728" class="wp-caption aligncenter" style="width: 310px"><a href="http://www.curtisgibby.com/blog/wp-content/uploads/2011/05/5-Wired-Breakdown-004.jpg"><img class="size-medium wp-image-728" title="The inside back cover - another ad" src="http://www.curtisgibby.com/blog/wp-content/uploads/2011/05/5-Wired-Breakdown-004-300x234.jpg" alt="The inside back cover - another ad" width="300" height="234" /></a><p class="wp-caption-text">The inside back cover - another ad</p></div>
<p>I started by going through the whole magazine from the front cover, and counting every page as either editorial content or an ad.  I gave the publishers the benefit of the doubt, calling anything that actually had to do with the magazine itself &#8220;content,&#8221; regardless of whether it was a boring index or a photo illustration without any actual information.  (As long as it wasn&#8217;t actively trying to get me to purchase a Best Buy TV, I called it good.)</p>
<div id="attachment_729" class="wp-caption aligncenter" style="width: 336px"><a href="http://www.curtisgibby.com/blog/wp-content/uploads/2011/05/5-Wired-Breakdown-005.jpg"><img class="size-full wp-image-729" title="The inside front cover and first page - both ads." src="http://www.curtisgibby.com/blog/wp-content/uploads/2011/05/5-Wired-Breakdown-005.jpg" alt="The inside front cover and first page - both ads." width="326" height="244" /></a><p class="wp-caption-text">The inside front cover and first page - both ads.</p></div>
<p>The first several pages were not promising &#8212; after the front cover, there were five ad pages in a row.  In fact, I was surprised to find out that most of the first half of the magazine had an ad on every other page.  It wasn&#8217;t until I got to the actual articles section near the back that I got several pages in a row of content without ads.</p>
<p>One page had a vertical ad that took up a column about a third of the page size.</p>
<div id="attachment_730" class="wp-caption aligncenter" style="width: 336px"><a href="http://www.curtisgibby.com/blog/wp-content/uploads/2011/05/5-Wired-Breakdown-007.jpg"><img class="size-full wp-image-730" title="The single split page with both editorial and ad" src="http://www.curtisgibby.com/blog/wp-content/uploads/2011/05/5-Wired-Breakdown-007.jpg" alt="The single split page with both editorial and ad" width="326" height="245" /></a><p class="wp-caption-text">The single split page with both editorial and ad</p></div>
<p style="text-align: left;">I tore out twenty sheets (ones that had ads on both sides) and collected four silly subscription cards.</p>
<div id="attachment_731" class="wp-caption aligncenter" style="width: 310px"><a href="http://www.curtisgibby.com/blog/wp-content/uploads/2011/05/5-Wired-Breakdown-008.jpg"><img class="size-medium wp-image-731" title="The twenty ripped-out pages" src="http://www.curtisgibby.com/blog/wp-content/uploads/2011/05/5-Wired-Breakdown-008-300x225.jpg" alt="The twenty ripped-out pages" width="300" height="225" /></a><p class="wp-caption-text">The twenty ripped-out pages</p></div>
<div id="attachment_732" class="wp-caption aligncenter" style="width: 310px"><a href="http://www.curtisgibby.com/blog/wp-content/uploads/2011/05/5-Wired-Breakdown-009.jpg"><img class="size-medium wp-image-732" title="The complete magazine after the breakdown" src="http://www.curtisgibby.com/blog/wp-content/uploads/2011/05/5-Wired-Breakdown-009-300x225.jpg" alt="The complete magazine after the breakdown" width="300" height="225" /></a><p class="wp-caption-text">The complete magazine after the breakdown</p></div>
<h2>tl;dr</h2>
<p>In the end, I found that the magazine was <strong>53.17% editorial content</strong> &#8212; 94.64 pages were editorial versus 83.36 pages of ads.</p>
<p>I&#8217;ve posted a <a href="https://spreadsheets.google.com/spreadsheet/ccc?key=0AvHUCh1GzSjXdDA2eXUwejdGb1Jud2xLdWhQZjNUY1E&amp;hl=en_US#gid=0" target="_blank">spreadsheet listing every page</a> at Google Docs.  The spreadsheet also lists where I found the insert cards and specifies the cumulative percentage of editorial content.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.curtisgibby.com/blog/2011/06/the-breakdown-wired-magazine-june-2011/feed/</wfw:commentRss>
		<slash:comments>4</slash:comments>
		</item>
		<item>
		<title>Tweaking Firefox tab colors, part 2 (The Firefox 4 edition)</title>
		<link>http://www.curtisgibby.com/blog/2011/03/tweaking-firefox-tab-colors-part-2-the-firefox-4-edition/</link>
		<comments>http://www.curtisgibby.com/blog/2011/03/tweaking-firefox-tab-colors-part-2-the-firefox-4-edition/#comments</comments>
		<pubDate>Thu, 31 Mar 2011 14:35:41 +0000</pubDate>
		<dc:creator>Curtis Gibby</dc:creator>
				<category><![CDATA[Programming]]></category>
		<category><![CDATA[CSS]]></category>
		<category><![CDATA[firefox]]></category>
		<category><![CDATA[firefox4]]></category>
		<category><![CDATA[tweaks]]></category>
		<category><![CDATA[userchrome.css]]></category>

		<guid isPermaLink="false">http://www.curtisgibby.com/blog/?p=715</guid>
		<description><![CDATA[]]></description>
			<content:encoded><![CDATA[<div id="attachment_716" class="wp-caption alignright" style="width: 262px"><a href="http://www.curtisgibby.com/blog/wp-content/uploads/2011/03/firefox4_tab_before.jpg"><img class="size-full wp-image-716" title="Colored tabs in Firefox 4 - not very colored anymore" src="http://www.curtisgibby.com/blog/wp-content/uploads/2011/03/firefox4_tab_before.jpg" alt="Colored tabs in Firefox 4 - not very colored anymore" width="252" height="26" /></a></dt>
</dl>
</div>
<p>Just when I got used to my new tab colors described in <a title="Different tab colors for different contexts" href="http://www.curtisgibby.com/blog/2010/12/different-tab-colors-for-different-contexts/" target="_blank">my previous post</a>, Firefox 4 was released and broke what I&#8217;d done.  I could still see a teeny difference between my green, yellow, and red tabs &#8212; a 2-pixel strip at the top of each of them.  But most of the tab was the default chrome &#8212; nice-looking, but not what I wanted.</p>
<p>So I started looking for a solution that would let me change the whole tab&#8217;s color in FF4, not just the top of the tab.  I downloaded <a href="https://addons.mozilla.org/en-US/firefox/addon/tab-mix-plus/" target="_blank">Tab Mix Plus</a>, which did work in Firefox 4, and reverse-engineered the CSS that it added to the page.  I found that it was adding a background-image to the tab&#8217;s CSS, like this:</p>
<pre class="brush:css">background-image: -moz-linear-gradient(bottom,rgba(10%,10%,10%,.4) 1px,transparent 1px), -moz-linear-gradient(#a6dfa6,#8dd68d) !important;</pre>
<div class="mceTemp">
<dl id="attachment_718" class="wp-caption alignleft" style="width: 211px;">
<dt class="wp-caption-dt"><a href="http://www.curtisgibby.com/blog/wp-content/uploads/2011/03/firefox4_tab_after1.jpg"><img class="size-full wp-image-718" title="Much better!" src="http://www.curtisgibby.com/blog/wp-content/uploads/2011/03/firefox4_tab_after1.jpg" alt="Much better!" width="201" height="26" /></a></dt>
</dl>
</div>
<p>I added that to the relevant section of my userChrome.css, restarted Firefox, and presto!  My tab was colored the way that it should be.</p>
<p>Then I realized that FF4&#8242;s chrome had inactive and hover states that were much more pronounced than before, much darker than an active tab.  And unlike my previous solution, Firefox didn&#8217;t automatically convert this into those hover and active states.</p>
<p>So I had to go back and add plain old CSS :hover and [selected="true"] rules to each of my colors, making the inactive tab the darkest, the hover, slightly lighter, and the active the lightest.  This is what I ended up with:</p>
<pre class="brush:css">/* Localhost colors */
tab[image*="-dev.net"]
{
 -moz-appearance: none;
 background-color:#d8f1d8 !important; /* what we had before -- the tiny little strip at the top */
 background-image: -moz-linear-gradient(bottom,rgba(10%,10%,10%,.4) 1px,transparent 1px), /* the line on the bottom */
 -moz-linear-gradient(#a6dfa6,#8dd68d) !important; /* the main color we're adding */
}

/* Localhost hover colors */
tab[image*="-dev.net"]:hover
{
 background-image: -moz-linear-gradient(bottom,rgba(10%,10%,10%,.4) 1px,transparent 1px),
 -moz-linear-gradient(#bfe8bf,#a6dfa6) !important;
}

/*  Localhost active colors */
tab[image*="-dev.net"][selected="true"]
{
 background-image: -moz-linear-gradient(#d8f1d8,#bfe8bf) !important; /* no line on the bottom here, since it's the active one */
}</pre>
<p>(Of course, repeated for each of my color groups.)</p>
<p>This is what the &#8220;live&#8221; red group looks like:</p>
<div class="mceTemp">
<dl id="attachment_719" class="wp-caption alignleft" style="width: 608px;">
<dt class="wp-caption-dt"><a href="http://www.curtisgibby.com/blog/wp-content/uploads/2011/03/firefox4_tab_after2.jpg"><img class="size-full wp-image-719" title="L: Inactive, C: Active, R: Hover" src="http://www.curtisgibby.com/blog/wp-content/uploads/2011/03/firefox4_tab_after2.jpg" alt="L: Inactive, C: Active, R: Hover" width="598" height="30" /></a><p class="wp-caption-text">L: Inactive, C: Active, R: Hover</p></div>
]]></content:encoded>
			<wfw:commentRss>http://www.curtisgibby.com/blog/2011/03/tweaking-firefox-tab-colors-part-2-the-firefox-4-edition/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>Creating on-the-fly MP3 playlists on the NMT</title>
		<link>http://www.curtisgibby.com/blog/2011/03/creating-on-the-fly-mp3-playlists-on-the-nmt/</link>
		<comments>http://www.curtisgibby.com/blog/2011/03/creating-on-the-fly-mp3-playlists-on-the-nmt/#comments</comments>
		<pubDate>Tue, 01 Mar 2011 15:17:07 +0000</pubDate>
		<dc:creator>Curtis Gibby</dc:creator>
				<category><![CDATA[Programming]]></category>
		<category><![CDATA[MP3]]></category>
		<category><![CDATA[Music]]></category>
		<category><![CDATA[NMT]]></category>
		<category><![CDATA[PCH]]></category>
		<category><![CDATA[PHP]]></category>
		<category><![CDATA[Popcorn Hour]]></category>

		<guid isPermaLink="false">http://www.curtisgibby.com/blog/?p=700</guid>
		<description><![CDATA[All I wanted was a way to quickly and easily get some music going on my nice home theater through my Popcorn Hour, preferably with a "shuffle" option -- start it up and let it run.  I built a custom PHP script to do just that.]]></description>
			<content:encoded><![CDATA[<p><a href="http://www.curtisgibby.com/blog/wp-content/uploads/2011/03/popcornhour-logo.png"><img class="alignleft size-full wp-image-708" title="popcornhour-logo" src="http://www.curtisgibby.com/blog/wp-content/uploads/2011/03/popcornhour-logo.png" alt="" width="170" height="72" /></a>I bought the excellent Popcorn Hour media server a couple of years ago, and I&#8217;ve always loved the job it does on my video files, especially with the equally fantastic <a href="http://mediaplayersite.com/YAMJ_Latest" target="_blank">YAMJ</a> that rebuilds the video jukebox every time I get a new TV show or movie.</p>
<p>But I&#8217;ve never really gotten the NMT to play well with my audio files &#8212; it doesn&#8217;t handle standard playlist formats like .pls or .m3u, so you&#8217;re stuck playing one song at a time unless you can figure out its own insane .jsp playlist format.<span id="more-700"></span></p>
<p><a href="http://www.curtisgibby.com/blog/wp-content/uploads/2011/03/Nmt-logo.png"><img class="alignright size-full wp-image-712" title="Nmt-logo" src="http://www.curtisgibby.com/blog/wp-content/uploads/2011/03/Nmt-logo.png" alt="" width="93" height="75" /></a>Most of the music jukebox programs that I found for the NMT seemed needlessly complicated, creating dozens of files (playlists, album cover images, html and XML) and forcing you to put your MP3s into a certain folder structure.  I didn&#8217;t need to be able to pick and choose any song from my extensive collection.  While my MP3s are generally pretty well-tagged, I do have dozens of files where I don&#8217;t know the album name, and that would mess up most of these playlist generators.</p>
<p>All I wanted was a way to quickly and easily get some music going on my nice home theater through my Popcorn Hour, preferably with a &#8220;shuffle&#8221; option &#8212; start it up and let it run.</p>
<p>A couple of weeks ago, I was getting desperate, so I tried the <a href="http://www.networkedmediatank.com/wiki/index.php/Music_Jukebox" target="_blank">Music Jukebox</a> program that so many people recommended on the NMT forum.  I gave it a subset of my music and turned it loose to create its myriad files.  Its output turned out as I expected &#8212; an index page, plus a page for each album, with playlists for each song and a &#8220;play all&#8221; playlist.  But I was interested in the &#8220;shuffle&#8221; option at the top of the page.  It took the regular album playlist .jsp file and fed it to a shuffle.php script running on the MyiHome server on the NMT.  &#8220;Ah,&#8221; I thought. &#8220;I can reverse-engineer this bad boy.&#8221;</p>
<p>I dove into the PHP code and found that it was reading in the playlist file, then putting each line (which corresponded to an individual song) into an array, shuffling that array, and echoing the whole thing back out to the server as the new &#8220;playlist.&#8221;  I figured I could do the same thing with PHP&#8217;s glob function to find all of my MP3 files, shuffle them, and output a line for each of them back to the NMT.  That&#8217;s what this first simple script does (you may have to update the specific paths to match your folder scheme):</p>
<pre class="brush:php">// get all of the MP3s in my "Music" folder's subfolders
$glob_files = glob("../Music/*/*.mp3");

// randomize
shuffle($glob_files);

// output in a playlist format that the NMT understands
foreach ($glob_files as $filename) {
    echo "$filename|0|0|file:///opt/sybhttpd/localhost.drives/HARD_DISK/Music/$filename|
";
}</pre>
<p>It was super simple, but it worked great.  I was listening to a random playlist of every single MP3 on my Popcorn Hour&#8217;s hard drive, with the album art and meta-data that the NMT&#8217;s default music player could read from the ID3 tags in my files.  (I still wish that the player had support for showing the lyrics of the currently-playing song, but that&#8217;s another quibble.)</p>
<p>Next, I wanted to recreate some of the smart-playlist functionality that you get with iTunes or Winamp or Songbird.  There are certain artists in my music library whose songs my wife doesn&#8217;t enjoy listening to, and on Sundays I only want to hear LDS and classical music.  So I came up with the idea of specific modes that would filter the songs according to an artist whitelist or blacklist:</p>
<pre class="brush:php">$glob_files = glob("../Music/*/*.mp3");
$mode = ( $_GET['mode'] ? $_GET['mode'] : "normal");

$artistWhitelist = null;
$artistBlacklist = null;

switch ($mode) {
	case "sarah":
		$artistBlacklist = array_map('strtolower', array(
			'Bush',
			[ ... ],
			'Weird Al Yankovic',
		));
		break;
	case "sunday":
		$artistWhitelist = array_map('strtolower', array(
			'Alan Silvestri',
			[ ... ],
			'Vivaldi',
		));
		break;
	default:
		break;
}
shuffle($glob_files);

foreach ($glob_files as $filepath) {

	// set the output as normal
	$output = "$filepath|0|0|file:///opt/sybhttpd/localhost.drives/HARD_DISK/Music/$filepath|
";
	$filename = basename($filepath, 'mp3');
	// my MP3 files are named like "Artist - Track.mp3"
	$splodedFilename = explode(' - ', $filename);
	$artist = strtolower($splodedFilename[0]);
	if (
		(!empty($artistWhitelist) &amp;&amp; !in_array($artist, $artistWhitelist)) || // if there's a whitelist and the artist isn't in that array, blank out the output for this file
		(!empty($artistBlacklist) &amp;&amp; in_array($artist, $artistBlacklist)) // if there's a blaclist and the artist is in that array, blank out the output for this file
	) {
		$output = "";
	}
    echo $output;
}</pre>
<p>That also worked well.  It does take a bit more time to start playing the first song than a normal playlist (usually about 5 &#8211; 10 seconds), but given that it&#8217;s chewing through more than 5,000 tracks, I&#8217;m okay with a few seconds of delay.</p>
<p>The code that I use in my NMT index file I borrowed from the generated HTML from Music Menu:</p>
<pre class="brush:html"><a href="http://localhost:8088/stream/file=/opt/sybhttpd/localhost.drives/HARD_DISK/MyMenu/shuffle.php">Music</a>
<a href="http://localhost:8088/stream/file=/opt/sybhttpd/localhost.drives/HARD_DISK/MyMenu/shuffle.php?mode=sunday">Sunday Music</a>
<a href="http://localhost:8088/stream/file=/opt/sybhttpd/localhost.drives/HARD_DISK/MyMenu/shuffle.php?mode=sarah">Sarah-Safe Music</a></pre>
<p>The next step would be to use one of the MP3 functions or libraries to actually read the ID3 tag from the MP3 file, to filter by genre and remove all of the Christmas songs, for example.  But I&#8217;m guessing that would take quite a bit longer to generate the playlist, and for now, I&#8217;m happy to either skip or listen to the odd holiday song that occasionally pops up.</p>
<p>In general, I now enjoy listening to my music through the Popcorn Hour on my big TV and nice stereo speakers.  Now if only I could make it scrobble my tracks to <a href="http://last.fm">Last.fm</a>&#8230;</p>
]]></content:encoded>
			<wfw:commentRss>http://www.curtisgibby.com/blog/2011/03/creating-on-the-fly-mp3-playlists-on-the-nmt/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>CSS woes at eBay</title>
		<link>http://www.curtisgibby.com/blog/2011/01/css-woes-at-ebay/</link>
		<comments>http://www.curtisgibby.com/blog/2011/01/css-woes-at-ebay/#comments</comments>
		<pubDate>Fri, 14 Jan 2011 14:31:09 +0000</pubDate>
		<dc:creator>Curtis Gibby</dc:creator>
				<category><![CDATA[Programming]]></category>
		<category><![CDATA[CSS]]></category>
		<category><![CDATA[ebay]]></category>
		<category><![CDATA[Fonts]]></category>

		<guid isPermaLink="false">http://www.curtisgibby.com/blog/?p=685</guid>
		<description><![CDATA[I don&#8217;t generally pay a ton of attention to web typography, but I must have it on my mind after building a new backend for our replicated sites.  I spotted this on an eBay order confirmation screen this morning: Yes, that&#8217;s three different fonts for three different headers&#8230; on the same page. The first is [...]]]></description>
			<content:encoded><![CDATA[<p>I don&#8217;t generally pay a ton of attention to web typography, but I  must have it on my mind after building a new backend for our replicated  sites.  I spotted this on an eBay order confirmation screen this  morning:</p>
<p><a href="/blog/wp-content/uploads/2011/01/ebay-checkout-fonts.png"><img title="ebay checkout fonts" src="/blog/wp-content/uploads/2011/01/ebay-checkout-fonts.png" alt="" width="524" height="169" /></a></p>
<p>Yes, that&#8217;s three different fonts for three different headers&#8230; on the same page.</p>
<p>The first is an H2 of class &#8220;g-m0 g-m dsp&#8221; that just inherits the body&#8217;s &#8220;Arial,Helvetica,sans-serif&#8221; font-family.</p>
<p>The  second is another H2, this one with class &#8220;h2Titles&#8221;.  It gets  font-family &#8220;Trebuchet&#8221; &#8212; which apparently I don&#8217;t have installed on my  machine, because I see the crappy default Times New Roman.  (Yes, they  specified exactly one font &#8212; incorrectly.  Apparently they haven&#8217;t  heard of font stacks.)</p>
<p>The third H2 is probably what they wanted for all of these.  It has class &#8220;h2Title&#8221; (as opposed to &#8220;h2Title<span style="color: #ff0000;">s</span>&#8221; above) and gets the correct font &#8220;Trebuchet MS&#8221;.</p>
<p>What a mess.  This is one of the biggest e-commerce companies in the world and they can&#8217;t get their CSS right.  (This isn&#8217;t exactly bleeding-edge web technology, guys &#8212; the font-family part of the CSS spec came out <a href="http://en.wikipedia.org/wiki/Css">14 years ago</a>.)</p>
<p>Here&#8217;s  how they could have prevented this train wreck of a page.  First, set  up a CSS reset that hits every single H2 (and anything else that you may want to look good) with a solid definition.  Next,  add some progressive enhancement to certain H2s by adding a class.   Third, check that the specified font rules are actually doing something to  the intended target (as in the number 2 &#8220;Trebuchet&#8221; case above).   Finally, at the very least, give your page a quick once-over to make sure that  everything looks as you intended.</p>
<p>At least they all got the same color &#8212; <span style="color: #5d5d5d;">#5D5D5D</span> looks pretty nice.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.curtisgibby.com/blog/2011/01/css-woes-at-ebay/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Different tab colors for different contexts</title>
		<link>http://www.curtisgibby.com/blog/2010/12/different-tab-colors-for-different-contexts/</link>
		<comments>http://www.curtisgibby.com/blog/2010/12/different-tab-colors-for-different-contexts/#comments</comments>
		<pubDate>Thu, 16 Dec 2010 17:54:41 +0000</pubDate>
		<dc:creator>Curtis Gibby</dc:creator>
				<category><![CDATA[Cool Web Stuff]]></category>
		<category><![CDATA[Programming]]></category>
		<category><![CDATA[CSS]]></category>
		<category><![CDATA[firefox]]></category>
		<category><![CDATA[tweaks]]></category>
		<category><![CDATA[userchrome.css]]></category>

		<guid isPermaLink="false">http://www.curtisgibby.com/blog/?p=675</guid>
		<description><![CDATA[As a web developer, I may have ten tabs open, each of which could be from any of my environments, and each of which may look identical until you click into it to see the actual URL.  So I spent a lot of time clicking back and forth between them trying to find the other page I'd been working on, until I found out how to change the tab color based on which domain it was on.]]></description>
			<content:encoded><![CDATA[<p>I love Firefox.  Love love love it, especially because I can tweak many things about it to make things work just the way I want.  (Like creating <a href="http://userscripts.org/users/6623/scripts">Greasemonkey scripts</a> to make other peoples&#8217; websites do <em>my</em> bidding.  Or syncing not only my bookmarks and passwords between computers, but also <a href="http://www.curtisgibby.com/blog/2010/08/syncing-stylish-userstyles-with-dropbox/">my Stylish userstyles</a>.)  <a href="http://www.google.com/chrome">Google Chrome</a> may be zippier, but until I can run <a href="http://adblockplus.org/en/">AdBlock Plus</a>, <a href="https://addons.mozilla.org/en-US/firefox/addon/12/">All-in-One Gestures</a>, <a href="https://addons.mozilla.org/en-US/firefox/addon/271/">Colorzilla</a>, <a href="https://addons.mozilla.org/en-US/firefox/addon/1843/">Firebug</a>, <a href="https://addons.mozilla.org/en-US/firefox/addon/5648/">FireShot</a>, <a href="https://addons.mozilla.org/en-US/firefox/addon/10868/">Firefox Sync</a>, <a href="https://addons.mozilla.org/en-US/firefox/addon/748/">Greasemonkey</a>, <a href="https://addons.mozilla.org/en-US/firefox/addon/11097/">Open With</a>, <a href="https://addons.mozilla.org/en-US/firefox/addon/2108/">Stylish</a>, and <a href="https://addons.mozilla.org/en-US/firefox/addon/2098/">Update Notifier</a> in it, I&#8217;m sticking with Firefox.</p>
<p>Anyway, the point here is that I wanted to have my Firefox tabs for different environments show up as different colors in my browser.  As a web developer, I spend a lot of time in a localhost development server, on a staging dev server, and on a live web site.  I may have ten tabs open, each of which could be from any of my environments, and each of which may look identical until you click into it to see the actual URL.  So I spent a lot of time clicking back and forth between them trying to find the other page I&#8217;d been working on.  I wanted a quick visual representation to show which of those environments I was in.</p>
<p>If you&#8217;ve never heard of userChrome.css, you can use it to change a lot of stuff that you don&#8217;t like about the &#8220;chrome&#8221; (or the look of the browser window itself &#8212; completely unrelated to the browser Google Chrome).  You add some CSS to the file (which in Windows is found in %appdata%/Mozilla/Firefox/Profiles/&lt;profile-id&gt;/chrome ), then save it and restart Firefox, and voilà, some change has been made to your chrome.</p>
<p>I found a <a href="http://forum.userstyles.org/comments.php?DiscussionID=1084">Stylish forum that asked about my very question</a>: can you customize the color or other style of the tab based on the domain of the URL?  Fortunately, the answer was yes.  What you have to do is write a CSS selector based on the favicon in the tab window.  (So if a site doesn&#8217;t have a favicon, this hack won&#8217;t work.  Fortunately, all of the ones I wanted to style do have a favicon, and most other sites on the web do too.)  The basic CSS selector looks like this:</p>
<pre class="brush:css">tab[image*="example.com"] {background:red !important;}</pre>
<p>That means, &#8220;For every tab that has a favicon whose url includes the text &#8216;example.com&#8217;, give it a background-color of red.&#8221;  In my case, I wanted my localhost to show light green, the staging server to show light yellow, and the live server to show light red.  This is the css that I came up with:</p>
<pre class="brush:css">tab[image*="localhost"] {background-color:#CBEDCB !important;} /* light green */
tab[image*="dev.mycompany.com"] {background-color:#EDEDCB !important;} /* light yellow */
tab[image*="live.mycompany.com"] {background-color:#EDCBCE !important;} /* light red */
</pre>
<p><a href="/blog/wp-content/uploads/2010/12/colors-in-tabs.png"><img class="aligncenter size-full wp-image-677" title="colors-in-tabs" src="/blog/wp-content/uploads/2010/12/colors-in-tabs.png" alt="" width="625" height="16" /></a><br />
This worked perfectly for me &#8212; now I can easily distinguish between all of my development environments.  Firefox even makes the active tab a brighter version of the same background color (or is it, &#8220;Firefox dims the non-active tabs&#8221;?  That seems more likely.), so you don&#8217;t have to specify a style to tell which tab is the active one.</p>
<p>I&#8217;d be interested to know if there&#8217;s a way to accomplish the same thing  in other major browsers, but this is how I did it in Firefox.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.curtisgibby.com/blog/2010/12/different-tab-colors-for-different-contexts/feed/</wfw:commentRss>
		<slash:comments>3</slash:comments>
		</item>
		<item>
		<title>Our year&#8230; in six photos</title>
		<link>http://www.curtisgibby.com/blog/2010/12/our-year-in-six-photos/</link>
		<comments>http://www.curtisgibby.com/blog/2010/12/our-year-in-six-photos/#comments</comments>
		<pubDate>Thu, 09 Dec 2010 13:52:35 +0000</pubDate>
		<dc:creator>Curtis Gibby</dc:creator>
				<category><![CDATA[Family]]></category>
		<category><![CDATA[Claire]]></category>
		<category><![CDATA[Match The Memory]]></category>

		<guid isPermaLink="false">http://www.curtisgibby.com/blog/?p=670</guid>
		<description><![CDATA[We did a lot of fun and fantastic things this year and, of course, added a baby to the mix.  Take a look at our 2010 &#8220;Christmas letter&#8221; &#8212; a personalized memory game that I made on Match The Memory.  Have fun playing it!]]></description>
			<content:encoded><![CDATA[<p><a href="http://matchthememory.com/gibby2010"><img class="alignnone" title="Gibby Family 2010" src="http://matchthememory.com/game_previews/gibby2010.png" alt="" width="250" height="250" /></a></p>
<p>We did a lot of fun and fantastic things this year and, of course, <a href="http://www.curtisgibby.com/blog/2010/09/and-then-there-were-five-the-story-of-claires-birth/">added a baby</a> to the mix.  Take a look at <a title="Gibby Family 2010 Memory Game" href="http://matchthememory.com/gibby2010">our 2010 &#8220;Christmas letter&#8221;</a> &#8212; a personalized memory game that I made on Match The Memory.  Have fun playing it!</p>
]]></content:encoded>
			<wfw:commentRss>http://www.curtisgibby.com/blog/2010/12/our-year-in-six-photos/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Telling Stories</title>
		<link>http://www.curtisgibby.com/blog/2010/09/telling-stories/</link>
		<comments>http://www.curtisgibby.com/blog/2010/09/telling-stories/#comments</comments>
		<pubDate>Mon, 27 Sep 2010 04:09:20 +0000</pubDate>
		<dc:creator>Curtis Gibby</dc:creator>
				<category><![CDATA[Family]]></category>
		<category><![CDATA[Random Stories]]></category>
		<category><![CDATA[Audrey]]></category>
		<category><![CDATA[Nathan]]></category>

		<guid isPermaLink="false">http://www.curtisgibby.com/blog/?p=665</guid>
		<description><![CDATA[Tonight when we were coming home from Grandma Gibby&#8217;s house, we were playing games made up by a 5-year-old. (Audrey said, &#8220;Let&#8217;s play a game called, &#8216;Let&#8217;s see if you can sing a song that you know&#8217;. How you play is, you sing a song that you know.&#8221;) When we got to the game called [...]]]></description>
			<content:encoded><![CDATA[<p>Tonight when we were coming home from Grandma Gibby&#8217;s house, we were playing games made up by a 5-year-old.  (Audrey said, &#8220;Let&#8217;s play a game called, &#8216;Let&#8217;s see if you can sing a song that you know&#8217;.  How you play is, you sing a song that you know.&#8221;)</p>
<p>When we got to the game called &#8220;Tell a story&#8221; (&#8220;How do you play it?&#8221; Sarah wondered aloud, and we laughed), Audrey told one about a queen and king who had a 5-year-old named Audrey and a baby named Claire and a 2-year-old named Nathan.  They lived in a royal palace and had lots of servants. One day they took a walk and found some more servants who didn&#8217;t have anywhere to live, so they hired them.  The end.</p>
<p>Sarah told an engaging story about a little dragon who wanted to breathe fire like his big brother, but no matter how hard he huffed and puffed, he just got a little bit of smoke.  Audrey was INTO this story, so much so that she started coming up with solutions for the little dragon&#8217;s problem.  Sarah whispered to me, &#8220;Who&#8217;s telling this story?&#8221;</p>
<p>When it was my turn, I came up with a highly inventive tale that went something like this: &#8220;Once there was a little boy named Randy who loved to play with his cowboy doll named Sheriff Moody.  [Moody rhymes with "goody" and "hoodie" in this story.]  Randy had a lot of toys that he liked to play with, but Sheriff Moody was his favorite.&#8221;</p>
<p>&#8220;Then Randy had a birthday, and all the toys were afraid that he would get a toy that was cooler than they were and he wouldn&#8217;t play with them anymore.  Randy&#8217;s mom gave him a spaceman toy called&#8230; Muzz Gightlear.  Randy thought Muzz Gightlear was really cool.&#8221;</p>
<p>At this point, Nathan interjected, &#8220;An&#8217; it was Buzz!&#8221;  We asked Audrey if she knew that I was really talking about Andy and Woody and Buzz Lightyear and she said no, but Nathan recognized my thinly veiled cribbing of the plot of Disney-Pixar&#8217;s beloved 1995 hit, <em><a href="http://www.amazon.com/gp/product/B000059XUT?ie=UTF8&amp;tag=curtisgibbysf-20&amp;linkCode=as2&amp;camp=1789&amp;creative=390957&amp;creativeASIN=B000059XUT">Toy Story</a></em>.  Pretty good for a kid who&#8217;s not yet three.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.curtisgibby.com/blog/2010/09/telling-stories/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>And then there were five&#8230; (The story of Claire&#8217;s birth)</title>
		<link>http://www.curtisgibby.com/blog/2010/09/and-then-there-were-five-the-story-of-claires-birth/</link>
		<comments>http://www.curtisgibby.com/blog/2010/09/and-then-there-were-five-the-story-of-claires-birth/#comments</comments>
		<pubDate>Thu, 16 Sep 2010 00:47:07 +0000</pubDate>
		<dc:creator>Curtis Gibby</dc:creator>
				<category><![CDATA[Family]]></category>
		<category><![CDATA[Baby]]></category>
		<category><![CDATA[Birth]]></category>
		<category><![CDATA[Claire]]></category>
		<category><![CDATA[Names]]></category>
		<category><![CDATA[Sarah]]></category>

		<guid isPermaLink="false">http://www.curtisgibby.com/blog/?p=619</guid>
		<description><![CDATA[The set-up When Sarah was about 20 weeks along with this baby, she began to lobby for us to not find out what the gender was until the baby was actually born.  After all, she figured, we could be surprised by learning if it was a boy or a girl at 20 weeks, or at [...]]]></description>
			<content:encoded><![CDATA[<h2>The set-up</h2>
<p><a href="http://www.curtisgibby.com/blog/wp-content/uploads/2010/09/5-May-Home-031.jpg"><img class="alignleft size-medium wp-image-633" title="25 weeks along" src="http://www.curtisgibby.com/blog/wp-content/uploads/2010/09/5-May-Home-031-142x300.jpg" alt="" width="142" height="300" /></a>When Sarah was about 20 weeks along with this baby, she began to lobby for us to <em>not</em> find out what the gender was until the baby was actually born.  After all, she figured, we could be surprised by learning if it was a boy or a girl at 20 weeks, or at 40 weeks.  Also, we already had one of each, so she wasn&#8217;t especially pining to have either a girl or a boy, and we already had the clothing for whichever kind of baby came out.  She figured that if she didn&#8217;t know, she&#8217;d also end up spending less money on clothes and stuff.  I supported her decision, even though I personally would have rather found out.  So we never got an ultrasound.</p>
<p>But as the weeks wore on, we began to regret our decision to not find out.  We had a great name picked out for a girl (Claire Rebecca Gibby), but we struggled with coming up with a good boy name.  We considered several &#8212; Seth, Henry, Thomas, Joseph &#8212; and spent hours trying to find one that had all the right qualities.  For me, that meant it couldn&#8217;t be too popular, but it still had to be common and recognizable;  Sarah wanted something distinctive, with character.  But we never settled on anything, even as Sarah&#8217;s due date drew closer.  We realized that if we&#8217;d gotten an ultrasound like most people do, we would have known whether it was a boy or a girl, and if we even had to worry about thinking up a boy name.</p>
<h2>Baby Time</h2>
<p>Our other two kids were early &#8212; 12 days for Audrey, and 10 days for Nathan &#8212; so we weren&#8217;t expecting Sarah to even make it to 39 weeks.  But as 39 and then 40 weeks came and went, Sarah started getting more miserable.  &#8220;I want my body back!&#8221; she&#8217;d exclaim.  Every time Sarah had a few good contractions, we&#8217;d hope that this was it&#8230; but then she&#8217;d get up and do something, and the contractions would peter out.  &#8220;I&#8217;m going to be pregnant forever,&#8221; she moaned.</p>
<p><a href="/blog/wp-content/uploads/2010/09/9-Claires-Birth-002.jpg"><img class="alignright size-medium wp-image-628" src="/blog/wp-content/uploads/2010/09/9-Claires-Birth-002.jpg" alt="" width="203" height="270" /></a>On Monday, September 13 (three days after her due date), Sarah woke up with the same kind of contractions, but they were pretty regular.  I went to work, confident in the knowledge that I could get home within 5 minutes of when she called me.  Sarah got her doctor to come check her by mid-morning, and she was at a 4-5 cm dilation and 90% effaced &#8212; it was going to happen sometime today!  He went back to work (probably to cancel a bunch of other patients!) but promised that he&#8217;d be back when she needed him.  Sarah called our moms and her sisters to come down to our house, and got me to come home from work at lunch time.</p>
<p>By the time I got home, her contractions were almost a minute long and less than four minutes apart.  She really was in good labor.  Judy took Audrey to school, and my mom took Nathan to the store with her to keep him out of our hair.  Dr. Wright came back and we got the pool set up in our bathroom by about 1:30 p.m.</p>
<p><a href="http://www.curtisgibby.com/blog/wp-content/uploads/2010/09/Claire-917.jpg"><img class="alignleft size-medium wp-image-645" src="http://www.curtisgibby.com/blog/wp-content/uploads/2010/09/Claire-917-300x214.jpg" alt="" width="252" height="180" /></a>I got my swimsuit on and jumped in the tub with Sarah, and she got to work having good contractions.  I was against the back wall, and she was leaning back on me for support.  I rubbed her back and tummy, poured water on her belly, whispered encouraging words.  Being in the water helped her manage the pain.  A midwife and a midwife-in-training showed up to lend a hand to Dr. Wright, and Alaura started snapping pictures.  Once between contractions, my mom brought Nathan up to see what was going on, and he was happy and shy.</p>
<p><a href="http://www.curtisgibby.com/blog/wp-content/uploads/2010/09/Claire-919.jpg"><img class="alignright size-medium wp-image-643" src="http://www.curtisgibby.com/blog/wp-content/uploads/2010/09/Claire-919-300x225.jpg" alt="" width="252" height="190" /></a>When the doctor checked her again, she was just at 5-6 cm dilated and fully effaced.  She was afraid that it would take a long time to be fully dilated, but soon Sarah&#8217;s &#8220;vocalizations&#8221; got louder and more intense and she felt the urge to push &#8212; it was really baby time.  At one point in the middle of a contraction, she cried out, &#8220;I&#8217;m so excited to have this baby!&#8221;  The midwives had never heard someone so enthusiastic and happy to be giving birth.</p>
<p>Eventually, Sarah could reach down and feel the baby&#8217;s head.  It only took her half an hour to get from that 5-6 to 10 centimeters.  When she actually pushed the baby out, the doctor grabbed her and placed her onto Sarah&#8217;s chest. We covered the baby with towels and got them wet to keep her warm.  We didn&#8217;t even check to see if she was a boy or a girl for a few minutes; we just looked and looked at her head and fingers, so happy that she was finally with us.</p>
<p><a href="http://www.curtisgibby.com/blog/wp-content/uploads/2010/09/Claire-926.jpg"><img class="aligncenter size-medium wp-image-647" src="http://www.curtisgibby.com/blog/wp-content/uploads/2010/09/Claire-926-300x261.jpg" alt="" width="300" height="261" /></a></p>
<p><a href="http://www.curtisgibby.com/blog/wp-content/uploads/2010/09/Claire-927.jpg"><img class="aligncenter size-medium wp-image-649" src="http://www.curtisgibby.com/blog/wp-content/uploads/2010/09/Claire-927-238x300.jpg" alt="" width="238" height="300" /></a></p>
<p>When the doctor peeked under the towel and announced that it was a girl, we were very relieved.  And we immediately said her name, &#8220;Claire.&#8221;</p>
<p><a href="http://www.curtisgibby.com/blog/wp-content/uploads/2010/09/9-Claires-Birth-004.jpg"><img class="aligncenter size-medium wp-image-650" title="9 - Claire's Birth 004" src="http://www.curtisgibby.com/blog/wp-content/uploads/2010/09/9-Claires-Birth-004-300x225.jpg" alt="" width="300" height="225" /></a></p>
<p><a href="http://www.curtisgibby.com/blog/wp-content/uploads/2010/09/9-Claires-Birth-014.jpg"><img class="aligncenter size-medium wp-image-654" src="http://www.curtisgibby.com/blog/wp-content/uploads/2010/09/9-Claires-Birth-014-300x225.jpg" alt="" width="300" height="225" /></a></p>
<p><a href="http://www.curtisgibby.com/blog/wp-content/uploads/2010/09/Claire-946.jpg"><img class="alignright size-medium wp-image-651" src="http://www.curtisgibby.com/blog/wp-content/uploads/2010/09/Claire-946-260x300.jpg" alt="" width="149" height="173" /></a>Sarah&#8217;s sister Zilpha missed the birth by five minutes because she hadn&#8217;t gotten the first messages that we&#8217;d left for her, but Judy and Alaura were both there to witness it, and Mom and Nathan came up to see the baby while we were still in the tub.  Audrey got home from school an hour after Claire was born, and she was  so happy that we&#8217;d had a little sister for her instead of a brother.</p>
<h2>Conclusions</h2>
<p><a href="http://www.curtisgibby.com/blog/wp-content/uploads/2010/09/9-Claires-Birth-015.jpg"><img class="size-medium wp-image-652 alignleft" src="http://www.curtisgibby.com/blog/wp-content/uploads/2010/09/9-Claires-Birth-015-225x300.jpg" alt="" width="180" height="240" /></a>Claire ended up being 7 pounds, 14 ounces and 20 inches long, which surprised us &#8212; we thought she&#8217;d be bigger because she had longer to cook in the womb.  But she&#8217;s perfectly healthy and we&#8217;re happy to have her with us.</p>
<p>This was our first home birth, and we liked how it all turned out.  We knew where everything was and could easily grab anything we needed during the labor and delivery.  We didn&#8217;t have to rush to the hospital, we didn&#8217;t have to fill out forms before we could have a baby, we didn&#8217;t have to listen to any security lectures about not letting strangers walk off with our child, and we didn&#8217;t have to hear any other newborns crying all night.  Dr. Wright and his crew took care of cleaning up the tub and the towels and everything in the bathroom.  We just quickly settled back into life at home with our three kids.</p>
<p><a href="http://www.curtisgibby.com/blog/wp-content/uploads/2010/09/9-Claires-Birth-040.jpg"><img class="aligncenter size-medium wp-image-655" src="http://www.curtisgibby.com/blog/wp-content/uploads/2010/09/9-Claires-Birth-040-300x171.jpg" alt="" width="300" height="171" /></a></p>
<p><object width="480" height="385"><param name="movie" value="http://www.youtube.com/v/Vqf7Z51hDPY?fs=1&amp;hl=en_US"></param><param name="allowFullScreen" value="true"></param><param name="allowscriptaccess" value="always"></param><embed src="http://www.youtube.com/v/Vqf7Z51hDPY?fs=1&amp;hl=en_US" type="application/x-shockwave-flash" allowscriptaccess="always" allowfullscreen="true" width="480" height="385"></embed></object></p>
]]></content:encoded>
			<wfw:commentRss>http://www.curtisgibby.com/blog/2010/09/and-then-there-were-five-the-story-of-claires-birth/feed/</wfw:commentRss>
		<slash:comments>3</slash:comments>
		</item>
		<item>
		<title>Syncing Stylish userstyles with Dropbox</title>
		<link>http://www.curtisgibby.com/blog/2010/08/syncing-stylish-userstyles-with-dropbox/</link>
		<comments>http://www.curtisgibby.com/blog/2010/08/syncing-stylish-userstyles-with-dropbox/#comments</comments>
		<pubDate>Tue, 24 Aug 2010 13:55:51 +0000</pubDate>
		<dc:creator>Curtis Gibby</dc:creator>
				<category><![CDATA[Programming]]></category>
		<category><![CDATA[Dropbox]]></category>
		<category><![CDATA[Firefox Sync]]></category>
		<category><![CDATA[Stylish]]></category>
		<category><![CDATA[userstyles]]></category>

		<guid isPermaLink="false">http://www.curtisgibby.com/blog/?p=607</guid>
		<description><![CDATA[The one gripe I had with Stylish is that it doesn't automatically let you sync your styles across computers. But then I came up with the idea of keeping userstyles synced up via Dropbox, and now it works great!  I'll show you how to do it here.]]></description>
			<content:encoded><![CDATA[<p><a href="http://www.curtisgibby.com/blog/wp-content/uploads/2010/08/stylish1.png"><img class="alignright size-full wp-image-611" title="Stylish" src="http://www.curtisgibby.com/blog/wp-content/uploads/2010/08/stylish1.png" alt="" width="177" height="175" /></a>I&#8217;ve used Firefox&#8217;s <a href="https://addons.mozilla.org/en-US/firefox/addon/2108/">Stylish plugin</a> for years to get rid of stuff that I don&#8217;t want to see on all kinds of web sites.  Once you know how CSS works, the plugin makes it easy to tweak the look of any page by adding a quick {width:100%;} or {display:none;} to your own personalized CSS userstyle for each site.<span id="more-607"></span></p>
<p>The one gripe I&#8217;ve had with Stylish is that it doesn&#8217;t automatically let you sync your styles across computers.  I&#8217;d make a change to a site&#8217;s style on my work computer, then get frustrated that I had to make the same change on my home machine.  I keep hoping that <a href="https://addons.mozilla.org/en-US/firefox/addon/10868/">Firefox Sync</a> (formerly Weave) will add support for syncing the file where Stylish stores its content (a sqlite file called, creatively enough, stylish.sqlite), but it hasn&#8217;t happened yet.</p>
<p><a href="http://www.curtisgibby.com/blog/wp-content/uploads/2010/08/dropbox_logo.png"><img class="alignleft size-full wp-image-613" title="dropbox_logo" src="http://www.curtisgibby.com/blog/wp-content/uploads/2010/08/dropbox_logo.png" alt="" width="231" height="60" /></a>But then I came up with the idea of userstyle syncing via <a href="http://www.dropbox.com">Dropbox</a> &#8212; it&#8217;s a great service and I already had the client installed on all of the computers that I wanted to sync, so I just had to figure out how to do it.  <a href="http://archive.robwilkerson.org/2008/11/12/redux-synchronizing-firefox-through-dropbox/index.html">This blog entry</a> by Rob Wilkerson talked about how to sync all of your Firefox preferences and bookmarks; I already had that part covered with Firefox Sync, but it was the inspiration for me to get off my butt and make my Stylish dreams come true.</p>
<p>At first I thought I&#8217;d have to copy my sqlite file into the Dropbox, then make symlinks in my Firefox folder to that file, like Rob did.  They&#8217;re called Junctions in Windows parlance, and they&#8217;re a little more tricky to work with than symlinks in *nix.  (But they are <a href="http://www.howtogeek.com/howto/windows-vista/using-symlinks-in-windows-vista/">natively supported in Windows Vista and up</a>, which two out of the three machines I&#8217;d be syncing were running.  I&#8217;d have to download a special program to get it working in XP on my old laptop.)</p>
<p>But when I poked around a bit in about:config, I found this option: <strong>extensions.stylish.dbFile</strong>.  It was set to the full file path of the stylish.sqlite file in my Firefox profile directory.</p>
<p><img class="alignnone size-full wp-image-616" title="about-config-stylish" src="http://www.curtisgibby.com/blog/wp-content/uploads/2010/08/about-config-stylish.png" alt="" width="595" height="149" /></p>
<p>I tried copying the file into my Dropbox, then setting the value of the dbFile option to that file path instead.  (&#8220;C:\Users\Curtis\Documents\My Dropbox\stylish.sqlite&#8221; in my case.)  When I restarted Firefox, my styles were working right, and I was able to make a change in a userstyle and see Dropbox re-upload it to the cloud.</p>
<p><a href="http://www.curtisgibby.com/blog/wp-content/uploads/2010/08/dropbox-stylish.png"><img class="alignright size-full wp-image-617" title="dropbox-stylish" src="http://www.curtisgibby.com/blog/wp-content/uploads/2010/08/dropbox-stylish.png" alt="" width="326" height="219" /></a>So then I just had to go into about:config on all of the other client machines and change the extensions.stylish.dbFile option to the path of the Dropbox stylish.sqlite file on that machine.  It works perfectly! I can add a bit of CSS to Stylish on any one of the computers and it is automatically reflected in the other copies of Firefox on the other computers.</p>
<p>This is a brute-force method: you don&#8217;t have the option of automatically merging the styles from the various client computers into the unified stylish.sqlite like you would with Firefox Sync, but my userstyles were pretty close across the computers anyway, so it wasn&#8217;t a big deal.  Hooray for Firefox, for Stylish, and for Dropbox!  Great software all around, and like peanut butter and chocolate, they go even better together!</p>
]]></content:encoded>
			<wfw:commentRss>http://www.curtisgibby.com/blog/2010/08/syncing-stylish-userstyles-with-dropbox/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
	</channel>
</rss>

<!-- Dynamic page generated in 0.459 seconds. -->
<!-- Cached page generated by WP-Super-Cache on 2012-05-17 17:21:02 -->
<!-- Compression = gzip -->
