<?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>McDonaldLand</title>
	<atom:link href="http://www.mcdonaldland.info/feed/" rel="self" type="application/rss+xml" />
	<link>http://www.mcdonaldland.info</link>
	<description>A magical discussion of software, economics, and other assorted theories. but mainly software.</description>
	<lastBuildDate>Wed, 16 May 2012 15:45:06 +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>Application Design for Mobile Devices</title>
		<link>http://www.mcdonaldland.info/2012/05/16/application-design-for-mobile-devices/</link>
		<comments>http://www.mcdonaldland.info/2012/05/16/application-design-for-mobile-devices/#comments</comments>
		<pubDate>Wed, 16 May 2012 15:45:06 +0000</pubDate>
		<dc:creator>finn0013</dc:creator>
				<category><![CDATA[Software]]></category>

		<guid isPermaLink="false">http://www.mcdonaldland.info/?p=342</guid>
		<description><![CDATA[As I watch the mobile software market explode I can&#8217;t help but notice a pattern that keeps repeating itself. Like software architecture design patterns, software packages follow distinct patterns that have been repeating over the past 20-30 years. While there is a lot of history before this point, let&#8217;s start at mainframes and terminals. See [...]]]></description>
			<content:encoded><![CDATA[<p>As I watch the mobile software market explode I can&#8217;t help but notice a pattern that keeps repeating itself. Like software architecture <a href="http://www.cafepress.com/codergear" target="newwindow">design patterns</a>, software packages follow distinct patterns that have been repeating over the past 20-30 years.</p>
<p>While there is a lot of history before this point, let&#8217;s start at mainframes and terminals. See a pattern here?</p>
<ul>
<li><strong>Remote &#8211; Terminal / Mainframe</strong><br />
During this phase of our history one could sit down at a dumb terminal that had a direct connection to the mainframe. This would provide remote access to the functionality on the server but wouldn&#8217;t provide much other functionality.</li>
<li><strong>Local &#8211; Thick client apps<br />
</strong>Next came thick client apps. That is, applications that are physically installed on a computer. This typically moved a lot of the processing off the central system and onto a stand alone computer. A good example of this is word processing.</li>
<li><strong>Remote/Local &#8211; Distributed thick client apps<br />
</strong>Once thick clients were widespread the software industry quickly realized they had a problem. They needed easy ways to update their thick client applications but also needed to be able to gather and aggregate data across all of the installations. The resulting evolution was a set of applications that could communicate with a central server as well as install updates as necessary, all without needing a technician physically present.</li>
<li><strong>Remote &#8211; Web based apps<br />
</strong>The software industry quickly realized that the bulk of the functionality that they were installing on people&#8217;s computers could easily be handled via the internet, given the advance of software and networking technologies. Thus, the web based app was born. These apps provide 90% of what most users need without the overhead of distributing, installing, and supporting thick client software. Note, however that specific app needs still have to be addressed with this clients, even in this evolution, 3D rendering being a good example.</li>
<li><strong>Local &#8211; Thick client mobile apps<br />
</strong>As the mobile world started to mature we found that the hardware in our mobile devices was becoming much more powerful and capable of handling apps. At this time the browser capabilities of these devices as well as the ability to have fast mobile networking was sufficiently infantile that once again we found ourselves utilizing thick client apps as the best way to deliver functionality.</li>
<li><strong>Remote/Local &#8211; Distributed thick client mobile apps</strong><br />
Once again, technology advances delivered us better mobile browsers and a newfound ability to handle much faster networking on mobile devices, giving birth to the distributed thick client apps for mobile devices. These apps, in many regards, follow the same basic principles as the distributed thick clients of the PC era. They are installed but can update themselves and communicate with a remote server or servers.</li>
<li><strong>Remote &#8211; Mobile responsive apps<br />
</strong>This phase of our evolution is unfolding now and is really just starting to gain traction. Over the next year this will become the de facto way that the majority of companies get their data into a mobile device. The responsive layouts concept is a way of designing a web site/application in a such a way that it understands what kind of device (PC, phone, tablet, etc.) it is being displayed on and applies the correct styling for that type device. Bank of America has a pretty good example of this. If you visit their mobile site you are seeing the same basic content you would on their primary site, however it has been styled so that it works well and is easy to use on your mobile device.</li>
</ul>
<p>Predicting what comes next in this evolution isn&#8217;t exact but also isn&#8217;t particularly difficult. We&#8217;ll likely see bridges to cross some of the major gaps that currently tie us to mobile devices, such as:</p>
<ul>
<li><strong>Browser support for mobile features</strong><br />
Mobile browsers will likely continue to begin supporting, or at least provide an API for supporting, multiple features that are device specific, such as GPS or the accelerometer. Likewise, mobile operating systems will continue to evolve in such a way that allows the browser to more easily interact with the mobile system.</li>
<li><strong>Generic push notification capabilities</strong><br />
One of the major limitations today that cause companies to gravitate towards thick client mobile apps are push notifications. If I want to be able to notify a user of a particular event the only way to do so today is to utilize the push API for a particular device. My hope is that this functionality will become standardized in such a way that notifications can be sent to a central location (albeit, possibly different device dependent locations) that knows how to notify the device in a manner suitable to that device.For example, my web application may trigger an event that then notifies the Apple servers of the event and provides a unique key that was authorized by and identifies the device. The Apple servers would then know how to send the notification to that device based on the unique id. Users would be able to easily control who does and doesn&#8217;t have access to push to them in the same manner they do today, only the system would be distributed.</li>
</ul>
<p>Until these changes take place there will always be a need for a thick client mobile app in certain situations. Just don&#8217;t write a custom thick client app for a mobile device unless you actually need the features that are offered by the mobile device you are writing for. If you just want an app for the sake of having an app, spend your money having a good designer build a mobile responsive layout for your site. However, if you actually need things like GPS, accelerometer, notifications, or other device specific features, you really don&#8217;t have much choice, in present day, but to write a thick client mobile app. In this situation you should still follow the web based paradigm as much as possible and keep as much content web based as you can.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.mcdonaldland.info/2012/05/16/application-design-for-mobile-devices/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Site maintenance</title>
		<link>http://www.mcdonaldland.info/2012/02/02/site-maintenance/</link>
		<comments>http://www.mcdonaldland.info/2012/02/02/site-maintenance/#comments</comments>
		<pubDate>Thu, 02 Feb 2012 02:14:24 +0000</pubDate>
		<dc:creator>finn0013</dc:creator>
				<category><![CDATA[Uncategorized]]></category>

		<guid isPermaLink="false">http://www.mcdonaldland.info/?p=334</guid>
		<description><![CDATA[Tonight. Hopefully up before morning, eastern time. Sorry for the inconvenience. [Finished...]]]></description>
			<content:encoded><![CDATA[<p>Tonight. Hopefully up before morning, eastern time. </p>
<p>Sorry for the inconvenience.</p>
<p>[Finished...]</p>
]]></content:encoded>
			<wfw:commentRss>http://www.mcdonaldland.info/2012/02/02/site-maintenance/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Mark Turansky talks trash.</title>
		<link>http://www.mcdonaldland.info/2012/01/15/mark-turansky-talks-trash/</link>
		<comments>http://www.mcdonaldland.info/2012/01/15/mark-turansky-talks-trash/#comments</comments>
		<pubDate>Sun, 15 Jan 2012 22:05:26 +0000</pubDate>
		<dc:creator>finn0013</dc:creator>
				<category><![CDATA[Uncategorized]]></category>

		<guid isPermaLink="false">http://www.mcdonaldland.info/?p=328</guid>
		<description><![CDATA[Indeed, Mark Turansky does talk trash. Click The Great Trashy (yes, that&#8217;s a Fraggle Rock reference&#8230;) for the full story. &#160;]]></description>
			<content:encoded><![CDATA[<p>Indeed, <a href="http://markturansky.com/" target="_new">Mark Turansky</a> does talk trash.</p>
<p>Click The Great Trashy (yes, that&#8217;s a Fraggle Rock reference&#8230;) for the full story.</p>
<p>&nbsp;</p>
<p><a href="http://www.postandcourier.com/news/2012/jan/15/composting/" target="_new"><img class="aligncenter" title="The Great Trashy" src="http://images1.wikia.nocookie.net/__cb20101120181313/muppet/images/thumb/b/b8/Trash_heap.jpg/300px-Trash_heap.jpg" alt="The Great Trashy" width="300" height="400" /></a></p>
]]></content:encoded>
			<wfw:commentRss>http://www.mcdonaldland.info/2012/01/15/mark-turansky-talks-trash/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>Jaguars</title>
		<link>http://www.mcdonaldland.info/2011/12/24/jaguars/</link>
		<comments>http://www.mcdonaldland.info/2011/12/24/jaguars/#comments</comments>
		<pubDate>Sat, 24 Dec 2011 20:48:27 +0000</pubDate>
		<dc:creator>finn0013</dc:creator>
				<category><![CDATA[Uncategorized]]></category>

		<guid isPermaLink="false">http://www.mcdonaldland.info/?p=317</guid>
		<description><![CDATA[Fire Gabbert. Fire the receivers coach.]]></description>
			<content:encoded><![CDATA[<p>Fire Gabbert. Fire the receivers coach. </p>
]]></content:encoded>
			<wfw:commentRss>http://www.mcdonaldland.info/2011/12/24/jaguars/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Zach&#8217;s Venemous Snake Bite</title>
		<link>http://www.mcdonaldland.info/2011/12/14/zachs-venemous-snake-bite/</link>
		<comments>http://www.mcdonaldland.info/2011/12/14/zachs-venemous-snake-bite/#comments</comments>
		<pubDate>Wed, 14 Dec 2011 19:08:06 +0000</pubDate>
		<dc:creator>finn0013</dc:creator>
				<category><![CDATA[Misc]]></category>

		<guid isPermaLink="false">http://www.mcdonaldland.info/?p=305</guid>
		<description><![CDATA[A family friend was out at a local park with her children and nephew just before Thanksgiving when her nephew, Zach, stepped over a log and was bit twice by a 6+ foot Canebrake rattlesnake. He has been in the hospital ever since. The Post and Courier is keeping up with his progress so I&#8217;ll [...]]]></description>
			<content:encoded><![CDATA[<p>A family friend was out at a local park with her children and nephew just before Thanksgiving when her nephew, Zach, stepped over a log and was bit twice by a 6+ foot Canebrake rattlesnake.</p>
<p>He has been in the hospital ever since.</p>
<p>The Post and Courier is keeping up with his progress so I&#8217;ll not go into those details. Here is a link to one:<br />
<a title="http://www.postandcourier.com/news/2011/dec/08/snakebite-victim-improves/" href="http://www.postandcourier.com/news/2011/dec/08/snakebite-victim-improves/">http://www.postandcourier.com/news/2011/dec/08/snakebite-victim-improves/</a></p>
<p>He has had over 40 vials of anti-venom throughout this ordeal, each of which can cost upwards of $10,000. He has been hospitalized in intensive care for nearly a month now and has been on breathing support.</p>
<p>Needless to say, the medical costs associated with this can be huge. I&#8217;d ask that if you can give anything, even if it is just a couple bucks, you visit the button below and do so. The button below is a PayPal account set up in Zach&#8217;s name. You don&#8217;t have to have a PayPal account and can use any major credit card for payment.</p>
<p>Thank you in advance for your support.</p>
<form target="newwindow" action="https://www.paypal.com/cgi-bin/webscr" method="post">
<input type="hidden" name="cmd" value="_s-xclick">
<input type="hidden" name="hosted_button_id" value="PFTNR8X8EB356">
<input type="image" src="https://www.paypalobjects.com/en_US/i/btn/btn_donateCC_LG.gif" border="0" name="submit" alt="PayPal - The safer, easier way to pay online!">
<img alt="" border="0" src="https://www.paypalobjects.com/en_US/i/scr/pixel.gif" width="1" height="1"><br />
</form>
]]></content:encoded>
			<wfw:commentRss>http://www.mcdonaldland.info/2011/12/14/zachs-venemous-snake-bite/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>The truth about the Flat Tax</title>
		<link>http://www.mcdonaldland.info/2011/10/26/the-truth-about-the-flat-tax/</link>
		<comments>http://www.mcdonaldland.info/2011/10/26/the-truth-about-the-flat-tax/#comments</comments>
		<pubDate>Wed, 26 Oct 2011 13:53:51 +0000</pubDate>
		<dc:creator>finn0013</dc:creator>
				<category><![CDATA[Economics and Politics]]></category>

		<guid isPermaLink="false">http://www.mcdonaldland.info/?p=303</guid>
		<description><![CDATA[We&#8217;ve heard a lot about flat taxes lately, with the GOP race heating up. The flat tax, in principle, sounds fair. After all, if we are all taxed at say, 10%, each would have a proportion equal to their income, right? Let&#8217;s look at an example. We&#8217;ll use nice, round numbers to keep things easy [...]]]></description>
			<content:encoded><![CDATA[<p>We&#8217;ve heard a lot about flat taxes lately, with the GOP race heating up. The flat tax, in principle, sounds fair. After all, if we are all taxed at say, 10%, each would have a proportion equal to their income, right?</p>
<p>Let&#8217;s look at an example. We&#8217;ll use nice, round numbers to keep things easy to digest and assume the chosen income tax rate is 10%. The following is the breakdown for what you&#8217;d expect to pay at different income levels:</p>
<p>&nbsp;</p>
<div id="attachment_308" class="wp-caption aligncenter" style="width: 224px"><a href="http://www.mcdonaldland.info/wp-content/uploads/2011/10/flat_tax-basic.png"><img class="size-full wp-image-308" title="Basic flat tax example" src="http://www.mcdonaldland.info/wp-content/uploads/2011/10/flat_tax-basic.png" alt="Basic flat tax example" width="214" height="95" /></a><p class="wp-caption-text">Figure 1: Basic flat tax example</p></div>
<p>Pretty simple and fair, right? Maybe, but it isn&#8217;t quite that simple.</p>
<p>Flat taxes are based on standard income. In general, investment income is often taxed at lower rates than regular income, provided it is considered to be a <a href="http://en.wikipedia.org/wiki/Qualified_dividend" target="new_window">qualified dividend</a>. A qualified dividend, simplified, is a payout from an investment that is considered to be a long term investment. This lower rate varies but is typically lower than the income tax rate and is one of the reasons why <em>some</em> extremely wealthy Americans are able to pay lower tax <strong>rates</strong> than their less wealthy counterparts.</p>
<p>Most of the wealthiest Americans are company owners and heavy investors, which gives them the opportunity to choose how to route their income. For example, as a business owner, I can choose to pay myself a small salary but pay very high annual dividends, thus diverting the majority of my income to qualified dividends, which are generally taxed at a lower rate.</p>
<p>How&#8217;s this work? Let&#8217;s use another very simple example to illustrate. Let&#8217;s assume now that qualified dividends are taxed at a 5% interest rate and all other aspects of the prior example remain true, with the exception that the top two earners in our scenario have shifted where their revenue derives from in order to minimize taxes owed:</p>
<p>&nbsp;</p>
<div id="attachment_310" class="wp-caption aligncenter" style="width: 516px"><a href="http://www.mcdonaldland.info/wp-content/uploads/2011/10/flat_tax-div1.png"><img class="size-full wp-image-310" title="Example using dividend income." src="http://www.mcdonaldland.info/wp-content/uploads/2011/10/flat_tax-div1.png" alt="Example using dividend income." width="506" height="85" /></a><p class="wp-caption-text">Figure 2: Example using dividend income.</p></div>
<p>It is important to note that paying a lower tax rate doesn&#8217;t mean paying less taxes. As we see in the example above, wealthier individuals still pay more in gross taxes, however their proportion of income paid in taxes is a much lower percentage than their less wealthy counterparts, which is <a href="http://www.politifact.com/truth-o-meter/statements/2011/aug/18/warren-buffett/warren-buffett-says-super-rich-pay-lower-taxes-oth/" target="new_window_2">what Warren Buffet pointed out</a> recently.</p>
<p>In short, the tax code is very complex. By diverting funds through different investment and holding strategies, accountants are able to reduce, and sometimes eliminate, taxes all together.</p>
<p>A flat tax could work. However, what most flat tax plans fail to account for is where the majority of income comes from. If 90% of the revenue individuals receive come from dividends, it would make sense to tax that revenue as income, not as investment payouts. But still, it isn&#8217;t that simple &#8211; for example, how should retirees that have no income except from dividends be taxed? Would it make a difference if these retirees have annual dividend payouts of only $30,000? What if their annual payout was $3,000,000? It isn&#8217;t cut and dry.</p>
<p>Regardless of your political orientation, don&#8217;t take any political plans at face value. When you hear a 30 second clip on the news or read 2 paragraphs you don&#8217;t have enough information to fully understand a complex and well planned change to a very complex institution.</p>
<p>Don&#8217;t support policies blindly. Research and understand what you are supporting.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.mcdonaldland.info/2011/10/26/the-truth-about-the-flat-tax/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Play Fridge Plans</title>
		<link>http://www.mcdonaldland.info/2011/01/03/play-fridge-plans/</link>
		<comments>http://www.mcdonaldland.info/2011/01/03/play-fridge-plans/#comments</comments>
		<pubDate>Mon, 03 Jan 2011 02:40:39 +0000</pubDate>
		<dc:creator>finn0013</dc:creator>
				<category><![CDATA[Misc]]></category>

		<guid isPermaLink="false">http://www.mcdonaldland.info/?p=284</guid>
		<description><![CDATA[For Christmas we were looking at a refrigerator to go with our kids&#8217; play stove/microwave/sink combo. We looked around a bit and kept finding that they were way more expensive than they needed to be and would still take some work to get them to match the set we have. So my wife started looking [...]]]></description>
			<content:encoded><![CDATA[<p>For Christmas we were looking at a refrigerator to go with our kids&#8217; play stove/microwave/sink combo. We looked around a bit and kept finding that they were way more expensive than they needed to be and would still take some work to get them to match the set we have.</p>
<p>So my wife started looking around and came across <a href="http://ana-white.com/" target="_blank">http://ana-white.com/</a>, which had plans for a pretty simple play fridge. The one she had was a little bit too small and didn&#8217;t quite match what we have already, but seeing the plans made me realize how easy it was to put together a simple set of plans that did match what we have.</p>
<p>So I drew up some plans, which are available from the link below. The fridge turned out great. It matches the existing set in size, color, and style. The kids love it. The total cost was around $50 but would have been even less had I not gone to a home store for all my lumber.</p>
<p>Here are some pics (click for full sized image):</p>

<a href='http://www.mcdonaldland.info/2011/01/03/play-fridge-plans/frontclosed/' title='FrontClosed'><img width="150" height="150" src="http://www.mcdonaldland.info/wp-content/uploads/2011/01/FrontClosed-150x150.jpg" class="attachment-thumbnail" alt="FrontClosed" title="FrontClosed" /></a>
<a href='http://www.mcdonaldland.info/2011/01/03/play-fridge-plans/frontopen/' title='FrontOpen'><img width="150" height="150" src="http://www.mcdonaldland.info/wp-content/uploads/2011/01/FrontOpen-150x150.jpg" class="attachment-thumbnail" alt="FrontOpen" title="FrontOpen" /></a>
<a href='http://www.mcdonaldland.info/2011/01/03/play-fridge-plans/withstove/' title='WIthStove'><img width="150" height="150" src="http://www.mcdonaldland.info/wp-content/uploads/2011/01/WIthStove-150x150.jpg" class="attachment-thumbnail" alt="WIthStove" title="WIthStove" /></a>

<p>You can download the step by step plans here:<br />
<a href="http://www.mcdonaldland.info/wp-content/uploads/2011/01/PlayFridgePlans.pdf" target="_blank">Play Fridge Plans</a><br/></p>
<p>If you found these plans useful, please consider making a small donation. The ad revenue for this site doesn&#8217;t quite cover rent.</p>
<form action="https://www.paypal.com/cgi-bin/webscr" method="post" target="newwindow">
<input name="cmd" type="hidden" value="_s-xclick" />
<input name="hosted_button_id" type="hidden" value="VP4AB5Z3HSQQA" />
<input alt="PayPal - The safer, easier way to pay online!" name="submit" src="https://www.paypal.com/en_US/i/btn/btn_donateCC_LG.gif" type="image" /> <img src="https://www.paypal.com/en_US/i/scr/pixel.gif" border="0" alt="" width="1" height="1" /><br />
</form>
]]></content:encoded>
			<wfw:commentRss>http://www.mcdonaldland.info/2011/01/03/play-fridge-plans/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Web based drawing canvas (no HTML5)</title>
		<link>http://www.mcdonaldland.info/2010/11/09/web-based-drawing-canvas/</link>
		<comments>http://www.mcdonaldland.info/2010/11/09/web-based-drawing-canvas/#comments</comments>
		<pubDate>Tue, 09 Nov 2010 08:21:02 +0000</pubDate>
		<dc:creator>finn0013</dc:creator>
				<category><![CDATA[Software]]></category>

		<guid isPermaLink="false">http://www.mcdonaldland.info/?p=274</guid>
		<description><![CDATA[I have a need for a web based drawing tool, much like Microsoft Paint &#8211; just a simple canvas that allows me to draw on it. I&#8217;ve searched around a bit and have found that the majority of the tools are Flash based and the ones that are not are lacking in one way or [...]]]></description>
			<content:encoded><![CDATA[<p>I have a need for a web based drawing tool, much like Microsoft Paint &#8211; just a simple canvas that allows me to draw on it. I&#8217;ve searched around a bit and have found that the majority of the tools are Flash based and the ones that are not are lacking in one way or another.</p>
<p>So I decided to create a simple, purely web based drawing tool. This works in all browsers and even works on my iPad (although I have to click each square to form the drawing on the iPad since dragging simply moves the screen). The canvas, with a drawing, is shown in Figure 1.</p>
<p>It uses some simple JavaScript and CSS to achieve the effect. The grid lines, border, and cell size are all controlled by CSS. Just click or click and drag to draw. Do the same while holding down the SHIFT key to erase (draw in alternate color). I chose to use the SHIFT key combination for color 2 to avoid conflict with context menus when right clicking and OS specific uses for ALT and CTRL.</p>
<p style="text-align: center;"><a href="http://www.mcdonaldland.info/files/canvas/canvas.html" target="_blank"><img title="Canvas" src="http://www.mcdonaldland.info/wp-content/uploads/2010/11/grid11.png" alt="" width="246" height="209" /></a><br />
<em>Figure 1: Picture of a drawing done on &#8220;Canvas&#8221; (demo link below).<br />
</em></p>
<p>Everything is encapsulated inside the Canvas object, so it is really easy to use. All you need is a DIV, a little bit of CSS, and the couple lines of JavaScript below.</p>
<p>Here&#8217;s how to use it:</p>
<pre>// Creates the canvas - just make sure you have a DIV with an id of "drawingArea"
// The last parameter of false allows editing - set to true for read only
// Note that these are squares - actual square size is set via CSS
var myCanvas = new Canvas("drawingArea", 60, 40, false);

// This will change the drawing colors
myCanvas.setFillColor("#CCCCCC"); // #000 by default
myCanvas.setEraseColor("#555555"); // #FFF by default

// This will resize the canvas, preserving what portions of the drawing it can
myCanvas.resize(100, 10); // 100 wide by 10 high

// This will save the contents of the canvas down to a JSON string
var myData = myCanvas.save();

// This will load a drawing from a JSON string
myCanvas.load(myData);</pre>
<p>You can view a working demo <a href="http://www.mcdonaldland.info/files/canvas/canvas.html" target="_blank">here</a>.</p>
<p>You can find the JS file here:<br />
<a href="http://www.mcdonaldland.info/files/canvas/canvas.js" target="_blank">http://www.mcdonaldland.info/files/canvas/canvas.js</a></p>
<p>Note that you&#8217;ll also need the JSON2 JS file as well:<br />
<a href="http://www.mcdonaldland.info/files/canvas/json2.js" target="_blank">http://www.mcdonaldland.info/files/canvas/json2.js</a></p>
<p>An improvement idea:<br />
When mouse moves fast, lines have gaps in them. It would be pretty easy to write an algorithm that figures out empty squares between two points and fills them in. Alternatively, it wouldn&#8217;t be too difficult to handle this without tables by tracking the mouse location within the DIV then drawing points/lines.</p>
<p>Feel free to use this as you see fit. I just ask that you:</p>
<ol>
<li>Leave the copyright information at the top of the JS file in place.</li>
<li>Don&#8217;t sell the code or any product that has this code as the core feature without my consent.</li>
</ol>
<p>Enjoy!</p>
]]></content:encoded>
			<wfw:commentRss>http://www.mcdonaldland.info/2010/11/09/web-based-drawing-canvas/feed/</wfw:commentRss>
		<slash:comments>6</slash:comments>
		</item>
		<item>
		<title>JavaScript Event to an Object Instance</title>
		<link>http://www.mcdonaldland.info/2010/11/05/javascript-event-to-an-object-instance/</link>
		<comments>http://www.mcdonaldland.info/2010/11/05/javascript-event-to-an-object-instance/#comments</comments>
		<pubDate>Sat, 06 Nov 2010 00:04:22 +0000</pubDate>
		<dc:creator>finn0013</dc:creator>
				<category><![CDATA[Software]]></category>

		<guid isPermaLink="false">http://www.mcdonaldland.info/?p=262</guid>
		<description><![CDATA[I searched the web for quite a while and couldn&#8217;t find a good answer to this problem, so I figured I&#8217;d post it to save the next person a little time. I have a situation where I want to send an event to an instance of a JavaScript object. I could get it to go [...]]]></description>
			<content:encoded><![CDATA[<p>I searched the web for quite a while and couldn&#8217;t find a good answer to this problem, so I figured I&#8217;d post it to save the next person a little time.</p>
<p>I have a situation where I want to send an event to an instance of a JavaScript object. I could get it to go to the object itself, but was having trouble getting it to apply to only a specific instance of the object.</p>
<p>The answer was surprisingly simple &#8211; just wrap the pointer to your event handler function in an anonymous function. Doing this gives the anonymous function (closure) access to the variables currently in scope, which means that I have access to my object instance now.</p>
<p>The code is below. The commented out event listener add lines were the original attempt that would result in &#8220;undefined&#8221; being printed to the screen instead of my instance variable value. The uncommented version correctly calls my instance, which prints &#8220;test&#8221; to the debug area of the screen each time it is clicked.</p>
<pre>// The object to handle the event...
function TestListenerObj(txt) {
    this.eventText = txt;
    this.handleEvent = function() {
        var debug = document.getElementById("debug");
        debug.innerHTML = debug.innerHTML + this.eventText + "&lt;br/&gt;";
        return false;
    }
}

// Sets up the event handler
function init() {
    var link = document.getElementById("test_link");
    var obj = new TestListenerObj("test");

    if (link.addEventListener) {
        // link.addEventListener("click", obj.handleEvent, false); // Calls "class" level handleEvent()
        link.addEventListener("click", function() { obj.handleEvent(); }, false); // Calls instance level handleEvent()
    } else {
        // link.attachEvent("onclick", obj.handleEvent ); // Calls "class" level handleEvent()
        link.attachEvent("onclick", function() { obj.handleEvent(); }); // Calls instance level handleEvent()
    }
}</pre>
<p>For a working example go <a href="http://www.mcdonaldland.info/files/ObjectEventHandler/ObjectEventHandler.html" target="_blank">here</a>. For complete source visit this link and view source. Just click the &#8220;Test&#8221; link on the example to see the event be handled by the object, which in this case just prints to the debug area.﻿</p>
]]></content:encoded>
			<wfw:commentRss>http://www.mcdonaldland.info/2010/11/05/javascript-event-to-an-object-instance/feed/</wfw:commentRss>
		<slash:comments>3</slash:comments>
		</item>
		<item>
		<title>Ruby based image crawler</title>
		<link>http://www.mcdonaldland.info/2010/05/18/ruby-based-image-crawler/</link>
		<comments>http://www.mcdonaldland.info/2010/05/18/ruby-based-image-crawler/#comments</comments>
		<pubDate>Wed, 19 May 2010 02:47:40 +0000</pubDate>
		<dc:creator>finn0013</dc:creator>
				<category><![CDATA[Software]]></category>

		<guid isPermaLink="false">http://www.mcdonaldland.info/?p=242</guid>
		<description><![CDATA[I don&#8217;t write much code these days and felt it was time to sharpen the saw. I have a need to download a ton of images from a site (I got permission first&#8230;) but it is going to take forever to do by hand. Even though there are tons of tools out there for image [...]]]></description>
			<content:encoded><![CDATA[<p>I don&#8217;t write much code these days and felt it was time to <a href="https://www.stephencovey.com/7habits/7habits-habit7.php" target="_blank">sharpen the saw</a>.</p>
<p>I have a need to download a ton of images from a site (I got permission first&#8230;) but it is going to take forever to do by hand. Even though there are tons of tools out there for image crawling I figured this would be a great exercise to brush up on some skills and delve further into a language I am still fairly new to, Ruby. This allows me to use basic language constructs, network IO, and file IO, all while getting all the images I need in a fast manner.</p>
<p>As I have mentioned a few times on this blog, I am still new to Ruby so any advice for how to make this code cleaner is appreciated.</p>
<p>You can download the file here: <a href="http://www.mcdonaldland.info/files/crawler/crawl.rb" target="_blank">http://www.mcdonaldland.info/files/crawler/crawl.rb</a></p>
<p>Here is the source:</p>
<pre>require 'net/http'
require 'uri'

class Crawler

  # This is the domain or domain and path we are going
  # to crawl. This will be the starting point for our
  # efforts but will also be used in conjunction with
  # the allow_leave_site flag to determine whether the
  # page can be crawled or not.
  attr_accessor :domain

  # This flag determines whether the crawler will be
  # allowed to leave the root domain or not.
  attr_accessor :allow_leave_site

  # This is the path where all images will be saved.
  attr_accessor :save_path

  # This is a list of extensions to skip over while
  # crawling through links on the site.
  attr_accessor : omit_extensions # Remove space between : and o - WordPress tries to make this a smiley if I leave them together.

  # This keeps track of all the pages we have visited
  # so we don't visit them more than once.
  attr_accessor :visited_pages

  # This keeps track of all the images we have downloaded
  # so we don't download them more than once.
  attr_accessor :downloaded_images

  def begin_crawl
    # Check to see if the save path ends with a slash. If so, remove it.
    remove_save_path_end_slash

    if domain.nil? || domain.length &lt; 4 || domain[0, 4] != "http"
      @domain = "http://#{domain}"
    end

    crawl(domain)
  end

  private

  def remove_save_path_end_slash        
    sp = save_path[save_path.length - 1, 1]

    if sp == "/" || sp == "\\"
      save_path.chop!
    end
  end

  def initialize
    @domain = ""
    @allow_leave_site = false
    @save_path = ""
    @omit_extensions = []
    @visited_pages = []
    @downloaded_images = []
  end

  def crawl(url = nil)

    # If the URL is empty or nil we can move on.
    return if url.nil? || url.empty?

    # If the allow_leave_site flag is set to false we
    # want to make sure that the URL we are about to
    # crawl is within the domain.
    return if !allow_leave_site &amp;&amp; (url.length &lt; domain.length || url[0, domain.length] != domain)

    # Check to see if we have crawled this page already.
    # If so, move on.
    return if visited_pages.include? url

    puts "Fetching page: #{url}"

    # Go get the page and note it so we don't visit it again.
    res = fetch_page(url)
    visited_pages &lt;&lt; url

    # If the response is nil then we cannot continue. Move on.
    return if res.nil?

    # Some links will be relative so we need to grab the
    # document root.
    root = parse_page_root(url)

    # Parse the image and anchor tags out of the result.
    images, links = parse_page(res.body)

    # Process the images and links accordingly.
    handle_images(root, images)
    handle_links(root, links)
  end

  def parse_page_root(url)
    end_slash = url.rindex("/")
    if end_slash &gt; 8
      url[0, url.rindex("/")] + "/"
    else
      url + "/"
    end
  end

  def discern_absolute_url(root, url)
    # If we don't have an absolute path already, let's make one.            
    if !root.nil? &amp;&amp; url[0,4] != "http"

      # If the URL begins with a slash then it is domain
      # relative so we want to append it to the domain.
      # Otherwise it is document relative so we want to
      # append it to the current directory.
      if url[0, 1] == "/"
        url = domain + url
      else
        url = root + url
      end
    end    

    while !url.index("//").nil?
      url.gsub!("//", "/")
    end

    # Our little exercise will have replaced the two slashes
    # after http: so we want to add them back.
    url.gsub!("http:/", "http://")

    url
  end

  def handle_images(root, images)
    if !images.nil?
      images.each {|i|

        # Make sure all single quotes are replaced with double quotes.
        # Since we aren't rendering javascript we don't really care
        # if this breaks something.
        i.gsub!("'", "\"")        

        # Grab everything between src=" and ".
        src = i.scan(/src=[\"\']([^\"\']+)/i)
        if !src.nil?
          src = src[0]
          if !src.nil?
            src = src[0]
          end
        end

        # If the src is empty move on.
        next if src.nil? || src.empty?

        # We want all URLs we follow to be absolute.
        src = discern_absolute_url(root, src)

        save_image(src)
      }
   end
  end

  def save_image(url)
    # Check to see if we have saved this image already.
    # If so, move on.
    return if downloaded_images.include? url        

    # Save this file name down so that we don't download
    # it again in the future.
    downloaded_images &lt;&lt; url

    # Parse the image name out of the url. We'll use that
    # name to save it down.
    file_name = parse_file_name(url)

    while File.exist?(save_path + "/" + file_name)
      file_name = "_" + file_name
    end

    # Get the response and data from the web for this image.
    response = fetch_page(url)

    # If the response is not nil, save the contents down to
    # an image.
    if !response.nil?
      puts "Saving image: #{url}"    

      File.open(save_path + "/" + file_name, "wb+") do |f|
        f &lt;&lt; response.body
      end
    end
  end

  def parse_file_name(url)
    # Find the position of the last slash. Everything after
    # it is our file name.
    spos = url.rindex("/")    
    url[spos + 1, url.length - 1]
  end

  def handle_links(root, links)
    if !links.nil?
      links.each {|l|    

        # Make sure all single quotes are replaced with double quotes.
        # Since we aren't rendering javascript we don't really care
        # if this breaks something.
        l.gsub!("'", "\"")

        # Grab everything between href=" and ".
        href = l.scan(/(\href+)="([^"\\]*(\\.[^"\\]*)*)"/i)
        if !href.nil?
          href = href[0]
          if !href.nil?
            href = href[1]
          end
        end

        # We don't want to follow mailto or empty links
        next if href.nil? || href.empty? || (href.length &gt; 6 &amp;&amp; href[0,6] == "mailto")

        # We want all URLs we follow to be absolute.
        href = discern_absolute_url(root, href)

        # Down the rabbit hole we go...
        crawl(href)
      }
    end
  end

  def parse_page(html)    
    images = html.scan(/&lt;img [^&gt;]*&gt;/i)
    links = html.scan(/&lt;a [^&gt;]*&gt;/i)

    return [ images, links ]
  end

  def fetch_page(url, limit = 10)
    # Make sure we are supposed to fetch this type of resource.
    return if should_omit_extension(url)

    # You should choose better exception.
    raise ArgumentError, 'HTTP redirect too deep' if limit == 0

    begin
      response = Net::HTTP.get_response(URI.parse(url))
    rescue
      # The URL was not valid - just log it can keep moving
      puts "INVALID URL: #{url}"
    end

    case response
      when Net::HTTPSuccess     then response
      when Net::HTTPRedirection then fetch_page(response['location'], limit - 1)
      else
        # We don't want to throw errors if we get a response
        # we are not expecting so we will just keep going.
        nil
    end
  end

  def should_omit_extension(url)
    # Get the index of the last slash.
    spos = url.rindex("/")

    # Get the index of the last dot.
    dpos = url.rindex(".")

    # If there is no dot in the string this will be nil, so we
    # need to set this to 0 so that the next line will realize
    # that there is no extension and can continue.
    if dpos.nil?
      dpos = 0
    end

    # If the last dot is before the last slash, we don't have
    # an extension and can return.
    return false if spos &gt; dpos

    # Grab the extension.
    ext = url[dpos + 1, url.length - 1]

    # The return value is whether or not the extension we
    # have for this URL is in the omit list or not.
    omit_extensions.include? ext

  end

end

# TODO: Update each comparison to be a hash comparison (possibly in a hash?) in order
# to speed up comparisons. Research to see if this will even make a difference in Ruby.

crawler = Crawler.new
crawler.save_path = "C:\SavePath"
crawler.omit_extensions = [ "doc", "pdf", "xls", "rtf", "docx", "xlsx", "ppt",
                          "pptx", "avi", "wmv", "wma", "mp3", "mp4", "pps", "swf" ]
crawler.domain = "http://www.yoursite.com/"
crawler.allow_leave_site = false
crawler.begin_crawl

# Bugs fixed:
# 1. Added error handling around call to HTTP.get_response in order to handle timeouts and other errors
#
# 2. Added check upon initialization to remove the trailing slash on the save path, if it exists.
<a></a></pre>
]]></content:encoded>
			<wfw:commentRss>http://www.mcdonaldland.info/2010/05/18/ruby-based-image-crawler/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
	</channel>
</rss>

