<?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>Less Talk, More Do &#187; Browser Add-ons</title>
	<atom:link href="http://www.chrisfinke.com/category/addons/feed/" rel="self" type="application/rss+xml" />
	<link>http://www.chrisfinke.com</link>
	<description>Christopher Finke is a software engineer. He is available for birthday parties and bar mitzvahs.</description>
	<lastBuildDate>Thu, 29 Jul 2010 04:23:28 +0000</lastBuildDate>
	<generator>http://wordpress.org/?v=2.9.2</generator>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
			<item>
		<title>YouTube Comment Snob in the news</title>
		<link>http://www.chrisfinke.com/2010/06/11/youtube-comment-snob-in-the-news/</link>
		<comments>http://www.chrisfinke.com/2010/06/11/youtube-comment-snob-in-the-news/#comments</comments>
		<pubDate>Sat, 12 Jun 2010 03:02:55 +0000</pubDate>
		<dc:creator>Christopher Finke</dc:creator>
				<category><![CDATA[Browser Add-ons]]></category>
		<category><![CDATA[Life]]></category>
		<category><![CDATA[YouTube Comment Snob]]></category>

		<guid isPermaLink="false">http://www.chrisfinke.com/?p=1692</guid>
		<description><![CDATA[YouTube Comment Snob got some press from the BBC's Webscape segment; the coverage starts around the three-minute mark, right after a very complimentary bit on Jay Meattle's Shareaholic.

 ]]></description>
			<content:encoded><![CDATA[<p><a href="http://www.chrisfinke.com/wp-content/plugins/wordpress-feed-statistics/feed-statistics.php?url=L2FkZG9ucy95b3V0dWJlLWNvbW1lbnQtc25vYi8=">YouTube Comment Snob</a> got some press from <a href="http://www.chrisfinke.com/wp-content/plugins/wordpress-feed-statistics/feed-statistics.php?url=aHR0cDovL25ld3MuYmJjLmNvLnVrLzIvaGkvcHJvZ3JhbW1lcy9jbGlja19vbmxpbmUvODcxNzc2NC5zdG0=">the BBC's Webscape segment</a>; the coverage starts around the three-minute mark, right after a very complimentary bit on <a href="http://www.chrisfinke.com/wp-content/plugins/wordpress-feed-statistics/feed-statistics.php?url=aHR0cDovL3d3dy5zaGFyZWFob2xpYy5jb20v">Jay Meattle's Shareaholic</a>.</p>
<p><embed width="448" height="287" allowfullscreen="true" allowscriptaccess="always" wmode="default" quality="high" flashvars="embedReferer=&amp;embedPageUrl=http%3A%2F%2Fnews.bbc.co.uk%2F2%2Fhi%2Fprogrammes%2Fclick_online%2F8717764.stm&amp;widgetRevision=20677_20946&amp;legacyPlayerRevision=20573_20923&amp;config_settings_language=default&amp;config_settings_showShareButton=false&amp;companionSize=300x60&amp;companionType=adi&amp;preroll=http%3A%2F%2Fad.doubleclick.net%2Fpfadx%2Fbbccom.live.site.news%2Fnews_clickonline_content%3Bsectn%3Dnews%3Bctype%3Dcontent%3Bnews%3Dclick%3Badsense_middle%3Dadsense_middle%3Badsense_mpu%3Dadsense_mpu%3Breferrer%3Dnonbbc%3Breferrer_domain%3D%3Brsi%3DJ08781_10139%3Brsi%3DJ08781_10168%3Bslug%3Dclick%3Bheadline%3Dwebscape-visualsearchesonthemobilephone%3Bslot%3Dcompanion%3Bsz%3D512x288%3Btile%3D5&amp;config=http%3A%2F%2Fnews.bbc.co.uk%2Fplayer%2Femp%2Fconfig%2Fdefault.xml%3F2_26_20946_20100610111019&amp;domId=emp_8723291&amp;playlist=http%3A%2F%2Fnews.bbc.co.uk%2Fmedia%2Femp%2F8720000%2F8723200%2F8723291.xml&amp;holding=http%3A%2F%2Fnewsimg.bbc.co.uk%2Fmedia%2Fimages%2F47999000%2Fjpg%2F_47999214_webscape-526_512.jpg&amp;config_settings_autoPlay=false&amp;config_settings_showPopoutButton=false&amp;autoPlay=false&amp;config_plugin_fmtjLiveStats_pageType=eav2&amp;config_plugin_fmtjLiveStats_edition=International&amp;fmtjDocURI=%2F2%2Fhi%2Fprogrammes%2Fclick_online%2F8717764.stm&amp;companionId=bbccom_companion_8723291&amp;config_settings_showUpdatedInFooter=true" id="embeddedPlayer_8723291" src="http://newsimg.bbc.co.uk/player/emp/2_26_20946/widgets/10shell.swf?revision=20959" type="application/x-shockwave-flash"/></p>
 <img src="http://www.chrisfinke.com/wp-content/plugins/wordpress-feed-statistics/feed-statistics.php?view=1&post_id=1692" width="1" height="1" style="display: none;" />]]></content:encoded>
			<wfw:commentRss>http://www.chrisfinke.com/2010/06/11/youtube-comment-snob-in-the-news/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>ScribeFire for Google Chrome</title>
		<link>http://www.chrisfinke.com/2010/04/08/scribefire-for-google-chrome/</link>
		<comments>http://www.chrisfinke.com/2010/04/08/scribefire-for-google-chrome/#comments</comments>
		<pubDate>Fri, 09 Apr 2010 03:57:46 +0000</pubDate>
		<dc:creator>Christopher Finke</dc:creator>
				<category><![CDATA[Browser Add-ons]]></category>
		<category><![CDATA[Google Chrome]]></category>
		<category><![CDATA[ScribeFire]]></category>

		<guid isPermaLink="false">http://www.chrisfinke.com/2010/04/08/scribefire-for-google-chrome/</guid>
		<description><![CDATA[I&#39;ve published a post over on the ScribeFire blog with the details, but if you&#39;re running Google Chrome, you can now install ScribeFire for Google Chrome:

This first (alpha) version took three weeks of development, contains about 3,000 lines of JavaScript, uses jQuery, and is completely open-source. Oh, and I&#39;m using it to write this blog [...]]]></description>
			<content:encoded><![CDATA[<p>I&#39;ve published a <a href="http://www.chrisfinke.com/wp-content/plugins/wordpress-feed-statistics/feed-statistics.php?url=aHR0cDovL3d3dy5zY3JpYmVmaXJlLmNvbS8yMDEwLzA0LzA4L3NjcmliZWZpcmUtZm9yLWNocm9tZS1hdmFpbGFibGUtZm9yLWFscGhhLXRlc3Rpbmcv">post over on the ScribeFire blog</a> with the details, but if you&#39;re running Google Chrome, you can now <a href="http://www.chrisfinke.com/wp-content/plugins/wordpress-feed-statistics/feed-statistics.php?url=aHR0cDovL2NvZGUuZ29vZ2xlLmNvbS9wL3NjcmliZWZpcmUtY2hyb21lL2Rvd25sb2Fkcy9kZXRhaWw/bmFtZT1zY3JpYmVmaXJlLTAuMS4wLjAuY3J4JmFtcDtjYW49MiZhbXA7cT0jbWFrZWNoYW5nZXM=">install ScribeFire for Google Chrome</a>:</p>
<p><img alt="" src="http://www.scribefire.com/wp-content/uploads/2010/04/scribefire-chrome.png" style="width: 610px; height: 655px; " /></p>
<p>This first (alpha) version took three weeks of development, contains about 3,000 lines of JavaScript, uses <a href="http://www.chrisfinke.com/wp-content/plugins/wordpress-feed-statistics/feed-statistics.php?url=aHR0cDovL2pxdWVyeS5vcmcv">jQuery</a>, and is completely <a href="http://www.chrisfinke.com/wp-content/plugins/wordpress-feed-statistics/feed-statistics.php?url=aHR0cDovL2NvZGUuZ29vZ2xlLmNvbS9wL3NjcmliZWZpcmUtY2hyb21lL3NvdXJjZS9icm93c2UvI3N2bi90cnVuay9zY3JpYmVmaXJl">open-source</a>. Oh, and I&#39;m using it to write this blog post. &nbsp;</p>
 <img src="http://www.chrisfinke.com/wp-content/plugins/wordpress-feed-statistics/feed-statistics.php?view=1&post_id=1652" width="1" height="1" style="display: none;" />]]></content:encoded>
			<wfw:commentRss>http://www.chrisfinke.com/2010/04/08/scribefire-for-google-chrome/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Ambilight for Your Browser or: Monetizing an Add-on with Fat Plug</title>
		<link>http://www.chrisfinke.com/2010/03/26/ambilight-for-your-browser-or-monetizing-an-add-on-with-fat-plug/</link>
		<comments>http://www.chrisfinke.com/2010/03/26/ambilight-for-your-browser-or-monetizing-an-add-on-with-fat-plug/#comments</comments>
		<pubDate>Fri, 26 Mar 2010 14:04:14 +0000</pubDate>
		<dc:creator>Christopher Finke</dc:creator>
				<category><![CDATA[Browser Add-ons]]></category>
		<category><![CDATA[Fat Plug]]></category>
		<category><![CDATA[Mozilla Add-ons]]></category>
		<category><![CDATA[Mozilla Firefox]]></category>

		<guid isPermaLink="false">http://www.chrisfinke.com/?p=1627</guid>
		<description><![CDATA[I've written a new Firefox extension; it's called True Colors, and it bleeds the colors from the web page you're viewing into the tab bar and status bar.  Think of it as Ambilight for your browser.



The technical details behind the extension are interesting, but I won't go into detail on that here, since Splashnology's [...]]]></description>
			<content:encoded><![CDATA[<p>I've written a new Firefox extension; it's called <a href="http://www.chrisfinke.com/wp-content/plugins/wordpress-feed-statistics/feed-statistics.php?url=aHR0cDovL3d3dy5jaHJpc2ZpbmtlLmNvbS9maWxlcy9kb3dubG9hZHMvYWRkb25zL3RydWVfY29sb3JzLnhwaQ==">True Colors</a>, and it bleeds the colors from the web page you're viewing into the tab bar and status bar.  Think of it as <a href="http://www.chrisfinke.com/wp-content/plugins/wordpress-feed-statistics/feed-statistics.php?url=aHR0cDovL2VuLndpa2lwZWRpYS5vcmcvd2lraS9BbWJpbGlnaHQ=">Ambilight</a> for your browser.</p>
<p><a href="http://www.chrisfinke.com/wp-content/plugins/wordpress-feed-statistics/feed-statistics.php?url=aHR0cDovL3d3dy5jaHJpc2ZpbmtlLmNvbS9maWxlcy8yMDEwLzAzL3RydWUtY29sb3JzLWZsYXZvcnMucG5n"><img src="http://www.chrisfinke.com/files/2010/03/true-colors-flavors.png" alt="" title="True Colors: Flavors.me" width="700" class="alignnone size-full wp-image-1628" /></a></p>
<p><a href="http://www.chrisfinke.com/wp-content/plugins/wordpress-feed-statistics/feed-statistics.php?url=aHR0cDovL3d3dy5jaHJpc2ZpbmtlLmNvbS9maWxlcy8yMDEwLzAzL3RydWUtY29sb3JzLXplbi5wbmc="><img src="http://www.chrisfinke.com/files/2010/03/true-colors-zen.png" alt="" title="True Colors: CSS Zen Garden" width="700" class="alignnone size-full wp-image-1630" /></a></p>
<p><a href="http://www.chrisfinke.com/wp-content/plugins/wordpress-feed-statistics/feed-statistics.php?url=aHR0cDovL3d3dy5jaHJpc2ZpbmtlLmNvbS9maWxlcy8yMDEwLzAzL3RydWUtY29sb3JzLXNsYWtpbnNraS5wbmc="><img src="http://www.chrisfinke.com/files/2010/03/true-colors-slakinski.png" alt="" title="True Colors: Slakinski.com" width="700" class="alignnone size-full wp-image-1629" /></a></p>
<p>The technical details behind the extension are interesting, but I won't go into detail on that here, since <a href="http://www.chrisfinke.com/wp-content/plugins/wordpress-feed-statistics/feed-statistics.php?url=aHR0cDovL3d3dy5zcGxhc2hub2xvZ3kuY29tL2Jsb2cvaHRtbDUvMzgyLmh0bWw=">Splashnology's blog post</a> describing how Ambilight for video works explains 99% of the technique.</p>
<p>There's another important aspect to this extension. I've used it as a testbed for <a href="http://www.chrisfinke.com/wp-content/plugins/wordpress-feed-statistics/feed-statistics.php?url=aHR0cDovL2ZhdHBsdWcuY29tLw==">Fat Plug's add-on monetization system</a>.  A Fat Plug-enabled extension will add/change ads on various websites, and, in turn, funnel a portion of the revenue from those ads to the extension developer.</p>
<p>There's some controversy around this technique.  Mozilla has opted to deny any Fat Plug extensions that are submitted to the <a href="http://www.chrisfinke.com/wp-content/plugins/wordpress-feed-statistics/feed-statistics.php?url=aHR0cHM6Ly9hZGRvbnMubW96aWxsYS5vcmcv">Mozilla Add-ons Gallery</a>.  Website owners, I imagine, wouldn't appreciate their ads being replaced with ads that don't earn them any money.  (Although it would harm them no more than ad-blocking extensions, which Mozilla does allow.)</p>
<p>However, to an add-on developer, the idea is intriguing: "What if I collected half of all the website ad revenue from all of the users that use my extensions?"  A developer of a popular add-on could retire after a couple of years to the sands of Grand Cayman and spend his days writing free software that needs no monetization.</p>
<p>So True Colors is my testbed for Fat Plug's technology. I won't be uploading it to Mozilla Add-ons, and I won't be publishing it anywhere that doesn't make the Fat Plug integration obvious.  I'm not looking to stealthily trick users into becoming my little monetization machines, which is why I purposefully wrote a simple extension that doesn't add functionality to the browser as my first foray into Fat Plug.</p>
<p>If you're interested in seeing how Fat Plug modifies ads on websites, you can <a href="http://www.chrisfinke.com/wp-content/plugins/wordpress-feed-statistics/feed-statistics.php?url=aHR0cDovL3d3dy5jaHJpc2ZpbmtlLmNvbS9maWxlcy9kb3dubG9hZHMvYWRkb25zL3RydWVfY29sb3JzLnhwaQ==">install True Colors</a>, agree to the license agreement, and then set the preferences <b>extensions.fatplug.enableoutlinediv</b> and <b>extensions.fatplug.enableoutlinelink</b> to true in <a href="http://www.chrisfinke.com/wp-content/plugins/wordpress-feed-statistics/feed-statistics.php?url=YWJvdXQ6Y29uZmln">about:config</a>.  Any ads that Fat Plug adds or modifies will be outlined in red for your convenience.</p>
<p>If you're interested in the coloring functionality but are wary of the Fat Plug integration, you can <a href="http://www.chrisfinke.com/wp-content/plugins/wordpress-feed-statistics/feed-statistics.php?url=aHR0cDovL3d3dy5jaHJpc2ZpbmtlLmNvbS9maWxlcy9kb3dubG9hZHMvYWRkb25zL3RydWVfY29sb3JzLnhwaQ==">install the extension</a> and just not agree to the license agreement.  That will keep the tab and status bar coloring functionality but disable Fat Plug's code.</p>
<div class="key-point install-box">
<div class="install"><b><a href="http://www.chrisfinke.com/wp-content/plugins/wordpress-feed-statistics/feed-statistics.php?url=aHR0cDovL3d3dy5jaHJpc2ZpbmtlLmNvbS9maWxlcy9kb3dubG9hZHMvYWRkb25zL3RydWVfY29sb3JzLnhwaQ==" onclick=\"if(typeof(InstallTrigger)!='undefined') {var InstallXPI = {'True Colors': 'http://www.chrisfinke.com/files/downloads/addons/true_colors.xpi'}; InstallTrigger.install(InstallXPI); return false;}\" type=\" application/x-xpinstall\" title=\"Install True Colors\">Install the True Colors Add-on with Fat Plug Integration</a></b></div>
</div>
 <img src="http://www.chrisfinke.com/wp-content/plugins/wordpress-feed-statistics/feed-statistics.php?view=1&post_id=1627" width="1" height="1" style="display: none;" />]]></content:encoded>
			<wfw:commentRss>http://www.chrisfinke.com/2010/03/26/ambilight-for-your-browser-or-monetizing-an-add-on-with-fat-plug/feed/</wfw:commentRss>
		<slash:comments>5</slash:comments>
		</item>
		<item>
		<title>Making Add-on/User Communication Less Annoying</title>
		<link>http://www.chrisfinke.com/2010/02/27/making-add-onuser-communication-less-annoying/</link>
		<comments>http://www.chrisfinke.com/2010/02/27/making-add-onuser-communication-less-annoying/#comments</comments>
		<pubDate>Sun, 28 Feb 2010 00:09:57 +0000</pubDate>
		<dc:creator>Christopher Finke</dc:creator>
				<category><![CDATA[Browser Add-ons]]></category>
		<category><![CDATA[Life]]></category>
		<category><![CDATA[Mozilla Firefox]]></category>
		<category><![CDATA[Programming]]></category>
		<category><![CDATA[TwitterBar]]></category>

		<guid isPermaLink="false">http://www.chrisfinke.com/?p=1602</guid>
		<description><![CDATA[When a new user downloads TwitterBar, there are a number of things I want them to know or questions I want to ask them.  So what is the best method to communicate with an add-on user?
The solution I've been using for a while is to pop up a dialog like this:

There are several problems [...]]]></description>
			<content:encoded><![CDATA[<p>When a new user downloads <a href="http://www.chrisfinke.com/wp-content/plugins/wordpress-feed-statistics/feed-statistics.php?url=aHR0cHM6Ly9hZGRvbnMubW96aWxsYS5vcmcvZW4tVVMvZmlyZWZveC9hZGRvbi80NjY0">TwitterBar</a>, there are a number of things I want them to know or questions I want to ask them.  So what is the best method to communicate with an add-on user?</p>
<p>The solution I've been using for a while is to pop up a dialog like this:</p>
<p><img src="http://www.chrisfinke.com/files/2010/02/twitterbar-demand.png" alt="" title="" width="520" height="223" class="alignnone size-full wp-image-1603" /></p>
<p>There are several problems with this approach, all of which I decided to ignore when I implemented it:</p>
<ul>
<li>It steals the user's focus.</li>
<li>It's annoying.</li>
<li>The user might click cancel without reading it just to get rid of it.</li>
<li>It's annoying.</li>
<li>The user might immediately (but accidentally) click elsewhere, hiding the dialog behind another window, never to be seen again.</li>
<li>It's annoying.</li>
<li>It's extra code and work to pop up a special dialog like this.</li>
<li>It's annoying.</li>
</ul>
<p>Back when there was only one dialog, I decided that these were acceptable faults.  However, since then, I've come up with a few more questions I want to ask users, so now instead of one annoying dialog, there are three or four annoying dialogs - a new one appearing each time you restart Firefox.</p>
<p>Predictably (or so it should have been), users don't like to be assaulted with new dialogs each time they start their browser.  Most likely, they're starting their browser for some purpose other than using my add-on, so my add-on shouldn't steal their attention.  As one user so elegantly put it,</p>
<blockquote><p>"I really love the TwitterBar, but after the most recent TwitterBar update, I noticed I kept getting these <b>annoying as hell</b> pop-ups from TwitterBar about TwitterBar. After the third one (while I was in the middle of doing something and became distracted with this pop-up dialog box TwitterBar tip of the day), I uninstalled it. <b> If you want to keep your clients, don't constantly tap them on the shoulder.</b>"</p></blockquote>
<p>I had already been working on redesigning these add-on/user interactions when I got that email, so the user's message reinforced what I had suspected: I was alienating my userbase.</p>
<p>Here's the new scheme I've settled on for now:</p>
<p><img src="http://www.chrisfinke.com/files/2010/02/twitterbar-request.png" alt="" title="" width="710" height="192" class="alignnone size-full wp-image-1604" /></p>
<p>It's a notification bar, much like the one that appears when Firefox blocks a popup.  It has these positive qualities:</p>
<ul>
<li>It doesn't steal focus or interrupt the user.</li>
<li>It's not in-your-face, so it's less likely (I assume) to be dismissed without thought.</li>
<li>It can't be lost behind another window.</li>
<li>The amount of code to implement it is less, and it's more in tune with the browser interface.</li>
<li>It's not <em>as</em> annoying.</li>
</ul>
<p>I'd love your feedback on this change.  Is it enough? Should I stop bothering users altogether and just let them discover their way around the add-on? I'm open to all ideas.</p>
<p>(If you'd like to try a version of TwitterBar with this new notification method, you can <a href="http://www.chrisfinke.com/wp-content/plugins/wordpress-feed-statistics/feed-statistics.php?url=aHR0cDovL2NvZGUuZ29vZ2xlLmNvbS9wL2ZpcmVmb3gtdHdpdHRlcmJhci9kb3dubG9hZHMvZGV0YWlsP25hbWU9dHdpdHRlcmJhci0yLjkuMWIzLnhwaSYjMDM4O2Nhbj0yJiMwMzg7cT0jbWFrZWNoYW5nZXM=">download it here</a>. Although, if you've already seen the old dialog-style version of these notifications, you won't see the new-style ones anyway.)</p>
 <img src="http://www.chrisfinke.com/wp-content/plugins/wordpress-feed-statistics/feed-statistics.php?view=1&post_id=1602" width="1" height="1" style="display: none;" />]]></content:encoded>
			<wfw:commentRss>http://www.chrisfinke.com/2010/02/27/making-add-onuser-communication-less-annoying/feed/</wfw:commentRss>
		<slash:comments>21</slash:comments>
		</item>
		<item>
		<title>TwitterBar 2.9 Available: Post to Multiple Twitter Accounts</title>
		<link>http://www.chrisfinke.com/2010/02/24/twitterbar-2-9-available-post-to-multiple-twitter-accounts/</link>
		<comments>http://www.chrisfinke.com/2010/02/24/twitterbar-2-9-available-post-to-multiple-twitter-accounts/#comments</comments>
		<pubDate>Wed, 24 Feb 2010 19:36:12 +0000</pubDate>
		<dc:creator>Christopher Finke</dc:creator>
				<category><![CDATA[Browser Add-ons]]></category>
		<category><![CDATA[Mozilla Firefox]]></category>
		<category><![CDATA[Twitter]]></category>
		<category><![CDATA[TwitterBar]]></category>

		<guid isPermaLink="false">http://www.chrisfinke.com/?p=1592</guid>
		<description><![CDATA[Version 2.9 of TwitterBar for Firefox was made available on Mozilla Add-ons today, and it has a very cool new feature: you can now use TwitterBar with more than one Twitter account.
To post to a specific account, just type your message like this:
I am posting to my other account. --@other_account --post

If you haven't yet authorized [...]]]></description>
			<content:encoded><![CDATA[<p>Version 2.9 of <a href="http://www.chrisfinke.com/wp-content/plugins/wordpress-feed-statistics/feed-statistics.php?url=aHR0cHM6Ly9hZGRvbnMubW96aWxsYS5vcmcvZW4tVVMvZmlyZWZveC9hZGRvbi80NjY0">TwitterBar for Firefox</a> was made available on Mozilla Add-ons today, and it has a very cool new feature: you can now use TwitterBar with more than one Twitter account.</p>
<p>To post to a specific account, just type your message like this:</p>
<blockquote><p>I am posting to my other account. --@other_account --post</p></blockquote>
<p><img src="http://www.chrisfinke.com/files/2010/02/post-to-account.png" alt="" title="" width="354" height="51" class="alignnone size-full wp-image-1596" /></p>
<p>If you haven't yet authorized TwitterBar for @other_account, you'll be walked through the authorization process.  </p>
<p>If you've authorized more than one account, and you don't specify which account you want to post to, you'll be given a list of choices:</p>
<p><img src="http://www.chrisfinke.com/files/2010/02/account-choices.png" alt="" title="" width="439" height="213" class="alignnone size-full wp-image-1598" /></p>
<p>You can manage your accounts from the TwitterBar options (just type "--options").</p>
<p><img src="http://www.chrisfinke.com/files/2010/02/twitterbar-accounts.png" alt="" title="" width="436" height="114" class="alignnone size-full wp-image-1595" /></p>
<p>Finally, to authorize a new account without posting to it, just type "--account" in the URL bar.</p>
<p>To install this new version of TwitterBar, <b><a href="http://www.chrisfinke.com/wp-content/plugins/wordpress-feed-statistics/feed-statistics.php?url=aHR0cHM6Ly9hZGRvbnMubW96aWxsYS5vcmcvZW4tVVMvZmlyZWZveC9hZGRvbi80NjY0">download it from Mozilla Add-ons.</a></b></p>
<p>The next obvious step is the ability to post to multiple accounts simultaneously, and the next version of TwitterBar will offer than feature.  If you'd like to beta-test that update, <a href="http://www.chrisfinke.com/wp-content/plugins/wordpress-feed-statistics/feed-statistics.php?url=bWFpbHRvOmNmaW5rZUBnbWFpbC5jb20=">e-mail me and let me know.</a></p>
 <img src="http://www.chrisfinke.com/wp-content/plugins/wordpress-feed-statistics/feed-statistics.php?view=1&post_id=1592" width="1" height="1" style="display: none;" />]]></content:encoded>
			<wfw:commentRss>http://www.chrisfinke.com/2010/02/24/twitterbar-2-9-available-post-to-multiple-twitter-accounts/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>Uploading form data and files with JavaScript (Mozilla)</title>
		<link>http://www.chrisfinke.com/2010/01/30/uploading-form-data-and-files-with-javascript-mozilla/</link>
		<comments>http://www.chrisfinke.com/2010/01/30/uploading-form-data-and-files-with-javascript-mozilla/#comments</comments>
		<pubDate>Sat, 30 Jan 2010 21:23:34 +0000</pubDate>
		<dc:creator>Christopher Finke</dc:creator>
				<category><![CDATA[Browser Add-ons]]></category>
		<category><![CDATA[JavaScript]]></category>
		<category><![CDATA[Mozilla]]></category>
		<category><![CDATA[Programming]]></category>

		<guid isPermaLink="false">http://www.chrisfinke.com/?p=1573</guid>
		<description><![CDATA[One problem I stumble across occasionally in writing Firefox extensions is properly uploading form data that includes a file - that is, assembling the POST request in JavaScript while still maintaining the sanctity of any file or string data.  You can't just do this:

var request = "--boundary\r\n some text\r\n--boundary" + fileBytes + "\r\n--boundary--";

I had [...]]]></description>
			<content:encoded><![CDATA[<p>One problem I stumble across occasionally in writing Firefox extensions is properly uploading form data that includes a file - that is, assembling the POST request in JavaScript while still maintaining the sanctity of any file or string data.  You can't just do this:</p>
<pre>
var request = "--boundary\r\n some text\r\n--boundary" + fileBytes + "\r\n--boundary--";
</pre>
<p>I had to spend a bit of time getting this just right in order to allow <a href="http://www.chrisfinke.com/wp-content/plugins/wordpress-feed-statistics/feed-statistics.php?url=aHR0cDovL3d3dy5zY3JpYmVmaXJlLmNvbS8=">ScribeFire</a> to upload media to <a href="http://www.chrisfinke.com/wp-content/plugins/wordpress-feed-statistics/feed-statistics.php?url=aHR0cDovL3Bvc3Rlcm91cy5jb20v">Posterous</a>, so I'm posting below the final solution at which I arrived; it was cobbled together from a dozen different examples I found around the Web (none of them solving the full problem), then lovingly massaged into the elegant function you see before you.  With this function, you can pass in an array of fields and files, and the request will be crafted and returned to you, ready for upload.</p>
<p>Instructions for use are in the comment block at the top of the function.</p>
<pre>
function createPostRequest(args) {
  /**
   * Generates a POST request body for uploading.
   *
   * args is an associative array of the form fields.
   *
   * Example:
   * var args = { "field1": "abc", "field2" : "def", "fileField" :
   *              { "file": theFile, "headers" : [ "X-Fake-Header: foo" ] } };
   *
   * theFile is an nsILocalFile; the headers param for the file field is optional.
   *
   * This function returns an array like this:
   * { "requestBody" : uploadStream, "boundary" : BOUNDARY }
   *
   * To upload:
   *
   * var postRequest = createPostRequest(args);
   * var req = new XMLHttpRequest();
   * req.open("POST", ...);
   * req.setRequestHeader("Content-Type","multipart/form-data; boundary="+postRequest.boundary);
   * req.setRequestHeader("Content-Length", (postRequest.requestBody.available()));
   * req.send(postRequest.requestBody);
   */

  function stringToStream(str) {
    function encodeToUtf8(oStr) {
      var utfStr = oStr;
      var uConv = Components.classes["@mozilla.org/intl/scriptableunicodeconverter"]
                    .createInstance(Components.interfaces.nsIScriptableUnicodeConverter);
      uConv.charset = "UTF-8";
      utfStr = uConv.ConvertFromUnicode(oStr);

      return utfStr;
    }

    str = encodeToUtf8(str);

    var stream = Components.classes["@mozilla.org/io/string-input-stream;1"]
                   .createInstance(Components.interfaces.nsIStringInputStream);
    stream.setData(str, str.length);

    return stream;
  }

  function fileToStream(file) {
    var fpLocal  = Components.classes['@mozilla.org/file/local;1']
                     .createInstance(Components.interfaces.nsILocalFile);
    fpLocal.initWithFile(file);

    var finStream = Components.classes["@mozilla.org/network/file-input-stream;1"]
                      .createInstance(Components.interfaces.nsIFileInputStream);
    finStream.init(fpLocal, 1, 0, false);

    var bufStream = Components.classes["@mozilla.org/network/buffered-input-stream;1"]
                      .createInstance(Components.interfaces.nsIBufferedInputStream);
    bufStream.init(finStream, 9000000);

    return bufStream;
  }

  var mimeSvc = Components.classes["@mozilla.org/mime;1"]
                  .getService(Components.interfaces.nsIMIMEService);
  const BOUNDARY = "---------------------------32191240128944"; 

  var streams = [];

  for (var i in args) {
    var buffer = "--" + BOUNDARY + "\r\n";
    buffer += "Content-Disposition: form-data; name=\"" + i + "\"";
    streams.push(stringToStream(buffer));

    if (typeof args[i] == "object") {
      buffer = "; filename=\"" + args[i].file.leafName + "\"";

      if ("headers" in args[i]) {
        if (args[i].headers.length > 0) {
          for (var q = 0; q < args[i].headers.length; q++){
            buffer += "\r\n" + args[i].headers[q];
          }
        }
      }

      var theMimeType = mimeSvc.getTypeFromFile(args[i].file);

      buffer += "\r\nContent-Type: " + theMimeType;
      buffer += "\r\n\r\n";

      streams.push(stringToStream(buffer));

      streams.push(fileToStream(args[i].file));
    }
    else {
      buffer = "\r\n\r\n";
      buffer += args[i];
      buffer += "\r\n";
      streams.push(stringToStream(buffer));
    }
  }

  var buffer = "--" + BOUNDARY + "--\r\n";
  streams.push(stringToStream(buffer));

  var uploadStream = Components.classes["@mozilla.org/io/multiplex-input-stream;1"]
                       .createInstance(Components.interfaces.nsIMultiplexInputStream);

  for (var i = 0; i < streams.length; i++) {
    uploadStream.appendStream(streams[i]);
  }

  return { "requestBody" : uploadStream, "boundary": BOUNDARY };
}
</pre>
 <img src="http://www.chrisfinke.com/wp-content/plugins/wordpress-feed-statistics/feed-statistics.php?view=1&post_id=1573" width="1" height="1" style="display: none;" />]]></content:encoded>
			<wfw:commentRss>http://www.chrisfinke.com/2010/01/30/uploading-form-data-and-files-with-javascript-mozilla/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Extending the Web, not just the browser, with Twitter Filter</title>
		<link>http://www.chrisfinke.com/2009/12/17/extending-the-web-not-just-the-browser-with-twitter-filter/</link>
		<comments>http://www.chrisfinke.com/2009/12/17/extending-the-web-not-just-the-browser-with-twitter-filter/#comments</comments>
		<pubDate>Thu, 17 Dec 2009 23:49:13 +0000</pubDate>
		<dc:creator>Christopher Finke</dc:creator>
				<category><![CDATA[Browser Add-ons]]></category>
		<category><![CDATA[Mozilla Firefox]]></category>
		<category><![CDATA[Twitter]]></category>
		<category><![CDATA[Twitter Filter]]></category>

		<guid isPermaLink="false">http://www.chrisfinke.com/?p=1469</guid>
		<description><![CDATA[Note: If you don't use or care about Twitter or browser extensions or the Web in general, you can safely skip the rest of this post.
One of the things that annoys me about Twitter is the constant "check-ins" from location apps like foursquare and Gowalla. Since I don't use these apps, I don't especially care [...]]]></description>
			<content:encoded><![CDATA[<p><i>Note: If you don't use or care about Twitter or browser extensions or the Web in general, you can safely skip the rest of this post.</i></p>
<p>One of the things that annoys me about Twitter is the constant "check-ins" from location apps like <a href="http://www.chrisfinke.com/wp-content/plugins/wordpress-feed-statistics/feed-statistics.php?url=aHR0cDovL2ZvdXJzcXVhcmUuY29tLw==">foursquare</a> and <a href="http://www.chrisfinke.com/wp-content/plugins/wordpress-feed-statistics/feed-statistics.php?url=aHR0cDovL2dvd2FsbGEuY29tLw==">Gowalla</a>. Since I don't use these apps, I don't especially care that you're at the Starbucks in Dallas or that you're the mayor of your bus stop.</p>
<p><img src="http://www.chrisfinke.com/files/2009/12/twitter-foursquare.png" alt="Foursquare checkins on Twitter" title="Foursquare checkins on Twitter" width="545" height="349" class="alignnone size-full wp-image-1472" /></p>
<p>To solve this problem, I wrote a browser add-on called <a href="http://www.chrisfinke.com/wp-content/plugins/wordpress-feed-statistics/feed-statistics.php?url=aHR0cHM6Ly9hZGRvbnMubW96aWxsYS5vcmcvZW4tVVMvZmlyZWZveC9hZGRvbi81NTE1OS8=">Twitter Filter</a>.  It adds a little "X" next to the source of each Twitter status update; if you click that X, you will never see updates from that source again (at least not on the Twitter website):</p>
<p><img src="http://www.chrisfinke.com/firstrun/twitterfilter-example.png" alt="8 minutes ago from foursquare (X)" /></p>
<p>The sources you've blocked are listed in Twitter's right sidebar so that you can easily unblock them:</p>
<p><img src="http://www.chrisfinke.com/firstrun/twitterfilter-blocklist.png" alt="Blocked Sources: foursquare, Gowalla" /></p>
<p>That's all there is to Twitter Filter, and it's a new type of browser add-on for me.  It has options, but no options dialogs.  There's no toolbar button, no browser sidebar -  everything related to the add-on is controlled via the Twitter Web interface, so it's not so much an extension of the browser but rather an extension of Twitter itself.  Go ahead and <a href="http://www.chrisfinke.com/wp-content/plugins/wordpress-feed-statistics/feed-statistics.php?url=aHR0cHM6Ly9hZGRvbnMubW96aWxsYS5vcmcvZW4tVVMvZmlyZWZveC9hZGRvbi81NTE1OS8=">install it</a> on a friend's computer and convince them that Twitter added the feature - it'll be fun!  Be sure to come back and recount your grand prank in the comments below.</p>
 <img src="http://www.chrisfinke.com/wp-content/plugins/wordpress-feed-statistics/feed-statistics.php?view=1&post_id=1469" width="1" height="1" style="display: none;" />]]></content:encoded>
			<wfw:commentRss>http://www.chrisfinke.com/2009/12/17/extending-the-web-not-just-the-browser-with-twitter-filter/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>TwitterBar is a winner!</title>
		<link>http://www.chrisfinke.com/2009/12/14/twitterbar-is-a-winner/</link>
		<comments>http://www.chrisfinke.com/2009/12/14/twitterbar-is-a-winner/#comments</comments>
		<pubDate>Mon, 14 Dec 2009 21:33:50 +0000</pubDate>
		<dc:creator>Christopher Finke</dc:creator>
				<category><![CDATA[Browser Add-ons]]></category>
		<category><![CDATA[Contest]]></category>
		<category><![CDATA[Mozilla Firefox]]></category>
		<category><![CDATA[TwitterBar]]></category>

		<guid isPermaLink="false">http://www.chrisfinke.com/?p=1459</guid>
		<description><![CDATA[(And so are you, for using it!)
It was announced today that TwitterBar is one of the ten winners of the Mozilla Mobile Add-on Challenge:
"After reviewing a multitude of submissions and much debate around many worthy contenders, the judges from the AMO and Mobile teams have chosen ten (10) of the “best” (innovative, useful, compatible) Firefox [...]]]></description>
			<content:encoded><![CDATA[<p>(And so are you, for using it!)</p>
<p>It was announced today that TwitterBar is one of the <a href="http://www.chrisfinke.com/wp-content/plugins/wordpress-feed-statistics/feed-statistics.php?url=aHR0cDovL21pc3Ntb2JpbGUud29yZHByZXNzLmNvbS8yMDA5LzEyLzE0L2NvbmdyYXRzLXRvLW91ci1tb2JpbGUtYWRkLW9uLWNoYWxsZW5nZS13aW5uZXJzLw==">ten winners of the Mozilla Mobile Add-on Challenge</a>:</p>
<blockquote><p>"After reviewing a multitude of submissions and much debate around many worthy contenders, the judges from the AMO and Mobile teams have chosen ten (10) of the “best” (innovative, useful, compatible) Firefox mobile add-ons. We’re very pleased to announce our winners (and thrilled to start using their add-ons soon) and award them each with a brand new <a href="http://www.chrisfinke.com/wp-content/plugins/wordpress-feed-statistics/feed-statistics.php?url=aHR0cDovL21hZW1vLm5va2lhLmNvbS9uOTAwLw==">Nokia N900</a>."</p></blockquote>
<p>I was really pleased with how the mobile version of TwitterBar turned out; I slimmed down the interface (which was already pretty slim), and I found a <a href="http://www.chrisfinke.com/wp-content/plugins/wordpress-feed-statistics/feed-statistics.php?url=aHR0cDovL2ZyZWFreWZyYW1lcy5kZXZpYW50YXJ0LmNvbS9hcnQvVHdpdHRlci1CaXJkLTEyNzc1NzIzMA==">great Twitter bird icon</a> that I modified to allow TwitterBar to have its own branding separate from Twitter:</p>
<p><img src="http://www.chrisfinke.com/firstrun/twitterbar-fennec.png" /></p>
<p>I'm planning on eventually using this same icon in the Firefox version of TwitterBar too so that there's consistent branding across the Mobile, Firefox, and <a href="http://www.chrisfinke.com/wp-content/plugins/wordpress-feed-statistics/feed-statistics.php?url=aHR0cHM6Ly9jaHJvbWUuZ29vZ2xlLmNvbS9leHRlbnNpb25zL2RldGFpbC9wYmFkZ2RnbGVwZ25ncG9laWpkZ2ljamNjb21hZGVrbQ==">Chrome versions</a> of TwitterBar.  What do you think?</p>
 <img src="http://www.chrisfinke.com/wp-content/plugins/wordpress-feed-statistics/feed-statistics.php?view=1&post_id=1459" width="1" height="1" style="display: none;" />]]></content:encoded>
			<wfw:commentRss>http://www.chrisfinke.com/2009/12/14/twitterbar-is-a-winner/feed/</wfw:commentRss>
		<slash:comments>4</slash:comments>
		</item>
	</channel>
</rss>
