<?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>Addicted To New by John Nunemaker &#187; Coding</title>
	<atom:link href="http://addictedtonew.com/archives/category/coding/feed/" rel="self" type="application/rss+xml" />
	<link>http://addictedtonew.com</link>
	<description>John Nunemaker\'s thoughts and such</description>
	<lastBuildDate>Wed, 26 Aug 2009 11:56:16 +0000</lastBuildDate>
	<generator>http://wordpress.org/?v=2.9.2</generator>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
			<item>
		<title>JavaScript Array Max and Equal Height Columns</title>
		<link>http://addictedtonew.com/archives/482/javascript-array-max-and-equal-height-columns/</link>
		<comments>http://addictedtonew.com/archives/482/javascript-array-max-and-equal-height-columns/#comments</comments>
		<pubDate>Thu, 12 Feb 2009 11:00:10 +0000</pubDate>
		<dc:creator>jnunemaker</dc:creator>
				<category><![CDATA[Coding]]></category>
		<category><![CDATA[javascript]]></category>
		<category><![CDATA[jquery]]></category>

		<guid isPermaLink="false">http://addictedtonew.com/?p=482</guid>
		<description><![CDATA[JavaScript has a Math.max function that allows you get the maximum between two numbers. That is cool, and all, but I rarely want to compare two numbers. More often, I&#8217;m looking for the maximum number of an array. For example, on a recent project, I wanted all children of an elements to be the same [...]]]></description>
			<content:encoded><![CDATA[<p>JavaScript has a Math.max function that allows you get the maximum between two numbers. That is cool, and all, but I rarely want to compare two numbers. More often, I&#8217;m looking for the maximum number of an array. For example, on a recent project, I wanted all children of an elements to be the same height. I didn&#8217;t want to deal with Faux columns and I was ok with relying on JavaScript this time.</p>
<p>The best way to set columns to an equal height is to just grab all the heights, get the max, and then set each element height to the max. I did a bit of search around and found an example of adding max to Array&#8217;s prototype. I wrapped that in an if statement that checks if max is currently defined, that way if max gets added to Array in the future, my version won&#8217;t conflict.</p>
<pre><code class="javascript">if (typeof Array.prototype['max'] == 'undefined') {
  Array.prototype.max = function() {
    return Math.max.apply({},this);
  }
}</code></pre>
<p>The trick in the code above is that using apply on the built in function allows max to receive an unlimited number of arguments. This allows me to do the following:</p>
<pre><code class="javascript">[1,2,3].max() // => 3</code></pre>
<p>In this instance (making equal height columns), I ended up with the following solution. </p>
<pre><code class="javascript">$.fn.equalHeightChildren = function() {
  return this.each(function() {
    var children = $(this).children();

    var tallest  = $.map(children, function(child) {
      return $(child).height();
    }).max();

    children.each(function() {
      var padding = parseInt($(this).css('padding-top')) +
                    parseInt($(this).css('padding-bottom'));
      $(this).height(tallest - padding);
    });
  });
}</code></pre>
<p>I use $.map to loop through the children and return an array of their heights. At the end of map, I call max() to return the greatest height. The nice thing about this solution is that it even takes into account padding and the box model.</p>
]]></content:encoded>
			<wfw:commentRss>http://addictedtonew.com/archives/482/javascript-array-max-and-equal-height-columns/feed/</wfw:commentRss>
		<slash:comments>3</slash:comments>
		</item>
		<item>
		<title>Logging for the Lazy</title>
		<link>http://addictedtonew.com/archives/473/logging-for-the-lazy/</link>
		<comments>http://addictedtonew.com/archives/473/logging-for-the-lazy/#comments</comments>
		<pubDate>Wed, 11 Feb 2009 22:24:25 +0000</pubDate>
		<dc:creator>jnunemaker</dc:creator>
				<category><![CDATA[Coding]]></category>
		<category><![CDATA[javascript]]></category>
		<category><![CDATA[logging]]></category>

		<guid isPermaLink="false">http://addictedtonew.com/?p=473</guid>
		<description><![CDATA[They say that laziness is a virtue in programmers. That is a good sign for me as I am the laziest of them all. When debugging JavaScript in Firefox or Safari, I use console.log all the time. There are two things about console.log that bother me.
Firstly, it is 11 characters. When I just want to [...]]]></description>
			<content:encoded><![CDATA[<p>They say that laziness is a virtue in programmers. That is a good sign for me as I am the laziest of them all. When debugging JavaScript in Firefox or Safari, I use console.log all the time. There are two things about console.log that bother me.</p>
<p>Firstly, it is 11 characters. When I just want to output something really quick, it really annoys me that it takes 11 characters just for the function name, not including whatever it is that I want to print out.</p>
<p>Secondly, console.log only takes one argument at a time. More often than not, I&#8217;m outputting the values of a few things, which means I have to type (or copy and paste) those 11 characters a lot. What I&#8217;ve started doing recently, is adding this simple log function to my projects.</p>
<pre><code class="javascript">function log() {
  if (window &amp;&amp; window.console &amp;&amp; window.console.log)
    for(var i=0, len = arguments.length; i &lt; len; i++)
      console.log(arguments[i]);
}</code></pre>
<p>This simple function allows me to do the following:</p>
<pre><code class="javascript">log(some_var)
log(one_var, two_var, three_var)</code></pre>
<p>It is only 3 characters and allows me to print out as many objects to the console as my heart desires. Nothing fancy, but it gets the job done and saves me some time and thought.</p>
]]></content:encoded>
			<wfw:commentRss>http://addictedtonew.com/archives/473/logging-for-the-lazy/feed/</wfw:commentRss>
		<slash:comments>3</slash:comments>
		</item>
		<item>
		<title>Creating a Network Bar with jQuery</title>
		<link>http://addictedtonew.com/archives/462/creating-a-network-bar-with-jquery/</link>
		<comments>http://addictedtonew.com/archives/462/creating-a-network-bar-with-jquery/#comments</comments>
		<pubDate>Fri, 23 Jan 2009 16:17:29 +0000</pubDate>
		<dc:creator>jnunemaker</dc:creator>
				<category><![CDATA[Coding]]></category>
		<category><![CDATA[javascript]]></category>
		<category><![CDATA[jquery]]></category>

		<guid isPermaLink="false">http://addictedtonew.com/?p=462</guid>
		<description><![CDATA[Network bars are making the rounds on a lot of sites. If you aren&#8217;t familiar with the term, it is usually a bar at the top of a site with links to other sites that are in the same network. Brandon, one of my friends, has a network bar on Open Soul that has links [...]]]></description>
			<content:encoded><![CDATA[<p>Network bars are making the rounds on a lot of sites. If you aren&#8217;t familiar with the term, it is usually a bar at the top of a site with links to other sites that are in the same network. Brandon, one of my friends, has a network bar on <a href="http://opensoul.org">Open Soul</a> that has links to his two other co-workers and to a few products and services they provide. Another great example is all of the sites created by <a href="http://sidebarcreative.com/">Sidebar</a>, such as <a href="http://mymilemarker.com/">My Mile Marker</a>, <a href="http://overheard.it/">Overheard.it</a>, and <a href="http://djangoplugables.com/">Django Pluggables</a>.</p>
<p><a href="http://addictedtonew.com/archives/450/new-blog-about-blogging/">Not too long ago</a>, I created my second tips site, <a href="http://blawgtips.com/">BlawgTips</a>. I wanted to drive traffic back and forth between BlawgTips and <a href="http://railstips.org/">RailsTips</a>, so I created a network bar that sits at the top of each of those. I was shocked at how easy it was. I only wanted it to be one request, so I included the styles inline in a style tag instead of calling another external stylesheet. Below is the code.</p>
<pre><code class="javascript">jQuery(document).ready(function($) {
  var styles = '&lt;style type="text/css"&gt;' +
    "#network_bar                 {float:left; display:inline; width:100%; margin:0; padding:0; background:#222; color:#ccc;}" +
    "#network_bar ul              {float:left; display:inline; margin:0; padding:0;}" +
    "#network_bar ul li           {float:left; display:inline; margin:0; padding:0; border-right:1px solid #333; list-style-type:none;}" +
    "#network_bar ul li a         {float:left; display:block; margin:0; padding:6px 10px; color:#aaa; font:11px/11px helvetica, arial, sans-serif !important; text-decoration:none; text-align:center;}" +
    "#network_bar ul li a:hover   {color:#fff;}" +
    "#network_bar ul li a.current {color:#fff;}" +
  '&lt;/style&gt;';

  var html = '&lt;div id="network_bar"&gt;' +
    '&lt;ul&gt;' +
      '&lt;li&gt;&lt;a href="http://blawgtips.com" title="Over-analyzing the simple art of blogging"&gt;BlawgTips&lt;/a&gt;&lt;/li&gt;' +
      '&lt;li&gt;&lt;a href="http://railstips.org" title="One man feverishly posting everything he learns"&gt;RailsTips&lt;/a&gt;&lt;/li&gt;' +
    '&lt;/ul&gt;' +
  '&lt;/div&gt;';

  $('head').append(styles);
  $('body').prepend(html);

  // to ensure that there is clearage after network bar
  $('#network_bar').next().css({clear: 'both'});

  $('#network_bar a').each(function() {
    var link = $(this);
    var is_current = new RegExp(link.attr('href')).match(window.location.href);
    if (is_current) {
      link.addClass('current');
    }
  });
});</code></pre>
<p>I define a style tag and some html. I then append the styles to the head and prepend the html to the body. I also add a clear:both to the element following the html added just to ensure things get cleared. I probably could switch that to css. Finally, I loop through the a tags in the network bar and add a class of current to the link that represents the current site a visitor is on. </p>
<p>That is it. <strong>The jQuery that actually does the work is less than 10 lines</strong>. Now I can put this in an external script and include it on multiple sites to get the exact same network bar on each of those sites. When I add a new site to the network, I simply update this one script and all the sites update with it. Pretty cool.</p>
]]></content:encoded>
			<wfw:commentRss>http://addictedtonew.com/archives/462/creating-a-network-bar-with-jquery/feed/</wfw:commentRss>
		<slash:comments>12</slash:comments>
		</item>
		<item>
		<title>Refactoring Tip: Move Functions into Objects</title>
		<link>http://addictedtonew.com/archives/444/refactoring-tip-move-functions-into-objects/</link>
		<comments>http://addictedtonew.com/archives/444/refactoring-tip-move-functions-into-objects/#comments</comments>
		<pubDate>Tue, 16 Dec 2008 04:22:03 +0000</pubDate>
		<dc:creator>jnunemaker</dc:creator>
				<category><![CDATA[Coding]]></category>
		<category><![CDATA[javascript]]></category>
		<category><![CDATA[refactoring]]></category>

		<guid isPermaLink="false">http://addictedtonew.com/?p=444</guid>
		<description><![CDATA[On the last project that I worked on, we were spending a lot of time learning and the code started to get out of control. Towards the end, I made a few passes through and started moving stuff around. Take the following two functions for example.
function addChat(name, room_jid, person_jid) {
  // add chat stuff
}

function [...]]]></description>
			<content:encoded><![CDATA[<p>On the last project that I worked on, we were spending a lot of time learning and the code started to get out of control. Towards the end, I made a few passes through and started moving stuff around. Take the following two functions for example.</p>
<pre><code class="javascript">function addChat(name, room_jid, person_jid) {
  // add chat stuff
}

function showChat(room) {
  // show chat stuff
}</code></pre>
<p>There is nothing wrong with the functions above but you can see the similarities. Both have chat in the name and both are operating on chat based stuff. What I did on the project is move them into a simple Chat object like this.</p>
<pre><code class="javascript">var Chat = {
  add: function(name, room_jid, person_jid) {
    // add chat stuff
  },

  show: function(room) {
    // show chat stuff
  }
}</code></pre>
<p>Now I don&#8217;t have to remember whether I named the function addChat or chatAdd. It is much easier to remember that we have a Chat object and that it has add and show methods. I&#8217;m obviously not going to have an Add object with a chat method. Catch my drift? I think this is one of the reasons I got so frustrated with PHP back in the day. The function names were a pain to remember and the parameter order was even worse. </p>
<p>Moving things to an object like this makes them easier to remember and allows your code to grow. If, for example, I wanted to keep track of the current chat with a variable or the number of active chats, I could simply add those to the Chat object. Using functions, your only option would be to have a global variable of sorts, and trust me, those lead to the path of ruin. :)</p>
]]></content:encoded>
			<wfw:commentRss>http://addictedtonew.com/archives/444/refactoring-tip-move-functions-into-objects/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>Refactoring Tip: Introduce Explaning Variables</title>
		<link>http://addictedtonew.com/archives/434/refactoring-tip-introduce-explaning-variables/</link>
		<comments>http://addictedtonew.com/archives/434/refactoring-tip-introduce-explaning-variables/#comments</comments>
		<pubDate>Mon, 24 Nov 2008 17:38:11 +0000</pubDate>
		<dc:creator>jnunemaker</dc:creator>
				<category><![CDATA[Coding]]></category>
		<category><![CDATA[javascript]]></category>
		<category><![CDATA[patterns]]></category>
		<category><![CDATA[refactoring]]></category>

		<guid isPermaLink="false">http://addictedtonew.com/?p=434</guid>
		<description><![CDATA[I am not one to latch on to fancily named patterns, nor have I read the book on it (I did give it a skim). That said, I have managed to learn a few and today I&#8217;ll share one of my favorites. You often hear people say that comments are code smell. &#8220;You should be [...]]]></description>
			<content:encoded><![CDATA[<p>I am not one to latch on to fancily named patterns, nor have I read <a href="http://www.refactoring.com/">the book on it</a> (I did give it a skim). That said, I have managed to learn a few and today I&#8217;ll share one of my favorites. You often hear people say that comments are code smell. &#8220;You should be able to tell what code is doing by just looking at the code,&#8221; they say from their perch on high. Well, I hate to break it to you, but they are kind of right. <strong>Your code should be the comments</strong>. Take the following snippet of JavaScript code:</p>
<pre><code class="javascript">// if google.com or www.google.com add http:// to the href
if (typeof(scheme) == 'undefined' || scheme == 'www.') { url = 'http://' + url; }
</code></pre>
<p>This code is from some JavaScript I&#8217;m working on that performs auto-linking of urls and email addresses. Note that there is a comment and if you read the comment you get an idea of what the code is doing. Now I just stated that comments possibly smell, so what can we do to remove the comment and yet retain the intent of the code?</p>
<pre><code class="javascript">var no_scheme  = typeof(scheme) == 'undefined',
    www_scheme = scheme == 'www.';
if (no_scheme || www_scheme) { url = 'http://' + url; }
</code></pre>
<p>We just used a pattern, namely that of <a href="http://www.refactoring.com/catalog/introduceExplainingVariable.html">introducing explaining variables</a>. The pattern probably seems obvious now that you see it, but how often do we code like the first example. In the example above, the explaining variables are introduced with the act of replacing the, not so obvious, conditions in the if statement, with variables that are named based on the intent of the condition. Our two lines of code are now three, but I guarantee the next programmer (which might even be yourself a few months later) in our code will appreciate that extra line. Everyone knows code gets changed quite often and comments rarely do which leads to confusing and out of date comments.</p>
<p>Next time you start busting out conditional statements or chaining methods together, consider how you could introduce an explaning variable that might make the code intent more clear.</p>
]]></content:encoded>
			<wfw:commentRss>http://addictedtonew.com/archives/434/refactoring-tip-introduce-explaning-variables/feed/</wfw:commentRss>
		<slash:comments>3</slash:comments>
		</item>
		<item>
		<title>Creating A jQuery Plugin From Scratch</title>
		<link>http://addictedtonew.com/archives/414/creating-a-jquery-plugin-from-scratch/</link>
		<comments>http://addictedtonew.com/archives/414/creating-a-jquery-plugin-from-scratch/#comments</comments>
		<pubDate>Thu, 20 Nov 2008 18:19:44 +0000</pubDate>
		<dc:creator>jnunemaker</dc:creator>
				<category><![CDATA[Coding]]></category>
		<category><![CDATA[javascript]]></category>
		<category><![CDATA[jquery]]></category>
		<category><![CDATA[plugins]]></category>

		<guid isPermaLink="false">http://addictedtonew.com/?p=414</guid>
		<description><![CDATA[The first few jQuery plugins I created were basically my attempt at doing prototype in jQuery. They were not idiomatic jQuery. I did a bit of googling and found some good examples and decided to write a really basic jQuery plugin just to cement the format in my head. I figured I would post it [...]]]></description>
			<content:encoded><![CDATA[<p>The first few jQuery plugins I created were basically my attempt at doing prototype in jQuery. They were not idiomatic jQuery. I did a bit of googling and found some good examples and decided to write a really basic jQuery plugin just to cement the format in my head. I figured I would post it here both to further cement it and as a way for you to learn if you want. If you only want to see the end result, <a href="http://github.com/jnunemaker/javascripts/tree/master/jquery.toggler.js">you can find it on GitHub</a>. </p>
<h2>Cross Library Safety</h2>
<p>The first thing I do is create a wrapper function which allows me to use $ and not cause conflicts with other JavaScript frameworks that may be included. It is simple and looks like this:</p>
<pre><code class="javascript">(function($) {
  // safe to use $ here and not cause conflicts
})(jQuery);</code></pre>
<h2>Create and Name Your Plugin Function</h2>
<p>Next, I created the function inside which my plugin will reside. Whatever you name this function will be how you and others use your plugin.</p>
<pre><code class="javascript">(function($) {
  $.fn.<strong>toggler</strong> = function() {
    // the plugin functionality goes in here
  }
})(jQuery);</code></pre>
<p>I have emboldened the function name in the code above to make it obvious. This means that to use the plugin I am creating, someone would have to do <code>$('#some_selector').toggler()</code>.</p>
<h2>Allow chainability</h2>
<p>The next thing to keep in mind is that because jQuery takes any selector, you could be dealing with one or more objects. This means you need to be sure that your plugin loops through each element matched by the selector and applies the plugin functionality.</p>
<pre><code class="javascript">(function($) {
  $.fn.toggler = function() {
    <strong>return this.each(function() {</strong>
      // apply plugin functionality to each element
    });
  }
})(jQuery);</code></pre>
<p>The other thing you will notice about the addition above is that I use return. One of the cool things about jQuery is the chainability (ie: <code>$('#some_div').hide().remove()</code>). Returning the <code>this.each</code> iteration allows your plugin to be chained with other jQuery operations and plugins.</p>
<h2>Start Building Plugin Functionality</h2>
<p>The goal of the plugin I was creating was to allow saying that a particular link is a toggler. So what is a toggler you ask? A toggler is a link that toggles the visibility of another element on the page. The connection of the link to the element is by using the href. By setting the link&#8217;s href to anchor to the id of another element, we get two things for free. First, if JavaScript is not enabled, the link will still anchor to the element on the page. Second, we know which element the link is suppose to toggle display for. Take the following html for example:</p>
<pre><code class="html">&lt;p&gt;&lt;a href="#foo" class="toggler"&gt;Toggler&lt;/a&gt;&lt;/p&gt;
&lt;div id="foo"&gt;Togglee&lt;/div&gt;</code></pre>
<p>The default behavior of the toggler link is to anchor to the Togglee div wherever it is on the page. We will then use the jQuery plugin we are making to hide the togglee div on page load and then toggle its display each time the toggler link is clicked. First, let&#8217;s hide the togglee div and add the click observer to the toggler link.</p>
<pre><code class="javascript">(function($) {
  $.fn.toggler = function() {
    return this.each(function() {
      <strong>this.togglee = $($(this).attr('href')).hide();
      $(this).click(onClick);</strong>
    });
  }
})(jQuery);</code></pre>
<p>The first bold line sets a togglee attribute on the toggler that is equal to the togglee jQuery element. Note the <code>$(this).attr('href')</code>. Using the html from above, this would return #foo. <code>$('#foo')</code> is equivalent to a jQuery object of the togglee div. We call <code>hide()</code> to hide the div by default. Because jQuery allows chaining, the hide() call returns the togglee jQuery object and we save a line of code. The long hand way of writing that line would be something like this:</p>
<pre><code class="javascript">this.togglee = $($(this).attr('href'));
this.togglee.hide();</code></pre>
<p>Because jQuery allows chaining, lines like the ones above can be combined and in my opinion remain readable. Chaining too many things together can lower readability and the obviousness of intent though, so always practice safe chaining.</p>
<h2>Observing Clicks</h2>
<p>The <code>$(this).click(onClick);</code> line above tells the toggler (which is <code>$(this)</code>) to run the function <code>onClick</code> whenever it gets clicked. We haven&#8217;t yet created the onClick function so let&#8217;s do that now.</p>
<pre><code class="javascript">(function($) {
  $.fn.toggler = function() {
    return this.each(function() {
      this.togglee = $($(this).attr('href')).hide();
      $(this).click(onClick);
    });

    <strong>function onClick() {
      this.togglee.toggle()
      return false;
    }</strong>
  }
})(jQuery);</code></pre>
<p><code>this</code> is automatically set to the element that fired the <code>onClick</code>, by jQuery, which is our toggler link. Because we assigned the togglee attribute to the toggler link, we can simple call <code>this.togglee.toggle() </code>and it will toggle the display of the togglee div. The <code>return false</code> tells the togglee link to not actually fire the normal event, which would append #foo to the window location.</p>
<h2>Allowing For Options</h2>
<p>At this point, we could be done but why not allow some options for our plugin. In this case, we&#8217;ll add the option to make the togglee div animate with a slide instead of simply showing and hiding. Check out the bold lines in the cold sample below to see what is needed to add options.</p>
<pre><code class="javascript">(function($) {
  $.fn.toggler = function(options) {

    <strong>var opts = $.extend({}, $.fn.toggler.defaults, options);</strong>

    return this.each(function() {
      this.togglee = $($(this).attr('href')).hide();
      $(this).click(onClick);
    });

    function onClick() {
      <strong>this.togglee[opts.animate ? 'slideToggle' : 'toggle']();</strong>
      return false;
    }
  }

  <strong>$.fn.toggler.defaults = {animate: false}</strong>
})(jQuery);</code></pre>
<p>The first bold line sets the opts variable and uses <a href="http://docs.jquery.com/Utilities/jQuery.extend">jQuery&#8217;s extend function</a> to do so. Basically, <code>$.extend</code> is a merge tool. In plain english here is what happens: it merges <code>$.fn.toggler.defaults</code> on top of <code>{}</code> and then merges <code>options</code> on top of the first merge. It guarantees that our <code>opts</code> variable will be a hash (<code>{}</code>), will have some defaults (<code>$.fn.toggler.defaults</code>) and yet can be overridden on a per case basis with options passed in by you, the developer (<code>options</code>).</p>
<p>In the second bold line, we tell togglee to call <code>slideToggle</code> if <code>opts.animate</code> is true, otherwise just call <code>toggle</code>. This uses the ternary operator and some cool JavaScript functionality. If <code>opts.animate</code> is true, it returns <code>'slideToggle'</code>, otherwise it returns <code>'toggle'</code>. This means if <code>opts.animate</code> is true, you would end up with <code>this.togglee['slideToggle']()</code>, which is the sweet functionality I referenced above that JavaScript natively provides. <code>this.togglee['slideToggle']</code> is a reference to the <code>slideToggle</code> function and when you apply the parenthesis it will invoke the <code>slideToggle</code> function. I feel this way is more succinct, is still readable and again, it saves you a few lines and an if/else statement. Not a big deal, but worth it in this case.</p>
<p>The third and final emboldened line just sets the defaults that get used in the first line if no options are provided by you when you call <code>toggler</code> on some elements.</p>
<h2>Example Uses With/Without Options</h2>
<p>Now that we have options, you can call the toggler function any of the following ways and it will work.</p>
<pre><code class="javascript">// will do simple toggle on click
$('a.toggler').toggler();

// will use slideToggle instead of simple toggle on click
$('a.toggler.animate').toggler({animate:true});</code></pre>
<p>That is pretty much it. You can now create a jQuery plugin that is jQuery-ish and has the ability to have options that can be adjusted on the fly, by you and the people who use your amazing plugin. The only other thing I would mention is most people seem to name their plugins jquery.{plugin name}.js. For example, I named this plugin jquery.toggler.js.</p>
<p>Overall, I am intrigued with jQuery. It doesn&#8217;t come with everything that Prototype does out of the box, but it is probably enough for most. Even if you do not switch to jQuery, I think it is important to give it a good run as it will help you think through JavaScript in a bit different light. As always, if I missed anything or I was unclear or wrong anywhere in the post, feel free to let me know and I will update.</p>
]]></content:encoded>
			<wfw:commentRss>http://addictedtonew.com/archives/414/creating-a-jquery-plugin-from-scratch/feed/</wfw:commentRss>
		<slash:comments>7</slash:comments>
		</item>
		<item>
		<title>Google App Engine Chicago Hackathon</title>
		<link>http://addictedtonew.com/archives/298/google-app-engine-chicago-hackathon/</link>
		<comments>http://addictedtonew.com/archives/298/google-app-engine-chicago-hackathon/#comments</comments>
		<pubDate>Sat, 02 Aug 2008 17:18:46 +0000</pubDate>
		<dc:creator>jnunemaker</dc:creator>
				<category><![CDATA[Coding]]></category>
		<category><![CDATA[app engine]]></category>
		<category><![CDATA[chicago]]></category>
		<category><![CDATA[google]]></category>
		<category><![CDATA[python]]></category>

		<guid isPermaLink="false">http://addictedtonew.com/?p=298</guid>
		<description><![CDATA[Google threw a hackathon last week for their app engine product at their Chicago offices. Myself, Steve, Dan Parker and Jon Hoyt attended. 
I wasn&#8217;t sure what to expect but knew we would have fun (pictures here). The event was very lax. Every couple hours Google would talk a bit about App Engine but other [...]]]></description>
			<content:encoded><![CDATA[<p>Google threw a hackathon last week for their app engine product at their Chicago offices. Myself, <a href="http://orderedlist.com/about/">Steve</a>, <a href="http://blog.behindlogic.com">Dan Parker</a> and <a href="http://jonmagic.com/">Jon Hoyt</a> attended. </p>
<p>I wasn&#8217;t sure what to expect but knew we would have fun (<a href="http://flickr.com/photos/johnnunemaker/sets/72157606501719938/">pictures here</a>). The event was very lax. Every couple hours Google would talk a bit about App Engine but other than that it was really just a hackathon. <strong>They encouraged us to build an application while we were there and walked around patiently answering questions</strong>. </p>
<p>We had a great time, despite not knowing a lot of python. Thus far, I&#8217;m not a huge fan of python but <strong>Google App Engine is pretty sweet</strong>. When the limits are removed and they start to support more languages, this thing is going to rock! That said, I&#8217;ll keep hacking with python, just so I can use it.</p>
<p>Oh, and obviously one of the high points was the schwag. I <strong>love</strong> schwag! I left with a full stomach, my thirsts quenched, an American Apparel App Engine T-shirt, a few funny stickers and magnets for the fridge. Speaking of full stomach, <strong>the food was awesome</strong>. Several different kinds of sandwiches, desserts, salads and drinks.</p>
<p><a href="http://www.flickr.com/photos/johnnunemaker/2724927291/" title="google app engine schwag by jnunemaker, on Flickr"><img src="http://farm4.static.flickr.com/3107/2724927291_7214e54216.jpg" style="width:470px;" class="image full" alt="google app engine schwag" /></a></p>
]]></content:encoded>
			<wfw:commentRss>http://addictedtonew.com/archives/298/google-app-engine-chicago-hackathon/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Escape HTML Using JavaScript</title>
		<link>http://addictedtonew.com/archives/264/escape-html-usingjavascript/</link>
		<comments>http://addictedtonew.com/archives/264/escape-html-usingjavascript/#comments</comments>
		<pubDate>Fri, 01 Aug 2008 20:10:08 +0000</pubDate>
		<dc:creator>jnunemaker</dc:creator>
				<category><![CDATA[Coding]]></category>
		<category><![CDATA[html]]></category>
		<category><![CDATA[javascript]]></category>
		<category><![CDATA[xss]]></category>

		<guid isPermaLink="false">http://addictedtonew.com/?p=264</guid>
		<description><![CDATA[I&#8217;m fooling around with a chat application and the first time Steve tried it out, he sent through the following as a message.
&#60;script&#62;alert('hi');&#60;/script&#62;
Obviously, I got an alert and laughed because I forgot to escape html in the chat body. Then, of course, before I could fix it, he sent through this: 
&#60;script&#62;document.getElementsByTagName('body')[0].style.display = 'none';&#60;/script&#62;
Quite promptly, [...]]]></description>
			<content:encoded><![CDATA[<p>I&#8217;m fooling around with a chat application and the first time <a href="http://orderedlist.com/about/">Steve</a> tried it out, he sent through the following as a message.</p>
<pre><code class="javascript">&lt;script&gt;alert('hi');&lt;/script&gt;</code></pre>
<p>Obviously, I got an alert and laughed because I forgot to escape html in the chat body. Then, of course, before I could fix it, he sent through this: </p>
<pre><code class="javascript">&lt;script&gt;document.getElementsByTagName('body')[0].style.display = 'none';&lt;/script&gt;</code></pre>
<p>Quite promptly, my whole screen went blank. Escaping the output in the templating engine I was using was simple, but what about when inserting a new chat using JavaScript? In Prototype, the following works.</p>
<pre><code class="javascript">$('foo').update("&lt;script&gt;alert('hi');&lt;/script&gt;".escapeHTML());</code></pre>
<p>I was using jQuery, though, so I searched around a bit for something that does the same. I&#8217;m usually quite deft with Google but I couldn&#8217;t find anything. The following is what I ended up with.</p>
<pre><code class="javascript">$('#foo').append(document.createTextNode("&lt;script&gt;alert('hi');&lt;/script&gt;");</code></pre>
<p>Since I couldn&#8217;t find it anywhere, I thought I would put it here. Hopefully, it won&#8217;t take the next bloke a few hours to figure it out.</p>
]]></content:encoded>
			<wfw:commentRss>http://addictedtonew.com/archives/264/escape-html-usingjavascript/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>Browser Support Is Too Hard</title>
		<link>http://addictedtonew.com/archives/261/browser-support-is-too-hard/</link>
		<comments>http://addictedtonew.com/archives/261/browser-support-is-too-hard/#comments</comments>
		<pubDate>Thu, 17 Jul 2008 22:50:38 +0000</pubDate>
		<dc:creator>jnunemaker</dc:creator>
				<category><![CDATA[Coding]]></category>
		<category><![CDATA[Software]]></category>
		<category><![CDATA[37signals]]></category>
		<category><![CDATA[apple]]></category>
		<category><![CDATA[browsers]]></category>
		<category><![CDATA[web]]></category>

		<guid isPermaLink="false">http://addictedtonew.com/?p=261</guid>
		<description><![CDATA[Supporting multiple browsers is too hard. I give up. From now on, I will only support the latest browser. No, not the latest version of each browser, but rather just the most recently released browser. For now, I will support Firefox 3 as it was just recently released. Safari 4 is in the works, so [...]]]></description>
			<content:encoded><![CDATA[<p>Supporting multiple browsers is too hard. I give up. From now on, I will only support the latest browser. No, not the latest version of each browser, but rather just the most recently released browser. For now, I will support Firefox 3 as it was just recently released. Safari 4 is in the works, so when that comes out I&#8217;ll update my apps to that. Also, I&#8217;ll be sure to add sniffers and detectors to redirect you to an unsupported browsers page. The next browser I support after that will probably be Internet Explorer 8. Actually, Webkit has nightly builds. I&#8217;ll just only support the latest nightly build of Webkit. </p>
<p>Hopefully, by now, you realize that last paragraph should be wrapped in a <code>&lt;sarcasm&gt;</code> tag. It seems like browser support, or rather lack there of, has been a hot topic amongst developers lately. I don&#8217;t have much to say but let me present with good and bad examples of handling browser support.</p>
<h2>Good Example</h2>
<p><img src="http://addictedtonew.com/wp-content/uploads/2008/07/37signals-product-blog.jpg" alt="37signals_product_blog.jpg" class="image full" /></p>
<p>Recently, 37Signals announced that they will be <a href="http://37signals.blogs.com/products/2008/07/basecamp-phasin.html">discontinuing support of Internet Explorer 6</a> in their products. The first thing they say in the post is when support is discontinued.</p>
<blockquote><p>On August 15th, 2008 we will begin phasing out support for Internet Explorer 6 across all 37signals products.</p>
</blockquote>
<p>Then they explain the implications of this decision.</p>
<blockquote><p>If you are using IE 7, Firefox 2 or 3, or Safari, you don&#8217;t have to do anything â€” everything will continue as is for you.</p>
</blockquote>
<p>Lastly, they explain why they made the decision.</p>
<blockquote><p>Supporting IE 6 means slower progress, less progress, and, in some places, no progress. We want to make sure the experience is the best it can be for the vast majority of our customers, and continuing to support IE 6 holds us back.</p>
</blockquote>
<p>I don&#8217;t know how intentional the order of that information was but it is pretty smart. The first thing people care about is when and what. They get that out of the way to assuage the fears that any may have that a product they pay for can no longer be used. Once they get those immediate needs covered, they discuss the why. People don&#8217;t care about the why until they know how it affects them. </p>
<p>IE 6 is an extremely outdated browser. It has performance issues and a newer version has been out since 2006. There is absolutely no reason to support IE6 for web applications anymore. 37Signals made a good decision and properly communicated it to their customers.</p>
<h2>Bad Example</h2>
<p><img src="http://addictedtonew.com/wp-content/uploads/2008/07/mobileme-login.jpg" alt="mobileme_login.jpg" class="image full" /></p>
<p>With much hype and excitement Apple recently launched <a href="http://www.apple.com/mobileme/">MobileMe</a>. Being a fanboy, I fired up my browser and signed up. Once into the app, I quickly became frustrated because nothing I clicked seemed to do anything. I know how the web works but I couldn&#8217;t get anything to do anything. Then it hit me. I wasn&#8217;t in Safari, I was in a version of Webkit (the engine that powers Safari). I closed Webkit and opened up Safari to find that everything worked. All the problems I had went away. Also, open up the app in IE7 and you get this message.</p>
<p><img src="http://addictedtonew.com/wp-content/uploads/2008/07/mobileme-ie7-message.jpg" alt="mobileme_ie7_message.jpg" class="image full" /></p>
<p>I can understand not supporting IE6 but IE7? Granted they say you can still use it but that it just doesn&#8217;t work as well. </p>
<blockquote><p>Internet Explorer 7 has known compatibility issues with modern web standards which affect Web 2.0 applications such as MobileMe.</p>
</blockquote>
<p>To me that is a total cop out. Maybe IE7 won&#8217;t perform as well but it is not so difficult to support that a message needs to be shown and users should be forced to click continue to actually use the app.</p>
<p>On top of the IE7 stuff, there are several little things that bother me about MobileMe. In an effort to make it feel more desktoppy, some normal web expectations were thrown to the wayside such as tab indexes and text selection. </p>
<h2>&lt;/rant&gt;</h2>
<p>Go ahead and drop support for IE6 in your web app. You deserve a break from it, but IE7? IE7 is not that difficult to support. There are several ways to skin a cat (or so I&#8217;ve heard) and usually one of them will work in all the major browsers.</p>
]]></content:encoded>
			<wfw:commentRss>http://addictedtonew.com/archives/261/browser-support-is-too-hard/feed/</wfw:commentRss>
		<slash:comments>4</slash:comments>
		</item>
		<item>
		<title>The Difference Between Good and Bad Software</title>
		<link>http://addictedtonew.com/archives/232/the-difference-between-good-and-bad-software/</link>
		<comments>http://addictedtonew.com/archives/232/the-difference-between-good-and-bad-software/#comments</comments>
		<pubDate>Sat, 22 Mar 2008 14:18:19 +0000</pubDate>
		<dc:creator>jnunemaker</dc:creator>
				<category><![CDATA[Coding]]></category>
		<category><![CDATA[Notre Dame]]></category>
		<category><![CDATA[Software]]></category>

		<guid isPermaLink="false">http://addictedtonew.com/archives/232/the-difference-between-good-and-bad-software/</guid>
		<description><![CDATA[I&#8217;ve been working on a really cool new feature for our website management system, Conductor. Initially, I drafted up the database tables I was going to need. I poured over them, making sure that I wasn&#8217;t forgetting anything. The whiteboard with the database tables is pictured below. Once I was satisfied with how I was [...]]]></description>
			<content:encoded><![CDATA[<p>I&#8217;ve been working on a really cool new feature for our website management system, Conductor. Initially, I drafted up the database tables I was going to need. I poured over them, making sure that I wasn&#8217;t forgetting anything. The whiteboard with the database tables is pictured below. Once I was satisfied with how I was going to store the data, I dove into the code and started implementing the whiteboard drawing I had created.</p>
<h2>Bad Start</h2>
<p><img src="http://addictedtonew.com/wp-content/uploads/2008/03/bad-start.jpg" alt="bad_start.jpg" width="415" height="267" class="photo" /></p>
<p>About three or four hours in, I realized that things weren&#8217;t going the way I wanted and that it was going to take a lot longer than expected to implement. The solution that I had come up with felt complex and was going to require a big rewrite to our theme system. Anytime something feels complex, I go back to the whiteboard because it usually means I haven&#8217;t fully thought it through. A bit frustrated, I went back to the whiteboard. This time instead of starting with how I would store the data, I focused on how I wanted to present the data (the interface that the end user would see). Again, you can see my scratching below.</p>
<h2>Good Start</h2>
<p><img src="http://addictedtonew.com/wp-content/uploads/2008/03/good-start.jpg" alt="good_start.jpg" width="415" height="267" class="photo" /></p>
<p>As I framed in the interface on the board, the problem started to seem simple and I came up with a new way of doing it that would require no alteration to our theme system or any other existing part of Conductor. Also, this new way makes more sense.</p>
<h2>Conclusion</h2>
<p>So what am I trying to get at? I think this has taught me the difference between good software and bad software. Bad software starts with the developer thinking how they are going to store the data and technically make it work. Good software starts with the end user. It firsts figures out what will be the easiest way for the user to learn and use the feature and then figures out technically how to do it. I don&#8217;t think this is a revelation or that I&#8217;ve never built anything in this manner. I am sure, though, that I wasn&#8217;t as aware of this before when building applications.</p>
<p><strong>Don&#8217;t start technical and force implementation. Start with the interface and let things come naturally.</strong></p>
]]></content:encoded>
			<wfw:commentRss>http://addictedtonew.com/archives/232/the-difference-between-good-and-bad-software/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Some Like It Hot</title>
		<link>http://addictedtonew.com/archives/228/some-like-it-hot/</link>
		<comments>http://addictedtonew.com/archives/228/some-like-it-hot/#comments</comments>
		<pubDate>Sat, 15 Mar 2008 15:40:19 +0000</pubDate>
		<dc:creator>jnunemaker</dc:creator>
				<category><![CDATA[Coding]]></category>
		<category><![CDATA[site news]]></category>

		<guid isPermaLink="false">http://addictedtonew.com/archives/228/some-like-it-hot/</guid>
		<description><![CDATA[Leave your feed reader for a bit, so you can check out my new design. The design and logo are the work of by my buddy, Oak, who I cannot give link cred because he is unable to design for himself. Maybe someday Oak. The development was all by me, obviously. It was an interesting [...]]]></description>
			<content:encoded><![CDATA[<p>Leave your feed reader for a bit, so you can check out my new design. The design and logo are the work of by my buddy, Oak, who I cannot give link cred because he is unable to design for himself. Maybe someday Oak. The development was all by me, obviously. It was an interesting slice and I recorded most of it so I&#8217;ll probably put out a new version of my &#8220;<a href="http://addictedtonew.com/archives/60/how-to-nail-a-sexy-layout/">How to nail a sexy layout</a>&#8221; series, screencasts included.</p>
<p>I was going to wait to launch this until I had finished my own blogging system (which I really haven&#8217;t started yet) but couldn&#8217;t wait. Chances are there are some bugs and I haven&#8217;t finished styling/updating everything yet, but there is enough to check out. </p>
<p>I have some cool ideas for this site and for <a href="http://railstips.org">railstips</a> in the near future. That is all for now, just thought I would give people a heads up.</p>
]]></content:encoded>
			<wfw:commentRss>http://addictedtonew.com/archives/228/some-like-it-hot/feed/</wfw:commentRss>
		<slash:comments>7</slash:comments>
		</item>
		<item>
		<title>I Take the Internet For Granted</title>
		<link>http://addictedtonew.com/archives/218/i-take-the-internet-for-granted/</link>
		<comments>http://addictedtonew.com/archives/218/i-take-the-internet-for-granted/#comments</comments>
		<pubDate>Thu, 06 Dec 2007 03:23:15 +0000</pubDate>
		<dc:creator>jnunemaker</dc:creator>
				<category><![CDATA[Coding]]></category>
		<category><![CDATA[General]]></category>
		<category><![CDATA[internet]]></category>
		<category><![CDATA[thoughts]]></category>

		<guid isPermaLink="false">http://addictedtonew.com/archives/218/i-take-the-internet-for-granted/</guid>
		<description><![CDATA[I hate grocery shopping but I love Starbucks and my computer so while Steph goes shopping at Meijer, I sit in the cafe and enjoy a non-fat latte while hacking away. One point of interest is that the Starbucks has no wifi. What this has made me aware of is how much I use the [...]]]></description>
			<content:encoded><![CDATA[<p>I hate grocery shopping but I love Starbucks and my computer so while Steph goes shopping at Meijer, I sit in the cafe and enjoy a non-fat latte while hacking away. One point of interest is that the Starbucks has no wifi. What this has made me aware of is how much I use the internet while coding. What is the name of that function? What was that bookmark on <a href="http://ma.gnolia.com">Ma.gnolia</a>? What was that feed I just read on Google Reader? I am constantly installing gems, searching for code snippets and looking up documentation while I code.</p>
<p>Whenever I run into a small problem, I Google it and I take the internet for granted. I continue in this pattern until I find myself without a beloved internet connection. It is then that I realize I don&#8217;t really know that much. I mean, what do I really know? I guess the answer to that question would be, Google. </p>
<p>Not a problem has arose that I have been unable to find a solution for, using the right keywords on Google. Noticing this tonight, as I sipped on my latte, it got me thinking. How ineffecient would I be if I had to code without the internet? Granted, I am a <strong>web</strong> developer, so at some point I would need the internet to deploy my work, but what would happen if each time I buried my nose in TextMate, I disconnected from the net. </p>
<p>Would I struggle for weeks until desperation forced me to turn it back on? Would I start to challenge my own brain for solutions instead of quickly finding and implementing a solution someone has blogged about? Would I begin to think outside the box and come up with innovative solutions to problems? Or, would I repeat everyone else&#8217;s mistakes when a simple search could have enlightened me? I don&#8217;t know. Got me thinking though.</p>
]]></content:encoded>
			<wfw:commentRss>http://addictedtonew.com/archives/218/i-take-the-internet-for-granted/feed/</wfw:commentRss>
		<slash:comments>9</slash:comments>
		</item>
		<item>
		<title>Integrating Google Analytics and Actionscript 3</title>
		<link>http://addictedtonew.com/archives/210/integrating-google-analytics-and-actionscript-3/</link>
		<comments>http://addictedtonew.com/archives/210/integrating-google-analytics-and-actionscript-3/#comments</comments>
		<pubDate>Mon, 03 Sep 2007 04:52:04 +0000</pubDate>
		<dc:creator>jnunemaker</dc:creator>
				<category><![CDATA[Coding]]></category>

		<guid isPermaLink="false">http://addictedtonew.com/archives/210/integrating-google-analytics-and-actionscript-3/</guid>
		<description><![CDATA[GA is quite easy to integrate with anything but the examples in the Help Center use AS2, at least last time I checked they did. Make sure you import the libraries you need and that you include the GA script above where you embed your swf and you are good to go. The following code [...]]]></description>
			<content:encoded><![CDATA[<p>GA is quite easy to integrate with anything but the examples in the Help Center use AS2, at least last time I checked they did. Make sure you import the libraries you need and that you include the GA script above where you embed your swf and you are good to go. The following code is untested but if you know any AS3 you should get the idea.</p>
<pre><code>package {
  import flash.display.Sprite;
  import flash.net.*;

  public class GATest extends Sprite {
    public function GATest():void {
      init();
    }

    private function init():void {
      sendToURL(new URLRequest("javascript:urchinTracker('/flash_event_folder/they_clicked_to_watch_a_video')"));
    }
  }
}</code></pre>
<p>Nothing fancy.</p>
]]></content:encoded>
			<wfw:commentRss>http://addictedtonew.com/archives/210/integrating-google-analytics-and-actionscript-3/feed/</wfw:commentRss>
		<slash:comments>4</slash:comments>
		</item>
		<item>
		<title>Building AS3 Files From TextMate</title>
		<link>http://addictedtonew.com/archives/201/building-as3-files-from-textmate/</link>
		<comments>http://addictedtonew.com/archives/201/building-as3-files-from-textmate/#comments</comments>
		<pubDate>Tue, 31 Jul 2007 00:48:40 +0000</pubDate>
		<dc:creator>jnunemaker</dc:creator>
				<category><![CDATA[Coding]]></category>

		<guid isPermaLink="false">http://addictedtonew.com/archives/201/building-as3-files-from-textmate/</guid>
		<description><![CDATA[Once again, here is another actionscript post. One of the things that got really annoying to me was re-running the builder to create my swf and test the actionscript I had been working on. I would modify an as file in TextMate, then click on iTerm, hit up and enter to rerun the last command, [...]]]></description>
			<content:encoded><![CDATA[<p>Once again, here is another actionscript post. One of the things that got really annoying to me was re-running the builder to create my swf and test the actionscript I had been working on. I would modify an as file in TextMate, then click on iTerm, hit up and enter to rerun the last command, and then view the swf in Finder. Way too much work. I have a bundle in TextMate called John&#8217;s Helpers. Inside that, I created a command called &#8216;Build File&#8217;, set the activation to Key Equivalent ctrl-b and the source to source.actionscript. Below is the code that does the dirty work.</p>
<p><img id="image202" src="http://addictedtonew.com/wp-content/uploads/2007/07/texmtate_build_as_file.jpg" alt="TextMate AS Command" class="img" /></p>
<pre><code>#!/usr/bin/env ruby -w

$LOAD_PATH << "#{ENV['TM_SUPPORT_PATH']}/lib"
require "web_preview"
require "open3"

html_header("Building ActionScript File")

if ENV.has_key?("AS_DOCUMENT_CLASS")
	filename = File.basename(ENV["AS_DOCUMENT_CLASS"])
	dir = File.dirname(ENV["AS_DOCUMENT_CLASS"])
else
	filename = File.basename(ENV['TM_FILEPATH'])
	dir = ENV["TM_DIRECTORY"]
end

puts "

Building #{filename} in #{dir}

"

swf = filename.gsub(".as", ".swf")
dir = dir.gsub(' ', '\ ') # fix space in path

puts "&lt;pre&gt;"

Open3.popen3("cd #{dir} &#038;&#038; /Applications/flex_sdk_2/bin/mxmlc #{filename}") do |stdin, stdout, stderr|
	puts stdout.gets
	if error = stderr.gets
		puts "\n\n" + error
	else
		system("open #{File.join(dir, swf)}")
	end
end

# system("cd #{dir} &#038;&#038; /Applications/flex_sdk_2/bin/mxmlc #{filename}")
puts "&lt;/pre&gt;"

html_footer</code></pre>
<h2>Assumptions</h2>
<ol>
<li>You have the <a href="http://www.adobe.com/products/flex/sdk/">free Flex SDK</a></li>
<li>The Flex SDK is installed in your Applications folder (ie: /Applications/flex_sdk_2/bin/mxmlc)</li>
</ol>
<h2>Two Ways of Using</h2>
<p>1) If you simply have a file open and you hit ctrl-b, it will create a swf of the same name in the same directory and then open it using Finder. Simple enough.</p>
<p><object classid="clsid:D27CDB6E-AE6D-11cf-96B8-444553540000" width="437" height="370" id="viddler"><param name="movie" value="http://www.viddler.com/player/6b8278bd/" /><param name="allowScriptAccess" value="always" /><param name="allowFullScreen" value="true" /><embed src="http://www.viddler.com/player/6b8278bd/" width="437" height="370" type="application/x-shockwave-flash" allowScriptAccess="always" allowFullScreen="true" name="viddler" ></embed></object></p>
<p>2) If you have a TextMate project saved with multiple ActionScript files, you can set a Project Specific Shell Variable named <samp>AS_DOCUMENT_CLASS</samp> equal to the full path to your main document class (ie: /Users/nunemaker/flash/carousel3/classes/Main.as). If that environment variable is set, no matter what ActionScript file you have open in your project, the main document class will be the only file built when you hit ctrl-b.</p>
<p><object classid="clsid:D27CDB6E-AE6D-11cf-96B8-444553540000" width="437" height="370" id="viddler"><param name="movie" value="http://www.viddler.com/player/b74e8f54/" /><param name="allowScriptAccess" value="always" /><param name="allowFullScreen" value="true" /><embed src="http://www.viddler.com/player/b74e8f54/" width="437" height="370" type="application/x-shockwave-flash" allowScriptAccess="always" allowFullScreen="true" name="viddler" ></embed></object></p>
]]></content:encoded>
			<wfw:commentRss>http://addictedtonew.com/archives/201/building-as3-files-from-textmate/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>ActionScript Is Easy</title>
		<link>http://addictedtonew.com/archives/200/actionscript-is-easy/</link>
		<comments>http://addictedtonew.com/archives/200/actionscript-is-easy/#comments</comments>
		<pubDate>Fri, 20 Jul 2007 03:37:17 +0000</pubDate>
		<dc:creator>jnunemaker</dc:creator>
				<category><![CDATA[Coding]]></category>

		<guid isPermaLink="false">http://addictedtonew.com/archives/200/actionscript-is-easy/</guid>
		<description><![CDATA[So I have been learning a lot of ActionScript the past week for a project at work and I&#8217;m continually amazed at how awesome AS3 is. Tonight in like five minutes I created a basic drawing app. I always thought that was really difficult but I am quickly learning that AS3 is actually very easy [...]]]></description>
			<content:encoded><![CDATA[<p>So I have been learning a lot of ActionScript the past week for a project at work and I&#8217;m continually amazed at how awesome AS3 is. Tonight in like five minutes I created a basic drawing app. I always thought that was really difficult but I am quickly learning that AS3 is actually very easy to learn (if you have a solid JavaScript and programming background). </p>
<h2>Screenshot</h2>
<p><a href="http://www.flickr.com/photos/johnnunemaker/855654331/" title="Photo Sharing"><img src="http://farm2.static.flickr.com/1168/855654331_679c5e1a5f.jpg" width="450" class="image" alt="AS3 Fun" /></a></p>
<p>The code below is all it takes to create the boring drawing app pictured above.</p>
<pre><code class="actionscript">package {
	import flash.display.Sprite;
	import flash.events.MouseEvent;

	public class DrawingApp extends Sprite {

		public function DrawingApp() {
			init();
		}

		private function init():void {
			graphics.lineStyle(1);
			stage.addEventListener(MouseEvent.MOUSE_DOWN, onMouseDown);
			stage.addEventListener(MouseEvent.MOUSE_UP, onMouseUp);
		}

		public function onMouseDown(event:MouseEvent):void {
			graphics.moveTo(mouseX, mouseY);
			stage.addEventListener(MouseEvent.MOUSE_MOVE, onMouseMove);
		}

		public function onMouseUp(event:MouseEvent):void {
			stage.removeEventListener(MouseEvent.MOUSE_MOVE, onMouseMove);
		}

		public function onMouseMove(event:MouseEvent):void {
			graphics.lineTo(mouseX, mouseY);
		}
	}
}</code></pre>
<p>You can try out the <a href="http://www.addictedtonew.com/examples/flash/DrawingApp.swf">example swf file here</a>. Just click on the link and use your mouse to draw as you would in Microsoft Paint.</p>
]]></content:encoded>
			<wfw:commentRss>http://addictedtonew.com/archives/200/actionscript-is-easy/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
	</channel>
</rss>

