<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>The Accidental Developer &#187; twitter</title>
	<atom:link href="http://osric.com/chris/accidental-developer/tag/twitter/feed/" rel="self" type="application/rss+xml" />
	<link>http://osric.com/chris/accidental-developer</link>
	<description>What if Gregor Samsa awoke a computer programmer?</description>
	<lastBuildDate>Mon, 30 Apr 2012 21:16:57 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.2.1</generator>
		<item>
		<title>JSONP and Sencha Touch</title>
		<link>http://osric.com/chris/accidental-developer/2011/02/jsonp-and-sencha-touch/</link>
		<comments>http://osric.com/chris/accidental-developer/2011/02/jsonp-and-sencha-touch/#comments</comments>
		<pubDate>Thu, 10 Feb 2011 01:21:09 +0000</pubDate>
		<dc:creator>Chris Herdt</dc:creator>
				<category><![CDATA[Javascript]]></category>
		<category><![CDATA[api]]></category>
		<category><![CDATA[callback]]></category>
		<category><![CDATA[json]]></category>
		<category><![CDATA[jsonp]]></category>
		<category><![CDATA[sencha touch]]></category>
		<category><![CDATA[twitter]]></category>

		<guid isPermaLink="false">http://osric.com/chris/accidental-developer/?p=330</guid>
		<description><![CDATA[I was recently trying to get a Sencha Touch demo up-and-running, but my callback functions after requests for JSON data never ran, and Firefox would throw errors along the lines of &#8220;invalid label.&#8221; I didn&#8217;t understand why&#8211;until I read more about JSONP. JSONP prefixes your JSON response with a function name, which runs when the [...]]]></description>
			<content:encoded><![CDATA[<p>I was recently trying to get a <a href="http://www.sencha.com/products/touch/">Sencha Touch</a> demo up-and-running, but my callback functions after requests for JSON data never ran, and Firefox would throw errors along the lines of &#8220;invalid label.&#8221; I didn&#8217;t understand why&#8211;until I read more about <a href="http://en.wikipedia.org/wiki/JSON#JSONP">JSONP</a>.</p>
<p>JSONP prefixes your JSON response with a function name, which runs when the response is retrieved. It&#8217;s a way of handling the data without a listener.</p>
<p>This means that your JSONP provider needs to detect a JSONP parameter, and then wrap or &#8220;pad&#8221; the response within the specified parameter value.</p>
<p>For Sencha Touch, the JSON returned should be wrapped in <em>Ext.util.JSONP.callback();</em>. If your JSON looks like this:</p>
<p><code>{"results":[{"name":"Chris"},{"name","Harry"}]}</code></p>
<p>then your JSONP should look like this:</p>
<p><code>Ext.util.JSONP.callback({"results":[{"name":"Chris"},{"name","Harry"}]});</code></p>
<p>Not that you should hard-code that function name anywhere in your JSON output&#8211;web-based APIs and services should pick up the function from your request and wrap the JSON for you. For example, the <a href="http://apiwiki.twitter.com/w/page/22554756/Twitter-Search-API-Method:-search">twitter search API</a> accepts a <em>callback</em> querystring parameter.</p>
<p><code>http://search.twitter.com/search.json?q=fakecriterions&amp;callback=myCallbackFunction</code></p>
<p>would wrap the JSON response inside</p>
<p><code>myCallbackFunction();</code></p>
<p>I ignored the extra letter in the acronym at my own peril&#8211;I figured it was just a trivial variation on JSON (which it is) that wouldn&#8217;t make any difference in how it was handled (but it does).</p>
]]></content:encoded>
			<wfw:commentRss>http://osric.com/chris/accidental-developer/2011/02/jsonp-and-sencha-touch/feed/</wfw:commentRss>
		<slash:comments>9</slash:comments>
		</item>
		<item>
		<title>Why I&#8217;m Not Friends with My Bank on Facebook</title>
		<link>http://osric.com/chris/accidental-developer/2011/01/do-not-friend-your-bank-on-facebook/</link>
		<comments>http://osric.com/chris/accidental-developer/2011/01/do-not-friend-your-bank-on-facebook/#comments</comments>
		<pubDate>Thu, 27 Jan 2011 03:46:06 +0000</pubDate>
		<dc:creator>Chris Herdt</dc:creator>
				<category><![CDATA[Facebook]]></category>
		<category><![CDATA[security]]></category>
		<category><![CDATA[twitter]]></category>
		<category><![CDATA[banking]]></category>
		<category><![CDATA[facebook]]></category>
		<category><![CDATA[flickr]]></category>
		<category><![CDATA[privacy]]></category>
		<category><![CDATA[social media]]></category>
		<category><![CDATA[socialmedia]]></category>
		<category><![CDATA[youtube]]></category>

		<guid isPermaLink="false">http://osric.com/chris/accidental-developer/?p=321</guid>
		<description><![CDATA[I received a request today from my financial institution asking me to follow them on Facebook, Twitter, Flickr, and YouTube. Aside from the fact that I doubt that their updates on these various services will enrich my life, there is another very good reason not to follow them: Security. It&#8217;s easy to trace your connections [...]]]></description>
			<content:encoded><![CDATA[<p>I received a request today from my financial institution asking me to follow them on Facebook, Twitter, Flickr, and YouTube.</p>
<p>Aside from the fact that I doubt that their updates on these various services will enrich my life, there is another very good reason not to follow them:</p>
<p>Security.</p>
<p>It&#8217;s easy to trace your connections online. Most of this information, for most users, is public. If you follow Bank A, it stands to reason that you have an account at Bank A&#8211;something a malicious person would not have known before. Even if your online persona isn&#8217;t directly connected to your name, you might be surprised at how easy it is to connect the two with a Google search.</p>
<ul>
<li>Want to know 9000 people with Citibank accounts? Check <a href="http://www.facebook.com/citibank">http://www.facebook.com/citibank</a></li>
<li>Want to know 6000 people with Wells Fargo accounts? Check <a href="http://twitter.com/#!/Ask_WellsFargo/followers">http://twitter.com/#!/Ask_WellsFargo/followers</a></li>
<li>Want to know 5 people with Bank of American accounts? Check <a href="http://www.youtube.com/user/bankofamerica/">http://www.youtube.com/user/bankofamerica/</a></li>
</ul>
<p>(That last item says a lot, I think.)</p>
<p>Any bank that suggests you follow them on social media must be pretty confident of their security! Or, more likely, their marketing teams and their security teams don&#8217;t talk to each other.</p>
<p>You wouldn&#8217;t stand on a street-corner handing out cards that say, &#8220;My name is Bob Billiards and I have an account at Bank A&#8221; would you? Then don&#8217;t follow your bank on a social media site.</p>
]]></content:encoded>
			<wfw:commentRss>http://osric.com/chris/accidental-developer/2011/01/do-not-friend-your-bank-on-facebook/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>7 Ways Twitter is Like Cigarette Smoking</title>
		<link>http://osric.com/chris/accidental-developer/2009/09/7-ways-twitter-is-like-cigarette-smoking/</link>
		<comments>http://osric.com/chris/accidental-developer/2009/09/7-ways-twitter-is-like-cigarette-smoking/#comments</comments>
		<pubDate>Wed, 16 Sep 2009 20:59:55 +0000</pubDate>
		<dc:creator>Chris Herdt</dc:creator>
				<category><![CDATA[twitter]]></category>
		<category><![CDATA[facebook]]></category>

		<guid isPermaLink="false">http://osric.com/chris/accidental-developer/?p=220</guid>
		<description><![CDATA["People who have never tried it don't get it" and 6 other ways in which Twitter is like cigarette smoking. One important difference: Twitter doesn't cause cancer.]]></description>
			<content:encoded><![CDATA[<p><strong>1. People who have never tried it don&#8217;t get it.</strong><br />
As far as I can tell, the naysayers have never tried Twitter. I&#8217;ve seen people complain about <a href="http://twitter.com">Twitter </a>on <a href="http://www.facebook.com">Facebook</a>, but a Facebook status update and a tweet are nearly the same: short snippets of information that you want to share.</p>
<p>The at-signs (@) and hashes (#) that have become ubiquitous on Twitter may be part of the problem. Although I feel that if you can decipher an emoticon you ought to be able to handle @replies and #hashtags.</p>
<p><strong>The difference?</strong><br />
A tweet is public if your Twitter timeline is public. (A timeline is akin to your wall on Facebook.) This is probably one reason why marketers love it: they get to push links out to the world, including search engines, whereas on Facebook you actually have to work to build an audience. (More on Facebook later.)</p>
<p><strong>2. It&#8217;s addictive.</strong><br />
Clearly, it can be. Maybe not to the same extent as nicotine, but some people can&#8217;t stay off Twitter. People complain about how many breaks smokers take. Sick of your friends leaving you alone at a party while they compose a tweet? Annoyed that they ignore you to check the latest on their Blackberries? Tired of your co-workers taking tweet breaks? Which leads to&#8230;</p>
<p><strong>3. It interrupts you.</strong><br />
Cravings for cigarettes driving you to distraction? Twitter can drive you insane. I quickly disabled updates on my phone, because I would have exceeded my 400 monthly SMS messages in the span of a few days. I installed <a href="http://www.twhirl.org/">twhirl</a>, and later <a href="http://tweetdeck.com/beta/">TweetDeck</a>, and found that I was getting notifications almost every minute. That&#8217;s no way to work. I changed my TweetDeck settings to check for updates every 40 minutes. I may find out about the latest celebrity death 10 minutes after you do, but I still have some semblance of mental focus.</p>
<p><strong>4. Users love to talk about it</strong><br />
Smokers love to talk about smoking. What brand you smoke, the way you hold your cigarettes, whether or not you prefer hard-packs or soft-packs, whether or not you pack your cigarettes before you open them&#8211;these are the sorts of conversations people have on their smoke breaks. My friend Brady cited all the unnecessary talking about smoking as a top reason to quit smoking.</p>
<p>Twitterers love to talk about Twitter. People are in love with Twitter right now, and they aren&#8217;t afraid to shout it from the rooftops. Which apps they use, who they follow, how it can turn their struggling companies into a giants. Even I am guilty of this: about a quarter of my tweets reference Twitter. I imagine this may fade over time, along with the accompanying backlash. After all, remember blowthedotoutyourass.com?</p>
<p><strong>5. You do it more when you&#8217;re drinking.</strong><br />
&#8230;and that&#8217;s not a good thing.</p>
<p><strong>6. Short and unsatisfying.</strong><br />
Oscar Wilde wrote, &#8220;A cigarette is the perfect type of a perfect pleasure.  It is exquisite, and it leaves one unsatisfied.&#8221; I&#8217;ve seen people pack a lot of info into a mere 140 characters, but sometimes 140 characters just isn&#8217;t enough. That is why more than half of the tweets I am perusing right now contain shortened links from sites like <a href="http://bit.ly/">bit.ly</a>, <a href="http://short.to">short.to</a>, <a href="http://ff.im">ff.im</a>, and <a href="http://tr.im">tr.im</a>.</p>
<p>[I actually really dislike shortened links, because they remove a critical piece of info--the destination URL--from the link. If someone posts a link with little-to-no explanation, I will not click on it for two reasons: one, there's no incentive, two, it could be spam or lead to a malicious web site.] </p>
<p><strong>7. It&#8217;s bad for your health.</strong><br />
OK, I admit it: that&#8217;s a weak link. Just don&#8217;t tweet while driving, OK? But just as smokers often pass on exercise, Twitter may cause people or companies to scrimp on more important things, like phone calls, face-to-face conversations, making good products, or even updating Facebook. Time spent on Twitter is time not spent on something else.</p>
<p>(That&#8217;s right, I said Facebook. As I mentioned to a friend recently, <em>if Facebook stepped on Twitter, Facebook would hardly notice</em>. Check out <a href="http://siteanalytics.compete.com/facebook.com+twitter.com/">Facebook vs. Twitter on Compete.com</a>. To which should you devote more time?)</p>
<p><strong>Afterthoughts</strong><br />
I should note that I have been tobacco-free for years and would never advocate tobacco use. On the other hand, I think with some caveats, Twitter can be fun, useful, and relatively harmless.</p>
<p>I decided to capitalize Twitter in this post because it is a proper noun. I&#8217;ll respect bell hooks&#8217; preference for lowercasing, but that&#8217;s where I decided to draw the line this time; I reserve the right to be inconsistent.</p>
<p><strong>Additions?</strong><br />
Feel free to contribute your own comparisons in the comments!</p>
]]></content:encoded>
			<wfw:commentRss>http://osric.com/chris/accidental-developer/2009/09/7-ways-twitter-is-like-cigarette-smoking/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Twitter Status IDs and Direct Message IDs</title>
		<link>http://osric.com/chris/accidental-developer/2009/08/twitter-status-ids-and-direct-message-ids/</link>
		<comments>http://osric.com/chris/accidental-developer/2009/08/twitter-status-ids-and-direct-message-ids/#comments</comments>
		<pubDate>Wed, 05 Aug 2009 02:20:13 +0000</pubDate>
		<dc:creator>Chris Herdt</dc:creator>
				<category><![CDATA[python]]></category>
		<category><![CDATA[twitter]]></category>
		<category><![CDATA[twitter api]]></category>
		<category><![CDATA[twitter bot]]></category>

		<guid isPermaLink="false">http://osric.com/chris/accidental-developer/?p=203</guid>
		<description><![CDATA[I built a twitter-bot in Python using the python-twitter API wrapper (code included in post). Twitter status update IDs and direct message (DM) IDs use different sequences, which is important if you are trying to retrieve messages posted after a specified ID.]]></description>
			<content:encoded><![CDATA[<p><img src="http://osric.com/chris/accidental-developer/wp-content/uploads/2009/08/twitter-bird.png" alt="twitter-bird" title="twitter-bird" width="80" height="55" class="alignleft size-full wp-image-206" />I recently created a <a href="http://twitter.com/osric8ball">Magic Eight Ball twitter-bot</a> as a demo. Written in <a href="http://www.python.org/">Python</a> using the <a href="http://code.google.com/p/python-twitter/">python-twitter</a> API wrapper, it runs every 2 minutes and polls <a href="http://twitter.com/">twitter</a> for new replies (status updates containing <em>@osric8ball</em>) and direct messages (DMs) to <em>osric8ball</em>. If there are any, it replies with a random 8-Ball response.</p>
<p>Every status update and DM has an associated numeric ID. Initially, I stored the highest ID in a log file and used that when I polled twitter (i.e. &#8220;retrieve all replies and DMs with ID > highest ID&#8221;). However, I discovered that status updates and DMs apparently are stored in separate tables on twitter&#8217;s backend, as they have a separate set of IDs. Since the highest status ID was an order of magnitude larger than the highest DM ID, my bot completely ignored all DMs. This was not entirely obvious at first, as the IDs looked very similar, other than an extra digit: 2950029179 and 273876291.</p>
<p>My fix for this was to store both the highest status update ID and the highest DM ID is separate log files.</p>
<p>Another interesting twist: you have to be a follower of a user in order to send that user a DM.<span id="more-203"></span><br />
At first I thought I had solved this by telling the bot to follow anyone who sent it a message. However, if you submit an API request to follow a user whom you are already following, it produces an error. So I added a check to see if the bot was already following the user, and, if not, follow the user.</p>
<p>In case anyone is interested, the entire code is below:<br />
<code>#!/usr/bin/python2.4</p>
<p>import twitter<br />
import random</p>
<p>replyfile = 'twitterreply.log'<br />
dmfile = 'twitterdm.log'<br />
last_id = 0</p>
<p>api = twitter.Api(username='osric8ball', password='[actualpassword]')</p>
<p>friends = api.GetFriends()</p>
<p>responses = ['Signs Point To Yes','Yes','You May Rely On It','Ask Again Later','Concentrate And Ask Again','Outlook Good','My Sources Say No','Better Not Tell You Now','Without A Doubt','Reply Hazy, Try Again','It Is Decidedly So','Cannot Predict Now','My Reply Is No','As I See It Yes','It Is Certain','Yes Definitely','Don\'t Count On It','Most Likely','Very Doubtful','Outlook Not So Good']</p>
<p>def areWeFriends(screen_name):<br />
        isFriend = 0<br />
        for friend in friends:<br />
                if friend.screen_name == screen_name:<br />
                        isFriend = 1<br />
        return isFriend</p>
<p>def makeFriend(screen_name):<br />
        if areWeFriends(screen_name) == 0:<br />
                api.CreateFriendship(user=screen_name)</p>
<p>def sendReply(screen_name):<br />
        makeFriend(screen_name)<br />
        response = responses[random.randint(0,19)]<br />
        api.PostUpdates('@' + screen_name + ': ' + response)<br />
        print '@' + screen_name + ': ' + response</p>
<p>def sendDirectMessage(screen_name):<br />
        makeFriend(screen_name)<br />
        response = responses[random.randint(0,19)]<br />
        api.PostDirectMessage(screen_name,response)<br />
        print 'd ' + screen_name + ': ' + response</p>
<p>#Read logs<br />
log = open(replyfile, 'r')<br />
last_reply_id = log.read()<br />
log.close()</p>
<p>log = open(dmfile, 'r')<br />
last_dm_id = log.read()<br />
log.close()</p>
<p>if last_reply_id &gt; 0 and last_dm_id &gt; 0:</p>
<p>        #Get replies and direct messages<br />
        replies = api.GetReplies(since_id=last_reply_id)<br />
        directMessages = api.GetDirectMessages(since_id=last_dm_id)</p>
<p>        #Update logs<br />
        if directMessages != []:<br />
                last_dm_id = directMessages[0].id</p>
<p>        if replies != []:<br />
                last_reply_id = replies[0].id</p>
<p>        if last_reply_id &gt; 0:<br />
                log = open(replyfile,'w')<br />
                log.write( str(last_reply_id) )<br />
                log.close()</p>
<p>        if last_dm_id &gt; 0:<br />
                log = open(dmfile,'w')<br />
                log.write( str(last_dm_id) )<br />
                log.close()</p>
<p>        # Loop through replies<br />
        for reply in replies:<br />
                sendReply(reply.user.screen_name)</p>
<p>        # Loop through direct messages<br />
        for directMessage in directMessages:<br />
                sendDirectMessage(directMessage.sender_screen_name)</p>
<p>else:<br />
        print 'Unable to read ' + replyfile + ' or ' + dmfile<br />
</code></p>
]]></content:encoded>
			<wfw:commentRss>http://osric.com/chris/accidental-developer/2009/08/twitter-status-ids-and-direct-message-ids/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Installing Adobe AIR and Tweetdeck on an Asus eee 701</title>
		<link>http://osric.com/chris/accidental-developer/2009/04/installing-adobe-air-and-tweetdeck-on-an-asus-eee-701/</link>
		<comments>http://osric.com/chris/accidental-developer/2009/04/installing-adobe-air-and-tweetdeck-on-an-asus-eee-701/#comments</comments>
		<pubDate>Fri, 01 May 2009 03:18:52 +0000</pubDate>
		<dc:creator>Chris Herdt</dc:creator>
				<category><![CDATA[Uncategorized]]></category>
		<category><![CDATA[adobe air]]></category>
		<category><![CDATA[asus eee]]></category>
		<category><![CDATA[facebook]]></category>
		<category><![CDATA[tweetdeck]]></category>
		<category><![CDATA[twitter]]></category>

		<guid isPermaLink="false">http://osric.com/chris/accidental-developer/?p=165</guid>
		<description><![CDATA[Tweetdeck is an Adobe AIR application that is a twitter client, and recently also a Facebook client. My attempts to install Adobe AIR on the Asus eee 701 (running the default Xandros distro) were foiled several times in spite of following the instructions: Download Adobe AIR Make the AdobeAIRInstaller.bin file executable Run the .bin file [...]]]></description>
			<content:encoded><![CDATA[<p><a href="http://www.tweetdeck.com/beta/">Tweetdeck</a> is an <a href="http://get.adobe.com/air/">Adobe AIR</a> application that is a <a href="http://twitter.com/">twitter</a> client, and recently also a <a href="http://www.facebook.com/">Facebook</a> client.</p>
<p>My attempts to install Adobe AIR on the Asus eee 701 (running the default Xandros distro) were foiled several times in spite of following the instructions:</p>
<ol>
<li>Download Adobe AIR</li>
<li>Make the AdobeAIRInstaller.bin file executable</li>
<li>Run the .bin file as a superuser</li>
</ol>
<p>I got a nice friendly fail message from the Adobe AIR installer every time.</p>
<p>I found a few relevant forum posts, e.g. <a href="http://forums.adobe.com/thread/204867"> Adobe Air Linux won&#8217;t install on Eee PC</a>, that suggested memory was an issue. Sure enough, running in Full Desktop Mode with 1440&#215;900 screen resolution (on an external display), I only had about 90MB of 500MB free.</p>
<p>I restarted the eee in Easy Mode and then immediately ran AdobeAirInstaller.bin. Success! (I later found these same instructions on the <a href="http://forum.eeeuser.com/viewtopic.php?pid=547238">eee user forums</a>.)</p>
<p>Installing Tweetdeck was trivial at that point: download the .air file, find it in the File Manager, and double-click it. However, when I ran it, it didn&#8217;t <em>do</em> anything. At one point I got a message that I was running an unknown desktop, and that Tweetdeck required Gnome or KDE.</p>
<p>I restarted in Full Desktop Mode, and was surprised to find a Tweetdeck icon already on the desktop. I ran it and was prompted to use KWallet, a KDE password manager. I canceled out of that, and found that Tweetdeck opened, but still didn&#8217;t <em>do</em> anything.</p>
<p>I tried again, activated the KWallet password manager, and then it worked! Tweetdeck prompted me for my twitter login, I additionally logged in to Facebook, and now I have a mean, lean, social networking machine.</p>
]]></content:encoded>
			<wfw:commentRss>http://osric.com/chris/accidental-developer/2009/04/installing-adobe-air-and-tweetdeck-on-an-asus-eee-701/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Javascript textarea counter</title>
		<link>http://osric.com/chris/accidental-developer/2008/11/javascript-textarea-counter/</link>
		<comments>http://osric.com/chris/accidental-developer/2008/11/javascript-textarea-counter/#comments</comments>
		<pubDate>Sat, 15 Nov 2008 19:33:26 +0000</pubDate>
		<dc:creator>Chris Herdt</dc:creator>
				<category><![CDATA[Best Practices]]></category>
		<category><![CDATA[Javascript]]></category>
		<category><![CDATA[User Interface]]></category>
		<category><![CDATA[delicious]]></category>
		<category><![CDATA[forms]]></category>
		<category><![CDATA[jquery]]></category>
		<category><![CDATA[textarea]]></category>
		<category><![CDATA[twitter]]></category>

		<guid isPermaLink="false">http://osric.com/chris/accidental-developer/?p=109</guid>
		<description><![CDATA[I&#8217;ve been thinking more about the textarea counter issue that I mentioned in my previous post (&#8220;Users Paste Differently&#8220;). First of all, I noticed that some of the textarea counter scripts date back to at least 2000, so this has been a problem that developers have been looking to solve for 8 years. I checked [...]]]></description>
			<content:encoded><![CDATA[<p>I&#8217;ve been thinking more about the textarea counter issue that I mentioned in my previous post (&#8220;<a href="http://osric.com/chris/accidental-developer/?p=103">Users Paste Differently</a>&#8220;).</p>
<p>First of all, I noticed that some of the textarea counter scripts date back to at least 2000, so this has been a problem that developers have been looking to solve for 8 years. I checked the <a href="http://www.w3.org/html/wg/html5/">HTML 5 specification</a> and found that in HTML 5, the <a href="http://www.w3.org/html/wg/html5/#the-textarea-element">textarea element has a maxlength attribute</a>. Presumably user agents will build in the most elegant solution.</p>
<p>But what is the current most elegant solution?<span id="more-109"></span><br />
I checked a couple sites that I know use textarea counters well: <a href="http://delicious.com/">Delicious</a> and <a href="http://twitter.com/">Twitter</a>.</p>
<p><strong>Delicious</strong><br />
<div id="attachment_118" class="wp-caption alignnone" style="width: 420px"><a href="http://osric.com/chris/accidental-developer/wp-content/uploads/2008/11/delicious-textarea-counters.png"><img src="http://osric.com/chris/accidental-developer/wp-content/uploads/2008/11/delicious-textarea-counters.png" alt="Textarea counters on Delicious.com" title="delicious-textarea-counters" width="410" height="66" class="size-full wp-image-118" /></a><p class="wp-caption-text">Textarea counters on Delicious.com</p></div></p>
<p><strong>Twitter</strong><br />
<div id="attachment_120" class="wp-caption alignnone" style="width: 394px"><a href="http://osric.com/chris/accidental-developer/wp-content/uploads/2008/11/twitter-textarea-counters.png"><img src="http://osric.com/chris/accidental-developer/wp-content/uploads/2008/11/twitter-textarea-counters.png" alt="Textarea counters on Twitter.com" title="twitter-textarea-counters" width="384" height="80" class="size-full wp-image-120" /></a><p class="wp-caption-text">Textarea counters on Twitter.com</p></div></p>
<p>I like how prominent the character count is in Twitter, although perhaps too terse, but if Javascript is disabled it displays nothing at all. On the other hand, in Delicious displays &#8220;1000 characters max&#8221; if Javascript is off (instead of &#8220;1000 characters left&#8221;), which is still useful information. (I would avoid using the abbreviation <em>max</em>, though, and use <em>maximum</em> or <em>limit</em> instead, which might be better understood by those for whom English is a second language.)</p>
<p>I like Twitter&#8217;s &#8220;warning track&#8221; that lets the user know they need to keep it concise and wrap it up, although I find it confusing that they used bright red to denote both the &#8220;dangerously close to&#8221; as well as &#8220;over&#8221; the limit. The positive bright red numbers could easily be misconstrued as over the limit, since red is a color we frequently use to denote errors.</p>
<p>Twitter&#8217;s counter responds to onBlur and onChange, whereas the counter in Delicious is triggered by neither.</p>
<p>Both get one thing right that I think most other textarea counters get wrong: they don&#8217;t truncate the user&#8217;s text. Deleting something that the user has typed (or pasted) is definitely a bad idea for at least two reasons: the user may not realize the input was truncated and may submit incomplete info, and that the user, upon discovering that the input requires editing, may choose to cut text from someplace other than the end. Instead, both versions alert the user that they are over the limit and provide information on how many characters need to be cut to stay within the limit.</p>
<p>(As an aside, one thing I find curious is that both count an <em>Enter</em> keystroke as one character. I&#8217;ve run into issues with this before because a line break on a Windows-based system should insert 2 ASCII characters: a Carriage Return (CR) and a Line Feed (LF). *nix systems, including OS X, will insert a Line Feed (LF). However, I haven&#8217;t been able to reproduce this issue with recent testing. If it is still an issue, I imagine they handle this on the back-end by converting the CRLF to LF before inserting it into the database?)</p>
<p>In short, my recommendations are:</p>
<ul>
<li>Don&#8217;t truncate the user&#8217;s input; let the user correct it</li>
<li>Let the user know how far over the limit he or she is</li>
<li>Provide guidelines even if Javascript is disabled</li>
<li>onBlur and onChange should also trigger the counter, in case the user is pasting text</li>
<li>Keep the counter message simple and clear</li>
</ul>
<p>Another idea I had for a visual counter:<br />
<div id="attachment_116" class="wp-caption alignnone" style="width: 260px"><a href="http://osric.com/chris/accidental-developer/wp-content/uploads/2008/11/counter-bar.png"><img src="http://osric.com/chris/accidental-developer/wp-content/uploads/2008/11/counter-bar.png" alt="Counter - characters remaining" title="counter-bar" width="250" height="20" class="size-full wp-image-116" /></a><p class="wp-caption-text">Counter - characters remaining</p></div><br />
Aside from turning red once past the limit, though I&#8217;m not sure how it would visually convey to the user by how much the text exceeds the limits.</p>
<p><strong>How can a counter be implemented programatically?</strong><br />
I would like to set something up so that the appropriate event handlers are attached to textarea elements automatically. I found a <a href="http://jquery.com/">jQuery</a> plugin, <a href="http://plugins.jquery.com/project/CharLimit">Char Limit</a>, but in addition to not meeting the recommendations I made above, I don&#8217;t like how the developer has to specify the character limit in the Javascript (and apply the same limit for all textarea elements).</p>
<p>I think a clever, although imperfect, solution would be to have jQuery (or any Javascript of your choice) turn any static character limit messages (like the one that Delicious provides if Javascript is disabled) into dynamic character counters. For example, with the following code, the Javascript could find any elements with id attributes matching *_counter, take the numeric part as the limit, and build a character counter:<br />
<code>&lt;textarea name="example" id="example"&gt;&lt;/textarea&gt;<br />
&lt;div id="example_counter"&gt;300 characters maximum&lt;/div&gt;</code></p>
<p>It&#8217;s problematic for several reasons: another element on the page could have an id that matches *_counter, the non-Javascript message could  contain more than one numeric part, and the developers would have be consistent in naming the textareas and accompanying divs. But I think it is in many ways an improvement over the inline Javascript I&#8217;ve seen in some oft-used solutions.</p>
]]></content:encoded>
			<wfw:commentRss>http://osric.com/chris/accidental-developer/2008/11/javascript-textarea-counter/feed/</wfw:commentRss>
		<slash:comments>7</slash:comments>
		</item>
	</channel>
</rss>

