<?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>Guillermo Rauch&#039;s Devthought &#187; Client side</title>
	<atom:link href="http://www.devthought.com/category/blog/client-side/feed/" rel="self" type="application/rss+xml" />
	<link>http://www.devthought.com</link>
	<description></description>
	<lastBuildDate>Mon, 30 Jan 2012 16:38:59 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.3.1</generator>
		<item>
		<title>A String is not an Error</title>
		<link>http://www.devthought.com/2011/12/22/a-string-is-not-an-error/</link>
		<comments>http://www.devthought.com/2011/12/22/a-string-is-not-an-error/#comments</comments>
		<pubDate>Thu, 22 Dec 2011 19:11:59 +0000</pubDate>
		<dc:creator>Guillermo Rauch</dc:creator>
				<category><![CDATA[Blog]]></category>
		<category><![CDATA[Client side]]></category>
		<category><![CDATA[Server side]]></category>

		<guid isPermaLink="false">http://next.devthought.com/?p=1241</guid>
		<description><![CDATA[I decided to write a little article to discourage an unfortunately common pattern in Node.JS modules (and browser JavaScript, to a lesser extent) that can boil down to these two examples: // A: function myFunction () { if (somethingWrong) { &#8230; <a href="http://www.devthought.com/2011/12/22/a-string-is-not-an-error/">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<p>I decided to write a little article to discourage an unfortunately common pattern in Node.JS modules (and browser JavaScript, to a lesser extent) that can boil down to these two examples:</p>
<pre class='highlight ' lang="javascript">// A:
function myFunction () {
  if (somethingWrong) {
    throw 'This is my error'
  }
  return allGood;
}
</pre>
<p>and</p>
<pre class='highlight ' lang="javascript">// B: async Node.JS-style callback with signature `fn(err, …)`
function myFunction (callback) {
  doSomethingAsync(function () {
    // …
    if (somethingWrong) {
      callback('This is my error')
    } else {
      callback(null, …);
    }
  });
}
</pre>
<p>In both cases, passing a string instead of an error results in reduced interoperability between modules. It breaks contracts with APIs that might be performing <code>instanceof Error</code> checks, or that want to know <em>more</em> about the error.</p>
<p><span id="more-1241"></span></p>
<p><code>Error</code> objects, as we&#8217;ll see, have very interesting properties in modern JavaScript engines besides holding the message passed to the constructor.</p>
<h2>The stack property</h2>
<p>The fundamental benefit of Error objects is that they automatically keep track of where they were built and originated.</p>
<p>The mechanism of how this happens is specific to each JavaScript engine and/or browser that implements it.</p>
<h2>V8 (Node.JS)</h2>
<p>The way that V8 handles this, which directly affects us who develop in Node.JS is described by the <a href="http://code.google.com/p/v8/wiki/JavaScriptStackTraceApi">StackTraceApi</a> document.</p>
<p>We can test its behavior by simply initializing a <code>Error</code> object and inspecting its <code>stack</code> property:</p>
<pre class='highlight ' lang="javascript">// error.js
var err = new Error();
console.log(typeof err.stack);
console.log(err.stack);</pre>
<pre class="highlight" lang="text">∞ node error.js
string
Error
    at Object.&lt;anonymous&gt; (/private/tmp/error.js:2:11)
    at Module._compile (module.js:411:26)
    at Object..js (module.js:417:10)
    at Module.load (module.js:343:31)
    at Function._load (module.js:302:12)
    at Array.0 (module.js:430:10)
    at EventEmitter._tickCallback (node.js:126:26)
</pre>
<p>As you can see, even without <code>throw</code>ing or passing it around, V8 is able to tell us exactly where that object was created, and how it got there.</p>
<p>By default, V8 limits the stack trace size to 10 frames. You can alter this by changing the <code>Error.stackTraceLimit</code> during runtime.</p>
<pre class='highlight ' lang="javascript">Error.stackTraceLimit = 0; // disables it
Error.stackTraceLimit = Infinity; // disables any limit
</pre>
<h4>Custom Errors</h4>
<p>If you wanted to extend the native <code>Error</code> object so that stack collection is preserved, you can do so by calling the <code>captureStackTrace</code> function. This is an example extracted from the <a href="http://github.com/learnboost/mongoose">Mongoose ODM</a></p>
<pre class='highlight ' lang="javascript">function MongooseError (msg) {
  Error.call(this);
  Error.captureStackTrace(this, arguments.callee);
  this.message = msg;
  this.name = 'MongooseError';
};

MongooseError.prototype.__proto__ = Error.prototype;
</pre>
<p>The second argument passed to the <code>captureStackTrace</code> prevents unnecessary noise  in the <code>stack</code> generation by hiding the <code>MongooseError</code> constructor calls from the stack.</p>
<h4>Beyond stack strings</h4>
<p>As you might have noticed in my previous code example, I purposedly printed the <code>typeof</code> of the <code>stack</code> property. As it turns out, it&#8217;s a regular String with a format optimized for readability.</p>
<p>V8, much like Java, allows complete runtime introspection of the stack. Instead of a string, we can access an array of <code>CallSite</code>s that retain as much information as possible about the function call in the stack, including the object scope (<code>this</code>).</p>
<p>In this example, we override the <code>prepareStackTrace</code> function to access this raw array and examine it. We call `getFileName` and other methods on each <code>CallSite</code> (all the available methods are described <a href="http://code.google.com/p/v8/wiki/JavaScriptStackTraceApi#Customizing_stack_traces">here</a>)</p>
<pre class='highlight ' lang="javascript">function a () {
  b();
}

function b () {
  var err = new Error;

  Error.prepareStackTrace = function (err, stack) {
    return stack;
  };

  Error.captureStackTrace(err, b);

  err.stack.forEach(function (frame) {
    console.error(' call: %s:%d - %s'
      , frame.getFileName()
      , frame.getLineNumber()
      , frame.getFunctionName());
  });
}

a();
</pre>
<p>This is an example of the output this script produces:</p>
<pre class='highlight ' lang="javascript">∞ node error-2.js
call: /private/tmp/error-2.js:3 - a
call: /private/tmp/error-2.js:23 -
call: module.js:432 - Module._compile
call: module.js:450 - Module._extensions..js
call: module.js:351 - Module.load
call: module.js:310 - Module._load
call: module.js:470 - Module.runMain
call: node.js:192 - startup.processNextTick.process._tickCallback
</pre>
<p>All this functionality would of course be non-existent if we were to pass around strings, therefore drastically shrinking our debugging panorama.</p>
<p>For real-world usage, restoring the original <code>prepareStackTrace</code> after overriding it is probably a good idea. Thankfully, TJ Holowaychuck has released a tiny <a href="http://github.com/visionmedia/callsite">callsite</a> module to make this painless.</p>
<h2>Browsers</h2>
<p>Like the V8 document states:</p>
<blockquote>
<p><em>The API described here is specific to V8 and is not supported by any other JavaScript implementations. Most implementations do provide an error.stack property but the format of the stack trace is likely to be different from the format described here</em></p>
</blockquote>
<ul>
<li>Firefox exposes <code>error.stack</code>. It has its own format.</li>
<li>Opera exposes <code>error.stacktrace</code>. It has its own format.</li>
<li>IE has no stack.</li>
</ul>
<p>A very interesting solution to this is provided by <a href="https://github.com/eriwen/javascript-stacktrace">javascript-stacktrace</a>, which attempts to normalize a printed stack trace across all browsers.</p>
<p>On IE (and older versions of Safari), for example, it uses a clever method: it recursively looks for the <code>caller</code> property of a function, calls <code>toString</code> on it and parses out the function name.</p>
<pre class='highlight ' lang="javascript">var currentFunction = arguments.callee.caller;
while (currentFunction) {
  var fn = currentFunction.toString();
  var fname = fn.substring(fn.indexOf(&amp;amp;quot;function&amp;amp;quot;) + 8, fn.indexOf('')) || 'anonymous';
  callstack.push(fname);
  currentFunction = currentFunction.caller;
}
</pre>
<h2>Conclusions</h2>
<ul>
<li>When doing async I/O (in Node.JS or otherwise), since <code>throw</code>ing is not a<br />
possibility (as it results in uncaught exceptions), <code>Error</code>s are the only way to<br />
allow proper stack trace collection.</li>
<li>Even in non-V8 browser environments, it&#8217;s probably a good idea to still initialize<br />
<code>Error</code>s. The API exists in all browsers, and the extended API facilities that V8<br />
provides are bound to be available to most engines in the future.</li>
<li>If you&#8217;re throwing or passing around strings for errors, consider switching today!</li>
</ul>
<p>The examples in the beginning of the post can thus be rewritten this way:</p>
<pre class='highlight ' lang="javascript">// A:
function myFunction () {
  if (somethingWrong) {
    throw new Error('This is my error')
  }
  return allGood;
}
</pre>
<p>and</p>
<pre class='highlight ' lang="javascript">// B: async Node.JS-style callback with signature `fn(err, …)`
function myFunction (callback) {
  doSomethingAsync(function () {
    // …
    if (somethingWrong) {
      callback(new Error('This is my error'))
    } else {
      callback(null, …);
    }
  });
}
</pre>
]]></content:encoded>
			<wfw:commentRss>http://www.devthought.com/2011/12/22/a-string-is-not-an-error/feed/</wfw:commentRss>
		<slash:comments>16</slash:comments>
		</item>
		<item>
		<title>JSConf 2010 Slides</title>
		<link>http://www.devthought.com/2010/05/03/jsconf-2010-slides/</link>
		<comments>http://www.devthought.com/2010/05/03/jsconf-2010-slides/#comments</comments>
		<pubDate>Mon, 03 May 2010 13:07:08 +0000</pubDate>
		<dc:creator>Guillermo Rauch</dc:creator>
				<category><![CDATA[Blog]]></category>
		<category><![CDATA[Client side]]></category>
		<category><![CDATA[javascript]]></category>
		<category><![CDATA[jsconf]]></category>

		<guid isPermaLink="false">http://devthought.com/?p=1144</guid>
		<description><![CDATA[For those of us who didn&#8217;t make it, I&#8217;ve compiled a list of slides + blog posts from the JSConf 2010 Track A speakers Alex Russell &#8211; &#8220;Google Chrome Frame&#8221; Post: http://alex.dojotoolkit.org/ Slides: http://alex.dojotoolkit.org/10/jsconf/gcf.html Francisco Tolmasky &#8211; &#8220;Socratic: Documentation Done &#8230; <a href="http://www.devthought.com/2010/05/03/jsconf-2010-slides/">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<p>For those of us who didn&#8217;t make it, I&#8217;ve compiled a list of slides + blog posts from the JSConf 2010 Track A speakers</p>
<p><strong>Alex Russell &#8211; &#8220;Google Chrome Frame&#8221;</strong><br />
Post: <a href="http://alex.dojotoolkit.org/">http://alex.dojotoolkit.org/</a><br />
Slides: <a href="http://alex.dojotoolkit.org/10/jsconf/gcf.html">http://alex.dojotoolkit.org/10/jsconf/gcf.html</a></p>
<p><strong>Francisco Tolmasky &#8211; &#8220;Socratic: Documentation Done Right&#8221;</strong><br />
GitHub: <a href="http://github.com/tolmasky/socratic">http://github.com/tolmasky/socratic</a><br />
Slides: ?</p>
<p><strong>Aaron Newton &#8211; &#8220;Programming To Patterns&#8221;</strong><br />
Slides: <a href="http://www.slideshare.net/guest2ee5e2c/programming-to-patterns-presentation">http://www.slideshare.net/guest2ee5e2c/programming-to-patterns-presentation</a> (not up-to-date)</p>
<p><strong>Jed Schmidt &#8211; &#8220;A (fab) approach to web apps&#8221;</strong><br />
GitHub: <a href="http://github.com/jed/fab">http://github.com/jed/fab</a><br />
Slides: <a href="http://www.flickr.com/photos/tr4nslator/sets/72157623883700702/show/">http://www.flickr.com/photos/tr4nslator/sets/72157623883700702/show/</a></p>
<p><strong>Dmitry Baranovskiy &#8211; &#8220;Raphaël the Great&#8221;</strong><br />
Slides: <a href="http://www.slideshare.net/Dmitry.Baranovskiy/raphal-js-conf">http://www.slideshare.net/Dmitry.Baranovskiy/raphal-js-conf</a></p>
<p><strong>Douglas Crockford &#8211; &#8220;Really, JavaScript?&#8221;</strong><br />
?</p>
<p><strong>Tobias Schneider &#8211; &#8220;Flash is dead, long live Flash!&#8221;</strong><br />
GitHub: <a href="http://github.com/tobeytailor/gordon">http://github.com/tobeytailor/gordon</a><br />
Slides: <a href="http://www.slideshare.net/ConfEcho/flash-is-dead-long-live-flash">http://www.slideshare.net/ConfEcho/flash-is-dead-long-live-flash</a></p>
<p><strong>Makinde Adeagbo &#8211; &#8220;Primer: Facebook&#8217;s 2k of JavaScript to power (almost) all interactions&#8221;</strong><br />
Slides: <a href="http://www.slideshare.net/makinde/javascript-primer">http://www.slideshare.net/makinde/javascript-primer</a></p>
<p><strong>Steve Souders &#8211; &#8220;The Best of Steve&#8221;</strong><br />
Slides: <a href="http://www.slideshare.net/souders/jsconf-us-2010">http://www.slideshare.net/souders/jsconf-us-2010</a></p>
<p><strong>Jenn Lukas &#8211; &#8220;JavaScript and Web Standards Sitting in a Tree&#8221;</strong><br />
Slides: <a href="http://www.slideshare.net/JennLukas/javascript-and-web-standards-sitting-in-a-tree">http://www.slideshare.net/JennLukas/javascript-and-web-standards-sitting-in-a-tree</a></p>
<p><strong>Ryan Dahl &#8211; &#8220;Less is More in Node.js&#8221;</strong><br />
Slides: <a href="http://nodejs.org/jsconf2010.pdf">http://nodejs.org/jsconf2010.pdf</a></p>
<p><strong>Billy Hoffman &#8211; &#8220;JavaScript&#8217;s Evil Side&#8221;</strong><br />
Slides: ?</p>
<p><strong>John David Dalton &#8211; &#8220;All you can leet&#8221;</strong><br />
Slides: <a href="http://www.slideshare.net/johndaviddalton/jsconf-all-you-can-leet">http://www.slideshare.net/johndaviddalton/jsconf-all-you-can-leet</a></p>
<p><strong>Aaron Quint &#8211; &#8220;Making Bacon / Making Code&#8221;</strong><br />
GitHub: <a href="http://github.com/quirkey/sammy">http://github.com/quirkey/sammy</a><br />
Post: <a href="http://www.quirkey.com/blog/2010/04/20/making-baconmaking-code-jsconf-2010/">http://www.quirkey.com/blog/2010/04/20/making-baconmaking-code-jsconf-2010/</a><br />
Slides: <a href="http://swinger.quirkey.com/#/preso/aq-jsconf/display/1">http://swinger.quirkey.com/#/preso/aq-jsconf/display/1</a><br />
Video: <a href="http://bit.ly/9j7u3L">http://bit.ly/9j7u3L</a></p>
<p><strong>Dion Almaer, Ben Galbraith, and Matt McNulty &#8211; &#8220;The mobile web&#8221;</strong><br />
Slides: <a href="http://www.slideshare.net/dion/the-mobile-web-2010-jsconf">http://www.slideshare.net/dion/the-mobile-web-2010-jsconf</a></p>
]]></content:encoded>
			<wfw:commentRss>http://www.devthought.com/2010/05/03/jsconf-2010-slides/feed/</wfw:commentRss>
		<slash:comments>15</slash:comments>
		</item>
		<item>
		<title>Socket.IO: sockets for the rest of us</title>
		<link>http://www.devthought.com/2010/03/17/socketio-sockets-for-the-rest-of-us/</link>
		<comments>http://www.devthought.com/2010/03/17/socketio-sockets-for-the-rest-of-us/#comments</comments>
		<pubDate>Wed, 17 Mar 2010 20:57:38 +0000</pubDate>
		<dc:creator>Guillermo Rauch</dc:creator>
				<category><![CDATA[Client side]]></category>

		<guid isPermaLink="false">http://devthought.com/?p=1137</guid>
		<description><![CDATA[Over at LearnBoost, I just released Socket.IO, a normalized Socket API that hides the complexity of the realtime transports. With code as simple as this: socket = new io.Socket('localhost'); socket.connect(); socket.send('some data'); socket.addEvent('message', function(data){ alert('got some data' + data); }); &#8230; <a href="http://www.devthought.com/2010/03/17/socketio-sockets-for-the-rest-of-us/">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<p>Over at LearnBoost, I just <a href="http://www.learnboost.com/socket-io-sockets-for-the-rest-of-us/">released</a> <code class="inline">Socket.IO</code>,  a normalized Socket API that hides the complexity of the realtime transports.</p>
<p>With code as simple as this:</p>
<pre class='highlight ' lang="JavaScript">
socket = new io.Socket('localhost');
socket.connect();
socket.send('some data');
socket.addEvent('message', function(data){
    alert('got some data' + data);
});
</pre>
<p>you&#8217;ll be leveraging:</p>
<p><span id="more-1137"></span></p>
<ul>
<li>WebSocket</li>
<li>Adobe Flash Socket</li>
<li>ActiveX HTMLFile (IE)</li>
<li>Server-Sent Events (Opera)</li>
<li>XHR with multipart encoding</li>
<li>XHR with long-polling</li>
</ul>
<p>And on the server side, things are equally simple. This is a chat application written in Socket.IO-node, the Node.JS backend implementation:</p>
<pre class='highlight ' lang="JavaScript">
var buffer = [], json = JSON.stringify;

io.listen(server, {

	onClientConnect: function(client){
		client.send(json({ buffer: buffer }));
		client.broadcast(json({ announcement: client.sessionId + ' connected' }));
	},

	onClientDisconnect: function(client){
		client.broadcast(json({ announcement: client.sessionId + ' disconnected' }));
	},

	onClientMessage: function(message, client){
		var msg = { message: [client.sessionId, message] };
		buffer.push(msg);
		if (buffer.length > 15) buffer.shift();
		client.broadcast(json(msg));
	}

});
</pre>
<p>As usual, head to <a href="http://github.com/LearnBoost">GitHub</a> to experiment with the code.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.devthought.com/2010/03/17/socketio-sockets-for-the-rest-of-us/feed/</wfw:commentRss>
		<slash:comments>13</slash:comments>
		</item>
		<item>
		<title>TextboxList 0.4 for jQuery is here!</title>
		<link>http://www.devthought.com/2009/11/11/textboxlist-04-for-jquery-is-here/</link>
		<comments>http://www.devthought.com/2009/11/11/textboxlist-04-for-jquery-is-here/#comments</comments>
		<pubDate>Wed, 11 Nov 2009 21:10:02 +0000</pubDate>
		<dc:creator>Guillermo Rauch</dc:creator>
				<category><![CDATA[Client side]]></category>
		<category><![CDATA[jquery]]></category>
		<category><![CDATA[release]]></category>
		<category><![CDATA[textboxlist]]></category>
		<category><![CDATA[upgrade]]></category>

		<guid isPermaLink="false">http://devthought.com/?p=1069</guid>
		<description><![CDATA[Big update for my dear jQuery users. I&#8217;m rolling out TextboxList for jQuery 0.4 with these updates: [FEATURE] Autocompletion with on-demand server querying [ENHANCEMENT] All classes moved to $. to avoid global namespace pollution. Please make sure to prepend $. &#8230; <a href="http://www.devthought.com/2009/11/11/textboxlist-04-for-jquery-is-here/">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<p>Big update for my dear jQuery users. I&#8217;m rolling out TextboxList for jQuery 0.4 with these updates:</p>
<ul>
<li>[FEATURE] Autocompletion with on-demand server querying</li>
<li>
<p>[ENHANCEMENT] All classes moved to $. to avoid global namespace pollution. Please make sure to prepend <code class="inline">$.</code> to TextboxList if you are upgrading from an older version:</p>
<pre class='highlight ' lang="javascript">
   new $.TextboxList('#element');
</pre>
</li>
<li>
<p>[FEATURE] Easier jQuery-friendly initialization like this:</p>
<pre class='highlight ' lang="javascript">
   $('#element').textboxlist({options});
</pre>
<p>However, if you still need to access the TextboxList instance to call additional methods (like <code class="inline">add</code>), you&#8217;ll have to continue to use <code class="inline">new $.TextboxList</code></p>
</li>
<li>[BUGFIX] <code class="inline">GrowingInput</code> now works in noConflict mode</p>
<li>[BUGFIX] Fix for <code class="inline">GrowingInput</code> to handle special characters and correctly calculate the input length.</li>
<li>[BUGFIX] Fix for support of multiple addKeys</li>
<li>[BUGFIX] Fix for focus problem when TextboxList gains focus through focusing an editable input</li>
<li>[BUGFIX] Autocomplete search term is now trimmed (thanks Mike Feng)</li>
<li>[BUGFIX] Fix for when the max option is used</li>
<li>[BUGFIX] Fix for unique = true and autocomplete.</li>
</ul>
<p>As usual, head to the <a href="http://devthought.com/projects/jquery/textboxlist/">project page</a> for download.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.devthought.com/2009/11/11/textboxlist-04-for-jquery-is-here/feed/</wfw:commentRss>
		<slash:comments>50</slash:comments>
		</item>
		<item>
		<title>TextboxList 0.4: On-Demand suggestions</title>
		<link>http://www.devthought.com/2009/06/01/textboxlist-04-on-demand-suggestions/</link>
		<comments>http://www.devthought.com/2009/06/01/textboxlist-04-on-demand-suggestions/#comments</comments>
		<pubDate>Mon, 01 Jun 2009 12:07:42 +0000</pubDate>
		<dc:creator>Guillermo Rauch</dc:creator>
				<category><![CDATA[Client side]]></category>
		<category><![CDATA[autocomplete]]></category>
		<category><![CDATA[release]]></category>
		<category><![CDATA[textboxlist]]></category>

		<guid isPermaLink="false">http://devthought.com/?p=983</guid>
		<description><![CDATA[TextboxList 0.4 is out, with new features: check option, which can allow you to specify a function to filter out new boxes that do not meet a requirement encode now receives the complete values, not only the id or string &#8230; <a href="http://www.devthought.com/2009/06/01/textboxlist-04-on-demand-suggestions/">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<p>TextboxList 0.4 <a href="/projects/mootools/textboxlist/">is out</a>, with new features:</p>
<ul>
<li><code class="inline">check</code> option, which can allow you to specify a function to filter out new boxes that do not meet a requirement</li>
<li><code class="inline">encode</code> now receives the complete values, not only the id or string of the bit. This gives you full control of what you want to send to the server.</li>
<li>
<p>Autocomplete now works with on-demand suggestions. As easy as this:</p>
<pre class='highlight ' lang="javascript">
new TextboxList('form_tags_input_4', {unique: true, plugins: {autocomplete: {
	minLength: 3,
	queryRemote: true,
	remote: {url: 'autocomplete2.php'}
}}});
</pre>
</li>
</ul>
<p>And some bugfixes:</p>
<ul>
<li>Fixed missing index when unique: false and autocomplete were used, which resulted in an error</li>
<li>Fixed problems with items with id 0, which incorrectly evaluated as false.</li>
</ul>
<p>Head to <a href="/wp-content/projects/mootools/textboxlist/Demo/">the demo</a> to see the new autocomplete in action, and as usual, report any bugs you might encounter.<br />
Update: 0.5 is out already, which fixes a bug with the traditional use of Autocomplete. Sorry for the trouble!</p>
]]></content:encoded>
			<wfw:commentRss>http://www.devthought.com/2009/06/01/textboxlist-04-on-demand-suggestions/feed/</wfw:commentRss>
		<slash:comments>44</slash:comments>
		</item>
		<item>
		<title>An IE6 post</title>
		<link>http://www.devthought.com/2009/05/21/an-ie6-post/</link>
		<comments>http://www.devthought.com/2009/05/21/an-ie6-post/#comments</comments>
		<pubDate>Thu, 21 May 2009 11:10:37 +0000</pubDate>
		<dc:creator>Guillermo Rauch</dc:creator>
				<category><![CDATA[Client side]]></category>
		<category><![CDATA[browsers]]></category>
		<category><![CDATA[ie6]]></category>

		<guid isPermaLink="false">http://devthought.com/?p=957</guid>
		<description><![CDATA[No matter how much we all hate IE6, we never seem to agree on what&#8217;s the best way to finally get rid of it. Web designers and developers alike have realized that investing too much time and effort in fixing &#8230; <a href="http://www.devthought.com/2009/05/21/an-ie6-post/">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<p>No matter how much we all hate IE6, we never seem to agree on what&#8217;s the best way to finally get rid of it. Web designers and developers alike have realized that investing too much time and effort in fixing its quirks is not viable from a business perspective, but they still want to reach that audience.</p>
<p>This ambivalence is what still drives people, like myself, to keep writing about the infamous browser.</p>
<p><span id="more-957"></span></p>
<h3>The tradeoff</h3>
<p>The first premise we have to take into account is best summarized by <a href="http://dowebsitesneedtolookexactlythesameineverybrowser.com/">this little website</a>. There&#8217;s only two scenarios in which you can go to great lengths to make your website look (almost) exactly the same on IE6 and the rest:</p>
<ul>
<li>You have a very big budget, and a potentially huge IE6 audience. This is the case of websites like Facebook. If you read the Javascript and CSS of their widgets, you&#8217;ll know what I mean. The tradeoff here: money invested, poor markup and hacks all around</li>
<li>Your website is just too simple. Why would you not try to fix a few CSS issues if your website is just too simple? If there&#8217;s no complex Javascript going on, and you have a nice little fixed-width website, there&#8217;s no reason why your site should look extremely different.</li>
</ul>
<h3>Mistake 1: make your site look like crap on IE6</h3>
<p>The <a href="http://forabeautifulweb.com/blog/about/universal_internet_explorer_6_css/">Universal Internet Explorer 6 CSS</a> is the first big mistake I want to talk about. The idea here is that instead of wasting time on IE6 hacks, you just use a premade stylesheet, instead of disabling styling altogether. <a href="http://forabeautifulweb.com/demo/2009/05/21/alistapart.html">This is</a> what A List Apart would look like if it was implemented.</p>
<p>This approach is flawed for a wide range of reasons:</p>
<ul>
<li>The idea behind this universal stylesheet is that disabling style would make your website look broken. However, your sites <strong>will</strong> look broken.
<ul>
<li>If you use a logo with a dark background, it&#8217;ll definitely not fit the white background the stylesheet imposes. The same goes for menus and any other graphical item that might not be ready for a white contrast.</li>
<li>If a prior version of your website or brand did work on IE6, and after a redesign you implement this, again, people will think something is really off.</li>
<li>There&#8217;s no &#8220;Universal JavaScript&#8221; solution. And as we all know, many of our scripts interact with the CSS present in the page. Disabling styling will also mean either disabling JavaScript or having to fix it for IE6 too, with the sort of hacks the universal stylesheet wanted to avoid in the first place (for example, conditional styling).</li>
</ul>
</li>
<li>It shouldn&#8217;t be black and white, there&#8217;s gray. At this time, most IE6 quirks have been perfectly documented. Most have very easy solutions: it&#8217;s almost a second-nature for me to add <code class="inline">zoom: 1</code> to clear floats. Of course, making border-radius work on IE6 can be painful, but that&#8217;s exactly what you should be doing. Don&#8217;t go for all the small details: shadows, rounded corners, transparency. Or do it if the budget and time allows it. The key here is that <em>you can still deliver your brand identity to IE6 without major efforts</em>.</li>
</ul>
<p>Developers strive to deliver an identity to all possible mediums. If they design custom iPhone versions, why can&#8217;t they streamline their stylesheet to make it look fairly good on IE? As an example, my website worked almost perfectly on IE6 with little work. However, when I triggered the rain in my clouds, it just crashed. As a result, I just disabled that particular effect.</p>
<h3>Mistake 2: not explaining the user why IE6 is bad</h3>
<p>As I was reading the comments on <a href="http://www.zeldman.com/2009/05/21/a-new-answer-to-the-ie6-question/#comments">Jeffrey Zeldman&#8217;s post</a>, I couldn&#8217;t help but be reminded of how condescending developers can be towards their users. The key here is that <em>people will switch if they understand why</em>.</p>
<p>Let&#8217;s look at some of the proposed solutions to make users switch.</p>
<ul>
<li><a href="http://css-tricks.com/ie-6-blocker-script/">IE 6 Blocker overlay</a>. Blocks content, doesn&#8217;t explain why the switch is encouraged</li>
<li><a href="http://www.pushuptheweb.com/">Push up the web</a>. Doesn&#8217;t block content, but doesn&#8217;t explain why the switch is encouraged and to top it off, it presents itself as sort of a deceiving &#8220;operating system important notice&#8221;.</li>
<li><a href="http://ie6update.com/">IE6Update</a> takes the cake. Not only does it completely imitate a Microsoft warning in a deceptive way, but chances a very high that the user itself closed a similar message box a long time ago! Remember that Microsoft itself pushed the upgrade to IE7, even through the system automated updates. To top it off, this message doesn&#8217;t remotely explain how your website is better in a modern browser, so it&#8217;s an &#8220;easy close&#8221; for your average IE6 visitor.</li>
</ul>
<h3>The correct approach</h3>
<ol>
<li>Deliver the content</li>
<li>Make your website look OK on IE6, and somewhat similar.</li>
<li><strong>Encourage</strong> the switch. If you&#8217;re looking for a universal solution for this, I would suggest placing a prominent link to <a href="http://www.quirksmode.org/upgrade.html">PPK upgrade page</a>. He presents the information in a very concise and reasonable way, that everyone can understand. The best idea, however, is to customize the message for <em>your</em> visitors. Explain why your website would be better in another browser. What they&#8217;re missing. How easier some tasks would become with better JavaScript widgets or how nicer the navigation could be.</li>
</ol>
]]></content:encoded>
			<wfw:commentRss>http://www.devthought.com/2009/05/21/an-ie6-post/feed/</wfw:commentRss>
		<slash:comments>23</slash:comments>
		</item>
		<item>
		<title>TextboxList 0.3 and jQuery version out!</title>
		<link>http://www.devthought.com/2009/04/21/textboxlist-03-and-jquery-version-out/</link>
		<comments>http://www.devthought.com/2009/04/21/textboxlist-03-and-jquery-version-out/#comments</comments>
		<pubDate>Tue, 21 Apr 2009 15:17:02 +0000</pubDate>
		<dc:creator>Guillermo Rauch</dc:creator>
				<category><![CDATA[Client side]]></category>
		<category><![CDATA[jquery]]></category>
		<category><![CDATA[release]]></category>

		<guid isPermaLink="false">http://devthought.com/?p=855</guid>
		<description><![CDATA[Moo TextboxList 0.3 changes: HTML for bits not showing properly fixed highlightSelector not working (due to a typo) fixed GrowingInput missing pad function added (only affected if you customized growing.mini option) Improved clicking the whole widget behavior Other tiny enhancements &#8230; <a href="http://www.devthought.com/2009/04/21/textboxlist-03-and-jquery-version-out/">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<p>Moo TextboxList 0.3 changes:</p>
<ul>
<li>HTML for bits not showing properly fixed</li>
<li><code class="inline">highlightSelector</code> not working (due to a typo) fixed</li>
<li><code class="inline">GrowingInput</code> missing pad function added (only affected if you customized growing.mini option)</li>
<li>Improved clicking the whole widget behavior</li>
<li>Other tiny enhancements / cleanup</li>
</ul>
<p>Secondly, in the best interest of the JavaScript community, I&#8217;ve ported TextboxList to jQuery. The API changes slightly due to the different OOP approach, but all the functionality is intact. Head to <a href="/projects/jquery/textboxlist/">jQuery TextboxList</a> project page for more.</p>
<p>Update: 0.2 is out for jQuery. Bugs in autocompleter and IE have been addressed.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.devthought.com/2009/04/21/textboxlist-03-and-jquery-version-out/feed/</wfw:commentRss>
		<slash:comments>46</slash:comments>
		</item>
		<item>
		<title>JavaScript RegExp based highlighting for MooTools and jQuery</title>
		<link>http://www.devthought.com/2009/04/04/javascript-regexp-based-highlighting-function-for-mootools-and-jquery/</link>
		<comments>http://www.devthought.com/2009/04/04/javascript-regexp-based-highlighting-function-for-mootools-and-jquery/#comments</comments>
		<pubDate>Sat, 04 Apr 2009 18:55:07 +0000</pubDate>
		<dc:creator>Guillermo Rauch</dc:creator>
				<category><![CDATA[Client side]]></category>
		<category><![CDATA[highlighting]]></category>
		<category><![CDATA[jquery]]></category>
		<category><![CDATA[mootools]]></category>
		<category><![CDATA[snippet]]></category>

		<guid isPermaLink="false">http://devthought.com/?p=725</guid>
		<description><![CDATA[How it works A regular expression looks for text outside HTML tags. It uses a callback function to perform replacements to simulate native lookahead support. When is this sort of replacement suitable ? Remote HTML responses (ajax) highlighting Autocompleters suggestion &#8230; <a href="http://www.devthought.com/2009/04/04/javascript-regexp-based-highlighting-function-for-mootools-and-jquery/">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<h3>How it works</h3>
<p>A regular expression looks for text outside HTML tags. It uses a callback function to perform replacements to simulate native lookahead support.</p>
<p>When is this sort of replacement suitable ?</p>
<ul>
<li>Remote HTML responses (ajax) highlighting</li>
<li>Autocompleters suggestion highlighting</li>
<li>User-typed HTML, WYSIWIGs, etc.</li>
</ul>
<p>Generally speaking, the only downside of this method, since it deals with the innerHTML, is that all attached events and properties are lost when the replacement is performed.</p>
<p><span id="more-725"></span></p>
<p>Note: this code is designed to match only beginning of words. If you want to match anywhere, remove <code class="inline">\\b</code> from the regular expression. And if you expect <code class="inline">&lt;script&gt;</code> tags, definitely don&#8217;t use it.</p>
<h3>MooTools version (<a href="/wp-content/articles/highlight-moo/">demo</a>)</h3>
<pre class='highlight ' lang="javascript">
Element.implement({

	highlight: function(search, insensitive, klass){
		var regex = new RegExp('(<[^>]*>)|(\\b'+ search.escapeRegExp() +')', insensitive ? 'ig' : 'g');
		return this.set('html', this.get('html').replace(regex, function(a, b, c){
			return (a.charAt(0) == '<') ? a : '<strong class="'+ klass +'">' + c + '</strong>';
		}));
	}

});
</pre>
<h3>jQuery version (<a href="/wp-content/articles/highlight-jquery/">demo</a>)</h3>
<pre class='highlight ' lang="javascript">
jQuery.fn.extend({

	highlight: function(search, insensitive, klass){
		var regex = new RegExp('(<[^>]*>)|(\\b'+ search.replace(/([-.*+?^${}()|[\]\/\\])/g,"\\$1") +')', insensitive ? 'ig' : 'g');
		return this.html(this.html().replace(regex, function(a, b, c){
			return (a.charAt(0) == '<') ? a : '<strong class="'+ klass +'">' + c + '</strong>';
		}));
	}

});
</pre>
]]></content:encoded>
			<wfw:commentRss>http://www.devthought.com/2009/04/04/javascript-regexp-based-highlighting-function-for-mootools-and-jquery/feed/</wfw:commentRss>
		<slash:comments>10</slash:comments>
		</item>
		<item>
		<title>The APNG Class</title>
		<link>http://www.devthought.com/2009/03/11/the-apng-class/</link>
		<comments>http://www.devthought.com/2009/03/11/the-apng-class/#comments</comments>
		<pubDate>Wed, 11 Mar 2009 04:26:53 +0000</pubDate>
		<dc:creator>Guillermo Rauch</dc:creator>
				<category><![CDATA[Client side]]></category>
		<category><![CDATA[apng]]></category>
		<category><![CDATA[mootools plugin]]></category>
		<category><![CDATA[release]]></category>

		<guid isPermaLink="false">http://devthought.com/?p=464</guid>
		<description><![CDATA[If you&#8217;re looking for an object-oriented, straightforward way to animate those alpha transparent PNGs, look no further. Check out Devthought&#8217;s latest release, APNG 0.1]]></description>
			<content:encoded><![CDATA[<p>If you&#8217;re looking for an object-oriented, straightforward way to animate those alpha transparent PNGs, look no further.</p>
<p>Check out Devthought&#8217;s latest release, <a href="/projects/mootools/apng/">APNG 0.1</a></p>
]]></content:encoded>
			<wfw:commentRss>http://www.devthought.com/2009/03/11/the-apng-class/feed/</wfw:commentRss>
		<slash:comments>7</slash:comments>
		</item>
		<item>
		<title>More please.</title>
		<link>http://www.devthought.com/2009/03/09/more-please/</link>
		<comments>http://www.devthought.com/2009/03/09/more-please/#comments</comments>
		<pubDate>Mon, 09 Mar 2009 23:36:48 +0000</pubDate>
		<dc:creator>Guillermo Rauch</dc:creator>
				<category><![CDATA[Client side]]></category>
		<category><![CDATA[mootools]]></category>
		<category><![CDATA[mootools more]]></category>
		<category><![CDATA[release]]></category>

		<guid isPermaLink="false">http://devthought.com/?p=429</guid>
		<description><![CDATA[You wanted more, we give you More. Today the new MooTools More RC1 is being released, with an outstanding number of new plugins. More functionality, but with the quality you come to expect from the MooTools framework. Most of the &#8230; <a href="http://www.devthought.com/2009/03/09/more-please/">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<p><img src="http://devthought.com/wp-content/uploads/2009/03/mootools.png" alt="mootools" title="mootools" width="184" height="46" class="alignnone size-medium wp-image-430" /></p>
<p>You wanted more, we give you More. Today the new MooTools More RC1 <a href="http://mootools.net/blog/2009/03/09/more-to-love/">is being released</a>, with an outstanding number of new plugins. More functionality, but with the quality you come to expect from the MooTools framework.</p>
<p>Most of the new components come from the excellent Aaron&#8217;s <a href="http://clientcide.com">Clientcide</a> library. I contributed to the improvement, refining and testing of some of his vast code, which brings More to its present state.</p>
<p>The goal here is to provide more great, simple and extensible tools to make developers&#8217; lives easier. I suggest you head to the <a href="http://www.mootools.net/docs_rc1/">Docs</a> or <a href="http://www.mootools.net/more_rc1">Builder</a> page right away to start trying out the new stuff. As always, head to Lighthouse to report the bugs you encounter, or even to suggest new additions or features.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.devthought.com/2009/03/09/more-please/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
	</channel>
</rss>

