<?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"
	>

<channel>
	<title>acatalept/blog</title>
	<atom:link href="http://acatalept.com/blog/feed/" rel="self" type="application/rss+xml" />
	<link>http://acatalept.com/blog</link>
	<description>random notes of toil and hardship at the hands of our new master, the computer.</description>
	<pubDate>Fri, 09 Oct 2009 20:11:15 +0000</pubDate>
	<generator>http://wordpress.org/?v=2.6.3</generator>
	<language>en</language>
			<item>
		<title>Compare objects recursively in Javascript</title>
		<link>http://acatalept.com/blog/2009/10/09/compare-objects-recursively-in-javascript/</link>
		<comments>http://acatalept.com/blog/2009/10/09/compare-objects-recursively-in-javascript/#comments</comments>
		<pubDate>Fri, 09 Oct 2009 17:23:52 +0000</pubDate>
		<dc:creator>acat</dc:creator>
		
		<category><![CDATA[Programming]]></category>

		<guid isPermaLink="false">http://acatalept.com/blog/?p=60</guid>
		<description><![CDATA[This is a need I've run into more than once, yet there doesn't seem to be an elegant off-the-shelf solution that can handle a wide range of use cases, including simple (flat) objects, linear (one-dimensional) arrays, arrays of objects, and complex objects (objects within objects).
So here's a [relatively] straightforward recursive object comparison function that features [...]]]></description>
			<content:encoded><![CDATA[<p>This is a need I've run into more than once, yet there doesn't seem to be an elegant off-the-shelf solution that can handle a wide range of use cases, including simple (flat) objects, linear (one-dimensional) arrays, arrays of objects, and complex objects (objects within objects).</p>
<p>So here's a [relatively] straightforward recursive object comparison function that features <strong>optional loose type comparison</strong> (strict by default) for those times when you're working with data from different sources, (e.g., which give you quoted numbers ("3" == 3) or empty strings ("" == null == undefined == 0 == "0")), but your task at hand doesn't distinguish among these semantic differences.<br />
<span id="more-60"></span></p>
<p>Note that performance on huge objects has not been tested, but should be acceptable.  Of course, there's likely room for improvement ;)</p>

<div class="wp_syntax"><table><tr><td class="line_numbers"><pre>1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
</pre></td><td class="code"><pre class="javascript"><span style="color: #ccc">// compare two objects recursively</span>
<span style="color: #ccc">// doesn't rely on specifics of object creation or property order</span>
<span style="color: #ccc">// performs strict type comparison on values by default, unless loose is set to TRUE</span>
&nbsp;
<span style="color: #ccc">// USAGE</span>
&nbsp;
<span style="color: #ccc">// obj1 = {'key1': 1, 'key2': 2};</span>
<span style="color: #ccc">// obj2 = {'key2': 2, 'key1': 1};</span>
<span style="color: #ccc">// objectCompare(obj1, obj2); // returns true</span>
&nbsp;
<span style="color: #ccc">// obj1 = {'a': 0, 'b': ''};</span>
<span style="color: #ccc">// obj2 = {'b': null}; // don't even declare an 'a' property, so it will be undefined - note that number of properties is ignored when doing loose comparison</span>
<span style="color: #ccc">// objectCompare(obj1, obj2, true); // returns true... for 'a', 0 == undefined, and for 'b', '' == null</span>
&nbsp;
<span style="color: #ccc">// will even compare arrays:</span>
<span style="color: #ccc">// obj1 = [0, 1];</span>
<span style="color: #ccc">// obj2 = [null, '1'];</span>
<span style="color: #ccc">// objectCompare(obj1, obj2, true); // returns true</span>
&nbsp;
<span style="color: #ccc">// or even arrays of objects:</span>
<span style="color: #ccc">// obj1 = [{'a': 1}, {'b': '0'}];</span>
<span style="color: #ccc">// obj2 = [{'a': '1'}, {'b': null}];</span>
<span style="color: #ccc">// objectCompare(obj1, obj2, true); // returns true</span>
&nbsp;
<span style="color: #ccc">// note that arrays are compared by index, so out-of-sequence arrays should be sorted before comparing</span>
&nbsp;
<span style="color: #000;">function</span> objectCompare<span style="color: #666;">&#40;</span>obj1<span style="color: #666;">,</span> obj2<span style="color: #666;">,</span> loose<span style="color: #666;">&#41;</span> <span style="color: #666;">&#123;</span>
&nbsp;
  <span style="color: #ccc">// if loose is NOT TRUE, first do a quick comparison of lengths</span>
  <span style="color: #ccc">// quick &amp; dirty attempt to avoid comparing all property values on large or complex objects</span>
  <span style="color: #000;">var</span> count1 <span style="color: #666;">=</span> <span style="color: #B4C24B;">0</span><span style="color: #666;">,</span> count2 <span style="color: #666;">=</span> <span style="color: #B4C24B;">0</span><span style="color: #666;">;</span>
  <span style="color: #000;">if</span> <span style="color: #666;">&#40;</span><span style="color: #666;">!</span>loose<span style="color: #666;">&#41;</span><span style="color: #666;">&#123;</span>
    <span style="color: #000;">for</span> <span style="color: #666;">&#40;</span>i <span style="color: #000;">in</span> obj1<span style="color: #666;">&#41;</span><span style="color: #666;">&#123;</span>
      count1<span style="color: #666;">++;</span>
    <span style="color: #666;">&#125;</span>
    <span style="color: #000;">for</span> <span style="color: #666;">&#40;</span>i <span style="color: #000;">in</span> obj2<span style="color: #666;">&#41;</span><span style="color: #666;">&#123;</span>
      count2<span style="color: #666;">++;</span>
    <span style="color: #666;">&#125;</span>
  <span style="color: #666;">&#125;</span>
&nbsp;
  <span style="color: #000;">if</span> <span style="color: #666;">&#40;</span>count1 <span style="color: #666;">!=</span> count2<span style="color: #666;">&#41;</span><span style="color: #666;">&#123;</span> <span style="color: #ccc">// lengths are different, so no need to compare values</span>
    <span style="color: #000;">return</span> <span style="color: #000;">false</span><span style="color: #666;">;</span>
  <span style="color: #666;">&#125;</span>
  <span style="color: #000;">else</span> <span style="color: #666;">&#123;</span> <span style="color: #ccc">// lengths are the same (or loose is TRUE), so continue to compare individual property values</span>
    <span style="color: #000;">for</span> <span style="color: #666;">&#40;</span>i <span style="color: #000;">in</span> obj1<span style="color: #666;">&#41;</span> <span style="color: #666;">&#123;</span>
      <span style="color: #000;">if</span> <span style="color: #666;">&#40;</span><span style="color: #000;">typeof</span> obj1<span style="color: #666;">&#91;</span>i<span style="color: #666;">&#93;</span> <span style="color: #666;">==</span> <span style="color: #B4C24B;">'object'</span> <span style="color: #666;">&amp;&amp;</span> <span style="color: #000;">typeof</span> obj2<span style="color: #666;">&#91;</span>i<span style="color: #666;">&#93;</span> <span style="color: #666;">==</span> <span style="color: #B4C24B;">'object'</span><span style="color: #666;">&#41;</span> <span style="color: #666;">&#123;</span> <span style="color: #ccc">// both items are objects</span>
        <span style="color: #000;">if</span> <span style="color: #666;">&#40;</span><span style="color: #666;">!</span>objectCompare<span style="color: #666;">&#40;</span>obj1<span style="color: #666;">&#91;</span>i<span style="color: #666;">&#93;</span><span style="color: #666;">,</span> obj2<span style="color: #666;">&#91;</span>i<span style="color: #666;">&#93;</span><span style="color: #666;">,</span> loose<span style="color: #666;">&#41;</span><span style="color: #666;">&#41;</span><span style="color: #666;">&#123;</span> <span style="color: #ccc">// see if objects match</span>
          <span style="color: #000;">return</span> <span style="color: #000;">false</span><span style="color: #666;">;</span>
        <span style="color: #666;">&#125;</span>
      <span style="color: #666;">&#125;</span>
      <span style="color: #000;">else</span> <span style="color: #000;">if</span> <span style="color: #666;">&#40;</span>
        loose <span style="color: #ccc">// loose comparison, 42 == &quot;42&quot;, null == '' == undefined</span>
        <span style="color: #666;">&amp;&amp;</span>
        <span style="color: #666;">!</span><span style="color: #666;">&#40;</span>
          <span style="color: #666;">&#40;</span>obj1<span style="color: #666;">&#91;</span>i<span style="color: #666;">&#93;</span> <span style="color: #666;">||</span> <span style="color: #B4C24B;">''</span><span style="color: #666;">&#41;</span> <span style="color: #666;">==</span> <span style="color: #666;">&#40;</span>obj2<span style="color: #666;">&#91;</span>i<span style="color: #666;">&#93;</span> <span style="color: #666;">||</span> <span style="color: #B4C24B;">''</span><span style="color: #666;">&#41;</span> <span style="color: #ccc">// this will work in all cases EXCEPT (&quot;0&quot; ?= 0|null|undefined), which will evaluate to (&quot;0&quot; ?= &quot;&quot;), which is of course FALSE</span>
          <span style="color: #666;">||</span>
          <span style="color: #666;">&#40;</span> <span style="color: #ccc">// if either value is a number, try to convert both to numbers and compare - this will work around above exception</span>
            <span style="color: #666;">&#40;</span><span style="color: #000;">typeof</span> obj1<span style="color: #666;">&#91;</span>i<span style="color: #666;">&#93;</span> <span style="color: #666;">==</span> <span style="color: #B4C24B;">'number'</span> <span style="color: #666;">||</span> <span style="color: #000;">typeof</span> obj2<span style="color: #666;">&#91;</span>i<span style="color: #666;">&#93;</span> <span style="color: #666;">==</span> <span style="color: #B4C24B;">'number'</span><span style="color: #666;">&#41;</span>
            <span style="color: #666;">&amp;&amp;</span>
            Number<span style="color: #666;">&#40;</span>obj1<span style="color: #666;">&#91;</span>i<span style="color: #666;">&#93;</span><span style="color: #666;">&#41;</span> <span style="color: #666;">==</span> Number<span style="color: #666;">&#40;</span>obj2<span style="color: #666;">&#91;</span>i<span style="color: #666;">&#93;</span><span style="color: #666;">&#41;</span>
          <span style="color: #666;">&#41;</span>
        <span style="color: #666;">&#41;</span>
      <span style="color: #666;">&#41;</span><span style="color: #666;">&#123;</span> <span style="color: #ccc">// only one item is an object, or objects don't match</span>
        <span style="color: #000;">return</span> <span style="color: #000;">false</span><span style="color: #666;">;</span>
      <span style="color: #666;">&#125;</span>
      <span style="color: #000;">else</span> <span style="color: #000;">if</span> <span style="color: #666;">&#40;</span>
        <span style="color: #666;">!</span>loose <span style="color: #ccc">// strict comparison, 42 != &quot;42&quot;, null != '' != undefined</span>
        <span style="color: #666;">&amp;&amp;</span>
        <span style="color: #666;">!</span><span style="color: #666;">&#40;</span>obj1<span style="color: #666;">&#91;</span>i<span style="color: #666;">&#93;</span> <span style="color: #666;">===</span> obj2<span style="color: #666;">&#91;</span>i<span style="color: #666;">&#93;</span><span style="color: #666;">&#41;</span>
      <span style="color: #666;">&#41;</span><span style="color: #666;">&#123;</span>
        <span style="color: #000;">return</span> <span style="color: #000;">false</span><span style="color: #666;">;</span>
      <span style="color: #666;">&#125;</span>
    <span style="color: #666;">&#125;</span>
  <span style="color: #666;">&#125;</span>
&nbsp;
  <span style="color: #000;">return</span> <span style="color: #000;">true</span><span style="color: #666;">;</span> <span style="color: #ccc">// all tests passed, objects are equivalent</span>
<span style="color: #666;">&#125;</span></pre></td></tr></table></div>

]]></content:encoded>
			<wfw:commentRss>http://acatalept.com/blog/2009/10/09/compare-objects-recursively-in-javascript/feed/</wfw:commentRss>
		</item>
		<item>
		<title>Gmail POP/IMAP access with Outlook: keeps asking for password</title>
		<link>http://acatalept.com/blog/2009/10/07/gmail-popimap-access-with-outlook-keeps-asking-for-password/</link>
		<comments>http://acatalept.com/blog/2009/10/07/gmail-popimap-access-with-outlook-keeps-asking-for-password/#comments</comments>
		<pubDate>Wed, 07 Oct 2009 19:23:20 +0000</pubDate>
		<dc:creator>acat</dc:creator>
		
		<category><![CDATA[Fixes / Hacks / Tweaks]]></category>

		<category><![CDATA[Software]]></category>

		<guid isPermaLink="false">http://acatalept.com/blog/?p=55</guid>
		<description><![CDATA[Quick solution: RTFM (yes, it was right there on Google's help page) - clear the captcha by going to:
http://www.google.com/accounts/DisplayUnlockCaptcha
or if you use Google Apps:
https://www.google.com/a/yourdomain.com/UnlockCaptcha

I've had a number of issues with Outlook over the years, and it's always proven to be an uphill battle when something goes wrong.  In this case, I was trying to [...]]]></description>
			<content:encoded><![CDATA[<p>Quick solution: <a href="http://mail.google.com/support/bin/answer.py?answer=75289">RTFM</a> (yes, it was right there on Google's help page) - clear the captcha by going to:</p>
<pre>http://www.google.com/accounts/DisplayUnlockCaptcha</pre>
<p>or if you use Google Apps:</p>
<pre>https://www.google.com/a/yourdomain.com/UnlockCaptcha</pre>
<p><span id="more-55"></span></p>
<p>I've had a number of issues with Outlook over the years, and it's always proven to be an uphill battle when something goes wrong.  In this case, I was trying to setup POP access in Outlook 2003 (this same solution should apply to other Outlook versions as well), and Outlook would repeatedly pop up an "Invalid credentials" window when trying to send/receive, even though the "Test Settings" procedure during account setup was successful.</p>
<p>This wasn't a case of mistyping the password, or forgetting to check the Save Password box, or a corrupt profile, or missing registry settings, etc. (been there, done that, none of those solutions worked).  What finally worked was the answer to the Top Most Common Error on, of all places, <a href="http://mail.google.com/support/bin/answer.py?answer=75289">Google's own Gmail help website</a>: clear the captcha.</p>
<p>Yes, I am that dense.  I'm just glad I found this solution before completely wiping out and reinstalling Office.</p>
<p>In any case, not sure why the captcha was being triggered - I'm guessing this is usually only a result of too many invalid login attempts, so maybe something was tripped while doing the initial account setup in Outlook.</p>
<p>YMMV.  Good luck!</p>
]]></content:encoded>
			<wfw:commentRss>http://acatalept.com/blog/2009/10/07/gmail-popimap-access-with-outlook-keeps-asking-for-password/feed/</wfw:commentRss>
		</item>
		<item>
		<title>Google Chrome slow under Sandboxie?</title>
		<link>http://acatalept.com/blog/2009/09/29/google-chrome-slow-under-sandboxie/</link>
		<comments>http://acatalept.com/blog/2009/09/29/google-chrome-slow-under-sandboxie/#comments</comments>
		<pubDate>Wed, 30 Sep 2009 03:19:57 +0000</pubDate>
		<dc:creator>acat</dc:creator>
		
		<category><![CDATA[Fixes / Hacks / Tweaks]]></category>

		<category><![CDATA[Software]]></category>

		<category><![CDATA[Windows]]></category>

		<guid isPermaLink="false">http://acatalept.com/blog/?p=45</guid>
		<description><![CDATA[I was having trouble getting Chrome to play nicely with Sandboxie - it loads and runs, but it was slow to show the "New Tab" page (with thumbnails of your most visited sites), the History page, and, well, most websites in general - so it appeared as though Chrome was trying to copy some needed [...]]]></description>
			<content:encoded><![CDATA[<p>I was having trouble getting Chrome to play nicely with <a href="http://www.sandboxie.com">Sandboxie</a> - it loads and runs, but it was slow to show the "New Tab" page (with thumbnails of your most visited sites), the History page, and, well, most websites in general - so it appeared as though Chrome was trying to copy some needed files into the sandbox every time it loaded a page...  Note that I have my sandbox set to automatically delete when the last sandboxed program ends to ensure I'm cleaning up after myself.</p>
<p>I couldn't find any specifics elsewhere, but after a little tweaking I solved the problem:<br />
<span id="more-45"></span></p>
<ol>
<li>Go into the Sandbox Settings for the sandbox in question.</li>
<li>Make sure you check the checkbox at the bottom left of the window labeled "Apply changes when switching to another page".</li>
<li>Under the Resource Access section, go into File Access, then Direct Access.</li>
<li>Next to the dropdown labeled "The list above applies to", click the Add Pgm button, and find your Chrome executable, e.g. for Windows XP:
<pre>C:\Documents and Settings\[Your User Name]\Local Settings\Application Data\Google\Chrome\Application\chrome.exe</pre>
</li>
<li>Make sure "chrome.exe" is selected next to "The list above applies to", then click the Add button, and find your Chrome User Data folder, e.g. for Windows XP:
<pre>C:\Documents and Settings\[Your User Name]\Local Settings\Application Data\Google\Chrome\User Data</pre>
</li>
<li>Now highlight the User Data entry you just added, click the Edit/Add button, and put an asterisk (*) at the end of the line, e.g. for Windows XP:e.g. for Windows XP:
<pre>C:\Documents and Settings\[Your User Name]\Local Settings\Application Data\Google\Chrome\User Data\*</pre>
<p>Tthis will include all files and folders within the User Data folder.</li>
<li>Next, back under the Sandbox Settings configuration tree, go to Resource Access -> File Access -> Read-Only Access, and follow the above steps to add the Chrome Application folder - when you are done, your entry should read (again, for Windows XP):
<pre>C:\Documents and Settings\[Your User Name]\Local Settings\Application Data\Google\Chrome\Application\*</pre>
</li>
</ol>
<p>Now click OK to get back out of the Sandbox Settings, close all your sandboxed programs and delete the contents.  Now every time you run Chrome in this sandbox, it should be as fast as (or at most only fractionally slower than) Chrome outside the sandbox.</p>
<p>I haven't tested this thoroughly, but so far it seems a good compromise between allowing Chrome access to all of its own files (though it may stumble when trying to update to a new version - more testing needed), while preventing any possible drive-by downloads or other executables from entering and running on my system.</p>
]]></content:encoded>
			<wfw:commentRss>http://acatalept.com/blog/2009/09/29/google-chrome-slow-under-sandboxie/feed/</wfw:commentRss>
		</item>
		<item>
		<title>Make Firefox Location Bar search work like Google Chrome&#8217;s address bar</title>
		<link>http://acatalept.com/blog/2009/06/09/make-firefox-location-bar-search-work-like-google-chromes-address-bar/</link>
		<comments>http://acatalept.com/blog/2009/06/09/make-firefox-location-bar-search-work-like-google-chromes-address-bar/#comments</comments>
		<pubDate>Tue, 09 Jun 2009 20:57:19 +0000</pubDate>
		<dc:creator>acat</dc:creator>
		
		<category><![CDATA[Fixes / Hacks / Tweaks]]></category>

		<category><![CDATA[Software]]></category>

		<guid isPermaLink="false">http://acatalept.com/blog/?p=43</guid>
		<description><![CDATA[The new Location bar in Firefox 3.x will, by default, take any non-URL input and:

If it's a single word (no spaces): first attempt to prepend "www.", and/or append ".com", then lookup in OpenDNS to see if this makes a valid server name - if so, you are automatically redirected to this found server
If there is [...]]]></description>
			<content:encoded><![CDATA[<p>The new Location bar in Firefox 3.x will, by default, take any non-URL input and:</p>
<ol>
<li>If it's a single word (no spaces): first attempt to prepend "www.", and/or append ".com", then lookup in OpenDNS to see if this makes a valid server name - if so, you are automatically redirected to this found server</li>
<li>If there is a space: it is assumed this is a search phrase, so the the input is passed (by default) to Google's Browse By Name service.  This works similarly to a standard Google web search, however if the search phrase is associated with an "authoritative" server (as deemed by Google), you are automatically redirected to this server (similar to an I'm Feeling Lucky search).</li>
</ol>
<p>To disable these behaviors, resulting in similar functionality to Google Chrome's address bar, just make a couple changes in Firefox's hidden <strong>about:config</strong> settings (that is, type "about:config" in the address bar and hit Enter):</p>
<ol>
<li>Change the value of "browser.fixup.alternate.enabled" to <strong>false</strong></li>
<li>Change the value of "keyword.URL" to
<pre>http://www.google.com/search?q=</pre>
<p>Note that there is nothing after the equal sign.</li>
</ol>
<p>This appears to work up through Firefox 3.5b4.</p>
]]></content:encoded>
			<wfw:commentRss>http://acatalept.com/blog/2009/06/09/make-firefox-location-bar-search-work-like-google-chromes-address-bar/feed/</wfw:commentRss>
		</item>
		<item>
		<title>Quick workaround for slow network printer (Windows XP SP2 and Vista)</title>
		<link>http://acatalept.com/blog/2009/05/04/quick-workaround-for-slow-network-printer-windows-xp-sp2-and-vista/</link>
		<comments>http://acatalept.com/blog/2009/05/04/quick-workaround-for-slow-network-printer-windows-xp-sp2-and-vista/#comments</comments>
		<pubDate>Mon, 04 May 2009 18:03:29 +0000</pubDate>
		<dc:creator>acat</dc:creator>
		
		<category><![CDATA[Hardware]]></category>

		<category><![CDATA[Windows]]></category>

		<guid isPermaLink="false">http://acatalept.com/blog/?p=41</guid>
		<description><![CDATA[I've had one particular network printer (installed on a local TCP/IP port) that has been incredibly slow since we've had it installed: it seems to be some bottleneck with the process of communicating with the printer in general, since even opening the printer properties window (or switching tabs within that window) can take 5-10 seconds, [...]]]></description>
			<content:encoded><![CDATA[<p>I've had one particular network printer (installed on a local TCP/IP port) that has been incredibly slow since we've had it installed: it seems to be some bottleneck with the process of communicating with the printer in general, since even opening the printer properties window (or switching tabs within that window) can take 5-10 seconds, and sending over a print job generally hangs the sending application for a similar amount of time.  However, pings are fine (<1ms), and two other network printers configured similarly work just fine, and I've exhausted most other possibilities (cabling, network hardware, port settings) for solving the issue.</p>
<p>However, it appears to be an odd bug in Windows, the workaround for which may not work in all cases, but seems to fix this issue.  I had the printer installed on a local TCP/IP port (it has a built-in print server with a static IP), but by following <a href="http://weblog.bergersen.net/archives/2005/01/why_is_network.html">this advice</a>, I assigned the NetBIOS name for the printer to an unused LPT port at a command prompt:</p>
<pre>net use LPT2 \\printserver\printername</pre>
<p>And then, in the printer's Properties window, under the Ports tab, I changed the port from the TCP/IP port I had originally used to LPT2.</p>
<p>Voila - instant fix.</p>
]]></content:encoded>
			<wfw:commentRss>http://acatalept.com/blog/2009/05/04/quick-workaround-for-slow-network-printer-windows-xp-sp2-and-vista/feed/</wfw:commentRss>
		</item>
		<item>
		<title>View Rendered Source in Internet Explorer</title>
		<link>http://acatalept.com/blog/2009/04/20/view-rendered-source-in-ie/</link>
		<comments>http://acatalept.com/blog/2009/04/20/view-rendered-source-in-ie/#comments</comments>
		<pubDate>Mon, 20 Apr 2009 15:02:43 +0000</pubDate>
		<dc:creator>acat</dc:creator>
		
		<category><![CDATA[Programming]]></category>

		<category><![CDATA[Web design &amp; hosting]]></category>

		<guid isPermaLink="false">http://acatalept.com/blog/?p=39</guid>
		<description><![CDATA[IE 6 and 7 can be a nightmare for debugging Javascript, especially after working with the quality tools available for other browsers such as Firebug for Firefox.  However, one small step in the right direction would be the ability to View Source for the currently rendered page, after Javascript has been executed (since typically [...]]]></description>
			<content:encoded><![CDATA[<p>IE 6 and 7 can be a nightmare for debugging Javascript, especially after working with the quality tools available for other browsers such as <a href="http://getfirebug.com/">Firebug</a> for Firefox.  However, one small step in the right direction would be the ability to View Source for the currently rendered page, <em>after</em> Javascript has been executed (since typically the View Source command displays the source code as it was sent by the server, prior to any script execution).<br />
<span id="more-39"></span><br />
To do this, you need to create a small Javascript bookmarklet: <a href="javascript:(function(){c=unescape(document.documentElement.innerHTML);c=c.replace(/&amp;/g,'&amp;amp;');c=c.replace(/%3C/g,'&amp;lt;');c=c.replace(/%3E/g,'&amp;gt;');x=window.open();x.document.write('&lt;html&gt;&lt;head&gt;&lt;title&gt;Rendered Source&lt;/title&gt;&lt;/head&gt;&lt;body bgcolor=&quot;#ffffcc&quot;&gt;&lt;pre&gt;'+c+'&lt;/pre&gt;&lt;/body&gt;&lt;/html&gt;');x.document.close();})();">View Rendered Source</a> (right-click this link and Add To Favorites), that will take the current page's HTML source, in its current state (even if modified by scripts, AJAX calls, etc.), and display it in a popup window.  This source for this bookmarklet is the following:</p>
<pre>
javascript:(

function(){
  var c = unescape(document.documentElement.innerHTML);
  c=c.replace(/&#038;/g,'&amp;amp;');
  c=c.replace(/%3C/g,'&amp;lt;');
  c=c.replace(/%3E/g,'&amp;gt;');
  var x = window.open();
  x.document.write('&lt;html>&lt;head>&lt;title>Rendered Source&lt;/title>&lt;/head>&lt;body bgcolor="#ffffcc">&lt;pre>' + c + '&lt;/pre>&lt;/body>&lt;/html>');
  x.document.close();
}

)();
</pre>
<p>Looking at the above, we can see that we're getting the document's innerHTML, replacing <a href="http://www.w3schools.com/HTML/html_entities.asp">HTML Entities</a> with safe substitutes, opening a new popup window, and writing the source code to the popup.</p>
<p>Now you can at least see what your script is up to, as IE sees it.</p>
]]></content:encoded>
			<wfw:commentRss>http://acatalept.com/blog/2009/04/20/view-rendered-source-in-ie/feed/</wfw:commentRss>
		</item>
		<item>
		<title>Create an empty (zero-length) text file in Windows</title>
		<link>http://acatalept.com/blog/2009/01/19/create-an-empty-zero-length-text-file-in-windows/</link>
		<comments>http://acatalept.com/blog/2009/01/19/create-an-empty-zero-length-text-file-in-windows/#comments</comments>
		<pubDate>Mon, 19 Jan 2009 15:09:11 +0000</pubDate>
		<dc:creator>acat</dc:creator>
		
		<category><![CDATA[Windows]]></category>

		<guid isPermaLink="false">http://acatalept.com/blog/?p=35</guid>
		<description><![CDATA[Run the following from a command prompt or batch file:
@echo&#124;find /I /V "echo" > file.txt
Most other, more straightforward techniques will result in a file size greater than zero bytes (usually containing spaces, linefeeds, or other less-than-obvious text).
]]></description>
			<content:encoded><![CDATA[<p>Run the following from a command prompt or batch file:</p>
<pre>@echo|find /I /V "echo" > file.txt</pre>
<p>Most other, more straightforward techniques will result in a file size greater than zero bytes (usually containing spaces, linefeeds, or other less-than-obvious text).</p>
]]></content:encoded>
			<wfw:commentRss>http://acatalept.com/blog/2009/01/19/create-an-empty-zero-length-text-file-in-windows/feed/</wfw:commentRss>
		</item>
		<item>
		<title>Dead Space (PC) tweaks</title>
		<link>http://acatalept.com/blog/2008/11/14/dead-space-pc-tweaks/</link>
		<comments>http://acatalept.com/blog/2008/11/14/dead-space-pc-tweaks/#comments</comments>
		<pubDate>Fri, 14 Nov 2008 05:55:49 +0000</pubDate>
		<dc:creator>acat</dc:creator>
		
		<category><![CDATA[Games]]></category>

		<guid isPermaLink="false">http://acatalept.com/blog/?p=23</guid>
		<description><![CDATA[Since I've found this game is frustrating many users (myself included) with its tendency to force your mouse to work like a console game controller, among other things, I did some digging to overcome some of the issues I was having.

Very sluggish mouse input: Disable v-sync in the game options.  You might still be [...]]]></description>
			<content:encoded><![CDATA[<p>Since I've found this game is frustrating many users (myself included) with its tendency to force your mouse to work like a console game controller, among other things, I did some digging to overcome some of the issues I was having.</p>
<ul>
<li><strong>Very sluggish mouse input:</strong> Disable <a href="http://www.tweakguides.com/Graphics_9.html">v-sync</a> in the game options.  You might still be able to force v-sync in your video driver configuration (<a href="http://www.tweakguides.com/NVFORCE_6.html">see here for Nvidia driver</a>) to eliminate tearing.</li>
<li><strong>Mouse input too slow / "swimmy":</strong> You can only increase the mouse sensitivity so far in the game options, but if that's still not sensitive enough for you, try editing the setting manually in the config file.  Open the file called <code>config.txt</code> in this folder under Windows XP:
<pre>C:\Documents and Settings\&lt;YOUR USER NAME&gt;\Local Settings\Application Data\Electronic Arts\Dead Space</pre>
<p>or this folder under Vista:</p>
<pre>C:\Users\&lt;YOUR USER NAME&gt;\Local Settings\Application Data\Electronic Arts\Dead Space</pre>
<p>Look for a setting for <code>Control.MouseSensitivity</code> - this only goes up to 1.0 from the in-game options menu, but you can theoretically set it quite a bit higher.  I currently have it set to 2.0, which is a pretty decent improvement.  <strong>Note:</strong> setting this too high will make the mouse <em>much</em> too sensitive in the in-game menus, so turn it up slowly and experiment.</li>
<li><strong>Brightness too high even at lowest setting:</strong> this one can also be tweaked in the config file above.  The setting is called <code>Window.Gamma</code> - the in-game brightness adjustment only sets this as low as 0.0, but apparently it can go negative.  Currently I have it set to -0.5, and it looks much more creepy and atmospheric.</li>
</ul>
<p>Hopefully EA will patch the claustrophobic, controller-esque feeling of the mouse at some point in the future, but otherwise these settings make a huge improvement over the out-of-the-box experience.</p>
]]></content:encoded>
			<wfw:commentRss>http://acatalept.com/blog/2008/11/14/dead-space-pc-tweaks/feed/</wfw:commentRss>
		</item>
		<item>
		<title>Stable quicksort in Javascript</title>
		<link>http://acatalept.com/blog/2008/10/28/stable-quicksort-in-javascript/</link>
		<comments>http://acatalept.com/blog/2008/10/28/stable-quicksort-in-javascript/#comments</comments>
		<pubDate>Tue, 28 Oct 2008 18:30:37 +0000</pubDate>
		<dc:creator>acat</dc:creator>
		
		<category><![CDATA[Programming]]></category>

		<category><![CDATA[Web design &amp; hosting]]></category>

		<guid isPermaLink="false">http://acatalept.com/blog/?p=21</guid>
		<description><![CDATA[Firefox < v3.0 doesn't have a stable Array.sort() function - that is, it doesn't maintain indexes for elements of equal value.  This is undefined in the ECMA spec, and has been fixed in Firefox as of version 3 (and curiously enough has been stable in IE all along).  As a result, I set [...]]]></description>
			<content:encoded><![CDATA[<p>Firefox < v3.0 doesn't have a stable Array.sort() function - that is, it doesn't maintain indexes for elements of equal value.  This is undefined in the ECMA spec, and has been fixed in Firefox as of version 3 (and curiously enough has been stable in IE all along).  As a result, I set out to find a stable, efficient Array.sort() replacement/supplement.<br />
<span id="more-21"></span><br />
<a href="http://en.wikipedia.org/wiki/Mergesort">Mergesort</a> is famous for being stable by design, and fast, though not terribly memory efficient.  However, it uses a lot of code, and I couldn't manage to find a stable implementation of it.</p>
<p>After doing a little homework, I decided to modify <a href="http://en.wikipedia.org/wiki/Quicksort#Algorithm">this quicksort pseudocode</a> to get the results I was after.  Some would argue that <a href="http://stackoverflow.com/questions/70402/why-is-quicksort-better-than-mergesort">quicksort's worst case performance is slower than mergesort</a>, but for my purposes (small datasets) this was moot.</p>
<p>Here is the resulting code:</p>
<pre>
// STABLE implementation of quick sort to replace unstable Array.sort method in Firefox
quickSort = function(arr) {

  // return if array is unsortable
  if (arr.length <= 1){
    return arr;
  }

  var less = Array(), greater = Array();

  // select and remove a pivot value pivot from array
  // a pivot value closer to median of the dataset may result in better performance
  var pivotIndex = Math.floor(arr.length / 2);
  var pivot = arr.splice(pivotIndex, 1)[0];

  // step through all array elements
  for (var x = 0; x < arr.length; x++){

    // if (current value is less than pivot),
    // OR if (current value is the same as pivot AND this index is less than the index of the pivot in the original array)
    // then push onto end of less array
    if (
      (arr[x] < pivot)
      ||
      (arr[x] == pivot &#038;& x < pivotIndex)  // this maintains the original order of values equal to the pivot
    ){
      less.push(arr[x]);
    }

    // if (current value is greater than pivot),
    // OR if (current value is the same as pivot AND this index is greater than or equal to the index of the pivot in the original array)
    // then push onto end of greater array
    else {
      greater.push(arr[x]);
    }
  }

  // concatenate less+pivot+greater arrays
  return quickSort(less).concat([pivot], quickSort(greater));
};
</pre>
<p>Of course, this will only sort an array of values (strings, numbers), so to sort an array of objects by a given property, I modified the above to produce:</p>
<pre>
// STABLE implementation of quick sort to replace unstable Array.sort method in Firefox
// if sorting an array of objects, key = name of object property to compare
// otherwise leave key undefined
quickSort = function(arr, key) {

  // return if array is unsortable
  if (arr.length <= 1){
    return arr;
  }

  var less = Array(), greater = Array();

  // select and remove a pivot value pivot from array
  // a pivot value closer to median of the dataset may result in better performance
  var pivotIndex = Math.floor(arr.length / 2);
  var pivot = arr.splice(pivotIndex, 1)[0];

  // step through all array elements
  for (var x = 0; x < arr.length; x++){

    // if (current value is less than pivot),
    // OR if (current value is the same as pivot AND this index is less than the index of the pivot in the original array)
    // then push onto end of less array
    if (
      (
        !key  // no object property name passed
        &#038;&
        (
          (arr[x] < pivot)
          ||
          (arr[x] == pivot &#038;& x < pivotIndex)  // this maintains the original order of values equal to the pivot
        )
      )
      ||
      (
        key  // object property name passed
        &#038;&
        (
          (arr[x][key] < pivot[key])
          ||
          (arr[x][key] == pivot[key] &#038;& x < pivotIndex)  // this maintains the original order of values equal to the pivot
        )
      )
    ){
      less.push(arr[x]);
    }

    // if (current value is greater than pivot),
    // OR if (current value is the same as pivot AND this index is greater than or equal to the index of the pivot in the original array)
    // then push onto end of greater array
    else {
      greater.push(arr[x]);
    }
  }

  // concatenate less+pivot+greater arrays
  return quickSort(less, key).concat([pivot], quickSort(greater, key));
};
</pre>
<h1>Code samples</h1>
<p>Now we can define an array of objects such as:</p>
<pre>
var objects = [
  {id: 1, type: 'fruit', name: 'apple', color: 'yellow'},
  {id: 2, type: 'vegetable', name: 'tomato', color: 'red'},
  {id: 3, type: 'fruit', name: 'apple', color: 'red'},
  {id: 4, type: 'vegetable', name: 'pepper', color: 'red'}
];
</pre>
<p>Then sort by color with a call to:</p>
<pre>
objects = quickSort(objects, 'color');

// sorted
objects = [
  {id: 2, type: 'vegetable', name: 'tomato', color: 'red'},
  {id: 3, type: 'fruit', name: 'apple', color: 'red'},
  {id: 4, type: 'vegetable', name: 'pepper', color: 'red'},
  {id: 1, type: 'fruit', name: 'apple', color: 'yellow'}
];
</pre>
<p>Then sort by type:</p>
<pre>
objects = quickSort(objects, 'type');

// sorted
objects = [
  {id: 3, type: 'fruit', name: 'apple', color: 'red'},
  {id: 1, type: 'fruit', name: 'apple', color: 'yellow'},
  {id: 2, type: 'vegetable', name: 'tomato', color: 'red'},
  {id: 4, type: 'vegetable', name: 'pepper', color: 'red'}
];
</pre>
<p>Then sort by name:</p>
<pre>
objects = quickSort(objects, 'name');

// sorted
objects = [
  {id: 3, type: 'fruit', name: 'apple', color: 'red'},
  {id: 1, type: 'fruit', name: 'apple', color: 'yellow'},
  {id: 4, type: 'vegetable', name: 'pepper', color: 'red'},
  {id: 2, type: 'vegetable', name: 'tomato', color: 'red'}
];
</pre>
]]></content:encoded>
			<wfw:commentRss>http://acatalept.com/blog/2008/10/28/stable-quicksort-in-javascript/feed/</wfw:commentRss>
		</item>
		<item>
		<title>MySQL inner join to perform update from same table</title>
		<link>http://acatalept.com/blog/2008/09/09/mysql-inner-join-to-perform-update-from-same-table/</link>
		<comments>http://acatalept.com/blog/2008/09/09/mysql-inner-join-to-perform-update-from-same-table/#comments</comments>
		<pubDate>Tue, 09 Sep 2008 19:15:13 +0000</pubDate>
		<dc:creator>acat</dc:creator>
		
		<category><![CDATA[Programming]]></category>

		<category><![CDATA[Web design &amp; hosting]]></category>

		<guid isPermaLink="false">http://acatalept.com/blog/?p=20</guid>
		<description><![CDATA[Typically, using SELECT in a subquery to perform an UPDATE on the same table, such as:

UPDATE table1 AS target
SET field1 = (
    SELECT field2
    FROM table1 AS source
    WHERE source.id = target.id
)

is illegal in MySQL.  To achieve the desired effect, you can perform an INNER [...]]]></description>
			<content:encoded><![CDATA[<p>Typically, using SELECT in a subquery to perform an UPDATE on the same table, such as:</p>
<pre>
UPDATE table1 AS target
SET field1 = (
    SELECT field2
    FROM table1 AS source
    WHERE source.id = target.id
)
</pre>
<p>is illegal in MySQL.  To achieve the desired effect, you can perform an INNER JOIN in the UPDATE:</p>
<pre>
UPDATE table1 AS target
INNER JOIN table1 AS source USING(id)
SET target.field1 = source.field2
</pre>
]]></content:encoded>
			<wfw:commentRss>http://acatalept.com/blog/2008/09/09/mysql-inner-join-to-perform-update-from-same-table/feed/</wfw:commentRss>
		</item>
	</channel>
</rss>
