<?xml version='1.0' encoding='UTF-8'?><?xml-stylesheet href="http://www.blogger.com/styles/atom.css" type="text/css"?><feed xmlns='http://www.w3.org/2005/Atom' xmlns:openSearch='http://a9.com/-/spec/opensearchrss/1.0/' xmlns:georss='http://www.georss.org/georss' xmlns:gd='http://schemas.google.com/g/2005' xmlns:thr='http://purl.org/syndication/thread/1.0'><id>tag:blogger.com,1999:blog-8501278254137514883</id><updated>2012-01-17T08:51:10.095-08:00</updated><category term='apidesign'/><category term='gwt'/><category term='musicvideo'/><category term='gears'/><category term='language'/><category term='gmaps'/><title type='text'>pamela fox's blog</title><subtitle type='html'></subtitle><link rel='http://schemas.google.com/g/2005#feed' type='application/atom+xml' href='http://blog.pamelafox.org/feeds/posts/default'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8501278254137514883/posts/default?max-results=100'/><link rel='alternate' type='text/html' href='http://blog.pamelafox.org/'/><link rel='hub' href='http://pubsubhubbub.appspot.com/'/><link rel='next' type='application/atom+xml' href='http://www.blogger.com/feeds/8501278254137514883/posts/default?start-index=101&amp;max-results=100'/><author><name>Pamela Fox</name><uri>http://www.blogger.com/profile/15947664772001597300</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><generator version='7.00' uri='http://www.blogger.com'>Blogger</generator><openSearch:totalResults>104</openSearch:totalResults><openSearch:startIndex>1</openSearch:startIndex><openSearch:itemsPerPage>100</openSearch:itemsPerPage><entry><id>tag:blogger.com,1999:blog-8501278254137514883.post-8583580362187548008</id><published>2012-01-17T08:51:00.000-08:00</published><updated>2012-01-17T08:51:10.106-08:00</updated><title type='text'>Website Monitoring Services</title><content type='html'>&lt;p&gt;After posting the iPhone app for &lt;a href="http:///www.eatdifferent.com"&gt;EatDifferent&lt;/a&gt; in the App store last week, I've seen a noticeable increase in new user signups &amp;mdash; despite the fact that there's no signup through the app itself, only through the website. That means more traffic to the App Engine hosted webapp, and unfortunately last night, it meant more traffic than my webapp was configured to handle. My webapp went over quota at around 10:30pm and served 503s until midnight, at which point the App Engine quotas reset and it started fresh. I was sleeping at the time, blissfully unaware that it was over quota, and I didn't find out until the next morning, thanks to a personal email from a friend and early user. 
&lt;/p&gt;
&lt;p&gt;
Why didn't I find out? Well, I have a lot of error logging in my app, but 503s don't actually trigger the error logging, since that logging is in the app code itself, so I didn't see any errors come through my inbox. Most webapps are like that &amp;mdash; when their host goes down, their logging goes down with it &amp;mdash; so that's why many website monitoring services exist. These services live outside of your webapp (hopefully on a different hosting system altogether), ping it every so often to make sure its returning HTTP 200s as expected, and alert you when it's not. I knew about such services, but of course, I didn't think to set myself up with one until after I needed it. You live, you learn. 
&lt;/p&gt;
&lt;p&gt;
After beating myself up for a few hours in the morning, I started investigating website monitoring services &amp;mdash; and by investigating, I mean that I asked my Twitter followers for their recommendations. Here's what they suggested:
&lt;/p&gt;
&lt;ul&gt;
 &lt;li&gt;&lt;a href="http://monitor.us/index.jsp"&gt;Monitor.us&lt;/a&gt;
 &lt;li&gt;&lt;a href="http://www.watchmouse.com/en/"&gt;WatchMouse&lt;/a&gt;
 &lt;li&gt;&lt;a href="http://www.pingdom.com/a1/"&gt;Pingdom&lt;/a&gt;
 &lt;li&gt;&lt;a href="http://www.uptimerobot.com/about.asp"&gt;UptimeRobot&lt;/a&gt;
 &lt;li&gt;&lt;a href="https://www.blamestella.com/"&gt;BlameStella&lt;/a&gt;
 &lt;li&gt;&lt;a href="http://newrelic.com/"&gt;NewRelic&lt;/a&gt;
 &lt;li&gt;&lt;a href="https://www.cloudkick.com/"&gt;CloudKick&lt;/a&gt;
&lt;/ul&gt;

&lt;p&gt;All of those services offer standard downtime monitoring, but some of them also offer performance monitoring and offer their service as an API or SaaS. For my purposes, I wanted something easy and free, and since it doesn't hurt to have multiple monitoring services, I went with UptimeRobot and a Pingdom free plan. They both offer alerts over email, SMS, and Twitter, plus Pingdom offers an Android app with push notifications. It was easy to set them up, and (its funny saying this about a service) hopefully, I will never have to hear from them... But just in case, I'm glad they're around!
&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8501278254137514883-8583580362187548008?l=blog.pamelafox.org' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.pamelafox.org/feeds/8583580362187548008/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=8501278254137514883&amp;postID=8583580362187548008' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8501278254137514883/posts/default/8583580362187548008'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8501278254137514883/posts/default/8583580362187548008'/><link rel='alternate' type='text/html' href='http://blog.pamelafox.org/2012/01/website-monitoring-services.html' title='Website Monitoring Services'/><author><name>Pamela Fox</name><uri>http://www.blogger.com/profile/15947664772001597300</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8501278254137514883.post-470232954396607515</id><published>2012-01-16T18:55:00.000-08:00</published><updated>2012-01-16T18:55:35.076-08:00</updated><title type='text'>Testing Facebook Login with Selenium</title><content type='html'>&lt;p&gt;
On &lt;a href="http://www.eatdifferent.com"&gt;EatDifferent&lt;/a&gt;, I give users two options for signing up: Facebook, for people that like the convenience of using FB to sign in everywhere, and email+password, for people that hate Facebook. I see about 50/50 usage for these options, so they are both equally important &amp;mdash; which means testing both of them are equally important.
&lt;/p&gt;
&lt;p&gt;Until today, however, I only had integration tests for email signup and login, because, well, I was afraid. All I have to do for email login testing is enter a few text fields, but for Facebook testing, I would need to navigate to the Facebook popup window and manipulate *their* DOM, and I would need a test user account that was really and a truly a test user (and not my cat, who actually is surprisingly active on Facebook). As I was making some changes that affected Facebook users today, I decided it was time to face my fears. Good thing I did, because testing Facebook login turned out to be pretty easy. Read on to see how I did it...
&lt;/p&gt;

&lt;h3&gt;Create a Test User&lt;/h3&gt;
&lt;p&gt;
In the land of old, creating a test Facebook user meant digging up an old email address and signing up with your cat's details. That kind of sucked, since you only have so many old email addresses, and it wasn't exactly Facebook TOU-friendly. Thankfully, Facebook introduced a way earlier this year to create multiple test users, both programmatically and from the developer dashboard. For the purpose of my tests, I only need one test user, so I created him semi-manually with these steps:
&lt;/p&gt;
&lt;ul&gt;
 &lt;li&gt;Go to &lt;a href="http://developers.facebook.com/apps"&gt;http://developers.facebook.com/apps&lt;/a&gt;, and select your app. Click 'Edit app' and then 'Roles' on the left-hand side. 
 &lt;li&gt;Under 'Test Users', click 'Add'. Select '1' and don't select 'Authorize this app' (if your purpose is to test authorization).
 &lt;li&gt;Once created, click 'Modify' in the 'Test Users' section. You'll see a table with information about the test user, like their name (which you can change to something snappier, like "Sharky Shark" :) and ID. 
 &lt;li&gt;Now you need to find out the user's password, so you can enter that with Selenium. First, get an access token for your app by putting this URL in the browser and replacing the client_id and client_secret with your app key and app secret: 
&lt;pre&gt;https://graph.facebook.com/oauth/access_token?client_id=APP_KEY&amp;client_secret=APP_SECRET&amp;grant_type=client_credentials&lt;/pre&gt;
 &lt;li&gt;Now paste this URL in the browser, replacing the ID with your test user ID, access_token with the string you just got, and password with your desired test password:
&lt;pre&gt;https://graph.facebook.com/TEST_USER_ID?password=TEST_PASSWORD&amp;method=post&amp;access_token=ACCESS_TOKEN&lt;/pre&gt;
 &lt;li&gt;Click 'Login' in the users table so that you're logged into Facebook as them. Visit their profile, take note of their email address, and change any desired fields (depending on what your app uses - I gave mine a profile pic and location).
&lt;/ul&gt;
&lt;p&gt;Presto, now you have a test user.&lt;/p&gt;

&lt;h3&gt;Test the Facebook Popup&lt;/h3&gt;

&lt;p&gt;For my integration tests, I use Selenium with its &lt;a href="http://selenium.googlecode.com/svn/trunk/docs/api/py/api.html"&gt;Python API&lt;/a&gt; and Python's &lt;a href="http://docs.python.org/library/unittest.html"&gt;unittest&lt;/a&gt; module. 
&lt;/p&gt;

&lt;p&gt;For my &lt;code&gt;FacebookTests&lt;/code&gt; test case, I extend my &lt;a href="https://gist.github.com/1624190"&gt;BaseTests&lt;/a&gt; class and add two test methods, one for testing authorization and the other for testing login.&lt;/p&gt;
&lt;script src="https://gist.github.com/1624226.js?file=facebook_tests.py"&gt;&lt;/script&gt;
&lt;br&gt;
&lt;p&gt;Those test methods use the &lt;code&gt;FacebookDom&lt;/code&gt; helper class (an extension of my &lt;a href="https://gist.github.com/1624214"&gt;DomHelper&lt;/a&gt; class) for finding and manipulating the Facebook window and DOM. Note that after the user has granted the authorization, Facebook will no longer ask for authorization unless the user specifically revokes it - so my &lt;code&gt;do_authorize_flow&lt;/code&gt; function checks to see if the auth button is actually there before trying to click it.
&lt;/p&gt;
&lt;script src="https://gist.github.com/1624229.js?file=facebook_dom.py"&gt;&lt;/script&gt;
&lt;br&gt;

&lt;p&gt;Ta-da, now you have a tested Facebook authorization and login flow! Some may argue that you shouldn't try to test 3rd party APIs because they may go down or be flaky or such and that you should mock them out instead, but I'm of the philosophy that integration tests should try to mimic the production environment as much as possible. And hey, I want to know if Facebook goes down, changes their response, or becomes flaky.
&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8501278254137514883-470232954396607515?l=blog.pamelafox.org' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.pamelafox.org/feeds/470232954396607515/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=8501278254137514883&amp;postID=470232954396607515' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8501278254137514883/posts/default/470232954396607515'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8501278254137514883/posts/default/470232954396607515'/><link rel='alternate' type='text/html' href='http://blog.pamelafox.org/2012/01/testing-facebook-login-with-selenium.html' title='Testing Facebook Login with Selenium'/><author><name>Pamela Fox</name><uri>http://www.blogger.com/profile/15947664772001597300</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8501278254137514883.post-7709559438749154353</id><published>2011-10-07T12:46:00.000-07:00</published><updated>2011-10-07T12:46:58.041-07:00</updated><title type='text'>Ada Lovelace Day: Women that Inspire Me</title><content type='html'>&lt;p&gt;Today is &lt;a href="http://findingada.com/"&gt;Ada Lovelace Day&lt;/a&gt;, a day to celebrate the women of math, science, and technology, and the challenge today is to write a blog post highlighting a woman that inspires us. I blogged an &lt;a href="http://blog.pamelafox.org/2009/03/ada-lovelace-tribute-q-with-my-mum.html"&gt;interview with my mum&lt;/a&gt; a few years ago (the first woman in tech I ever knew!), so this year, I thought I'd highlight a few women that inspire me today.&lt;/p&gt;

&lt;ul&gt;
   &lt;li&gt;&lt;img src="https://twimg0-a.akamaihd.net/profile_images/1550267186/Screen_shot_2011-09-19_at_12.31.26_PM_reasonably_small.png" style="float:right"&gt;&lt;b&gt;Sara Chipps:&lt;/b&gt;
&lt;p&gt;
Sara started &lt;a href="http://girldevelopit.com"&gt;GirlDevelopIt&lt;/a&gt; in New York, with the goal of getting more women in web development by actually teaching them how to do it. She inspired me to run a &lt;a href="http://www.meetup.com/girldevelopit-sydney""&gt;GirlDevelopIt in Sydney&lt;/a&gt;, and I still remember those months as some of my favorite down under. In addition to being the force behind GDI, Sara still develops - just yesterday, &lt;a href="http://www.sarajchipps.com/2011/10/add-blocker-a-solution-for-annoying-google-notifications.html"&gt;she wrote an uber-useful Chrome extension&lt;/a&gt; that I installed instantly. 
&lt;/p&gt;
&lt;p&gt;
Follow Sara online:
&lt;a href="https://twitter.com/sarajchipps"&gt;Twitter&lt;/a&gt; | &lt;a href="https://plus.google.com/103364296998918440771/posts"&gt;Google+&lt;/a&gt; | &lt;a href="http://www.sarajchipps.com/"&gt;sarajchipps.com&lt;/a&gt;
&lt;/p&gt;

 &lt;!-- &lt;li style="clear:right"&gt;&lt;img src="https://twimg0-a.akamaihd.net/profile_images/1208639395/TwitPic_reasonably_small.jpg" style="float:right"&gt; &lt;b&gt;Lukas Blakk:&lt;/b&gt; Lukas is a release engineer working in the Mozilla SF. Similar to Sarah, Lukas wants to see more women in technology -- specifically in the Python community. Lukas started &lt;a href="http://pystar.org/"&gt;PyStar&lt;/a&gt;, weekend workshops aimed at teaching Python, and in just the last 6 months, there have been workshops in 5 cities. I've helped out in the bay area workshops, and it's always rewarding and impressive to see a room of women go from newbies to programmers in a matter of hours. &lt;br&gt;
Follow Lukas online:
&lt;a href="http://twitter.com/lsblakk"&gt;Twitter&lt;/a&gt; | &lt;a href="https://plus.google.com/117791572332002155814/posts"&gt;Google+&lt;/a&gt; | &lt;a href="http://crashopensource.blogspot.com/"&gt;crashopensource.blogspot.com&lt;/a&gt; --&gt;

  &lt;li style="clear:right"&gt;&lt;img src="https://twimg0-a.akamaihd.net/profile_images/1340259468/gtrapani_wadman_2011_160_reasonably_small.jpg" style="float:right"&gt; &lt;b&gt;Gina Trapani:&lt;/b&gt;

&lt;p&gt;I first knew of Gina for starting &lt;a href="http://lifehacker.com/"&gt;lifehacker&lt;/a&gt;, a popular blog of tips for using tech and optimizing your digital life (and the biggest source of traffic for my little &lt;a href="http://lifehacker.com/231994/angry-and-need-to-cuss-try-the-profane-game"&gt;Profane Game&lt;/a&gt;). I then knew her as the author of &lt;a href="http://www.amazon.com/Complete-Guide-Google-Wave/dp/0982592604/ref=ntt_at_ep_dpt_4"&gt;"The Complete Guide to Google Wave"&lt;/a&gt;, an attempt to explain how to use Wave to the average joe. I was on the Wave team then, and I knew that was no small feat. And now, I know her as a developer, working on &lt;a href="http://thinkupapp.com/"&gt;an open-source web app&lt;/a&gt; for social media analysis. Blogger, author, coder, speaker - Gina does it all. 
&lt;/p&gt;
&lt;p&gt;
Follow Gina online: &lt;a href="https://twitter.com/ginatrapani"&gt;Twitter&lt;/a&gt; | &lt;a href="https://plus.google.com/113612142759476883204/posts"&gt;Google+&lt;/a&gt; | &lt;a href="http://ginatrapani.org/"&gt;ginatrapani.org&lt;/a&gt;
&lt;/p&gt;

 &lt;li style="clear:right"&gt;&lt;img src="https://twimg0-a.akamaihd.net/profile_images/64573331/leigh.h_200809_reasonably_small.jpg" style="float:right"&gt; &lt;b&gt;Leigh Fonseca:&lt;/b&gt;
&lt;p&gt;I met Leigh just this week,  at the &lt;a href="http://www.witi.com/center/conferences/2011/summit/nextgen.php"&gt;WITI Next-Gen Summit&lt;/a&gt;, where Leigh and I talked to high school girls about how we got into tech and why we love it. Leigh started off with a history degree, but when she realized she had a thing for analyzing customer data, she started data science departments at Rhapsody and then BookRenter, where she is now. Most companies don't have data scientists nor realize they need one, so Leigh is paving the way for others with her interest. When she's not analyzing data, she's preparing for triathlons. Impressive. 
&lt;/p&gt;
&lt;p&gt;
Follow Leigh online: &lt;a href="https://twitter.com/missleigh"&gt;Twitter&lt;/a&gt; | &lt;a href="https://plus.google.com/115970934954469680539/posts"&gt;Google+&lt;/a&gt; | &lt;a href="http://dataparty.blogspot.com/"&gt;dataparty.blogspot.com&lt;/a&gt;
&lt;/p&gt;
 &lt;li style="clear:right"&gt;&lt;b&gt;Kendall Ronzano:&lt;/b&gt;
&lt;p&gt;I also met Kendall this week - she's actually one of the girls that Leigh and I talked to at the conference. She's a high school junior who's already started programming for her robotics team (C++!) and wants to learn more. She's also set a fun challenge for herself: &lt;a href="http://nerdgirlhomes.wordpress.com/"&gt;build a house&lt;/a&gt;. I hope Kendall represents the next generation of women in tech! 
&lt;/p&gt;
&lt;/ul&gt;

&lt;p&gt;So, who inspires you?&lt;/p&gt;
&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8501278254137514883-7709559438749154353?l=blog.pamelafox.org' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.pamelafox.org/feeds/7709559438749154353/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=8501278254137514883&amp;postID=7709559438749154353' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8501278254137514883/posts/default/7709559438749154353'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8501278254137514883/posts/default/7709559438749154353'/><link rel='alternate' type='text/html' href='http://blog.pamelafox.org/2011/10/ada-lovelace-4-inspiring-women-in-tech.html' title='Ada Lovelace Day: Women that Inspire Me'/><author><name>Pamela Fox</name><uri>http://www.blogger.com/profile/15947664772001597300</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8501278254137514883.post-8186215950757419936</id><published>2011-08-03T21:16:00.000-07:00</published><updated>2011-08-03T21:39:03.334-07:00</updated><title type='text'>WDCNZ: The Developer Experience</title><content type='html'>&lt;p&gt;Last month, I had the honor of giving the first talk of the day at &lt;a href="http://wdcnz.com/"&gt;WDCNZ&lt;/a&gt;, a new conference in Wellington, New Zealand. WDCNZ was the brainchild of &lt;a href="https://twitter.com/#!/buildmaster"&gt;Owen Evans&lt;/a&gt;, one of the lead developers at Xero, and his goal in putting it together was to provide a full day of technical talks for web developers and to bring the local web development community together. I wanted to give a talk that would be interesting to web developers of all different sorts, and also would be something I'm passionate about myself - so I decided to give a talk around a topic I wrote a &lt;a href="http://developer-support-handbook.org"&gt;handbook about&lt;/a&gt; and discussed in &lt;a href="http://blog.pamelafox.org/2011/05/roundup-developer-documentation.html"&gt;recent blog posts&lt;/a&gt; - "The Developer Experience." 
&lt;/p&gt;
&lt;p&gt;For my talk, I wanted to explain what I think of as "developer experience", motivate people to really care about it, and give concrete examples of what makes for a great experience. It was an interesting talk to prepare and give, and hopefully gets other people thinking about the topic and giving similar talks in the future. I've embedded the slides and video below so you can watch for yourself what I said. Thank you to WDCNZ for giving me the opportunity to give the talk and for an awesome conference!
&lt;/p&gt;
&lt;p&gt;&lt;a href="http://www.slideshare.net/wuzziwug/developer-experience" title="The Developer Experience" target="_blank"&gt;The Developer Experience (Slides)&lt;/a&gt;&lt;/p&gt;
&lt;iframe src="http://www.slideshare.net/slideshow/embed_code/8589212" width="425" height="355" frameborder="0" marginwidth="0" marginheight="0" scrolling="no"&gt;&lt;/iframe&gt;

&lt;p&gt;&lt;a href="http://vimeo.com/27216846"&gt;The Developer Experience&lt;/a&gt; from &lt;a href="http://vimeo.com/user7782032"&gt;WDCNZ&lt;/a&gt; on &lt;a href="http://vimeo.com"&gt;Vimeo&lt;/a&gt;.&lt;/p&gt;
&lt;iframe src="http://player.vimeo.com/video/27216846?title=0&amp;amp;byline=0&amp;amp;portrait=0" width="400" height="225" frameborder="0"&gt;&lt;/iframe&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8501278254137514883-8186215950757419936?l=blog.pamelafox.org' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.pamelafox.org/feeds/8186215950757419936/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=8501278254137514883&amp;postID=8186215950757419936' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8501278254137514883/posts/default/8186215950757419936'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8501278254137514883/posts/default/8186215950757419936'/><link rel='alternate' type='text/html' href='http://blog.pamelafox.org/2011/08/wdcnz-developer-experience.html' title='WDCNZ: The Developer Experience'/><author><name>Pamela Fox</name><uri>http://www.blogger.com/profile/15947664772001597300</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8501278254137514883.post-8270546032999709951</id><published>2011-05-16T12:03:00.000-07:00</published><updated>2011-05-16T12:08:46.400-07:00</updated><title type='text'>So, what am I, exactly?</title><content type='html'>&lt;p&gt;
Lately I have struggled to find a good answer to the question "So, what are you?". When I was a kid, nobody asked me that - I was just a kid. At the most, they'd ask me what grade I was in, and that was easy. Then, in my first (and only) job at Google, when people asked me that, I could answer with my job title. But now that I'm not a kid or a Google employee, I'm not quite sure what I am. 
&lt;/p&gt;
&lt;p&gt;
My standard response has been "web developer." I do web development, I go to all the web development events, and all the people I helped as a Googler were web developers. But I'm not convinced, and I become less convinced the more I am approached by people looking for "web developers" thinking that I fit the bill. I know this doesn't bode well for my job opportunities in the future, but I don't think I'm actually a "web developer", at least not the kind they are looking for.
&lt;/p&gt;
&lt;p&gt;
See, when I do web development, I do it because it is the best way that I know to turn an idea into something tangible; I don't do it purely for the joy of programming. I don't dream of spending all day coding, I dream instead of making things that I enjoy, and maybe a few others too. In fact, I don't think I would be happy spending all day programming for months on end; I like too many other aspects of making things. I want to write about them, I want to brainstorm them, I want to tell the world about them. I want to spend equal parts of my life using the different parts of my brain, and I want to be able to share creations with the world as a result of that synergy.
&lt;/p&gt;
&lt;p&gt;
Why does it matter what I am, anyway? Well, first, I need an answer for all the people that I meet now, who want to be able to fit me into a nice bucket in their head. But, second, I need to figure out what I'm doing next in life. If I am a web developer, then I should probably join a new company, learn more web skills, and increase my knowledge there. But if I am not - and I suspect as much - maybe I should be picking a different path. I have done many side projects, and now it might be time for me to pick an idea and make it my main project, to see how far I can take it and how many people I can share it with. Or, put in the more usual terms of today's web world, perhaps I should become a (co-)founder.
&lt;/p&gt;
&lt;p&gt;
I am not 100% sure of this - part of me is worried that I don't have the focus to pick one idea and stay with it, part of me is worried that I'll pick the wrong idea, and part of me is worried that I'm not business-oriented enough to make something profitable. But the other part of me thinks that I should find out or I risk spending the rest of my life wondering.
&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8501278254137514883-8270546032999709951?l=blog.pamelafox.org' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.pamelafox.org/feeds/8270546032999709951/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=8501278254137514883&amp;postID=8270546032999709951' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8501278254137514883/posts/default/8270546032999709951'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8501278254137514883/posts/default/8270546032999709951'/><link rel='alternate' type='text/html' href='http://blog.pamelafox.org/2011/05/so-what-am-i-exactly.html' title='So, what am I, exactly?'/><author><name>Pamela Fox</name><uri>http://www.blogger.com/profile/15947664772001597300</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8501278254137514883.post-4577447356312300378</id><published>2011-05-13T10:34:00.000-07:00</published><updated>2011-05-13T10:44:35.718-07:00</updated><title type='text'>Reading My Way to Better Design</title><content type='html'>&lt;p&gt;I realized recently that I am completely capable of coding up a website frontend, but I struggle to make that website frontend look really good. My webdesign tends to be either too simple (“austere” is how one observer described it) or too tacky (my love for everything 80s seeps into all parts of my life). I was okay with this before when I was just making developer-facing demos, but now I’m at a stage where I want to make user-facing webapps, and I want the users to experience them and think “Wow, slick.” 
&lt;/p&gt;
&lt;p&gt;
So, I’ve set out to acquire a better taste in design, and I decided one way to do that is to surround myself on a daily basis with examples of great design. After Google’ing around and reading this &lt;a href="http://news.ycombinator.com/item?id=1103578)"&gt;HackerNews thread&lt;/a&gt;, I set up a folder in my Google Reader of 10 design-related blogs, and I now spend every morning reading through the posts (after drooling over my &lt;a href="http://www.primalpaleorecipes.com/#feed"&gt;recipes feed&lt;/a&gt;, of course). It’s a great mix of topics, ranging from web design how-tos to well-designed physical products. It's hard for me to quantify if my design skills are improving, but I am at least thinking much more about it than before and acknowledging its importance.
&lt;/p&gt;
&lt;p&gt;
If you want to do the same as me, you can subscribe to my &lt;a href="http://www.google.com/reader/atom/user%2F00961344416250096177%2Flabel%2Fwebdesign"&gt;folder feed&lt;/a&gt; or subscribe to the individual blogs listed below:
&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href='http://www.alistapart.com/articles/'&gt;A List Apart&lt;/a&gt; (&lt;a href='http://www.alistapart.com/site/rss'&gt;RSS&lt;/a&gt;)
&lt;li&gt;&lt;a href='http://www.brainpickings.org/'&gt;Brain Pickings&lt;/a&gt; (&lt;a href='http://feedproxy.google.com/brainpickings/rss'&gt;RSS&lt;/a&gt;)
&lt;li&gt;&lt;a href='http://ilovetypography.com/'&gt;I love typography&lt;/a&gt; (&lt;a href='http://feeds.feedburner.com/ILoveTypography'&gt;RSS&lt;/a&gt;)
&lt;li&gt;&lt;a href='http://logo.himalayasart.cn/en/'&gt;Logo Design Love&lt;/a&gt; (&lt;a href='http://feeds.feedburner.com/logodesignlove'&gt;RSS&lt;/a&gt;)
&lt;li&gt;&lt;a href='http://noisydecentgraphics.typepad.com/design/'&gt;Noisy Decent Graphics&lt;/a&gt; (&lt;a href='http://noisydecentgraphics.typepad.com/design/atom.xml'&gt;RSS&lt;/a&gt;)
&lt;li&gt;&lt;a href='http://www.smashingmagazine.com/'&gt;Smashing Magazine&lt;/a&gt; (&lt;a href='http://rss1.smashingmagazine.com/feed/'&gt;RSS&lt;/a&gt;)
&lt;li&gt;&lt;a href='http://www.swiss-miss.com/'&gt;swissmiss&lt;/a&gt; (&lt;a href='http://www.swiss-miss.com/feed'&gt;RSS&lt;/a&gt;)
&lt;li&gt;&lt;a href='http://ui-patterns.com/'&gt;UI-patterns.com&lt;/a&gt; (&lt;a href='http://feeds.feedburner.com/UI-patterns-com'&gt;RSS&lt;/a&gt;)
&lt;li&gt;&lt;a href='http://uxmovement.com/'&gt;UX Movement&lt;/a&gt; (&lt;a href='http://feeds.feedburner.com/uxmovement'&gt;RSS&lt;/a&gt;)
&lt;/ul&gt;

&lt;p&gt;Please let me know in the comments if you have other suggestions for great blogs to read (and books too, while you’re at it).
&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8501278254137514883-4577447356312300378?l=blog.pamelafox.org' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.pamelafox.org/feeds/4577447356312300378/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=8501278254137514883&amp;postID=4577447356312300378' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8501278254137514883/posts/default/4577447356312300378'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8501278254137514883/posts/default/4577447356312300378'/><link rel='alternate' type='text/html' href='http://blog.pamelafox.org/2011/05/reading-my-way-to-better-design.html' title='Reading My Way to Better Design'/><author><name>Pamela Fox</name><uri>http://www.blogger.com/profile/15947664772001597300</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8501278254137514883.post-3325976099643254943</id><published>2011-05-11T05:59:00.000-07:00</published><updated>2011-05-11T06:13:06.842-07:00</updated><title type='text'>No, Really, I'm Shy: My Ignite I/O Talk</title><content type='html'>&lt;p&gt;As many of you know, I'm kind of an &lt;a href="http://www.pamelafox.org/talks?q=ignite"&gt;Ignite&lt;/a&gt; junkie. I love the format - 5 minutes, 20 slides, 15 seconds auto-advance - and I love that I can use that format to talk about topics that I can't fill a whole hour with. At this year's Google I/O 2011 Ignite show, I got to give a talk on something that I think about a lot: my shyness. Most people don't believe me when I tell I am actually quite shy at my core, and so I dedicated my five minutes to explaining what shyness is to me and how I workaround it. The talk went well, and multiple folks approached me afterwards about their own shyness and hacks around it. Mission accomplished!
&lt;/p&gt;
&lt;p&gt;
You can watch &lt;a href="http://www.youtube.com/watch?v=52Ml_zax4A0&amp;t=24m9s"&gt;the video&lt;/a&gt; on Youtube - I'm at 24:09:
&lt;/p&gt;
&lt;object width="560" height="349"&gt;&lt;param name="movie" value="http://www.youtube.com/v/52Ml_zax4A0?fs=1&amp;amp;hl=en_US&amp;amp;start=1449"&gt;&lt;/param&gt;&lt;param name="allowFullScreen" value="true"&gt;&lt;/param&gt;&lt;param name="allowscriptaccess" value="always"&gt;&lt;/param&gt;&lt;param name="start" value="1449"&gt;&lt;/param&gt;&lt;embed src="http://www.youtube.com/v/52Ml_zax4A0?fs=1&amp;amp;hl=en_US&amp;amp;start=1449" type="application/x-shockwave-flash" width="560" height="349" allowscriptaccess="always" allowfullscreen="true"&gt;&lt;/embed&gt;&lt;/object&gt;
&lt;p&gt;
And/or you can read &lt;a href="http://www.slideshare.net/wuzziwug/no-really-im-shy"&gt;the slides&lt;/a&gt; on Slideshare:
&lt;/p&gt;
&lt;div style="width:425px" id="__ss_7924097"&gt; &lt;strong style="display:block;margin:12px 0 4px"&gt;&lt;a href="http://www.slideshare.net/wuzziwug/no-really-im-shy" title="No, Really, I&amp;#39;m Shy"&gt;No, Really, I&amp;#39;m Shy&lt;/a&gt;&lt;/strong&gt; &lt;iframe src="http://www.slideshare.net/slideshow/embed_code/7924097" width="425" height="355" frameborder="0" marginwidth="0" marginheight="0" scrolling="no"&gt;&lt;/iframe&gt;
&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8501278254137514883-3325976099643254943?l=blog.pamelafox.org' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.pamelafox.org/feeds/3325976099643254943/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=8501278254137514883&amp;postID=3325976099643254943' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8501278254137514883/posts/default/3325976099643254943'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8501278254137514883/posts/default/3325976099643254943'/><link rel='alternate' type='text/html' href='http://blog.pamelafox.org/2011/05/no-really-im-shy-my-ignite-io-talk.html' title='No, Really, I&apos;m Shy: My Ignite I/O Talk'/><author><name>Pamela Fox</name><uri>http://www.blogger.com/profile/15947664772001597300</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8501278254137514883.post-3828093423427689317</id><published>2011-05-06T15:43:00.000-07:00</published><updated>2011-05-06T16:38:00.230-07:00</updated><title type='text'>Roundup: Developer Documentation Generators</title><content type='html'>&lt;style&gt;
table.docs td, th {
  border-bottom: 1px solid #ccc;
}
&lt;/style&gt;
&lt;p&gt;While researching what developers love about their favorite API documentation sets for &lt;a href="http://blog.pamelafox.org/2011/05/roundup-developer-documentation.html"&gt;my last post&lt;/a&gt;, I also investigated what tools the API teams use to generate the documentation. Some teams just hand-write HTML, but most use code-based generators for the references and/or some sort of markdown for writing the guides. A good tool or toolset should make it easy to update the reference for every API release (outdated documentation should be avoided at all costs) and painless to write documentation about how to use the API (writing is one of those tasks that people put off - the less obstacles there are, the better). Based on my experience, here are the questions you should be asking when picking a tool:
&lt;/p&gt;
&lt;ul&gt;
  &lt;li&gt;&lt;b&gt;What is the input for the tool?&lt;/b&gt;
    &lt;ul&gt;
     &lt;li&gt;&lt;b&gt;Does it run over code and/or supplementary files?&lt;/b&gt; It's great to use a tool to automate your reference generation, but even better if you can use the same tool to write your developer's guide as well.
     &lt;li&gt;&lt;b&gt;What languages will it process?&lt;/b&gt; If your API is written in multiple languages (like &lt;a href="http://flurry.com"&gt;Flurry&lt;/a&gt;, the company I did this research for), you probably want to pick a tool that will work over all of them so you can have a consistent process and output.
     &lt;li&gt;&lt;b&gt;What style of comments does it parse?&lt;/b&gt; If you're already using comments to instruct your compiler, you won't want to use a different format just for the docs.
    &lt;/ul&gt;
  &lt;li&gt;&lt;b&gt;What is the output for the tool?&lt;/b&gt; HTML is a must, even better if it can do multi-page and single-page. PDF and other formats can also be quite useful.
  &lt;li&gt;&lt;b&gt;What is it written in?&lt;/b&gt; It needs to work in your development environment, and ideally hook into your build system.
  &lt;li&gt;&lt;b&gt;How easy is it to customize for your needs?&lt;/b&gt; The ideal tool includes easy customization options that don't require digging into the code, but is also open-source in case they don't do it for you.
&lt;/ul&gt;

&lt;p&gt;To give you an idea of (just a fraction of) what's out there, here is a breakdown of the documentation tools used by the APIs from the last post.&lt;/p&gt;

&lt;p&gt;&amp;nbsp;&lt;/p&gt;

&lt;h3&gt;Multi-Language Generators&lt;/h3&gt;

&lt;table class="docs"&gt;
 &lt;thead&gt;
  &lt;tr&gt;&lt;th&gt;Tool&lt;/th&gt;&lt;th&gt;Input files&lt;/th&gt;&lt;th&gt;Input language&lt;/th&gt;&lt;th&gt;Input comments&lt;/th&gt;&lt;th&gt;Output&lt;/th&gt;&lt;th&gt;Written in?&lt;/th&gt;&lt;th&gt;Examples&lt;/th&gt;
  &lt;/tr&gt;
  &lt;thead&gt;
  &lt;tbody&gt;
&lt;tr&gt;&lt;td&gt;&lt;a href='http://www.naturaldocs.org/'&gt;Natural Docs&lt;/a&gt;&lt;/td&gt;&lt;td&gt;In code or other files&lt;/td&gt;&lt;td&gt;C#, Perl, AS2, partial support for &lt;a href="http://www.naturaldocs.org/languages.html"&gt;other languages&lt;/a&gt;.&lt;/td&gt;&lt;td&gt;JavaDoc, or custom "natural syntax"&lt;/td&gt;&lt;td&gt;HTML&lt;/td&gt;&lt;td&gt;Perl&lt;/td&gt;&lt;td&gt;&lt;a href="http://www.jqplot.com/docs/files/usage-txt.html"&gt;jqPlot&lt;/a&gt;, &lt;a href="http://www.naturaldocs.org/users.html"&gt;Users list&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;&lt;a href='http://www.stack.nl/~dimitri/doxygen/index.html'&gt;Doxygen&lt;/a&gt;&lt;/td&gt;&lt;td&gt;In code or other files&lt;/td&gt;&lt;td&gt;C++, C, Java, Objective-C, Python, IDL, Fortran, VHDL, PHP, C#&lt;/td&gt;&lt;td&gt;JavaDoc or QT style, with some support for other styles&lt;/td&gt;&lt;td&gt;HTML, TEX, RTF, PS, PDF, ...&lt;/td&gt;&lt;td&gt;C++&lt;/td&gt;&lt;td&gt;&lt;a href="http://api.kde.org/"&gt;KDE&lt;/a&gt;, &lt;a href="http://www.stack.nl/~dimitri/doxygen/projects.html"&gt;Users list&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;&lt;a href='http://jashkenas.github.com/docco/'&gt;docco&lt;/a&gt;&lt;/td&gt;&lt;td&gt;In code&lt;/td&gt;&lt;td&gt;CoffeeScript, JS, Ruby, Python&lt;/td&gt;&lt;td&gt;Markdown&lt;/td&gt;&lt;td&gt;HTML&lt;/td&gt;&lt;td&gt;CoffeeScript&lt;/td&gt;&lt;td&gt;&lt;a href="http://quasipartikel.at/data-js/"&gt;data.js&lt;/a&gt; and &lt;a href="http://cloudapp.github.com/engine/"&gt;drops.coffee&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;&lt;a href='http://sphinx.pocoo.org/'&gt;Sphinx&lt;/a&gt;&lt;/td&gt;&lt;td&gt;In code or other files&lt;/td&gt;&lt;td&gt;Python, C/C++&lt;/td&gt;&lt;td&gt;RST&lt;/td&gt;&lt;td&gt;HTML, TEX, PDF&lt;/td&gt;&lt;td&gt;Python&lt;/td&gt;&lt;td&gt;&lt;a href="http://docs.python.org/library/string.html"&gt;Python&lt;/a&gt;, &lt;a href="http://docs.djangoproject.com"&gt;Django&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;&lt;a href='https://doc.php.net/php/dochowto/docbook-refs.php'&gt;DocBook&lt;/a&gt;&lt;/td&gt;&lt;td&gt;Generated from XML files&lt;/td&gt;&lt;td&gt;XML&lt;/td&gt;&lt;td&gt;&lt;/td&gt;&lt;td&gt;HTML, PDF, CHM, RTF, ...&lt;/td&gt;&lt;td&gt;PHP&lt;/td&gt;&lt;td&gt;&lt;a href="http://www.php.net/manual/en/function.fopen.php"&gt;PHP.net&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;
  &lt;/tbody&gt;
&lt;/table&gt;

&lt;p&gt;&amp;nbsp;&lt;/p&gt;

&lt;h3&gt;Single Language Generators&lt;/h3&gt;

&lt;table class="docs"&gt;
 &lt;thead&gt;
  &lt;tr&gt;&lt;th&gt;Tool&lt;/th&gt;&lt;th&gt;Input files&lt;/th&gt;&lt;th&gt;Input language&lt;/th&gt;&lt;th&gt;Input comments&lt;/th&gt;&lt;th&gt;Output&lt;/th&gt;&lt;th&gt;Written in?&lt;/th&gt;&lt;th&gt;Examples&lt;/th&gt;
  &lt;/tr&gt;
  &lt;thead&gt;
  &lt;tbody&gt;
&lt;tr&gt;&lt;td&gt;&lt;a href='http://www.oracle.com/technetwork/java/javase/documentation/index-jsp-135444.html'&gt;JavaDoc&lt;/a&gt;&lt;/td&gt;&lt;td&gt;In code&lt;/td&gt;&lt;td&gt;Java&lt;/td&gt;&lt;td&gt;JavaDoc&lt;/td&gt;&lt;td&gt;HTML&lt;/td&gt;&lt;td&gt;Java&lt;/td&gt;&lt;td&gt;&lt;a href="http://developer.android.com/reference/packages.html"&gt;Android&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;&lt;a href='https://github.com/davebalmer/joDoc#readme'&gt;joDoc&lt;/a&gt;&lt;/td&gt;&lt;td&gt;In code or other files&lt;/td&gt;&lt;td&gt;JS&lt;/td&gt;&lt;td&gt;Markdown&lt;/td&gt;&lt;td&gt;HTML&lt;/td&gt;&lt;td&gt;Perl&lt;/td&gt;&lt;td&gt;&lt;a href="http://docs.phonegap.com/"&gt;PhoneGap&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;&lt;a href='https://github.com/micmath/jsdoc'&gt;JSDoc 3&lt;/a&gt;&lt;/td&gt;&lt;td&gt;In code&lt;/td&gt;&lt;td&gt;JS&lt;/td&gt;&lt;td&gt;JSDoc&lt;/td&gt;&lt;td&gt;HTML&lt;/td&gt;&lt;td&gt;Java/JS&lt;/td&gt;&lt;td&gt;None yet, in beta.&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;&lt;a href='http://code.google.com/p/jsdoc-toolkit/'&gt;JSDoc 2 (JsDoc-toolkit)&lt;/a&gt;&lt;/td&gt;&lt;td&gt;In code&lt;/td&gt;&lt;td&gt;JS&lt;/td&gt;&lt;td&gt;JSDoc&lt;/td&gt;&lt;td&gt;HTML&lt;/td&gt;&lt;td&gt;Java/JS&lt;/td&gt;&lt;td&gt;&lt;a href='http://code.google.com/apis/maps/documentation/javascript/reference.html'&gt;Google Maps API v3&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;&lt;a href='https://github.com/nene/jsduck'&gt;JSDuck&lt;/a&gt;&lt;/td&gt;&lt;td&gt;In code&lt;/td&gt;&lt;td&gt;JS&lt;/td&gt;&lt;td&gt;Markdown, HTML, some JSDoc tags&lt;/td&gt;&lt;td&gt;HTML&lt;/td&gt;&lt;td&gt;Ruby&lt;/td&gt;&lt;td&gt;&lt;a href="http://docs.sencha.com/ext-js/4-0/api"&gt;Ext-JS 4&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;&lt;a href='https://github.com/daleharvey/erldocs'&gt;ErlDocs&lt;/a&gt;&lt;/td&gt;&lt;td&gt;In code&lt;/td&gt;&lt;td&gt;Erlang&lt;/td&gt;&lt;td&gt;&lt;/td&gt;&lt;td&gt;HTML&lt;/td&gt;&lt;td&gt;Erlang&lt;/td&gt;&lt;td&gt;&lt;a href="http://erldocs.com/"&gt;ErlDocs.com&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;
  &lt;/tbody&gt;
&lt;/table&gt;

&lt;p&gt;&amp;nbsp;&lt;/p&gt;

&lt;p&gt;If you're interested in exploring tools further, check out the &lt;a href="http://www.developer-support-handbook.org/documentation.html#generation"&gt;Documentation Generators section&lt;/a&gt; of my Developer Support handbook and this &lt;a href="http://en.wikipedia.org/wiki/Comparison_of_documentation_generators"&gt;nearly comprehensive comparison&lt;/a&gt; of documentation generators from Wikipedia. There are always new tools being built out there by developers not quite satisfied by the current offerings and going at it their own way - and that's a great thing for all of us.
&lt;/p&gt;

&lt;/p&gt;Let me know in the comments what tools you use (or are building yourself!) and your experience with them.&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8501278254137514883-3828093423427689317?l=blog.pamelafox.org' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.pamelafox.org/feeds/3828093423427689317/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=8501278254137514883&amp;postID=3828093423427689317' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8501278254137514883/posts/default/3828093423427689317'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8501278254137514883/posts/default/3828093423427689317'/><link rel='alternate' type='text/html' href='http://blog.pamelafox.org/2011/05/roundup-developer-documentation_06.html' title='Roundup: Developer Documentation Generators'/><author><name>Pamela Fox</name><uri>http://www.blogger.com/profile/15947664772001597300</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8501278254137514883.post-5822347178479991064</id><published>2011-05-05T10:08:00.000-07:00</published><updated>2011-05-05T16:22:11.930-07:00</updated><title type='text'>Roundup: The Best Developer Docs</title><content type='html'>&lt;style&gt;
table.docs td {
  border-bottom: 1px solid #ccc;
}
&lt;/style&gt;

&lt;p&gt;As I mentioned in my previous post on &lt;a href="http://blog.pamelafox.org/2011/04/what-makes-good-developer-experience.html"&gt;"What makes a good Developer Experience?"&lt;/a&gt;, I'm currently consulting with &lt;a href="http://www.flurry.com/"&gt;Flurry&lt;/a&gt; to advise them on improving their developer experience. They're starting with a revamp of their documentation and API reference. Per what I wrote in the &lt;a href="http://www.developer-support-handbook.org/documentation.html"&gt;Documentation chapter&lt;/a&gt; from the &lt;a href="http://www.developer-support-handbook.org/"&gt;Developer Support Handbook&lt;/a&gt;, good documentation should include tutorial style content, an API reference, and sample code, and should be fully linkable and searchable.
&lt;/p&gt;
&lt;p&gt;
To confirm that my criteria for good docs aligns with what developers in the wild think, I conducted an informal survey on Twitter asking developers for their favorite and least favorite docs. I reviewed their picks, and as I guessed, here's what was common amongst the favorites:
&lt;/p&gt;
&lt;ul&gt;
 &lt;li&gt;&lt;b&gt;Easy navigation:&lt;/b&gt; everything linked, clear table of contents, every page just takes 1-2 clicks to get to. Example: &lt;a href="http://www.yiiframework.com/doc/api/"&gt;Yii&lt;/a&gt;.
 &lt;li&gt;&lt;b&gt;Easy search:&lt;/b&gt;. prominent search box with autocomplete for method/class names. Example: &lt;a href="http://dev.sencha.com/deploy/ext-4.0.0/docs/"&gt;Sencha&lt;/a&gt;.
 &lt;li&gt;&lt;b&gt;Reference *and* guide:&lt;/b&gt; most offer both a technical breakdown of every part of the API (the reference) as well as a step-by-step narrative guide for using the API. Example:  &lt;a href="http://www.twilio.com/docs/"&gt;Twilio&lt;/a&gt;.
 &lt;li&gt;&lt;b&gt;Inline code samples:&lt;/b&gt; in the reference, every class/method comes with example code below the definition, and sometimes that code can even be run in the browser. (Or for HTTP APIs, sample request and responses in every data format are offered). Example: &lt;a href="http://jashkenas.github.com/coffee-script/#splats"&gt;CoffeeScript&lt;/a&gt;.
 &lt;li&gt;&lt;b&gt;Comments&lt;/b&gt;: a threaded comment system on every page, for developers to discuss issues or usage. Example: &lt;a href="http://api.jquery.com/addClass/"&gt;jQuery&lt;/a&gt;.
&lt;/ul&gt;

&lt;p&gt;And here are some cool bonus features from the favorites (that may not work for everyone):&lt;/p&gt;
&lt;ul&gt;
 &lt;li&gt;&lt;b&gt;Community edits&lt;/b&gt;: The &lt;a href="https://developer.mozilla.org/en-US/"&gt;Mozilla Developer Center&lt;/a&gt; lets anyone login and edit the information themselves.
 &lt;li&gt;&lt;b&gt;Feedback loop&lt;/b&gt;: The &lt;a href="http://docs.phonegap.com/"&gt;PhoneGap docs&lt;/a&gt; prompt the developers to give them feedback on every page, and they use that to improve the docs.
&lt;/ul&gt;

&lt;p&gt;Many of the favorites are written by the engineers themselves, which likely keeps them more up to date and accurate (and proves that engineers can write!).
&lt;/p&gt;

&lt;p&gt;The least favorite documentation sets typically suffer from basic usability issues, like lack of search or deep links. When you're writing documentation, you need to remember that your developers won't benefit from it unless they can find it - searchability and linkability should be a top priority.
&lt;/p&gt;

&lt;p&gt;I've rounded up the documentation sets in the tables below, with links, short description (including how they were generated, if known), and a thumbnail. I've also embedded a slideshow of the screenshots. Feel free to comment with your own opinions on what makes for a great set of developer docs!&lt;/p&gt;
&lt;/p&gt;

&lt;h3&gt;Screenshots&lt;/h3&gt;
&lt;br&gt;
&lt;object width="400" height="300"&gt; &lt;param name="flashvars" value="offsite=true&amp;lang=en-us&amp;page_show_url=%2Fphotos%2Fpamelafox%2Fsets%2F72157626654113484%2Fshow%2F&amp;page_show_back_url=%2Fphotos%2Fpamelafox%2Fsets%2F72157626654113484%2F&amp;set_id=72157626654113484&amp;jump_to="&gt;&lt;/param&gt; &lt;param name="movie" value="http://www.flickr.com/apps/slideshow/show.swf?v=71649"&gt;&lt;/param&gt; &lt;param name="allowFullScreen" value="true"&gt;&lt;/param&gt;&lt;embed type="application/x-shockwave-flash" src="http://www.flickr.com/apps/slideshow/show.swf?v=71649" allowFullScreen="true" flashvars="offsite=true&amp;lang=en-us&amp;page_show_url=%2Fphotos%2Fpamelafox%2Fsets%2F72157626654113484%2Fshow%2F&amp;page_show_back_url=%2Fphotos%2Fpamelafox%2Fsets%2F72157626654113484%2F&amp;set_id=72157626654113484&amp;jump_to=" width="400" height="300"&gt;&lt;/embed&gt;&lt;/object&gt;
&lt;br&gt;
&lt;br&gt;

&lt;h3&gt;Rave Reviews&lt;/h3&gt;

&lt;p&gt;Ordered by popularity, these documentation sets received all positive reviews. Great work!&lt;/p&gt;

&lt;table class="docs"&gt;
&lt;tr&gt;&lt;td&gt;&lt;a href='http://docs.jquery.com/Main_Page'&gt;jQuery&lt;/a&gt;&lt;/td&gt;&lt;td&gt;&lt;ul&gt;&lt;li&gt;One page for each method. Includes code examples and discussion.&lt;li&gt;Manually written.&lt;/ul&gt;&lt;/td&gt;&lt;td&gt;&lt;a href="http://www.flickr.com/photos/pamelafox/5690334841/" title="jQuery by fkedupmonkey, on Flickr"&gt;&lt;img src="http://farm6.static.flickr.com/5186/5690334841_03dd831ab3_t.jpg" width="100" height="87" alt="jQuery"&gt;&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;&lt;a href='http://docs.djangoproject.com/en/1.3/'&gt;Django&lt;/a&gt;&lt;/td&gt;&lt;td&gt;&lt;ul&gt;&lt;li&gt;One page for each topic, narrative tutorial-like structure.&lt;li&gt;Generated with RST and Sphinx, &lt;a href="http://docs.djangoproject.com/en/1.3/internals/documentation/"&gt;More info here&lt;/a&gt;.&lt;/ul&gt;&lt;/td&gt;&lt;td&gt;&lt;a href="http://www.flickr.com/photos/pamelafox/5690590333/" title="docs_django by fkedupmonkey, on Flickr"&gt;&lt;img src="http://farm6.static.flickr.com/5307/5690590333_17cc15d861_t.jpg" width="100" height="84" alt="docs_django"&gt;&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;&lt;a href='http://www.php.net/manual/en/'&gt;PHP&lt;/a&gt;&lt;/td&gt;&lt;td&gt;&lt;ul&gt;&lt;li&gt;One page for each method, includes examples and comments.&lt;li&gt;Generated with DocBook (XML), &lt;a href="https://doc.php.net/php/dochowto/chapter-framework.php"&gt;More info here&lt;/a&gt;.&lt;/ul&gt;&lt;/td&gt;&lt;td&gt;&lt;a href="http://www.flickr.com/photos/pamelafox/5691165044/" title="docs_php by fkedupmonkey, on Flickr"&gt;&lt;img src="http://farm6.static.flickr.com/5182/5691165044_585e20451b_t.jpg" width="100" height="91" alt="docs_php"&gt;&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;&lt;a href='http://jashkenas.github.com/coffee-script/'&gt;CoffeeScript&lt;/a&gt;&lt;/td&gt;&lt;td&gt;&lt;ul&gt;&lt;li&gt;One page developer's guide with interactive code examples in each section.&lt;/ul&gt;&lt;/td&gt;&lt;td&gt;&lt;a href="http://www.flickr.com/photos/pamelafox/5690335059/" title="CoffeeScript by fkedupmonkey, on Flickr"&gt;&lt;img src="http://farm6.static.flickr.com/5145/5690335059_21ea4302b0_t.jpg" width="100" height="95" alt="CoffeeScript"&gt;&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;&lt;a href='http://www.twilio.com/docs/'&gt;Twilio&lt;/a&gt;&lt;/td&gt;&lt;td&gt;&lt;ul&gt;&lt;li&gt;One page for each topic, includes example requests and responses for REST API and example XML for XML API.&lt;li&gt;Manually written by the engineers.&lt;/ul&gt;&lt;/td&gt;&lt;td&gt;&lt;a href="http://www.flickr.com/photos/pamelafox/5690335741/" title="Twilio by fkedupmonkey, on Flickr"&gt;&lt;img src="http://farm6.static.flickr.com/5266/5690335741_22e4fa121e_t.jpg" width="100" height="93" alt="Twilio"&gt;&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;&lt;a href='https://developer.mozilla.org/en-US/'&gt;Mozilla Developer Center&lt;/a&gt;&lt;/td&gt;&lt;td&gt;&lt;ul&gt;&lt;li&gt;One page for each topic, includes example code, encourages community edits.&lt;li&gt;Uses wiki/social CMS system, &lt;a href="http://www.mindtouch.com/"&gt;MindTouch&lt;/a&gt;&lt;/ul&gt;&lt;/td&gt;&lt;td&gt;&lt;a href="http://www.flickr.com/photos/pamelafox/5690336849/" title="MDC by fkedupmonkey, on Flickr"&gt;&lt;img src="http://farm6.static.flickr.com/5062/5690336849_58f40d577d_t.jpg" width="100" height="89" alt="MDC"&gt;&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;&lt;a href='http://docs.phonegap.com'&gt;PhoneGap&lt;/a&gt;&lt;/td&gt;&lt;td&gt;&lt;ul&gt;&lt;li&gt;One page for each class, includes both short and long example code, and a popup feedback widget.&lt;li&gt;Uses &lt;a href="https://github.com/davebalmer/joDoc"&gt;joDoc&lt;/a&gt; for automated generation.&lt;/ul&gt;&lt;/td&gt;&lt;td&gt;&lt;a href="http://www.flickr.com/photos/pamelafox/5690912504/" title="PhoneGap (Method) by fkedupmonkey, on Flickr"&gt;&lt;img src="http://farm6.static.flickr.com/5190/5690912504_3ec61592a1_t.jpg" width="100" height="89" alt="PhoneGap (Method)"&gt;&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;&lt;a href='http://documentcloud.github.com/backbone/'&gt;Backbone.js&lt;/a&gt;&lt;/td&gt;&lt;td&gt;&lt;ul&gt;&lt;li&gt;One page for each method (and example code), with framed (but still linkable) navigation.&lt;li&gt;Manually written.&lt;/ul&gt;&lt;/td&gt;&lt;td&gt;&lt;a href="http://www.flickr.com/photos/pamelafox/5690334971/" title="BackboneJS by fkedupmonkey, on Flickr"&gt;&lt;img src="http://farm6.static.flickr.com/5030/5690334971_4f810a2cbe_t.jpg" width="100" height="91" alt="BackboneJS"&gt;&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;&lt;a href='http://www.yiiframework.com/doc/api/'&gt;Yii&lt;/a&gt;&lt;/td&gt;&lt;td&gt;&lt;ul&gt;&lt;li&gt;One page for each class, lots of internal linking, prominent search with autocomplete. Includes code samples and links to original source code.&lt;li&gt;Generated with &lt;a href="http://www.yiiframework.com/wiki/186/how-to-generate-yii-like-documentation/"&gt;custom, open-source PHP tool&lt;/a&gt;.&lt;/ul&gt;&lt;/td&gt;&lt;td&gt;&lt;a href="http://www.flickr.com/photos/pamelafox/5690909550/" title="Yii Framework by fkedupmonkey, on Flickr"&gt;&lt;img src="http://farm6.static.flickr.com/5307/5690909550_0c2c9437a9_t.jpg" width="100" height="75" alt="Yii Framework"&gt;&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;&lt;a href='http://nodejs.org/docs/v0.4.7/api/'&gt;NodeJS&lt;/a&gt;&lt;/td&gt;&lt;td&gt;&lt;ul&gt;&lt;li&gt;One page for each topic, or can be viewed all on one single page. Includes code examples for each method.&lt;li&gt;Generated using &lt;a href="https://github.com/joyent/node/tree/da9b3340ebb7501ebb8a2896d2c259ffabdab340/tools/doctool"&gt;doctool&lt;/a&gt; and Markdown.&lt;/ul&gt;&lt;/td&gt;&lt;td&gt;&lt;a href="http://www.flickr.com/photos/pamelafox/5690909830/" title="NodeJS by fkedupmonkey, on Flickr"&gt;&lt;img src="http://farm6.static.flickr.com/5265/5690909830_f3f1946038_t.jpg" width="100" height="99" alt="NodeJS"&gt;&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;&lt;a href='http://www.playframework.org/documentation/1.2.1/home'&gt;Play! Framework&lt;/a&gt;&lt;/td&gt;&lt;td&gt;&lt;ul&gt;&lt;li&gt;Includes step-by-step tutorial and developer's guide (no reference).&lt;/ul&gt;&lt;/td&gt;&lt;td&gt;&lt;a href="http://www.flickr.com/photos/pamelafox/5690909996/" title="Play! Framework by fkedupmonkey, on Flickr"&gt;&lt;img src="http://farm6.static.flickr.com/5221/5690909996_a86ab65fe4_t.jpg" width="100" height="96" alt="Play! Framework"&gt;&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;&lt;a href='http://dev.sencha.com/deploy/ext-4.0.0/docs/'&gt;Sencha ExtJS&lt;/a&gt;&lt;/td&gt;&lt;td&gt;&lt;ul&gt;&lt;li&gt;One page for each class, highly linked, inline code examples, and search with auto-complete.&lt;li&gt;Generated using &lt;a href="https://github.com/nene/jsduck"&gt;JSDuck&lt;/a&gt; and Markdown.&lt;/ul&gt;&lt;/td&gt;&lt;td&gt;&lt;a href="http://www.flickr.com/photos/pamelafox/5690336055/" title="Sencha by fkedupmonkey, on Flickr"&gt;&lt;img src="http://farm6.static.flickr.com/5142/5690336055_56a4c3d3da_t.jpg" width="100" height="76" alt="Sencha"&gt;&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;&lt;a href='https://simplegeo.com/docs/'&gt;SimpleGeo&lt;/a&gt;&lt;/td&gt;&lt;td&gt;&lt;ul&gt;&lt;li&gt;Organized by topic with one page for each. Written in a narrative form and includes code examples.&lt;li&gt;Generated using Django and templates, &lt;a href="http://developers.simplegeo.com/blog/2011/05/05/writing-a-django-documentation"&gt;More info here&lt;/a&gt;.&lt;/ul&gt;&lt;/td&gt;&lt;td&gt;&lt;a href="http://www.flickr.com/photos/pamelafox/5690336365/" title="SimpleGeo by fkedupmonkey, on Flickr"&gt;&lt;img src="http://farm6.static.flickr.com/5146/5690336365_d8aa0c6e5c_t.jpg" width="100" height="94" alt="SimpleGeo"&gt;&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;&lt;a href='http://dev.twitter.com/doc'&gt;Twitter&lt;/a&gt;&lt;/td&gt;&lt;td&gt;&lt;ul&gt;&lt;li&gt;One page for each API endpoint ("resource"), with example request and responses in XML/ATOM/JSON.&lt;li&gt;Partially generated from code, manually curated by engineers.&lt;/ul&gt;&lt;/td&gt;&lt;td&gt;&lt;a href="http://www.flickr.com/photos/pamelafox/5690912138/" title="Twitter by fkedupmonkey, on Flickr"&gt;&lt;img src="http://farm6.static.flickr.com/5030/5690912138_8ea0ffcbe5_t.jpg" width="100" height="87" alt="Twitter"&gt;&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;&lt;a href='http://developer.android.com/reference/android/text/package-summary.html'&gt;Android&lt;/a&gt;&lt;/td&gt;&lt;td&gt;&lt;ul&gt;&lt;li&gt;Javadoc style, with ability to change language and API level, plus search with auto-complete. Incudes tutorial style articles as well.&lt;li&gt;Generated from code using JavaDoc.&lt;/ul&gt;&lt;/td&gt;&lt;td&gt;&lt;a href="http://www.flickr.com/photos/pamelafox/5690910532/" title="Android by fkedupmonkey, on Flickr"&gt;&lt;img src="http://farm6.static.flickr.com/5227/5690910532_b31e5fe625_t.jpg" width="100" height="86" alt="Android"&gt;&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;/table&gt;
&lt;br&gt;

&lt;h3&gt;Mixed Reviews&lt;/h3&gt;

&lt;p&gt;These documentation sets had both positive and negative reviews. (What works for one developer doesn't always work for another).&lt;/p&gt;

&lt;table class="docs"&gt;
&lt;tr&gt;&lt;td&gt;&lt;a href='http://docs.python.org/library/'&gt;Python&lt;/a&gt;&lt;/td&gt;&lt;td&gt;&lt;ul&gt;&lt;li&gt;One page for each topic, with embedded references and code examples. Complaints: no search/comments.&lt;li&gt;Generated using &lt;a href="http://sphinx.pocoo.org/"&gt;Sphinx&lt;/a&gt; and RST. &lt;/ul&gt;&lt;/td&gt;&lt;td&gt;&lt;a href="http://www.flickr.com/photos/pamelafox/5690909656/" title="Python by fkedupmonkey, on Flickr"&gt;&lt;img src="http://farm6.static.flickr.com/5146/5690909656_1d14595265_t.jpg" width="100" height="85" alt="Python"&gt;&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;&lt;a href='http://developers.facebook.com/docs/'&gt;Facebook&lt;/a&gt;&lt;/td&gt;&lt;td&gt;&lt;ul&gt;&lt;li&gt;A mix of reference style docs, articles, and github-hosted readmes. Includes search and (Facebook) comments. Complaints: too loosely organized.&lt;/ul&gt;&lt;/td&gt;&lt;td&gt;&lt;a href="http://www.flickr.com/photos/pamelafox/5690910766/" title="Facebook by fkedupmonkey, on Flickr"&gt;&lt;img src="http://farm6.static.flickr.com/5063/5690910766_7d73d9ac44_t.jpg" width="100" height="81" alt="Facebook"&gt;&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;/table&gt;

&lt;br&gt;

&lt;h3&gt;Not-So-Great Reviews&lt;/h3&gt;

&lt;p&gt;These documentation sets had all negative reviews. (Well, they can always improve!)&lt;/p&gt;

&lt;table class="docs"&gt;
&lt;tr&gt;&lt;td&gt;&lt;a href='http://www.ruby-doc.org/core/ '&gt;Ruby&lt;/a&gt;&lt;/td&gt;&lt;td&gt;&lt;ul&gt;&lt;li&gt;Javadoc style with framesets. Complaints: can't be searched or linked, no per-topic organization.&lt;li&gt;Generated from code using &lt;a href="http://rdoc.sourceforge.net/"&gt;RDoc&lt;/a&gt;.&lt;/ul&gt;&lt;/td&gt;&lt;td&gt;&lt;a href="http://www.flickr.com/photos/pamelafox/5690910646/" title="Ruby by fkedupmonkey, on Flickr"&gt;&lt;img src="http://farm6.static.flickr.com/5307/5690910646_90287e384b_t.jpg" width="100" height="97" alt="Ruby"&gt;&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;&lt;a href='https://affiliate-program.amazon.com/gp/advertising/api/detail/main.html'&gt;Amazon Products API&lt;/a&gt;&lt;/td&gt;&lt;td&gt;&lt;ul&gt;&lt;li&gt;Frameset docs, both tutorial and reference style. Complaints: takes many clicks to find the reference, provided sample code does not work.&lt;/ul&gt;&lt;/td&gt;&lt;td&gt;&lt;a href="http://www.flickr.com/photos/pamelafox/5690335537/" title="Amazon by fkedupmonkey, on Flickr"&gt;&lt;img src="http://farm6.static.flickr.com/5069/5690335537_f73e1167c8_t.jpg" width="100" height="88" alt="Amazon"&gt;&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;&lt;a href='https://www.paypal.com/documentation'&gt;Paypal&lt;/a&gt;&lt;/td&gt;&lt;td&gt;&lt;ul&gt;&lt;li&gt;Includes articles and reference docs. Complaints: instructions are dumbed down, deprecated information isn't marked as such, there are too many places to find a piece of information, not enough example code.&lt;/ul&gt;&lt;/td&gt;&lt;td&gt;&lt;a href="http://www.flickr.com/photos/pamelafox/5690335655/" title="Paypal by fkedupmonkey, on Flickr"&gt;&lt;img src="http://farm6.static.flickr.com/5061/5690335655_47036c12d9_t.jpg" width="100" height="75" alt="Paypal"&gt;&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;&lt;a href='http://docs.openlayers.org/'&gt;OpenLayers&lt;/a&gt;&lt;/td&gt;&lt;td&gt;&lt;ul&gt;&lt;li&gt;Wiki and reference. Complaints: No code examples, hard to find docs.&lt;li&gt;Generated using &lt;a href="http://www.naturaldocs.org/"&gt;NaturalDocs&lt;/a&gt;.&lt;/ul&gt;&lt;/td&gt;&lt;td&gt;&lt;a href="http://www.flickr.com/photos/pamelafox/5690911300/" title="OpenLayers by fkedupmonkey, on Flickr"&gt;&lt;img src="http://farm6.static.flickr.com/5261/5690911300_b9d81ce064_t.jpg" width="100" height="97" alt="OpenLayers"&gt;&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;&lt;a href='http://wiki.apache.org/couchdb/'&gt;CouchDB&lt;/a&gt;&lt;/td&gt;&lt;td&gt;&lt;ul&gt;&lt;li&gt;Wiki with articles by topic. Complaints: Hard to navigate.&lt;li&gt;Uses the &lt;A href="http://moinmo.in/"&gt;MoinMoin&lt;/a&gt; wiki engine.&lt;/ul&gt;&lt;/td&gt;&lt;td&gt;&lt;a href="http://www.flickr.com/photos/pamelafox/5690911192/" title="CouchDB by fkedupmonkey, on Flickr"&gt;&lt;img src="http://farm6.static.flickr.com/5301/5690911192_f6e55524a4_t.jpg" width="100" height="94" alt="CouchDB"&gt;&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;/table&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8501278254137514883-5822347178479991064?l=blog.pamelafox.org' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.pamelafox.org/feeds/5822347178479991064/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=8501278254137514883&amp;postID=5822347178479991064' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8501278254137514883/posts/default/5822347178479991064'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8501278254137514883/posts/default/5822347178479991064'/><link rel='alternate' type='text/html' href='http://blog.pamelafox.org/2011/05/roundup-developer-documentation.html' title='Roundup: The Best Developer Docs'/><author><name>Pamela Fox</name><uri>http://www.blogger.com/profile/15947664772001597300</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://farm6.static.flickr.com/5186/5690334841_03dd831ab3_t.jpg' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8501278254137514883.post-8187651466079153657</id><published>2011-04-28T21:18:00.000-07:00</published><updated>2011-04-28T22:12:54.702-07:00</updated><title type='text'>What makes a good "developer experience"?</title><content type='html'>&lt;p&gt;(Short version: To help me answer this question, &lt;a href="https://spreadsheets.google.com/spreadsheet/viewform?formkey=dEJEMWxxSWxrQ3FYWDBKX3lic1RwS1E6MQ"&gt;&lt;b&gt;fill out this survey&lt;/b&gt;&lt;/a&gt;. Thanks!)&lt;/p&gt;
&lt;p&gt;We are all quite familiar with the term "user experience" (UX) because as developers, we are typically spending our time developing products that we want people to use, and we want the UX to be positive so that they continue using them. However, we are now in the age of web APIs and developer platforms, and increasingly more of us are spending our time developing products for developers themselves to use.
&lt;/p&gt;
&lt;p&gt;&lt;img style="float:right; margin: 5px; " src="http://3.bp.blogspot.com/-65NQiLWcokg/TbpCrmyYwpI/AAAAAAAAD50/4iIokvcg2CQ/s320/developerexperience.png" /&gt; Just like with user products, we want the &lt;b&gt;"developer experience"&lt;/b&gt; (DX) to be positive so they continue developing on top of our service, and so they feel good relying on us to be part of their app's technology stack. When we talk about user experience, we focus on the usability of the user interface and the various user actions (like sign-in, search, share). A developer experience is very different, though, and when we talk about it, we should be focusing on the usability of the API and the developing-and-debugging experience. How does a developer first learn about your service? Where do they go when they need help? How easy is it for them to develop arbitrary apps on top of it? Can they use it successfully in their preferred environment? Those are the sort of questions that we need to ask to figure out what the developer experience is like.
&lt;/p&gt;
&lt;p&gt;
Developer experience  is important and non-trivial, but unfortunately, it's been nowhere near as discussed as user experience - a quick Google search yielded mostly this &lt;a href="http://www.uxmag.com/technology/effective-developer-experience"&gt;one article from UXMag&lt;/a&gt;. When I worked in developer relations at Google, we were basically tasked with designing the DX for our APIs and tools, and when I wrote up the &lt;a href="http://www.developer-support-handbook.org/"&gt;Developer Support Handbook,&lt;/a&gt; I was attempting to document some of what I learnt from my years on the Maps and Wave APIs. That handbook only talks about some aspects of the experience  - it doesn't talk about API usability at all - and it's only based on my own limited experience. I know that there is much more to be documented and discussed, and that there are many different types of developers and developer services out there, and just as with UX, there may not be just one set of DX principles that fits everything.
&lt;/p&gt;
&lt;p&gt;
Why do I bring this up? A few weeks ago, I met with a mobile analytics company called &lt;a href="http://www.flurry.com/"&gt;Flurry&lt;/a&gt; to discuss their developer experience and how they can improve it to better support their current developers and encourage future developers. I gave them my own opinions, but I really would love to hear the opinions of more developers to give me a broader perspective. To find out what you guys think about what makes a positive developer experience, I've put together a &lt;a href="https://spreadsheets.google.com/spreadsheet/viewform?formkey=dEJEMWxxSWxrQ3FYWDBKX3lic1RwS1E6MQ"&gt;short survey&lt;/a&gt;. Please fill it out if you have the time, or feel free to leave comments on this post. Thank you for your thoughts and for caring about what it means to have a good developer experience.&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8501278254137514883-8187651466079153657?l=blog.pamelafox.org' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.pamelafox.org/feeds/8187651466079153657/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=8501278254137514883&amp;postID=8187651466079153657' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8501278254137514883/posts/default/8187651466079153657'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8501278254137514883/posts/default/8187651466079153657'/><link rel='alternate' type='text/html' href='http://blog.pamelafox.org/2011/04/what-makes-good-developer-experience.html' title='What makes a good &quot;developer experience&quot;?'/><author><name>Pamela Fox</name><uri>http://www.blogger.com/profile/15947664772001597300</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://3.bp.blogspot.com/-65NQiLWcokg/TbpCrmyYwpI/AAAAAAAAD50/4iIokvcg2CQ/s72-c/developerexperience.png' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8501278254137514883.post-442062037740644310</id><published>2011-04-17T13:44:00.000-07:00</published><updated>2011-04-19T10:48:51.182-07:00</updated><title type='text'>SF jQuery Conference 2011: My Learnings</title><content type='html'>&lt;p&gt;For the last 5 years, I've really only attended conferences that I was speaking at or somehow representing Google at, and I was always paid by Google to attend. This past weekend, I convinced myself to pay out of my own pocket to attend a conference for the first time, and it was completely worth it.&lt;/p&gt;
&lt;p&gt;&lt;a href="http://events.jquery.org/2011/sf-bay-area/schedule/"&gt;jQCon&lt;/a&gt; was a 2-day event in the Microsoft Mountain View campus with a wide range of well-known speakers, like Nicholas Zakas, Steve Souders, Paul Irish, and of course, John Resig, plus equally skilled but lesser known contributors to the world of jQuery and JavaScript programming. It was a great way to learn new techniques and tools for client-side web app development from the people that are doing it 24/7 for some of the biggest sites on the web.
&lt;/p&gt;
&lt;p&gt;I personally gravitated to the more mobile-oriented talks, as I've recently become interested in mobile webapp development (I finally use my phone here!) and have been using jQuery mobile for the next version of &lt;a href="http://speakermeter.com"&gt;SpeakerMeter&lt;/a&gt;. I learnt a lot about how people are currently writing mobile webapps, and more importantly, I realized that this is a rapidly changing area, particularly as the line between desktop and mobile becomes increasingly blurry. I was hoping to find the "one true way" of making a HTML5 mobile webapp, but I've realized instead that I need to try the current ways out there (like PhoneGap + jQuery Mobile) and be ready for that to change.
&lt;/p&gt;
&lt;p&gt;I took notes throughout the talks on tips and resources, and am sharing them here both for my own reference and to give you an idea of what was discussed. I look forward to learning more at the next jQCon, whenever that may be. :)
&lt;/p&gt;

&lt;h2&gt;Day 1:&lt;/h2&gt;

&lt;h3&gt;&lt;a href="http://filamentgroup.com/lab/slides_from_our_jquery_conference_presentation_on_jquery_mobile/"&gt;jQuery Mobile&lt;/a&gt; (Todd Parker &amp; Scott Jehl)&lt;/h3&gt;
&lt;ul&gt;
 &lt;li&gt;Many developers are using jQuery Mobile in combination with PhoneGap to deploy mobile-optimized webapps.
 &lt;li&gt;jQuery Mobile now supports more mobile browsers, including Kindle Webkit.
 &lt;li&gt;The jQuery Mobile team put a lot of work into making all the controls accessible.
 &lt;li&gt;The team is working on an improvement that will include better URLs (hash-less) for browsers that support it (HTML5 pushState).
  &lt;li&gt;The team made sure that it was easy for developers to make custom themes/colors, and they want more developers to take advantage of that.
  &lt;li&gt;Browse the &lt;a href="http://www.jqmgallery.com/"&gt;jQuery Mobile gallery&lt;/a&gt; to see what other developers have done.
  &lt;li&gt;The &lt;a href="http://the-m-project.net/index.html"&gt;M Project&lt;/a&gt; is an open source project to make it easier to make mobile webapps with jQuery mobile.
  &lt;li&gt;The team recommends specifically optimizing the UI for iPad/tablets and not just using the standard narrow mobile layout. They hope in the future that the framework can do more of that for developers.
  &lt;li&gt;CSS3 media queries can be used to change the UI for different device sizes.
  &lt;li&gt;jQuery Mobile can be used with grids frameworks (can be useful for tablet layout).
 &lt;/ul&gt;

&lt;h3&gt;&lt;a href="http://stevesouders.com/docs/jqcon-20110416.pptx"&gt;Mobile Performance&lt;/a&gt; (Steve Souders)&lt;/h3&gt;

&lt;ul&gt;
 &lt;li&gt;Its better to have your site be fast when users first experience it - study showed slow sites lost users (and it took a while for them to come back).
  &lt;li&gt;Use &lt;a href="http://blaze.io"&gt;Blaze.io&lt;/a&gt; for seeing the mobile performance of your site (like webpagetest.org).
  &lt;li&gt;Use &lt;a href="http://pcapperf.appspot.com/"&gt;PCAP Web Performance Analyzer&lt;/a&gt; to analyze performance of websites (can be used locally).
  &lt;li&gt;Use &lt;a href="http://jdrop.org/"&gt;JDRop&lt;/a&gt; with mobile bookmarklets to store performance data in the cloud for later analysis.
  &lt;li&gt;Use data URIs and localStorage for better mobile performance.
&lt;/ul&gt;

&lt;h3&gt;&lt;a href="http://www.slideshare.net/nzakas/progressive-enhancement-20"&gt;Progressive Enhancement 2.0 - Because the Web isn't Print&lt;/a&gt; (Nicholas Zakas)&lt;/h3&gt;
&lt;ul&gt; &lt;li&gt;Read: &lt;a href="http://www.alistapart.com/articles/understandingprogressiveenhancement/"&gt;"Understanding Progressive Enhancement"&lt;/a&gt;
&lt;li&gt;"The relationship between a web browser and a webpage is like a television and a TV show."
&lt;li&gt;Examples of progressive enhancement in the real world: escalators and electric toothbrush.
&lt;li&gt;&lt;a href="http://dowebsitesneedtolookexactlythesameineverybrowser.com/"&gt;Websites don't need to look exactly the same in every browser.&lt;/a&gt;
&lt;li&gt;Don't try so hard to make old browsers do what new browsers can (consider effort versus value) - like rounded corners, drop shadows, and gradients.
&lt;li&gt;Developers use multiple browsers, but most users only use one browser - they won't know if the experience is different.
&lt;li&gt;Progressively enhance for browsers that support newer technology - Facebook chat is an example of a progressive enhancement.
&lt;/ul&gt;

&lt;h3&gt;&lt;a href="http://www.slideshare.net/antonkovalyov/integrating-code-quality-tools-into-your-jquery-development-workflow"&gt;Integrating Code Quality tools into your jQuery Development Workflow&lt;/a&gt; (Anton Kovalyov )&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="http://jshint.com/"&gt;JSHint&lt;/a&gt; is the alternative to JSLint - does not enforce so many "crocklamations" by default.
&lt;li&gt;Recommends using git precommit and postcommit hooks for running JSHint, to make sure all team members are using it. Break the build if it errors.
&lt;li&gt;Many community-written addons for integrating JSHint with IDEs. He likes &lt;a href="http://www.sublimetext.com/"&gt;Sublime&lt;/a&gt;.
&lt;li&gt;Read: &lt;a href="http://perfectionkills.com"&gt;Perfection Kills&lt;/a&gt;, &lt;a href="http://aminutewithbrendan.com"&gt;A minute with Brendan&lt;/a&gt;
&lt;/ul&gt;

&lt;h3&gt;&lt;a href="http://dl.dropbox.com/u/200135/talks/prototyping-unit-testing/builder/index.html"&gt;Prototyping and Unit Testing with Mockjax &amp; mockJSON&lt;/a&gt; (Elijah Manor)&lt;/h3&gt;

&lt;ul&gt;
 &lt;li&gt;&lt;a href="https://github.com/appendto/jquery-mockjax"&gt;MockJAX&lt;/a&gt; is a jQuery plugin for simulating AJAX requests and responses.
 &lt;li&gt;&lt;a href="https://github.com/mennovanslooten/mockJSON"&gt;MockJSON&lt;/a&gt; is a library for generating random JSON responses based on JSON templates. Works well with MockJAX.
&lt;/ul&gt;

&lt;h2&gt;Day 2:&lt;/h2&gt;

&lt;h3&gt;&lt;a href="http://dl.dropbox.com/u/99696/jqcon/HTML5%20-%20Polyfills%20and%20Shims%20-%20v2.ppt"&gt;Filling the HTML5 &amp; CSS3 Gaps with Polyfills and Shims&lt;/a&gt; (Rey Bango)&lt;/h3&gt;
&lt;ul&gt;
 &lt;li&gt;Rey is both a Microsoft employee and a jQuery team member - MS is a big supporter of jQuery.
 &lt;li&gt;A "polyfill" mimics a standard/future API and makes it work in older browsers, whereas a "shim" provides an arbitrary API for achieving some functionality. "Polyfill" was &lt;a href="http://remysharp.com/2010/10/08/what-is-a-polyfill/"&gt;named by Remy Sharp&lt;/a&gt; after the British term for spackling - it's like filling holes in old browser cracks.
  &lt;li&gt;When you are using a polyfill or shim, vet them carefully: see how many developers are working on them, how frequently they update them, etc.
&lt;li&gt;&lt;a href="https://github.com/Modernizr/Modernizr/wiki/HTML5-Cross-browser-Polyfills"&gt;Long list of polyfills and shims.&lt;/a&gt;
&lt;/ul&gt;

&lt;h3&gt;How jQuery is helping Pixar to make their movies (Philip Floetotto)&lt;/h3&gt;
&lt;ul&gt;
 &lt;li&gt;Pixar is a big Python user. For their project management system, they used Django for the backend and jQuery for the frontend.
 &lt;li&gt;They built their UI on top of the &lt;a href="http://tablesorter.com/docs/"&gt;TableSorter&lt;/a&gt; plugin.
&lt;/ul&gt;

&lt;h3&gt;&lt;a href="http://www.slideshare.net/dcneiner/presentational-jquery-7671131"&gt;Presentational jQuery&lt;/a&gt; (Doug Neiner)&lt;/h3&gt;
&lt;ul&gt;
 &lt;li&gt;Be concious of when you use linked stylesheets vs. STYLE tags vs. inline style setting. Never use jQuery to set initial state. Reduce use of .css() as much as possible.
  &lt;li&gt;"Use selectors like you run errands" - try to do as much in one call as you can.
  &lt;li&gt;Experiment with easing (on different properties) for better animations.
&lt;/ul&gt;

&lt;h3&gt;Breakout Session: jQuery Mobile&lt;/h3&gt;
&lt;p&gt;Much discussion on using jQuery Mobile to build static sites that are deployed as WebViews inside of native apps.&lt;/p&gt;
&lt;ul&gt;
 &lt;li&gt;Advantage of PhoneGap over Titanium is that it deploys to more mobile platforms.
 &lt;li&gt;&lt;a href="https://build.phonegap.com/apps"&gt;Phone Gap Build&lt;/a&gt; lets you deploy mobile apps without needing to download anything.
 &lt;li&gt;Use something like &lt;a href="http://json-template.googlecode.com/svn/trunk/doc/Introducing-JSON-Template.html"&gt;JSON Template&lt;/a&gt; or &lt;a href="http://handlebars.strobeapp.com/"&gt;Handlebars&lt;/a&gt; for client-side templating of the jQuery mobile headers and footers.
  &lt;li&gt;Use &lt;a href="http://www.httrack.com/"&gt;HT Track&lt;/a&gt; or &lt;a href="http://ringce.com/hyde"&gt;Hyde&lt;/a&gt; to use Django templates locally and still output a static site.
 &lt;li&gt;Recommended reading: &lt;a href="http://www.alistapart.com/articles/responsive-web-design/"&gt;Responsive Web Design&lt;/a&gt;.
&lt;/ul&gt;

&lt;h3&gt;&lt;a href="http://dl.dropbox.com/u/133599/stash/jQueryCon11.pdf"&gt;The Middle Way: Developing Hybrid Mobile Apps&lt;/a&gt; (Alex Kessinger)&lt;/h3&gt;
&lt;ul&gt;
 &lt;li&gt;Use localStorage to store data locally, and use LRU to stay under the 5MB size limit.
 &lt;li&gt;If using AppCache, inline everything (CSS, JS, HTML) so everything stays in sync in the cache.
 &lt;li&gt;For a better user experience, render *anything* to the user first (versus nothing), even fake DIVs.
 &lt;li&gt;For easier mobile debugging, try &lt;a href="http://jsconsole.com/"&gt;JSConsole&lt;/a&gt;.
 &lt;li&gt;&lt;a href="http://www.openappmkt.com/"&gt;OpenAppMkt&lt;/a&gt; is a marketplace specifically for mobile-optimized webapps.
&lt;/ul&gt;

&lt;h3&gt;Breakout Session: CouchDB + jQuery&lt;/h3&gt;
&lt;p&gt;Wrote a small &lt;a href="http://friendpaste.com/1Am5LLeuTrbDugOyW9jf5s"&gt;JQuery &amp; CouchDB&lt;/a&gt; app (with &lt;a href="http://friendpaste.com/5E2KXZa7NWAOFmuMO6VfBS"&gt;this view&lt;/a&gt;).&lt;/p&gt;

&lt;h3&gt;&lt;a href="http://www.slideshare.net/darcyclarke/mind-blowingux"&gt;Creating mind-blowing UX - "Building great user experiences with the help of jQuery"&lt;/a&gt; (Darcy Clarke)&lt;/h3&gt;
&lt;ul&gt;
 &lt;li&gt;User experience is about emotions - you want your users to have positive emotions when using your site. Surprise is an emotion that can be either positive or negative.
 &lt;li&gt;Inspirational design agencies: &lt;a href="http://f-i.com"&gt;F-I&lt;/a&gt;, &lt;a href="http://zurb.com"&gt;Zurb&lt;/a&gt;, &lt;a href="http://www.blitzagency.com/hi/"&gt;Blitz&lt;/a&gt;
&lt;/ul&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8501278254137514883-442062037740644310?l=blog.pamelafox.org' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.pamelafox.org/feeds/442062037740644310/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=8501278254137514883&amp;postID=442062037740644310' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8501278254137514883/posts/default/442062037740644310'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8501278254137514883/posts/default/442062037740644310'/><link rel='alternate' type='text/html' href='http://blog.pamelafox.org/2011/04/sf-jquery-conference-2011-my-learnings.html' title='SF jQuery Conference 2011: My Learnings'/><author><name>Pamela Fox</name><uri>http://www.blogger.com/profile/15947664772001597300</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8501278254137514883.post-7747447364102662114</id><published>2011-04-13T22:57:00.000-07:00</published><updated>2011-04-20T22:00:38.413-07:00</updated><title type='text'>Twenty Questions (With Myself)</title><content type='html'>&lt;p&gt;It's always fun to answer questions about yourself - remember those "About Me" books you would fill out as a kid? Well, I do, and I loved them, so when people ask me if I'm up for an interview, I always say yes. I recently answered a series of long &amp; short questions for a Mexican development agency's internal newsletter, and since that newsletter isn't online, I figured I'd share them here instead. Enjoy!&lt;/p&gt;

&lt;h3&gt;Short Questions&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;b&gt;Linux, Mac or Windows?&lt;/b&gt; Mac. I was raised in a Windows-using family - back when Macs weren’t Unix-based, but I recently converted to Mac and love it.
&lt;li&gt;&lt;b&gt;Twitter or blog?&lt;/b&gt; Both. I like the challenge of expressing something in 140 characteres, but I also like to write up my experiences and projects in much longer blog form.
&lt;li&gt;&lt;b&gt;iPhone or Android?&lt;/b&gt; Android...only because I got free Android phones from Google. I’d happily accept a free iPhone if it were to come my way. :)
&lt;li&gt;&lt;b&gt;Bread or tortilla?&lt;/b&gt; Neither. I’ve recently stopped eating grains of any sort (as they’re not actually that good for you). I miss tortilla more than bread though - growing up in Los Angeles, I was raised on quesadillas!
&lt;li&gt;&lt;b&gt;Wine or tequila?&lt;/b&gt; Wine. I save tequila-drinking for when I’m in Mexico and can drink the good stuff. :)
&lt;li&gt;&lt;b&gt;Day or night?&lt;/b&gt; Day. I’m afraid of the dark.
&lt;li&gt;&lt;b&gt;Warm weather or cold weather?&lt;/b&gt; Warm.
&lt;li&gt;&lt;b&gt;Sunny or rainy?&lt;/b&gt; Sunny! The rain is only fun if there’s a hot bath waiting for you at home.
&lt;/ul&gt;

&lt;br&gt;

&lt;h3&gt;What is your favorite…&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;b&gt;Book&lt;/b&gt;: I can’t come up with just one. My favorite book genre is short stories, and Roald Dahl has some of the best stories out there.
&lt;li&gt;&lt;b&gt;Gadget&lt;/b&gt;: Kindle. It stays charged forever, and since I hate charging things, that makes it my favorite thing.
&lt;li&gt;&lt;b&gt;Videogame&lt;/b&gt;: Puzzle Pirates. I don’t play it anymore, but it’s the only game that I’ve come close to an addiction with.
&lt;li&gt;&lt;b&gt;Programming Language&lt;/b&gt;: JavaScript. It’s weird, but it works.
&lt;li&gt;&lt;b&gt;Browser&lt;/b&gt;: Chrome. 
&lt;/ul&gt;

&lt;br&gt;

&lt;h3&gt;Tell us how did you get your first computer, and what age were you?&lt;/h3&gt;
   &lt;p&gt;I don’t actually remember a time when we didn’t own a computer - since my parents were effectively computer scientists since the day I was born, we always had computers in the house. I first remember using DOS to play a “Garfield” and a “Dinosaurs” game, and then we upgraded to Windows 3.1.

&lt;h3&gt;Why did you choose to be a programmer?&lt;/h3&gt;
   &lt;/p&gt;
   &lt;p&gt;I was always very in to computers as a kid- I loved using them to make posters and to browse the web. When I discovered programming - specifically web programming - I loved them even more. I made fun little games, I made a “cyberclub,” and I made websites for everything I did. 
   &lt;/p&gt;
   &lt;p&gt;
When it came time to deciding what to major in at college, I found it easy to pick Computer Science. I knew that no matter where my interests went, I could use my computer science skills to complement those interests, and I knew that I could always get a job with those skills.
   &lt;/p&gt;

&lt;h3&gt;As a programmer/developer, what is the thing that motivates you the most?&lt;/h3&gt;
&lt;p&gt;
I like the ability to make something, and to easily share that something. If I wasn’t a programmer, I think I would be an artist of some sort, so that I could fulfill my need to create that way. 
&lt;/p&gt;

&lt;h3&gt;In which programming language do you feel the most comfortable on?&lt;/h3&gt;
&lt;p&gt;
I am generally the most comfortable in “scripting languages,” and these days, I am the most familiar with JavaScript. I have always been attracted to scripting languages over compiled languages because I love the speed at which you can develop with them, and I find them generally more approachable. 
&lt;/p&gt;
&lt;p&gt;
On the server, I tend to use Python, but would love to try out using JavaScript there as well. I like the idea of getting to use the same language for both the frontend and the backend. The lines are blurring between them, so it makes sense for the language to be the same.
&lt;/p&gt;

&lt;h3&gt;Do you have a hobby that is not related to technology?&lt;/h3&gt;
&lt;p&gt;
Lately, I’ve gotten really into cooking. I’ve discovered that I get a similar creative rush from cooking as I do from coding. When I cook a meal, I get to enjoy the end result, I get to share it with whoever is around me, and I get to share with the world how I did it. When I code an app, I get to use the app, share it with other users, and open-source the code.
&lt;/p&gt;
&lt;p&gt;
The main difference between cooking and coding: far fewer bug reports, and no long-term maintenance required!
&lt;/p&gt;

&lt;h3&gt;How do you feel as a woman that works in a predominantly male environment?&lt;/h3&gt;
&lt;p&gt;
I usually don’t think about it that much. I grew up around a lot of males - I had a brother with a lot of male friends, and I tended to make a lot of male friends myself. So, I didn’t find it that weird in college or work to be surrounded by males, and in fact, I somewhat preferred it.
&lt;/p&gt;
&lt;p&gt;
(I wrote a much longer blog post about this &lt;a href="http://blog.pamelafox.org/2009/10/being-girl-in-cs-doesnt-suck.html"&gt;here&lt;/a&gt;.)
&lt;/p&gt;

&lt;h3&gt;Do you feel that you had to break the gender barrier or any stereotype because you are a woman in order to be considered a good programmer?&lt;/h3&gt;
&lt;p&gt;
I have to admit, I don’t actually think I’m a great programmer. I think I’m a pretty good programmer, but not great. I am able to achieve beyond my core programming skills because of my ability to combine multiple skills, my desire to create, and my desire to share my knowledge with others.
&lt;/p&gt;
&lt;p&gt;
I do often wish that I was a crazy-good programmer like my colleagues and peers, and I think to myself that I should take some classes or read some books to increase my skills...but then I think that I’m pretty happy with my diverse skillset.
&lt;/p&gt;
&lt;p&gt;
I do sometimes feel as if I have to break stereotypes when I am giving talks to new audiences, as some people see a girl on stage and immediately assume she’s not going to talk technical. By the end of the talk, they know better. :)
&lt;/p&gt;

&lt;h3&gt;What's your achievement that you feel the most proud of?&lt;/h3&gt;

&lt;p&gt;Looking over the past five years, I am most proud of my “teaching moments”  - the times when I taught someone something new, and could see their knowledge grow as a result. I’m sure I had many virtual teaching moments with developers in forums, but I am most proud of the in-person moments with students in classes. There’s something very real and very gratifying about watching students grow from the first day of a class to the very end.
&lt;/p&gt;

&lt;h3&gt;How do you do to keep your life under balance, I mean, keep learning, spend time with your family and friends, work hard, etc?&lt;/h3&gt;
&lt;p&gt;
I don’t. My father is a workaholic, and he instilled a similar work ethic in me.  When I am working, I’m putting all of myself into that, and I find it hard to justify making time for family and friends. I instead wait for them to force me to make time for them, and if they force me, well, I can’t say no.
&lt;/p&gt;
&lt;p&gt;
I recently left my job, and I’m looking forward to finally putting friends and family first, at least for a few months. In the end, it’s the people that you remember more than the work anyway.
&lt;/p&gt;

&lt;h3&gt;What projects do you have in mind for the near future?&lt;/h3&gt;
 
&lt;p&gt;Generally, I want to make apps that I would use, and if I’m lucky, a few other people would use as well. As I am currently obsessed with food and nutrition, I am experimenting in that area to see what apps might make it easier for me to eat healthily, to cook delicious meals, and to share nutrition information with others. 
&lt;/p&gt;
&lt;p&gt;
My basic strategy is this: Every day, when I encounter a situation that would be made better with an app, I write down the app idea. If I end up writing down an app idea multiple times, well, there’s a good chance I will make it.
&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8501278254137514883-7747447364102662114?l=blog.pamelafox.org' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.pamelafox.org/feeds/7747447364102662114/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=8501278254137514883&amp;postID=7747447364102662114' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8501278254137514883/posts/default/7747447364102662114'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8501278254137514883/posts/default/7747447364102662114'/><link rel='alternate' type='text/html' href='http://blog.pamelafox.org/2011/04/twenty-questions-with-myself.html' title='Twenty Questions (With Myself)'/><author><name>Pamela Fox</name><uri>http://www.blogger.com/profile/15947664772001597300</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8501278254137514883.post-4476075312695563505</id><published>2011-03-24T18:01:00.000-07:00</published><updated>2011-03-24T18:49:51.956-07:00</updated><title type='text'>What I Want in a Recipe Blogging Platform</title><content type='html'>&lt;p&gt;After spending years subsisting on the food from Google cafes and fast food restaurants, I finally got into cooking my own meals - and I can't believe I didn't discover the joys of cooking before. Right now, I'm mostly following other people's recipes from their personal blogs (which I've aggregated in &lt;a href="http://www.primalpaleorecipes.com/"&gt;this portal&lt;/a&gt;), but I've started to experiment with my own variations and concoctions as well. Both to share my newfound love of cooking and to document my experiments, I decided I should start my own food-centered blog.
&lt;/p&gt;
&lt;p&gt;
Before I could start my blog though, I had to pick a blogging platform. Given the number of food bloggers out there, I assumed there'd be one platform that stood above the rest and was the go-to for food bloggers - but alas, there wasn't. Of the 100 blogs that I subscribe to, 52 use WordPress (either .com or .org version), 34 use Blogger, 1 uses Tumblr, 1 uses Posterous, and the rest are custom built sites. Of those platforms, the only one that offers any food-related functionality would be a WordPress.org installation with recipe-related plugins, but given that a Wordpress install involves money and technical knowledge, it's unlikely that many of these amateur recipe bloggers would be using that. 
&lt;/p&gt;
&lt;p&gt;
Instead, each of these bloggers start with a generic blogging platform and do their best to munge it into a recipe blogging platform. Some get quite far, some not at all, and many end up somewhere in the middle. It's not a good situation for recipe bloggers - they have to spend time re-inventing the wheel when they could be spending that time making delicious food - and it's not a good situation for their readers- they must struggle to make sense of the different user experience on each recipe blog.
&lt;/p&gt;
&lt;p&gt;
This is why I think the web needs a recipe blogging platform. Based on my experience as both a consumer and producer of recipe blogs, here are the features that I would want:
&lt;/p&gt;
&lt;ul&gt;
 &lt;li&gt;&lt;img style="float:right;" src="http://2.bp.blogspot.com/-kquXwjV0QdY/TYvzmdObVoI/AAAAAAAADzc/OXYwxc7yMp8/s320/Screen%2Bshot%2B2011-03-24%2Bat%2B6.44.32%2BPM.png" border="0" /&gt;
&lt;b&gt;Recipe Index:&lt;/b&gt; The traditional way to browse a blog is to scroll through the most recent 10 posts, click, scroll through next 10, and so on. This is a bad way to browse recipes. Instead, users want to see a recipe index, typically broken down by meal types, like &lt;a href="http://blog.yourlighterside.com/p/eats-recipes.html"&gt;this one&lt;/a&gt; (which includes a legend) or &lt;a href="http://girlgoneprimal.blogspot.com/p/show-me-recipes.html"&gt;this one&lt;/a&gt; (which includes photos). The platform should auto-update the index every time an author posted a new recipe, and the categorization would be based on post tags.
  &lt;li&gt;&lt;b&gt;Recipe Microformats:&lt;/b&gt; Google now shows some recipe results using &lt;a href="http://www.google.com/support/webmasters/bin/answer.py?answer=173379"&gt;"rich snippets"&lt;/a&gt;, based on microformats or microdata that it finds in the HTML when it crawls. Many big sites have adopted these formats, since it's easy to apply across their database-generated recipe pages, but most amateur bloggers don't have the technical know-how or the time to work out the HTML each time. The platform should include a widget (like &lt;a href="https://chrome.google.com/extensions/detail/cgpnljccbfcjhhekfnikhpllfjpjidlj"&gt;this Chrome extension&lt;/a&gt;) for inserting a recipe with structured information, and make sure it adheres to the SEO best practices.
&lt;img src="http://www.google.com/help/hc/images/webmasters_173379_en.png"&gt;
  &lt;li&gt;&lt;b&gt;Printable recipes:&lt;/b&gt; It seems like a simple thing, but across all the blogs, I see readers constantly asking for an easy way to print just the recipe in a post, so they can sit it next to their stove while they cook. The platform should stick a "print" button on each post that formats it cookbook-style.
  &lt;li&gt;&lt;b&gt;Recommended Cookbooks/Gear:&lt;/b&gt; Some recipe bloggers include a page or link to an Amazon store with their favorite cookbooks or kitchen accessories. It's a great way for them to share what they themselves use, and to make a bit of extra revenue off their hobby. The platform should faciliate that.
  &lt;li&gt;&lt;img src="http://ecx.images-amazon.com/images/I/51fHPPpARgL._AA115_.jpg" align="right"&gt;&lt;b&gt;E-Book Generation:&lt;/b&gt; Once a recipe blogger builds up a sizeable collection of recipes and readers, they might want to generate an e-book of their recipes, like &lt;a href="http://www.marksdailyapple.com/the-primal-blueprint-reader-created-cookbook/"&gt;the reader-created cookbooks from Mark's Daily Apple&lt;/a&gt; and they may want to monetize off that e-book. For whatever reason, people will pay for the same content that's available online for free when it's in an e-book form, presumably because it's easier to consume or appears more professional, and if people will pay, then recipe bloggers should be able to take advantage of that. The platform should have a way of generating e-books (or even real books) and making it easy to purchase them, perhaps through &lt;a href="http://lulu.com"&gt;Lulu&lt;/a&gt;. 
  &lt;li&gt;&lt;b&gt;Food-related Themes:&lt;/b&gt; As we've learnt on the web, everyone likes to theme their web presence. When I searched on both Tumblr and Blogger, I found close to 0 food themes, and had to go for the "nature-y" themes instead. A recipe platform should be filled with themes that make your mouth water and fills you with dreams of bacon fairies.
  &lt;li&gt;&lt;b&gt;Step-by-step Photos:&lt;/b&gt; Many recipe bloggers include photos that show each step of a recipe, in addition to the final result, like in &lt;a href="http://nomnompaleo.com/post/2106747666/stir-fried-shiitake-and-broccoli-slaw"&gt;this recipe&lt;/a&gt;. The platform should make it easy to include these in the formatted recipe wizard and it could provide a slideshow-like view of the recipe, similar to what's offered on &lt;a href="http://instructables.com"&gt;instructables.com&lt;/a&gt;.
&lt;/ul&gt;
&lt;p&gt;
The platform could also do more in terms of community - making it easy for readers to find other blogs they might like, making it easy for people to comment on recipe posts with links to their own variation, and perhaps bringing in ratings &amp; reviews for the recipes.
&lt;/p&gt;
&lt;p&gt;
This platform could either be a brand new platform, or it could be a bundle of recipe-blogging tools that can complement existing blogging platforms. A brand new platform would have more flexibility in its functionality, but it would also need to re-create the functionality already mastered by existing platforms and it would need to offer migration tools, whereas a set of complementary tools could start being used today by existing and new recipe bloggers. The best thing could be a hybrid of both options.
&lt;/p&gt;
&lt;p&gt;
Since recipe bloggers at least start off as hobbyists (and many remain that way), such a platform or set of tools should start off as free or affordable, and offer premium features (like the e-book generation) for the more invested bloggers.
&lt;/p&gt;
&lt;p&gt;
I'm a web developer myself, so I could go ahead and make this platform tomorrow, but I'm not sure it's what I want to spend all my time on and I think it deserves to be worked on by a fully invested team for a good amount of time. You can't just throw a blogging platform out into the world, abandon it, and expect it to flourish. A blogging platform is all about the users, and when you create a webapp that is user-powered, you need to spend time listening to your users, improving it to better meet their needs, and growing the user base.
&lt;/p&gt;
&lt;p&gt;
So why have I written this post? I'm hoping that either 1) someone is already working on this and will take my feedback into account, 2) someone will be inspired to make this their baby, 3) someone will tell me this already exists. Now, I'm going to sit back and wait for one of those three to happen...and maybe cook some recipes in the meantime. :)
&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8501278254137514883-4476075312695563505?l=blog.pamelafox.org' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.pamelafox.org/feeds/4476075312695563505/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=8501278254137514883&amp;postID=4476075312695563505' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8501278254137514883/posts/default/4476075312695563505'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8501278254137514883/posts/default/4476075312695563505'/><link rel='alternate' type='text/html' href='http://blog.pamelafox.org/2011/03/what-i-want-in-recipe-blogging-platform.html' title='What I Want in a Recipe Blogging Platform'/><author><name>Pamela Fox</name><uri>http://www.blogger.com/profile/15947664772001597300</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://2.bp.blogspot.com/-kquXwjV0QdY/TYvzmdObVoI/AAAAAAAADzc/OXYwxc7yMp8/s72-c/Screen%2Bshot%2B2011-03-24%2Bat%2B6.44.32%2BPM.png' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8501278254137514883.post-1058329498190352854</id><published>2011-03-23T05:40:00.000-07:00</published><updated>2011-03-23T05:49:36.613-07:00</updated><title type='text'>The Developer Support Handbook (aka How I Did My Job)</title><content type='html'>&lt;p&gt;
When I started at Google, I was among the first handful of people in the Developer Relations team (then called "Developer Operations"). We were new to this area at Google, but I'd say that the whole tech world was fairly new to it as well. Web APIs were just becoming a big thing, and web companies were just learning about how to support and grow the diverse community of developers using their APIs. We didn't have much of a precedent about how to do our job, so we made stuff up along the way and iterated on whatever worked.  There is still experimentation going on, but much of how Google works with developers today is based on learnings from those early times (where "early" equals a mere 4 years ago - the web world moves at a rather fast pace).
&lt;/p&gt;
&lt;p&gt;
As I once said on Twitter, my personal policy is to "document the f*k out of everything." I like to document things - particularly processes - both because I am forgetful and like to have a reference to remind myself how to do things, and because I am a huge believer in sharing knowledge. When you share your knowledge with the world, you potentially make someone else's life easier and you also make sure that you're not the single point-of-failure for that knowledge. 
&lt;/p&gt;
&lt;p&gt;
&lt;a href="http://www.developer-support-handbook.org"&gt;&lt;img style="float:right; margin:0 0 10px 10px;cursor:pointer; cursor:hand;width: 150px;" src="http://3.bp.blogspot.com/-WwFuSHdzlfc/TYnrwXq6RrI/AAAAAAAADzE/-mpe4V3jYy0/s320/Screen%2Bshot%2B2011-03-23%2Bat%2B5.45.45%2BAM.png"/&gt;&lt;/a&gt;
So, a few years ago, I started documenting (nearly) everything that I had learnt in doing developer support at Google, figuring that both future colleagues and even non-Googlers might be interested in the learnings. As it turns out, there was a lot in my head that I wanted to get onto paper, and the documentation turned into a multi-chapter, multi-section affair, covering topics like documentation, forum support, issue tracking, communication, and nurturing top developers.  You can read it all online at &lt;a href="http://www.developer-support-handbook.org/"&gt;&lt;b&gt;developer-support-handbook.org&lt;/b&gt;&lt;/a&gt;, and if you want, you can even &lt;a href="http://code.google.com/p/developer-support-handbook/"&gt;check out its RST source&lt;/a&gt; and build it using &lt;a href="http://sphinx.pocoo.org/"&gt;Sphinx&lt;/a&gt;.
&lt;/p&gt;
&lt;p&gt;
I am not particularly proud of the handbook as a writing piece - I had never written anything so long before, and I found it quite difficult to keep a consistent voice and format, and to present the information succinctly. But, I do think the handbook does a good job of showing what "developer support" really entails, and gives you an idea for the kind of debates you'd face in such a role. If you only read one part of it, please read &lt;a href="http://www.developer-support-handbook.org/intro.html"&gt;the introduction&lt;/a&gt;, as it outlines the guiding principles behind the recommendations in the handbook, and behind the way I did my job. (Hint: The #1 principle is to care about your developers. :)
&lt;/p&gt;
&lt;p&gt;
I have since moved on from developer relations at Google, but as a developer myself, I still care deeply about how companies treat their developers and I hope to see more people talking about what it means to have well-designed APIs and to support thriving developer ecosystems. For example, Christian Heilmann put together the fantastic &lt;a href="http://developer-evangelism.com/"&gt;Developer Evangelist handbook&lt;/a&gt; during his time at Yahoo!, and it covers how to write great code samples and give great talks. I hope to see more writing, talks, and even conferences happening in this area in the future. Developer Relations is a tricky mix of communication and technology, and it deserves a closer look.
&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8501278254137514883-1058329498190352854?l=blog.pamelafox.org' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.pamelafox.org/feeds/1058329498190352854/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=8501278254137514883&amp;postID=1058329498190352854' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8501278254137514883/posts/default/1058329498190352854'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8501278254137514883/posts/default/1058329498190352854'/><link rel='alternate' type='text/html' href='http://blog.pamelafox.org/2011/03/developer-support-handbook-aka-how-i.html' title='The Developer Support Handbook (aka How I Did My Job)'/><author><name>Pamela Fox</name><uri>http://www.blogger.com/profile/15947664772001597300</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://3.bp.blogspot.com/-WwFuSHdzlfc/TYnrwXq6RrI/AAAAAAAADzE/-mpe4V3jYy0/s72-c/Screen%2Bshot%2B2011-03-23%2Bat%2B5.45.45%2BAM.png' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8501278254137514883.post-9159375869517410757</id><published>2011-03-22T17:51:00.001-07:00</published><updated>2011-03-22T18:17:20.122-07:00</updated><title type='text'>Sightseeing in Sydney: What to See, Eat, Drink, and Yell</title><content type='html'>&lt;p&gt;When I used to live in Sydney (way back 1 month ago), I often gave sightseeing tips to visiting Googlers, and I figured I'd share some of them here:&lt;/p&gt;
&lt;ul&gt;
 &lt;li&gt;&lt;a href="http://www.flickr.com/photos/pamelafox/4468940221/"&gt;&lt;img src="http://farm5.static.flickr.com/4022/4468940221_e0d3c08a62_s.jpg" align="right"&gt;&lt;/a&gt;&lt;b&gt;Visit the aquarium&lt;/b&gt;: There are lots of weird Aussie animals, like dugongs, sidenecked turtles, and platypi. It's a good option for a rainy day.
  &lt;li&gt;&lt;b&gt;Go "gold class" at the movie theater&lt;/b&gt;: It's a pricier ticket to sit in a special theater with a small number of plush throne-like seats and waiters that bring you drinks and snacks. It makes you feel damn special.
  &lt;li&gt;&lt;a href="http://www.flickr.com/photos/pamelafox/3336315069/in/set-72157614876337041/"&gt;&lt;img src="http://farm4.static.flickr.com/3302/3336315069_72f91e9e29_s.jpg" align="right"&gt;&lt;/a&gt;&lt;b&gt;Take walks&lt;/b&gt;: You must do the classic Bondi to Coogee walk (watch out for the cemetary on the way, &amp; skim the waters for dolphins). But there are tons more cool walks to do around the rather long and windy coast of Sydney. I recommend taking the ferry up to Watson's Bay and following &lt;a href="http://maps.google.com.au/maps/ms?ie=UTF8&amp;hl=en&amp;msa=0&amp;msid=109250181535574469723.00049479dcfb237bbe3b5&amp;ll=-33.849782,151.288605&amp;spn=0.023238,0.045447&amp;t=h&amp;z=15"&gt;this path&lt;/a&gt;. It takes you past the suicide cliff, then winds through an eerie forest with huge spiders, and ends up at a cute little beach.
   &lt;li&gt;&lt;b&gt;Taste wine&lt;/b&gt;: I didn't like wine before coming to Australia, but after being properly introduced to it by the Aussies, I now love it. You should try wines in the restaurants, but you should also tour wineries. From Sydney, it is a short trip to Hunter Valley for some pretty good wines. I took this  &lt;a href="http://www.boutiquewinetours.com.au/hunter-valley-wine-tours.cfm"&gt;van tour&lt;/a&gt; with a few friends.
&lt;li&gt;&lt;a href="http://www.flickr.com/photos/pamelafox/3142399223/"&gt;&lt;img src="http://farm4.static.flickr.com/3219/3142399223_4afe08281b_s.jpg" align="right"&gt;&lt;/a&gt;&lt;b&gt;Eat at the Sydney fish market&lt;/b&gt;: Go in the morning or at lunch, order some oysters and raw fish, and eat it outside. Warning: you must defend your food against the seagulls. They are &lt;b&gt;fierce&lt;/b&gt;.
   &lt;li&gt;&lt;b&gt;Try traditional "Aussie" foods&lt;/b&gt;: eat something made out of kangaroo (like a burger, which is fairly common), eat wedges with sour cream &amp; sweet chili sauce (at any pub), tim-tams (if you like sweets), oysters, and savory pies with mash and peas (most famously served at Harry's Cafe de Wheels).
&lt;/ul&gt;

&lt;p&gt;Oh, and my final tip? When you see a drunk Aussie walking down the street, yell "Aussie, Aussie, Aussie" at him (pronounced "Ozzie, ozzie, ozzie"). If he's a proper Aussie, he'll respond back with a raucous "Oy, oy, oy." Works nearly every time, and it always cracks me up.
&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8501278254137514883-9159375869517410757?l=blog.pamelafox.org' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.pamelafox.org/feeds/9159375869517410757/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=8501278254137514883&amp;postID=9159375869517410757' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8501278254137514883/posts/default/9159375869517410757'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8501278254137514883/posts/default/9159375869517410757'/><link rel='alternate' type='text/html' href='http://blog.pamelafox.org/2011/03/sightseeing-in-sydney-what-to-see-eat.html' title='Sightseeing in Sydney: What to See, Eat, Drink, and Yell'/><author><name>Pamela Fox</name><uri>http://www.blogger.com/profile/15947664772001597300</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://farm5.static.flickr.com/4022/4468940221_e0d3c08a62_t.jpg' height='72' width='72'/><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8501278254137514883.post-6090564542090079194</id><published>2011-03-22T08:21:00.000-07:00</published><updated>2011-03-22T08:29:39.089-07:00</updated><title type='text'>StartupBus: What I Learnt &amp; What I Loved</title><content type='html'>&lt;p&gt;
I've participated &amp; organized in many different programming events over the years, but nothing as crazy as &lt;a href="http://startupbus.com"&gt;StartupBus&lt;/a&gt;, an idea dreamed up by Aussie Elias Bizannes (who I met at StartupCamp, a similar event). Across the country on March 8th, a mix of developers, designers, &amp; business dev'ers boarded buses headed to Austin, Texas. We pitched ideas on the morning of the first day, formed teams over lunch, and spent the next two days coming up with a prototype. When we arrived in Austin, just in time for the start of SXSW interactive, selected teams got to pitch their startups at the semi-finals (our team &lt;a href="http://speakermeter.com"&gt;SpeakerMeter&lt;/a&gt; made it there!) and the finals (but not there), hoping to interest VCs in the potential success of their startups. 
&lt;/p&gt;
&lt;p&gt;
It was an incredible learning experience to be a part of StartupBus, and a great way to enjoy a different side of SXSW.
&lt;/p&gt;

&lt;h3&gt;What I Learnt:&lt;/h3&gt;
&lt;ul&gt;
  &lt;li&gt;&lt;b&gt;It's good to go slow.&lt;/b&gt;
  &lt;p&gt;
  When you say "make a startup in 48 hours", the typical reaction is "wow, that's not much time." But actually, we're really only coding the prototype, and most programming events these days are shorter than that. When you're not worried about fully working functionality or doing things "the right way", you can actually build quite a lot of functionality in that amount of time.
  &lt;/p&gt;
  &lt;p&gt;
  So, in fact, I felt like we were going at a much more relaxed pace on the StartupBus than at typical hackathons, and I appreciated that pace. It gave us time to actually think about what we were doing, time to debate the business plan, time to have long discussions with Xero's designer Philip about the idea, and time to completely revise the interface after that discussion. It also gave us time to take more leisurely meals, where we could get to know eachother more. (Remember: we were strangers, and now we were people spending 3 days squished next to eachother on a bus. Bonding's a good thing.)
  &lt;/p&gt;

 &lt;li&gt;&lt;b&gt;It is difficult to make webapps without a good internet connection - for more reasons than you'd think.&lt;/b&gt;
  &lt;p&gt;
 I knew that we'd be driving through uninhabited desert for most of the trip with questionable WIFI, so I tried not to propose a startups that would be too reliant on internet resources - but that's hard to do, there are few web startups these day that don't build on existing data and services. Our startup brought in Twitter and SXSW data, so we had to test that functionality at high connectivity times.&lt;/p&gt;
 &lt;p&gt;
 But I realized that I use the internet for much more than just connecting code to external websites when I'm building a webapp - I use it extensively for documentation and for problem-solving. Normally, a framework question can be answered in just a few minutes with a Google search, but with flaky wifi, that seemingly quick process can take minutes on end. If I was doing this next year, I'd download all possible framework documentation to disk, and maybe also download all of stackoverflow. :)
  &lt;/p&gt;

  &lt;li&gt;&lt;b&gt;Market research - even the most unscientific &amp; untargeted - can be damn useful.&lt;/b&gt;&lt;/li&gt;
  &lt;p&gt;
  When we stopped by in Santa Monica, the conductors gave us a challenge: walk around the streets and record video of at least three market research interviews with strangers. This admittedly freaked me out; I am quite shy by nature and hate to impose myself on other people - approaching strangers to ask them questions is the epitome of what I am afraid of doing. But, it's a part of the startup experience, so I grabbed my more balls-y teammate and hit the streets.
  &lt;/p&gt;
  &lt;p&gt;
   We had multiple folks turn our requests for an interview done, but we actually had just as many people stop and chat to us for several minutes. They were all university students (I guess they're all happy for an excuse to postpone doing assignments), so they were not a diverse market segment or even our target market segment, but they still gave us great insight into the design and intent of our startup. In fact, if I'd really listened closely to them, I might have pivoted the startup into an entirely university-oriented one - but I stuck with the original goal of solving my own problem, not theirs.
   &lt;/p&gt;
   &lt;p&gt;
   Now that I see the utility of just a bit of market research, I'm working on a survey to send out to our target market, and we're going to use the results of that survey to figure out our next steps. (Yes, I'm still working on our startup idea, as one of my numerous side projects.)
  &lt;/p&gt;

  &lt;li&gt;&lt;b&gt;There is a difference between making a webapp and making a startup.&lt;/b&gt;
  &lt;p&gt;
 I love making webapps - it's so easy these days to create something out of nothing (well, where nothing = existing libraries, frameworks, and APIs), and it's easy to share your creation with the world. But a webapp alone is not a startup. A startup is a team of people trying to make a product (often a webapp) that will gain users &amp; be profitable in some way - and those last two parts are not trivial. So we didn't just spend time on the bus coding, we also spent time marketing (tweeting &amp; blogging), doing the market research, coming up with a business plan, and drafting our pitch. &lt;/p&gt;
  &lt;p&gt;
  In retrospect, we probably could have done more of the startup stuff and less of the coding, and been more successful in terms of our visibility. It's easy for anyone to make a webapp, but it's hard for webapps to gain users that they can then be profitable from, and StartupBus is a great opportunity for potentially useful webapps to gain press and users as a result.
  &lt;/p&gt;
  &lt;p&gt;
  I went on StartupBus partially to figure out if I want to enter the startup world, or if I am content to stay in the webapp world. I still haven't quite figured that out, but at least I'm very aware that there is a difference between them.
  &lt;/p&gt;
&lt;/ul&gt;

&lt;h3&gt;What I Loved:&lt;/h3&gt;

&lt;ul&gt;
 &lt;li&gt;&lt;b&gt;I am now a part of the StartupBus community - and hopefully always will be.&lt;/b&gt;
  &lt;p&gt;
  The StartupBus founder, Elias, always likes to say that StartupBus is not so much about the actual startups made, but about the community that forms as result. The 3 days on the bus and 5 days at SXSW are an excuse for like-minded hackers &amp; entepreneurs to get to know eachother over a common experience. At SXSW, even if I didn't technically know someone, I knew I could approach them if they were wearing their StartupBus badge. Now, going forward, we feel comfortable approaching each other for business advice, for a place to crash during other tech events, for co-founder possibilities, and of course, just for hanging out.&lt;/p&gt;
  &lt;p&gt;
  Regardless of what I decide about the startup world, it's great to be a part of this incredibly passionate &amp; intelligent community.&lt;/p&gt;
&lt;/ul&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8501278254137514883-6090564542090079194?l=blog.pamelafox.org' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.pamelafox.org/feeds/6090564542090079194/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=8501278254137514883&amp;postID=6090564542090079194' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8501278254137514883/posts/default/6090564542090079194'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8501278254137514883/posts/default/6090564542090079194'/><link rel='alternate' type='text/html' href='http://blog.pamelafox.org/2011/03/startupbus-what-i-learnt-what-i-loved.html' title='StartupBus: What I Learnt &amp; What I Loved'/><author><name>Pamela Fox</name><uri>http://www.blogger.com/profile/15947664772001597300</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8501278254137514883.post-7869247506387347804</id><published>2011-03-20T09:55:00.000-07:00</published><updated>2011-04-06T14:54:13.496-07:00</updated><title type='text'>Similarity Web 2.0: Remaking My First Mashup, 5 Years Later</title><content type='html'>&lt;p&gt;One fateful summer five years ago, I accidentally stumbled upon the world of Web APIs - starting with the Amazon E-Commerce API. I was supposed to be working on a research project, but I couldn't resist the potential of the API. Amazon's catalog &amp; functionality at my fingertips? And I could do whatever I wanted with it? I just had to play with it. 
&lt;/p&gt;
&lt;p&gt;&lt;a href="http://imagine-it.org/amazong/arbore.php?XMLFileName=159184021X.xml"&gt;&lt;img style="float:right; margin:0 0 10px 10px;cursor:pointer; cursor:hand;width: 130px;" src="http://4.bp.blogspot.com/-4kKgWb8ar0A/TZzgkBbt7hI/AAAAAAAAD10/mLTcH9HEFRw/s320/Screen%2Bshot%2B2011-04-06%2Bat%2B2.51.41%2BPM.png"/&gt;&lt;/a&gt;
So I made my very first mashup: &lt;a href="http://imagine-it.org/amazong/vissimweb.htm"&gt;the Similarity Web&lt;/a&gt;. It's an app that uses the Amazon ItemLookup &amp; SimilarityLookup API calls to let you find a book &amp; visualize the web of books similar to it. It was a fun little app, and it even made me some money in referrals - especially after marketing guru Seth Godin linked to the &lt;a href="http://imagine-it.org/amazong/arbore.php?XMLFileName=159184021X.xml"&gt;"Purple Cow" web&lt;/a&gt; in his blog. Unfortunately, as it happens, Amazon deprecated the version of the ECS API that I was using, and the app stopped working. It's been on my to-do list for the last few years to revive it.
&lt;/p&gt;
&lt;p&gt;
&lt;a href="http://www.books-like-this.com/1893115941"&gt;&lt;img style="float:left; margin:0 10px 10px 10px;cursor:pointer; cursor:hand;width: 150px;" src="http://2.bp.blogspot.com/-qxV8kHOU6CY/TZzfgon5S0I/AAAAAAAAD1s/6Tb7X0AC9oM/s320/Screen%2Bshot%2B2011-04-06%2Bat%2B2.47.16%2BPM.png"/&gt;&lt;/a&gt;
Well, thanks to my former employer, I found an excuse to do just that. Google is holding &lt;a href="https://sites.google.com/site/lastcallforio2011/Home"&gt;a contest for free I/O tickets&lt;/a&gt;, and a few Fridays ago, they held the App Engine contest. After I made it through Round 1 (deploying a Fibonacci JSON-RPC service), I was presented with the Round II challenge: make an app that uses one of their more advanced APIs - blobstore, task queue, pipeline, mapper. I knew that I could use task queues in a couple different ways in Similarity Web, so at 5pm on that Friday, I started remaking it from scratch and at noon on Saturday, I submitted the &lt;a href="http://books-like-this.com/"&gt;fully functional remake&lt;/a&gt;.
&lt;/p&gt;
&lt;p&gt;
Much has changed in web development in the last 5 years - both in what I personally use and what the world uses - so I thought it'd be interesting to compare the technology stack for each version of the Similarity Web.
&lt;/p&gt;
&lt;table border="1"&gt;
 &lt;tr&gt;
  &lt;td&gt;&lt;b&gt;Hosting&lt;/b&gt;&lt;/td&gt;&lt;td&gt;&lt;a href="http://www.liquidweb.com/"&gt;LiquidWeb&lt;/a&gt; (shared hosting)&lt;/td&gt;&lt;td&gt; &lt;a href="http://code.google.com/appengine/"&gt;App Engine&lt;/a&gt;&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
  &lt;td&gt;&lt;b&gt;Backend Language&lt;/b&gt;&lt;/td&gt;&lt;td&gt;PHP&lt;/td&gt;&lt;td&gt;Python&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
  &lt;td&gt;&lt;b&gt;Amazon API&lt;/b&gt;&lt;/td&gt;&lt;td&gt;Raw HTTP calls&lt;/td&gt;&lt;td&gt;&lt;a href="http://pypi.python.org/pypi/bottlenose/0.1"&gt;Bottlenose wrapper library&lt;/a&gt;&lt;/td&gt;
  &lt;/tr&gt;
 &lt;tr&gt;
  &lt;td&gt;&lt;b&gt;Data Storage&lt;/b&gt;&lt;/td&gt;&lt;td&gt;Filesystem&lt;/td&gt;&lt;td&gt;Non-relational Datastore&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
  &lt;td&gt;&lt;b&gt;Data Format&lt;/b&gt;&lt;/td&gt;&lt;td&gt;XML&lt;/td&gt;&lt;td&gt;JSON&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
  &lt;td&gt;&lt;b&gt;Frontend Language&lt;/b&gt;&lt;/td&gt;&lt;td&gt;Pure JS&lt;/td&gt;&lt;td&gt;JS + &lt;a href="http://jquery.com"&gt;jQuery&lt;/a&gt;&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
   &lt;td&gt;&lt;b&gt;Visualization&lt;/b&gt;&lt;/td&gt;&lt;td&gt;Flash (AS2)&lt;/td&gt;&lt;td&gt;&lt;a href="http://thejit.org/"&gt;JavaScript InfoVis Toolkit&lt;/a&gt;&lt;/td&gt;
 &lt;/tr&gt;
&lt;/table&gt;

&lt;p&gt;
The general trend? The app is built on more scalable infrastructure, more web-friendly formats and standards, and more pre-existing libraries; it was faster to develop and works in more environments than before. Web development is getting better and better. Oh, and yes, I did get a Google I/O ticket! :)
&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8501278254137514883-7869247506387347804?l=blog.pamelafox.org' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.pamelafox.org/feeds/7869247506387347804/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=8501278254137514883&amp;postID=7869247506387347804' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8501278254137514883/posts/default/7869247506387347804'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8501278254137514883/posts/default/7869247506387347804'/><link rel='alternate' type='text/html' href='http://blog.pamelafox.org/2011/03/similarity-web-20-remaking-my-first.html' title='Similarity Web 2.0: Remaking My First Mashup, 5 Years Later'/><author><name>Pamela Fox</name><uri>http://www.blogger.com/profile/15947664772001597300</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://4.bp.blogspot.com/-4kKgWb8ar0A/TZzgkBbt7hI/AAAAAAAAD10/mLTcH9HEFRw/s72-c/Screen%2Bshot%2B2011-04-06%2Bat%2B2.51.41%2BPM.png' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8501278254137514883.post-746300549531144762</id><published>2011-02-28T21:28:00.000-08:00</published><updated>2011-02-28T21:34:38.531-08:00</updated><title type='text'>QuizCards: Learning While You Wait</title><content type='html'>&lt;p&gt;
As a computer user and programmer, I find myself with many "waiting" moments - seconds at a time where I am waiting for a page to load, waiting for code to compile, waiting for an app to deploy. I usually find myself using those waiting moments to read through the latest tweets in my Twitter app - but I thought to myself the other day that there must be a better use of that time. What can I do in a few seconds that might actually benefit me, instead of filling my head with mostly noise? (Not to hate on Twitter - but I think you know what I mean.) Well, I can learn something - I can learn something that only takes a few seconds - like a word or a fact. 
&lt;/p&gt;
&lt;p&gt;
That idea is what led me to create the &lt;a href="http://www.quizcards.info/"&gt;QuizCards Chrome extensions&lt;/a&gt; - interactive flash cards that are only a click away in your browser. When you install the extension, it sticks an icon in your Chrome browser bar (next to the wrench), and when you click that icon, a flash card pops up. 
&lt;/p&gt;
&lt;p&gt;&lt;img src="http://www.quizcards.info/img/screenshot_question.png"&gt;&lt;/p&gt;
&lt;p&gt;
Depending on your settings, you can answer it via multiple-choice (easiest), type-in with autocomplete, or type-in with no autocomplete (hardest). 
&lt;/p&gt;
&lt;p&gt;&lt;img src="http://www.quizcards.info/img/screenshot_typein.png"&gt;&lt;/p&gt;
&lt;p&gt;
Once you answer it, it tells you if you were right or wrong, and it keeps track of your statistics for that word. Behind the scenes, it uses the Leitner card learning system for figuring out which cards to show you next, so that it quizzes you more on the cards you know the least.
&lt;/p&gt;
&lt;p&gt;&lt;img src="http://www.quizcards.info/img/screenshot_answer.png"&gt;&lt;/p&gt;
&lt;p&gt;
There are many flash cards websites out there, but what I like about my extensions is their convenience, and their omnipresence. I don't have to remember to type in a URL, I just have to click the icon when I have a few extra moments. I feel a lot better now using my time to increase my linguistic and geographic knowledge than to increase my knowledge of tweets. And now when I do read tweets, I can spend more time to find the gems and respond to the ones that interest me.
&lt;/p&gt;
&lt;p&gt;
As for the flash cards topics: I started with &lt;a href="https://chrome.google.com/webstore/detail/nikenaeclebghemphbkfedjndafkfjan"&gt;World Capitals&lt;/a&gt;, since I'm frequently called out for not knowing world geography (despite having worked on Maps for 3 years), and then made &lt;a href="https://chrome.google.com/webstore/detail/lhjipgfbpbjcmndmdhjhpoeapdadfhmk"&gt;German vocab&lt;/a&gt;, &lt;a href="https://chrome.google.com/webstore/detail/dpcnddijflmmfjjlkcnmmbjhbkdnbhhk"&gt;Spanish vocab&lt;/a&gt;, and &lt;a href="https://chrome.google.com/webstore/detail/jlhcfbghojkmhebppenhjhhjejdcblja"&gt;U.S. Capitals&lt;/a&gt; versions. I now have an easy way of generating flash cards for any topic, provided I can easily get the question/answer data, so let me know if there's a particular topic that you'd like to learn, QuizCards-style. (If you're technical, you can also check out &lt;a href="https://github.com/pamelafox/chrome-cards"&gt;the code&lt;/a&gt; and read the README for instructions on making your own).
&lt;/p&gt;
&lt;p&gt;
You can see all of them at &lt;a href="http://www.quizcards.info/"&gt;QuizCards.info&lt;/a&gt;, and install whichever interests you. Give it a go! :)
&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8501278254137514883-746300549531144762?l=blog.pamelafox.org' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.pamelafox.org/feeds/746300549531144762/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=8501278254137514883&amp;postID=746300549531144762' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8501278254137514883/posts/default/746300549531144762'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8501278254137514883/posts/default/746300549531144762'/><link rel='alternate' type='text/html' href='http://blog.pamelafox.org/2011/02/quizcards-learning-while-you-wait.html' title='QuizCards: Learning While You Wait'/><author><name>Pamela Fox</name><uri>http://www.blogger.com/profile/15947664772001597300</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8501278254137514883.post-4477545899273071060</id><published>2011-02-15T09:43:00.000-08:00</published><updated>2011-02-15T10:00:47.201-08:00</updated><title type='text'>Translation Telephone: Having Fun with Language</title><content type='html'>&lt;p&gt;When I was a kid, I remember we often played this game we called &lt;a href="http://en.wikipedia.org/wiki/Chinese_whispers"&gt;"Telephone"&lt;/a&gt; where you'd sit in a circle, whisper a sentence into someone's ear, and they would try to understand what you said and whisper it to the next person. At the end, the original person would reveal both the original sentence and the final sentence. It was funny because the sentence would often mutate and take on new meanings at different points in the circle, depending on the interpretation skills of the listeners. 
&lt;/p&gt;
&lt;p&gt;
&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://4.bp.blogspot.com/-HCI7uaao5ns/TVq-xiWphzI/AAAAAAAADw0/4kUojjWuiMo/s1600/screenshot_messageend.jpg"&gt;&lt;img style="float:right; margin:0 0 10px 10px;cursor:pointer; cursor:hand;width: 250px;" src="http://4.bp.blogspot.com/-HCI7uaao5ns/TVq-xiWphzI/AAAAAAAADw0/4kUojjWuiMo/s320/screenshot_messageend.jpg" border="0" alt=""id="BLOGGER_PHOTO_ID_5573977247069079346" /&gt;&lt;/a&gt;
Well, since that game was fun, but I am sadly no longer surrounded by willing circles of friends, I wrote an online variation called &lt;a href="http://translation-telephone.com"&gt;"Translation Telephone"&lt;/a&gt;. Instead of using the interpretation skills of a circle friends, it uses the translation skills of &lt;a href="http://translate.google.com"&gt;Google Translate&lt;/a&gt;. After you give it a starting phrase, it translates that from one random language to another, and finally translates it back into the original language. The phrase often changes meaning into something that makes no sense or sometimes makes so much sense that it seems like a philosopher poet is underlying the system.
&lt;/p&gt;
&lt;p&gt;
For example, here ae some of my favorite transformations by Translation Telephone:
&lt;ul&gt;
 &lt;li&gt;It has a new take on inspirational quotes:
&lt;p&gt;
"Life is like a box of chocolates. You will never know what you are going to get." &amp;rarr; &lt;br&gt;
&lt;a href="http://www.translation-telephone.com/#2252"&gt;"Life is like a box of chocolates. You know how it is."&lt;/a&gt;
&lt;/p&gt;
 &lt;li&gt;It has its own opinion on political matters: 
&lt;p&gt;
"Capitalism: God's way of determining who is smart and who is poor." &amp;rarr; &lt;br&gt;
&lt;a href="http://www.translation-telephone.com/#2011"&gt;Capitalism: the path of God, what a smart decision that was wrong.
&lt;/a&gt;
&lt;/p&gt;
  &lt;li&gt;It has as many interpretations of Shakespeare as a college English class:
&lt;p&gt;
"To be. Or not to be. That is the question." &amp;rarr; &lt;br&gt;
&lt;a href="http://www.translation-telephone.com/#1213"&gt;"Challenges of life and death"&lt;/a&gt; &lt;br&gt;
&lt;a href="http://www.translation-telephone.com/#4217"&gt;"Me. There is no question."&lt;/a&gt; &lt;br&gt;
&lt;a href="http://www.translation-telephone.com/#1212"&gt;"World War II, EAR ICQ, or even worse, Sam songs"&lt;/a&gt;
 &lt;/p&gt;
&lt;/ul&gt;

&lt;p&gt;
As you can see, the funniest results are when you enter an inspirational phrase or quote that purports an opinion, as it has its way of inversing or changing the meaning in surprising ways.
&lt;/p&gt;

&lt;p&gt;
Just like in our real-life game of Telephone, there are often certain mutation points in the chain where the meaning changes more, and those points tend to be where the languages are the most different from eachother, or where they introduce words with ambiguous meanings. To make it easier for people to see where those mutations happen, I added an option to view each step translated back to the original language. 
&lt;/p&gt;
&lt;p&gt;
For example, I was surprised to see "You are my love" transform into &lt;a href="http://www.translation-telephone.com/#4235"&gt;"I have children"&lt;/a&gt;, but when I viewed the translations at each step, I realized it translated Portuguese "Tenho uma querida" (I have a darling) into "Ich habe ein Baby!" (I have a baby), and "baby" has the same ambiguous meaning in German as English. Be careful who you call your baby!
&lt;/p&gt;
&lt;p&gt;
I'm not the only one to come up with this idea  - there's a &lt;a href="http://www.conveythis.com/translation.php"&gt;"Bad Translator" site&lt;/a&gt; which translates from 10 to &lt;b&gt;50&lt;/b&gt; languages, and there's also someone who did something similar with the same name on &lt;a href="http://jinxidoru.blogspot.com/2009/03/translation-telephone.html"&gt;their personal blog&lt;/a&gt; a few years ago. I have tried to add more to this idea, however, by making every translation shareable and by letting users browse the &lt;a href="http://www.translation-telephone.com/recent"&gt;recent&lt;/a&gt; and &lt;a href="http://www.translation-telephone.com/popular"&gt;popular&lt;/a&gt; translations. At the request of an eager user, I've also created a &lt;a href="https://chrome.google.com/extensions/detail/cfocpdimpdkddnocofmcclllmjgkhngk"&gt;Chrome extension&lt;/a&gt; that gives you a right click menu for translating highlighted text. 
&lt;/p&gt;
&lt;p&gt;
To quote a review of the extension, "Translation Telephone was already a wonderful way to waste time. Now I can do it without thinking. You've destroyed any hope I ever had of being productive in my lifetime. Thank you!"
&lt;/p&gt;
&lt;p&gt;
I hope you also find Translation Telephone to be a wonderful way to waste time - and maybe a little educational too. :)
&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8501278254137514883-4477545899273071060?l=blog.pamelafox.org' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.pamelafox.org/feeds/4477545899273071060/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=8501278254137514883&amp;postID=4477545899273071060' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8501278254137514883/posts/default/4477545899273071060'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8501278254137514883/posts/default/4477545899273071060'/><link rel='alternate' type='text/html' href='http://blog.pamelafox.org/2011/02/translation-telephone-having-fun-with.html' title='Translation Telephone: Having Fun with Language'/><author><name>Pamela Fox</name><uri>http://www.blogger.com/profile/15947664772001597300</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://4.bp.blogspot.com/-HCI7uaao5ns/TVq-xiWphzI/AAAAAAAADw0/4kUojjWuiMo/s72-c/screenshot_messageend.jpg' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8501278254137514883.post-111965141516696495</id><published>2011-02-11T14:55:00.000-08:00</published><updated>2011-02-11T15:14:13.167-08:00</updated><title type='text'>Goodbye, Google; Hello, World!</title><content type='html'>&lt;p&gt;
Just over four years ago, I started working in one of the coolest departments at one of the best companies on the web: Google Developer Relations.  My job was to help developers be successful with our APIs, whatever it took. Sometimes that meant "grunt work" like spending hours trying to figure out why our API was broken in IE6, and sometimes that meant more glamorous things like traveling to exotic countries to talk about our API. Either way, it was time well spent when I could see the end result: developers doing awesome things with Google APIs. 
&lt;/p&gt;

&lt;p&gt;
It was the first and only job I've ever had, and it was the perfect job for me. I got to do so many things that I love: make things (mashups), teach people (developers) and learn things (web technology). But, as you've probably figured out from the past tense, it is no longer my job. 
&lt;/p&gt;

&lt;p&gt;
I could come up with many explanations for why I decided to leave Google, but it boils down to this: I'm ready for the next adventure. 
&lt;/p&gt;

&lt;h3&gt;What About…?&lt;/h3&gt;

&lt;p&gt;
I don't want you to worry that I've left anything at Google in an abandoned state, so here's a rundown of what I've worked on and who's on it now:&lt;/p&gt;
&lt;ul&gt;
  &lt;li&gt;&lt;b&gt;Maps API&lt;/b&gt;: Unbeknownst to the developers that still email me every day (even today!), I actually stopped working on the Maps API a year and a half ago. The Maps API team is now quite large and includes multiple support engineers that you'll see around the forums, like the very talented Chris and Luke.
  &lt;li&gt;&lt;b&gt;Wave API&lt;/b&gt;: Since Google decided not to continue the Wave project, the Wave APIs are effectively deprecated. Most of Wave is now open-source and is moving into the skilful hands of the Apache community.
  &lt;li&gt;&lt;b&gt;Shared Spaces:&lt;/b&gt; Along with several other former Wave team members, I helped launch this in Labs a few months ago. My colleagues will continue working on the ideas in that project and hopefully integrating the collaborative platform into other Google products.
  &lt;li&gt;&lt;b&gt;Google Sydney Developer Relations:&lt;/b&gt; When I came to Google Sydney, I was the only person working in Developer Relations here, and we didn't have much of a connection to the local developer scene. I decided to fix that by running events and meeting the developers here (who, as it turns out, are incredibly smart and sincere). There's now a whole Developer Relations crew in the office - Andrew on Go, Brett on Blogger, Nick on App Engine, Chris &amp; Luke on Maps - and I know they'll do a great job continuing to connect with the local developers.
&lt;/ul&gt;

&lt;br&gt;

&lt;h3&gt;What's Next…?&lt;/h3&gt;

&lt;p&gt;
I'm going nowhere in particular, or put another way, I'm going everywhere. I want to pursue the ideas in my head, I want to travel to the places I've never been, I want to see the people I haven't seen in years, I want to learn new things, I want to see where life takes me.
&lt;/p&gt;
&lt;p&gt;
I know, I know, that's vague - but on purpose. I want to make no plans, so that I can explore all the possibilities and see what makes me the happiest. Oh, and one of those possibilities includes becoming a hippie, which totally works into the "no plans" plan.
&lt;/p&gt;
I do have to somewhat decide on my location, since it appears that governments aren't into the "live wherever the hell you want with no paperwork or employment" idea. So for now, I will move back to the states, and likely live in San Francisco for a bit. (Yes, I'm a geek and I mapped where my friends live - based on marker density,  San Francisco is the optimal place to live for maximum friend visitation.)
&lt;/p&gt;

&lt;h3&gt;Thank You&lt;/h3&gt;

&lt;p&gt;
There were many things I loved about my job, but the thing I loved the best was the developers. I met so many different developers doing so many different things from so many different countries. To all the developers out there, thank you for constantly inspiring and impressing me, and thank you for making my four years on this job such a fulfilling experience.
&lt;/p&gt;

&lt;h3&gt;And I'm Off!&lt;/h3&gt;

&lt;p&gt;To quote the greatest comic strip of all time, "It's a magical world, Hobbes, ol' buddy… Let's go exploring!"&lt;/p&gt;

&lt;p&gt;:)&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8501278254137514883-111965141516696495?l=blog.pamelafox.org' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.pamelafox.org/feeds/111965141516696495/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=8501278254137514883&amp;postID=111965141516696495' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8501278254137514883/posts/default/111965141516696495'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8501278254137514883/posts/default/111965141516696495'/><link rel='alternate' type='text/html' href='http://blog.pamelafox.org/2011/02/goodbye-google-hello-world.html' title='Goodbye, Google; Hello, World!'/><author><name>Pamela Fox</name><uri>http://www.blogger.com/profile/15947664772001597300</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8501278254137514883.post-4909248403539299357</id><published>2011-01-27T04:14:00.000-08:00</published><updated>2011-01-28T22:25:07.004-08:00</updated><title type='text'>Actually Healthy Alternatives to Carb Comforts</title><content type='html'>&lt;p&gt;
According to the latest research (and a lot of the books I've been reading, like &lt;a href="http://www.amazon.com/gp/product/0982207700?tag=amazonsimilar-20"&gt;"The Primal Blueprint"&lt;/a&gt; and &lt;a href="http://www.amazon.com/gp/product/B003WUYOQ6?tag=amazonsimilar-20"&gt;"Why We Get Fat"&lt;/a&gt;), the most likely culprit for obesity and related health problems is carbohydrates.
&lt;/p&gt;
&lt;p&gt;
Unfortunately for those of us trying to get healthy, some of the foods that are highest in carbohydrates are also the foods that are staples of the western diet - bread, rice, and potatoes. If you're anything like me, you grew up on that stuff and can't imagine a life without them. But listen, here's the thing: most of the time that you're eating them, they're just an accessory - it's a holding device for our toppings, it's a convenient scooping device for our tips, it's an absorbing texture for our sauces. It doesn't make sense to consume excessive, unhealthy carbohydrates if they're just there as an accessory.
&lt;/p&gt;
&lt;p&gt;&lt;a href="http://www.amazon.com/gp/product/1740669924?tag=amazonsimilar-20"&gt;&lt;img style="float:right;" src="http://www.readings.com.au/covers/thumb/1740669924.jpg?1285642419"&gt;&lt;/a&gt;
Thankfully, clever people out there have figured out *actually* healthy alternatives for those accessories, like "cauliflower rice" and "zucchini bread." You can find the recipes for many of the alternatives online, but I discovered them through my new favorite cookbook, Jane Kennedy's &lt;a href="http://www.amazon.com/gp/product/1740669924?tag=amazonsimilar-20"&gt;"OMG! I can eat that?"&lt;/a&gt; I'm making my way through the cookbook now, and thought I would share some of what I've tried so far. Since not all of you will get the cookbook, I've linked each alternative to a similar recipe online. Try them out - you might not like all of them, but atleast you'll be aware that there are less carbalicious options out there for your favorite foods. 
&lt;/p&gt;
&lt;br&gt;
&lt;style&gt;
  .borderbottom {
    border-bottom: 1px dashed #ccc;
  }
&lt;/style&gt;
&lt;table style="clear:right"&gt; 
 &lt;tbody&gt;
  &lt;tr&gt;  
   &lt;td class="borderbottom" width="200" style="font-weight:bold"&gt;If you like... &lt;/td&gt;&lt;td class="borderbottom"  style="font-weight:bold"&gt;Then try:&lt;/td&gt;
  &lt;/tr&gt;&lt;tr&gt; 
   &lt;td&gt;&lt;b&gt;Rice&lt;/b&gt;&lt;/td&gt;
   &lt;td&gt;&lt;b&gt;&lt;a href="http://www.food.com/recipe/cauliflower-rice-low-carb-121423"&gt;Cauliflower Rice&lt;/a&gt;&lt;/b&gt;&lt;/td&gt;
  &lt;/tr&gt;&lt;tr&gt;
   &lt;td&gt;&lt;img src="http://upload.wikimedia.org/wikipedia/en/thumb/c/c8/Riceandcereal.JPG/220px-Riceandcereal.JPG" style="width:100px"/&gt;&lt;/td&gt;
   &lt;td&gt;&lt;a href="http://www.flickr.com/photos/pamelafox/5377178475/"&gt;&lt;img src="http://farm6.static.flickr.com/5045/5377178475_e681b001ff_t.jpg" /&gt;&lt;/a&gt;&lt;/td&gt;
  &lt;/tr&gt;&lt;tr&gt;
    &lt;td class="borderbottom"&gt;&lt;/td&gt;
    &lt;td class="borderbottom"&gt;I whip up a batch whenever I've made curry, like the beef/pumpkin one shown here, or my new favorite, Coconut Shrimp Curry.&lt;/td&gt;
  &lt;/tr&gt;&lt;tr&gt;
   &lt;td&gt;&lt;b&gt;Mashed Potatoes&lt;/b&gt;&lt;/td&gt;
   &lt;td&gt;&lt;b&gt;&lt;a href="http://www.grouprecipes.com/16247/mashed-cauliflower.html"&gt;Cauliflower Mash&lt;/a&gt;&lt;/b&gt;&lt;/td&gt;
  &lt;/tr&gt;&lt;tr&gt;
   &lt;td&gt;&lt;img src="http://upload.wikimedia.org/wikipedia/commons/thumb/3/39/MashedPotatoes.jpg/250px-MashedPotatoes.jpg" style="width:100px"&gt;&lt;/td&gt;
   &lt;td&gt;&lt;a href="http://www.flickr.com/photos/pamelafox/5371864255/"&gt;&lt;img src="http://farm6.static.flickr.com/5126/5371864255_a7607c87eb_t.jpg"/&gt;&lt;/a&gt;&lt;/td&gt;
  &lt;/tr&gt;&lt;tr&gt;
   &lt;td class="borderbottom"&gt;&lt;/td&gt;
   &lt;td class="borderbottom"&gt;I like to eat it with pan-fried steak and asparagus; it's a great texture complement.&lt;/td&gt;
  &lt;/tr&gt;&lt;tr&gt;
   &lt;td&gt;&lt;b&gt;Potato Chips&lt;/b&gt;&lt;/td&gt;
   &lt;td&gt;&lt;b&gt;&lt;a href="http://www.marksdailyapple.com/zucchini-chips-with-spicy-salsa/"&gt;Zucchini Chips&lt;/a&gt;&lt;/b&gt;&lt;/td&gt;
  &lt;/tr&gt;&lt;tr&gt;
   &lt;td&gt;&lt;img src="http://upload.wikimedia.org/wikipedia/commons/thumb/6/69/Potato-Chips.jpg/250px-Potato-Chips.jpg" style="width:100px"&gt;&lt;/td&gt;
   &lt;td&gt;&lt;img src="http://farm6.static.flickr.com/5209/5308383762_c759193654_t.jpg"&gt;&lt;/td&gt;
  &lt;/tr&gt;&lt;tr&gt;
   &lt;td class="borderbottom"&gt;&lt;/td&gt;
   &lt;td class="borderbottom"&gt;I make this as an afternoon snack, and dip them in homemade aioli on the side.&lt;/td&gt;
  &lt;/tr&gt;&lt;tr&gt;
   &lt;td&gt;&lt;b&gt;Pizza Crust&lt;/b&gt;&lt;/td&gt;
   &lt;td&gt;&lt;b&gt;&lt;a href="http://blog.yourlighterside.com/2009/05/zucchini-pizza-crust-recipe.html"&gt;Zucchini Pizza Crust&lt;/a&gt;&lt;/b&gt;&lt;/td&gt;
  &lt;/tr&gt;&lt;tr&gt;
   &lt;td&gt;&lt;img src="http://upload.wikimedia.org/wikipedia/commons/thumb/a/a3/Eq_it-na_pizza-margherita_sep2005_sml.jpg/220px-Eq_it-na_pizza-margherita_sep2005_sml.jpg" style="width:100px"&gt;&lt;/td&gt;
   &lt;td&gt;&lt;a href="http://www.flickr.com/photos/pamelafox/5356867394/"&gt;&lt;img src="http://farm6.static.flickr.com/5003/5356867394_2663279b23_t.jpg"&gt;&lt;/a&gt;&lt;/td&gt;
  &lt;/tr&gt;&lt;tr&gt;
   &lt;td class="borderbottom"&gt;&lt;/td&gt;
   &lt;td class="borderbottom"&gt;We piled our "crusts" high with yummy veggie and meat toppings.&lt;/td&gt;
  &lt;/tr&gt;&lt;tr&gt;
   &lt;td&gt;&lt;b&gt;Pita Bread&lt;/b&gt;&lt;/td&gt;
   &lt;td&gt;&lt;b&gt;&lt;a href="http://blog.yourlighterside.com/2009/05/zucchini-pizza-crust-recipe.html"&gt;Zucchini Pita&lt;/b&gt;&lt;/a&gt;&lt;/td&gt;
  &lt;/tr&gt;&lt;tr&gt;
   &lt;td&gt;&lt;img src="http://upload.wikimedia.org/wikipedia/en/thumb/0/01/Pitafelafel.jpg/200px-Pitafelafel.jpg" style="width:100px"&gt;&lt;/td&gt;
   &lt;td&gt;&lt;a href="http://www.flickr.com/photos/pamelafox/5369263523/"&gt;&lt;img src="http://farm6.static.flickr.com/5084/5369263523_ee84b1d3b7_t.jpg"&gt;&lt;/a&gt;&lt;/td&gt;
  &lt;/tr&gt;&lt;tr&gt;
   &lt;td class="borderbottom"&gt;&lt;/td&gt;
   &lt;td class="borderbottom"&gt;I used the same pizza crust recipe to make pitas for some Lamb Souvlaki.&lt;/td&gt;
  &lt;/tr&gt;&lt;tr&gt;
 &lt;/tbody&gt;
&lt;/table&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8501278254137514883-4909248403539299357?l=blog.pamelafox.org' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.pamelafox.org/feeds/4909248403539299357/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=8501278254137514883&amp;postID=4909248403539299357' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8501278254137514883/posts/default/4909248403539299357'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8501278254137514883/posts/default/4909248403539299357'/><link rel='alternate' type='text/html' href='http://blog.pamelafox.org/2011/01/actually-healthy-alternatives-to-carb.html' title='Actually Healthy Alternatives to Carb Comforts'/><author><name>Pamela Fox</name><uri>http://www.blogger.com/profile/15947664772001597300</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://farm6.static.flickr.com/5045/5377178475_e681b001ff_t.jpg' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8501278254137514883.post-5434305309247751795</id><published>2011-01-19T20:28:00.000-08:00</published><updated>2011-01-19T22:51:32.531-08:00</updated><title type='text'>New for Google Shared Spaces: Improved Interface, Inbox, Chrome Extension, &amp; Embedding</title><content type='html'>&lt;p&gt;Since launching &lt;a href="http://sharedspaces.googlelabs.com"&gt;Google Shared Spaces&lt;/a&gt; in Labs less than a month ago, we've been making fast iterations on the app - pushing an average of one new release each day.
&lt;/p&gt;
&lt;p&gt;
We purposefully launched Shared Spaces with the bare minimum set of features, so that we could listen to users and developers about what features they most want and need in order to benefit from this app, then implement the most desired features.
&lt;/p&gt;
&lt;p&gt;
Here's a rundown of the improvements we've made - try them out and let us know what you think!
&lt;/p&gt;

&lt;br&gt;&lt;br&gt;

&lt;h3&gt;Better, Resizeable Interface&lt;/h3&gt;
&lt;a href="http://4.bp.blogspot.com/_T1lquhCmKo8/TTfTm0Rj7TI/AAAAAAAADug/JEJZpLjvflg/s1600/screenshot_newinterface.png"&gt;&lt;img style="width: 250px; float: right;" src="http://4.bp.blogspot.com/_T1lquhCmKo8/TTfTm0Rj7TI/AAAAAAAADug/JEJZpLjvflg/s400/screenshot_newinterface.png"/&gt;&lt;/a&gt;
&lt;p&gt;We worked with &lt;a href="http://www.themaninblue.com/"&gt;Cameron Adams&lt;/a&gt;, the user interface designer behind Google Wave and cool projects like &lt;a href="http://visibletweets.com/"&gt;VisibleTweets&lt;/a&gt;, to come up with a sleeker interface for Shared Spaces. We also drew a lot of
inspiration from &lt;a href="http://ietherpad.com/"&gt;EtherPad&lt;/a&gt;, a similar tool for real-time textual collaboration.
&lt;/p&gt;
&lt;p&gt;Besides subtle style changes, the new interface moves the chat to the right-hand side and adds a full screen button, so users can work on wider width gadgets like the popular &lt;a href="http://sharedspaces.googlelabs.com/gallery/app?app_id=95001"&gt;ConceptDraw MindWave&lt;/a&gt; mind mapping tool.
&lt;/p&gt;

&lt;p&gt;(For those of you who hadn't seen it, here's a &lt;a href="http://3.bp.blogspot.com/_T1lquhCmKo8/TTfUbdo4MNI/AAAAAAAADuo/avlfFAX9-zI/s1600/google-shared-spaces-2.png"&gt;screenshot&lt;/a&gt; of the old interface.)&lt;/p&gt;

&lt;br&gt;&lt;br&gt;

&lt;h3&gt;Inbox&lt;/h3&gt;

&lt;p&gt;We launched with no way of keeping track of your spaces, figuring users could bookmark the ones they were interested in, a la Etherpad. But users (rightly) didn't want to have to worry about keeping track of their space URLs, they wanted to have a list of all their spaces in one place.
&lt;/p&gt;
&lt;p&gt;At the same time as the interface redesign, we added a universal header with your login information and a "My Spaces" link. That takes you to a list of your most recently modified spaces, with the option to view all of them and the ability to hide any of them. We know it's not a full-featured inbox like GMail's, but we think it's a sufficient way for users to manage their spaces while we build out other features.
&lt;/p&gt;

&lt;a href="http://4.bp.blogspot.com/_T1lquhCmKo8/TTfWYuswUCI/AAAAAAAADvA/leZxj_vK6Ic/s1600/screenshot_myspaces.png"&gt;&lt;img style="width: 400px; height: 130px;" src="http://4.bp.blogspot.com/_T1lquhCmKo8/TTfWYuswUCI/AAAAAAAADvA/leZxj_vK6Ic/s400/screenshot_myspaces.png"/&gt;&lt;/a&gt;

&lt;br&gt;&lt;br&gt;

&lt;h3&gt;Chrome Extension&lt;/h3&gt;

&lt;p&gt;Personally, I love to use Chrome extensions as a way to keep tabs on what's happening in my favorite communication tools without actually having to open them in a new window - Twitter, GMail, Wave, etc.
&lt;/p&gt;
&lt;p&gt;
So, we created a Chrome extension that both gives you a mini view of the gallery for quick space creation and a list of your most recently modified spaces. When someone modifies a space that you're on, the extension badge changes to let you know.
&lt;/p&gt;
&lt;a href="http://4.bp.blogspot.com/_T1lquhCmKo8/TTfUjYEJWDI/AAAAAAAADuw/5QvgQqGQ9q0/s1600/screenshot_chromeextension.png"&gt;&lt;img style="width: 400px; height: 168px;" src="http://4.bp.blogspot.com/_T1lquhCmKo8/TTfUjYEJWDI/AAAAAAAADuw/5QvgQqGQ9q0/s400/screenshot_chromeextension.png"/&gt;&lt;/a&gt;

&lt;br&gt;&lt;br&gt;

&lt;h3&gt;Embedding&lt;/h3&gt;

&lt;a href="http://1.bp.blogspot.com/_T1lquhCmKo8/TTfVp7CIgNI/AAAAAAAADu4/1s873GNVL10/s1600/screenshot_embedded.png"&gt;&lt;img style="width: 250px; float: right;" src="http://1.bp.blogspot.com/_T1lquhCmKo8/TTfVp7CIgNI/AAAAAAAADu4/1s873GNVL10/s400/screenshot_embedded.png"&gt;&lt;/a&gt;

&lt;p&gt;We live in a web where everyone, from developers to users, want to be able to mash their favorite products together. Our users asked us for the ability to embed their spaces in their webpages, on their Google Sites, and in iGoogle.&lt;/p&gt;
&lt;p&gt;For the typical case of embedding on a webpage, we launched an embed wizard that lets you tick some options and then generate a JavaScript code snippet (similar to Google Web Elements). For the Google properties (where JavaScript isn't allowed, but gadgets are), we automatically generate a gadget for each space, and we give users the URL of the gadget that they can then insert in their site or dashboard. For either method, users can click "Embed" in the space to get started. 
&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8501278254137514883-5434305309247751795?l=blog.pamelafox.org' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.pamelafox.org/feeds/5434305309247751795/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=8501278254137514883&amp;postID=5434305309247751795' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8501278254137514883/posts/default/5434305309247751795'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8501278254137514883/posts/default/5434305309247751795'/><link rel='alternate' type='text/html' href='http://blog.pamelafox.org/2011/01/new-for-google-shared-spaces-improved.html' title='New for Google Shared Spaces: Improved Interface, Inbox, Chrome Extension, &amp; Embedding'/><author><name>Pamela Fox</name><uri>http://www.blogger.com/profile/15947664772001597300</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://4.bp.blogspot.com/_T1lquhCmKo8/TTfTm0Rj7TI/AAAAAAAADug/JEJZpLjvflg/s72-c/screenshot_newinterface.png' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8501278254137514883.post-1115775421900458105</id><published>2010-12-29T12:04:00.000-08:00</published><updated>2010-12-29T12:18:50.380-08:00</updated><title type='text'>Why I Love(d) Wave</title><content type='html'>&lt;p&gt;&lt;em&gt;Note: I originally wrote this post in August, but decided not to publish it until now. I've left the text as it was then.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;As recently announced on the Google blog, Google has decided to discontinue Wave as a standalone project. As many of you know, I worked on Wave for the last year, as an advocate and support engineer for the APIs, and well, as you can imagine, I'm quite disappointed right now.
&lt;/p&gt;
&lt;p&gt;
I know that one of our failings in growing Wave usership was the inability to properly articulate what Wave is good for, and I think part of the reason is that Wave can't be simply compared to any existing service. Wave is a flexible and generic platform, one that can be used for groups discussion, for diary entries,  for event commentary,  for surveys. Of course, there are existing solutions for doing each of those things - but there is not one solution that does all of them. The thing I loved about Wave is that I could start a wave about a topic, and that wave could evolve from a survey to a discussion to a photo album (like when I asked folks what color I should dye my hair next), or be a combination of all three at once. I didn't have to know at the beginning what it would be, I didn't have to carefully weigh all the different options, I could just start a wave and see what it became. There are of course reasons for using specialized tools, like when you absolutely must have pristine formatting in a Word Document, but when you're collaborating with your group of colleagues or community of developers, I've found it's better 99% of the time to have the flexibility of Wave than the specialized features of 10 different services at once. That's why I will find it hard to stop using Wave (and I hope I don't have to), because I would have to replace it with myriad different tools.
&lt;/p&gt;
&lt;p&gt;
Because Wave is this flexible, we realized from the beginning that it should also be extendible, so that users could customize Wave for their own particular needs, and combine its conversational features with their own processes. Sure, you can do event planning with just text, but throw in a date picker gadget, RSVP gadgets and maps, and you've made planning that much more compelling. You can write your blog post drafts with just the native features of Wave, but after you throw in an approval gadget and blog post publishing robot, you've got a full blog post workflow in Wave, one that can be easily shared with your colleagues. 
&lt;/p&gt;
&lt;p&gt;
On the Wave engineering team, we had started to build extensions to streamline our own internal processes. For example, we have a system on the team where a different group of people are on-call each week, and it is their job to respond to the pages and alerts about server issues, and escalate them to other folks if they can't handle them. To supplement this system, we would create an on-call wave each week, and the on-call engineers could paste the alerts into that wave, ask questions about them, and anyone following the wave could discuss the alerts with them. To enhance this system, one of my colleagues wrote a robot that 1) created the new on-call wave each week on a chron job, adding the relevant people based on calendar entries, 2) added links to all the current server admin pages, and 3) pulled the alerts directly into the wave. So, now, we have what amounts to a semi-automated system, where a piece of software does what it's good at (bringing in structured data), and humans do what they're good at (conversing on top of that data). It really shows off the power of Wave to combine structure plus free-form conversation; to combine data plus humans.
&lt;/p&gt;
&lt;p&gt;
In Wave developer relations, we built multiple extensions to enhance our interactions with external developers. For example, we have a gallery of third-party extensions in Wave, and since we wanted that gallery to contain only user-friendly extensions, we created an App Engine app for developers to submit their extensions to the gallery. The app worked okay for storing the structured data about the pending submissions, but it was not conducive to having lengthy discussions about various aspects of an extension. As soon as I got the chance, I moved the process to Wave. Now, developers create a new submission wave, a robot fills it in with questions and fields, they answer the questions and click a button to share it with the review team. We add our own comments, and then click a button that physically puts it into the gallery. With the new wave-based process, we can get into inline discussions about their answers, I can start up private replies with my colleagues to ask for their unfiltered opinion, and we can attach images to show what we see or would like to see in the UI. We ended up with much better extensions, because we were able to have such fast and meaningful conversations -- and we didn't lose any of the structured data along the way. 
&lt;/p&gt;
&lt;p&gt;
My job is all about communication and collaboration, and that is what Wave excels in. The more I used Wave, the more I saw how Wave could make my job better, and the more I fell in love with the power and potential of Wave.
I hope that the ideas of Wave keep going, whether through other Google products or the ever-growing Wave open-source community, because I don't want to live in a world without them. 
&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8501278254137514883-1115775421900458105?l=blog.pamelafox.org' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.pamelafox.org/feeds/1115775421900458105/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=8501278254137514883&amp;postID=1115775421900458105' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8501278254137514883/posts/default/1115775421900458105'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8501278254137514883/posts/default/1115775421900458105'/><link rel='alternate' type='text/html' href='http://blog.pamelafox.org/2010/12/why-i-loved-wave.html' title='Why I Love(d) Wave'/><author><name>Pamela Fox</name><uri>http://www.blogger.com/profile/15947664772001597300</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8501278254137514883.post-3351361298169413753</id><published>2010-12-28T16:58:00.001-08:00</published><updated>2010-12-28T18:11:49.676-08:00</updated><title type='text'>Triaging Issues: The Wave-y Way</title><content type='html'>&lt;p&gt;&lt;em&gt;Note: This blog post was originally written to be posted on the Google Wave blog, but did not make it out before the cancellation of Wave. I am posting it here in case it is useful to Wave open-source developers in the future.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;In developer relations, one of our core roles is to respond to the bugs and feature requests for our APIs, and we do it both because hearing what developers want helps us shape our APIs, and because understanding the bugs that developers encounter is one of the best ways to deeply understand an API. As a general rule, we try to respond to all new issues within a week of their filing, and we usually accomplish this by holding a weekly triage meeting with colleagues to review new issues. Back when I worked on the Maps APIs, we were all in the same office, so we'd just crowd around a table with our laptops and mash through the bugs. But, now, on the Wave APIs team, my colleagues are spread entirely across the world, with me in Australia and them in both coasts of the United States. So, we needed a new way to triage, and being on the Wave team, we went the obvious route: use Wave!
&lt;/p&gt;
&lt;p&gt;
For our first weekly meeting, we simply met in a wave and pasted the untriaged issues ("Status-New") from our &lt;a href="http://code.google.com/p/google-wave-resources/issues/list"&gt;Google code issue tracker&lt;/a&gt; into the wave. Then we'd look at the issues and reply beneath the ones we were checking out to lay dibs on them, so we worked on whatever bugs were most up our technical alleys. While we were researching a particular bug and had questions about it, we could start an inline conversation beneath the bug, so in the end, we could both work in parallel and in collaboration. This way, we were able to both triage many bugs and feel confident in our triaging, since we could bounce ideas off colleagues easily during the process.
&lt;/p&gt;

&lt;p&gt;
&lt;a href="http://3.bp.blogspot.com/_T1lquhCmKo8/TRqXI1bD7oI/AAAAAAAADsg/LzOyZjdFQpI/s1600/screenshot_bugtriage_inline.png"&gt;&lt;img src="http://3.bp.blogspot.com/_T1lquhCmKo8/TRqXI1bD7oI/AAAAAAAADsg/LzOyZjdFQpI/screenshot_bugtriage_inline.png" style="width:450px"/&gt;&lt;/a&gt;
&lt;/p&gt;

&lt;p&gt;
After the first meeting, I started thinking that I could probably whip something together with our APIs that would streamline the triage process even more, and maybe make it possible for other teams to follow the same process. Around the same time, the project hosting team announced an Issue Tracker data API - perfect timing!
&lt;/p&gt;
&lt;p&gt;
So, with the powers of the &lt;a href="http://code.google.com/apis/wave/extensions/robots/index.html"&gt;Wave Robots API&lt;/a&gt; and &lt;a href="http://code.google.com/p/support/wiki/IssueTrackerAPIPython"&gt;Issue Tracker API&lt;/a&gt; Python client libraries combined, I wrote the Bug Triagey robot. When you add Triagey to a wave, the bot titles the wave with the current date and inserts a configuration gadget. That gadget lets you pick a triage template, or create a new one. In a template, you just need to specify the Google code project, the Status label, and optionally, a label to sort by. For example, my Wave APIs template specifies "google-wave-resources", "New", and "ApiType", as we try to categorize our issues by sub-APIs, and each of us specialize in different APIs.
&lt;/p&gt;


&lt;p&gt;
&lt;a href="http://2.bp.blogspot.com/_T1lquhCmKo8/TRqXPK_ZSXI/AAAAAAAADso/6VbVISUhZTs/s1600/screenshot_bugtriagey_wavedev.png"&gt;&lt;img src="http://2.bp.blogspot.com/_T1lquhCmKo8/TRqXPK_ZSXI/AAAAAAAADso/6VbVISUhZTs/screenshot_bugtriagey_wavedev.png"  style="width:450px"/&gt;&lt;/a&gt;
&lt;/p&gt;

&lt;p&gt;
After you're happy with the template, the bot loads the sorted issues into the wave, and puts dibs buttons under each one, so you can indicate if you're "Looking at" or if you've "Responded to" an issue. After clicking a button, Triagey changes the button to show your username, and after clicking the "respond" button, Triagey strikes the issue out. That way, it's easy for you to review the issues in the wave and immediately see which issues haven't been triaged yet, and who's working on what. And just like before, you can start inline conversations to discuss the bugs you're working on.
&lt;/p&gt;

&lt;p&gt;&lt;a href="http://2.bp.blogspot.com/_T1lquhCmKo8/TRqXUYAo3kI/AAAAAAAADsw/4hj0XRzJgvA/s1600/screenshot_bugtriageynew.png"&gt;&lt;img src="http://2.bp.blogspot.com/_T1lquhCmKo8/TRqXUYAo3kI/AAAAAAAADsw/4hj0XRzJgvA/screenshot_bugtriageynew.png"  style="width:450px"/&gt;&lt;/a&gt;
&lt;/p&gt;


&lt;p&gt;
Triagey is one of my favorite examples of how you can use Wave to combine automation and conversation to make collaboration easier and more efficient, and of how you can hold multiple structured conversations in a wave. To try it out yourself, install it from &lt;a href="https://wave.google.com/wave/waveref/googlewave.com/w+aaCZztk0A"&gt;this wave&lt;/a&gt;. To modify it for your own use (like to triage other items) or to see how it was built, grab the code from the &lt;a href="http://wave-samples-gallery.appspot.com/about_app?app_id=263001"&gt;samples gallery&lt;/a&gt;.
&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8501278254137514883-3351361298169413753?l=blog.pamelafox.org' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.pamelafox.org/feeds/3351361298169413753/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=8501278254137514883&amp;postID=3351361298169413753' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8501278254137514883/posts/default/3351361298169413753'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8501278254137514883/posts/default/3351361298169413753'/><link rel='alternate' type='text/html' href='http://blog.pamelafox.org/2010/12/triaging-issues-wave-y-way.html' title='Triaging Issues: The Wave-y Way'/><author><name>Pamela Fox</name><uri>http://www.blogger.com/profile/15947664772001597300</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://3.bp.blogspot.com/_T1lquhCmKo8/TRqXI1bD7oI/AAAAAAAADsg/LzOyZjdFQpI/s72-c/screenshot_bugtriage_inline.png' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8501278254137514883.post-5525738130057986227</id><published>2010-12-28T16:01:00.000-08:00</published><updated>2010-12-28T16:58:10.435-08:00</updated><title type='text'>Using App Engine to Turn Emails into waves</title><content type='html'>&lt;p&gt;&lt;em&gt;Note: This blog post was originally written to be posted on the Google Wave blog, but did not make it out before the cancellation of Wave. I am posting it here in case it is useful to Wave open-source developers in the future.
&lt;/p&gt;&lt;/em&gt;

&lt;p&gt;When I first discovered Google Wave and started working on its APIs, I realized that Wave had the potential to be a universal inbox one day, using the robots API to collect notifications from all the different inboxes and services that I use. I've since realized that many legacy services don't provide notification APIs but many of them do provide a common integration point - email - letting you specify an email address, and then sending new information to that address. Well, as it turns out, it's very easy to create an app in App Engine that can receive email at particular addresses, and then process that email. Using this technique, I can realize my dream of a universal inbox, by simply forwarding all my services to an AppEngine-powered email address, and appending the email content to a wave in my account. 
&lt;/p&gt;
&lt;p&gt;
So, I created the &lt;a href="http://wave-samples-gallery.appspot.com/about_app?app_id=283002"&gt;Mail Digester bot&lt;/a&gt; to do just that, and open-sourced &lt;a href="http://google-wave-resources.googlecode.com/svn/trunk/samples/extensions/robots/python/maildigester/"&gt;the code&lt;/a&gt; for all of you to base your own mail-receiving robots on. The app starts with a handler for all inbound emails, so it receives emails sent to any [address]@maildigester-bot.appspot.com. It then creates or finds the digest wave for the particular address, and appends a blip with the content of the email, converting any HTML emails to text. For example, if I send an email to "myemailupdates@maildigester-bot.appspot.com", and the app can't find any digest associated with "myemailupdates", it will create a new digest wave and add my wave address. The next time that I send an email to that address, it will find the wave in the datastore, and append a blip to it with the converted email. I wrote it this way so that I could easily create different addresses for different purposes and subscribe to a few different waves.
&lt;/p&gt;
&lt;a href="http://2.bp.blogspot.com/_T1lquhCmKo8/TRp-O5JSQ9I/AAAAAAAADsI/9yU0rYwiODE/s1600/cafelunch.png"&gt;&lt;img style="margin:0 0 10px 10px;cursor:pointer; cursor:hand;" src="http://2.bp.blogspot.com/_T1lquhCmKo8/TRp-O5JSQ9I/AAAAAAAADsI/9yU0rYwiODE/cafelunch.png"/&gt;&lt;/a&gt;

&lt;p&gt;
Once I created the robot, I set to work seeing how many services I could bring into Wave via email notifications. First, I set an address as the issue notification email for the &lt;a href="http://code.google.com/p/google-wave-resources/"&gt;google-wave-resources&lt;/a&gt; Google code project, so I could have a digest wave for all the issue updates. Next, I added another address as a member of the &lt;a href="http://groups.google.com/group/google-wave-api"&gt;Google-Wave-API&lt;/a&gt; google group, so I could have another digest wave for new group messages. Finally, I set another address as a Gmail forwarding address, piping all my inboxed emails into a third digest wave. I still need to pop out to Gmail or other services when I need to reply, but in fact, now that I do all my team and community collaboration inside Wave, I find I only need to respond once a day or so.
&lt;/p&gt;

&lt;a href="http://4.bp.blogspot.com/_T1lquhCmKo8/TRp-o0AsnjI/AAAAAAAADsQ/YoNUHz120pg/s1600/screenshot_maildigesternotify.png"&gt;&lt;img style="cursor:pointer; cursor:hand;" src="http://4.bp.blogspot.com/_T1lquhCmKo8/TRp-o0AsnjI/AAAAAAAADsQ/YoNUHz120pg/screenshot_maildigesternotify.png"/&gt;&lt;/a&gt;
     
&lt;p&gt;
Using the same principle of using a robot to respond to emails, several of my colleagues have built robots to respond to specific types of notifications. For example, one Wave engineer wrote an on-call robot that parses incoming pages from email and appends them to our weekly on-call wave, so that it's easy for us to discuss the contents of the page. Another food-loving colleague wrote a bot that turns the daily menus into waves, adding images of the food and rating widgets.
&lt;/p&gt;

&lt;a href="http://1.bp.blogspot.com/_T1lquhCmKo8/TRp-rtxin2I/AAAAAAAADsY/2wI1MWLpcMU/s1600/cafelunch.png"&gt;&lt;img style="cursor:pointer; cursor:hand;" src="http://1.bp.blogspot.com/_T1lquhCmKo8/TRp-rtxin2I/AAAAAAAADsY/2wI1MWLpcMU/cafelunch.png"/&gt;&lt;/a&gt;

&lt;p&gt;
Though it at first feels odd to be using email as an integral part of a wave robot, responding to email is actually a great way to integrate Wave with existing services in your organization and even add a collaboration layer on top of them. 
&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8501278254137514883-5525738130057986227?l=blog.pamelafox.org' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.pamelafox.org/feeds/5525738130057986227/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=8501278254137514883&amp;postID=5525738130057986227' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8501278254137514883/posts/default/5525738130057986227'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8501278254137514883/posts/default/5525738130057986227'/><link rel='alternate' type='text/html' href='http://blog.pamelafox.org/2010/12/using-app-engine-to-turn-emails-into.html' title='Using App Engine to Turn Emails into waves'/><author><name>Pamela Fox</name><uri>http://www.blogger.com/profile/15947664772001597300</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://2.bp.blogspot.com/_T1lquhCmKo8/TRp-O5JSQ9I/AAAAAAAADsI/9yU0rYwiODE/s72-c/cafelunch.png' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8501278254137514883.post-2943810137463677747</id><published>2010-12-28T15:52:00.000-08:00</published><updated>2010-12-28T16:00:48.731-08:00</updated><title type='text'>Issue Tracking in Wave</title><content type='html'>&lt;p&gt;&lt;em&gt;Note: This blog post was originally written to be posted on the Google Wave blog, but did not make it out before the cancellation of Wave. I am posting it here in case it is useful to Wave open-source developers in the future.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Like most folks in the software development field, we spend a fair bit of our time on the Google Wave team tracking bugs and feature requests. At Google, we use an internal tool for tracking issues, and that tool lets us set some initial info about the bug, choose its status from a set of options, set its priority level, and assign it to a colleague. From there on out, we can append comments to the issue to discuss it further. The tool works well as a way of tracking the status of bugs across many projects and people, but it doesn't work as well for working through bugs quickly, or for having more complex conversations on requests. On the other hand, Google Wave, works really well for collaborative debugging, since you can easily paste code in, attach files, and comment on each other's code, and of course, it works great have for having conversations that diverge into multiple threads. I really wanted a way to have the best of both worlds: the structured input of our tool, plus the collaborative conversations of a wave. So, we worked with a team to create the Issue Tracky extension to do just that.
&lt;/p&gt;

&lt;p&gt;
When you install Issue Tracky, you'll see both a new item in your "New Wave" drop down and an icon on your toolbar. You can use the former to create a new issue report from scratch, or you can select text in a wave and click the toolbar icon to turn it into an issue. In either case, a robot will fill the wave in with a title and info gadget, where you can pick the issue type, priority level, and assign the issue to a colleague. From there, you can add a description using all the Wave editing tools you're used to, attaching files or pasting formatted code, and then add your colleagues to the wave to discuss the issue.
&lt;/p&gt;

&lt;p&gt;
&lt;a href="http://3.bp.blogspot.com/_T1lquhCmKo8/TRp44vPo1pI/AAAAAAAADr4/eI6QC9iZzLY/s1600/screenshot_issuetracker.png"&gt;&lt;img style="margin:0 0 10px 10px;cursor:pointer; cursor:hand;" src="http://3.bp.blogspot.com/_T1lquhCmKo8/TRp44vPo1pI/AAAAAAAADr4/eI6QC9iZzLY/screenshot_issuetracker.png"/&gt;&lt;/a&gt;
&lt;/p&gt;

&lt;p&gt;The robot will automatically tag the wave based on the information in the gadget, so that you can create &lt;a href="http://googlewavedev.blogspot.com/2010/05/new-feature-make-your-waves-easier-to.html"&gt;saved searches&lt;/a&gt; for all of the bugs assigned to you (e.g. "type-bug assignee-pamelafox") or all of the high priority requests ("type-request priority-1"), and easily browse through them in weekly reviews or triage meetings.
&lt;/p&gt;

&lt;p&gt;
&lt;a href="http://3.bp.blogspot.com/_T1lquhCmKo8/TRp4-cb5SBI/AAAAAAAADsA/VvGAIjzk0vI/s1600/screenshot_bugsearch.png"&gt;&lt;img style="margin:0 0 10px 10px;cursor:pointer; cursor:hand;" src="http://3.bp.blogspot.com/_T1lquhCmKo8/TRp4-cb5SBI/AAAAAAAADsA/VvGAIjzk0vI/screenshot_bugsearch.png"/&gt;&lt;/a&gt;
&lt;/p&gt;

&lt;p&gt;
We've created a &lt;a href="https://wave.google.com/wave/waveref/googlewave.com/w+Q-LqLb29A"&gt;generic version&lt;/a&gt; of the Issue Tracky tool that anyone can play with, but we've also open-sourced the code, because we think that this is the kind of extension that companies will want to both use and customize for their own use, perhaps by integrating it with existing systems or changing the gadget to collect different pieces of information. To get started with your own version of it, &lt;a href="http://code.google.com/p/bugtracky-robot/source/checkout"&gt;download the code&lt;/a&gt; and follow the instructions in the &lt;a href="http://code.google.com/p/bugtracky-robot/source/browse/trunk/README"&gt;readme&lt;/a&gt;. If you have any questions or want to share how you've extended the codebase, stop by &lt;a href="http://code.google.com/apis/wave/forum.html"&gt;the forum&lt;/a&gt;.
&lt;/p&gt;

&lt;p&gt;
We hope this helps you have more productive discussions on the issues in your projects, and better collaboration with your teams. Enjoy! 
&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8501278254137514883-2943810137463677747?l=blog.pamelafox.org' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.pamelafox.org/feeds/2943810137463677747/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=8501278254137514883&amp;postID=2943810137463677747' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8501278254137514883/posts/default/2943810137463677747'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8501278254137514883/posts/default/2943810137463677747'/><link rel='alternate' type='text/html' href='http://blog.pamelafox.org/2010/12/issue-tracking-in-wave.html' title='Issue Tracking in Wave'/><author><name>Pamela Fox</name><uri>http://www.blogger.com/profile/15947664772001597300</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://3.bp.blogspot.com/_T1lquhCmKo8/TRp44vPo1pI/AAAAAAAADr4/eI6QC9iZzLY/s72-c/screenshot_issuetracker.png' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8501278254137514883.post-7176266443973502358</id><published>2010-12-28T14:41:00.000-08:00</published><updated>2010-12-28T15:23:04.265-08:00</updated><title type='text'>Google Shared Spaces: How We Made It</title><content type='html'>&lt;p&gt;
In my &lt;a href="http://blog.pamelafox.org/2010/12/google-shared-spaces-why.html"&gt;last post&lt;/a&gt;, I talked about &lt;b&gt;why&lt;/b&gt; we made &lt;a href="http://sharedspaces.googlelabs.com/"&gt;Google Shared Spaces&lt;/a&gt;. Now I want to talk about how we made it, as I think it may surprise a few folks. Much of the press about Shared Spaces claims that it is built off "Wave technology", when in fact, the only piece of Wave technology that Shared Spaces utilizes is the &lt;a href="http://code.google.com/apis/wave/extensions/gadgets/guide.html"&gt;Javascript Wave Gadgets API&lt;/a&gt;. Since what we set out to make was really pretty simple, we decided to start from scratch and use a combination of open-source frameworks and publicly available APIs.
&lt;/p&gt;

&lt;p&gt;
We use &lt;b&gt;&lt;a href="http://code.google.com/appengine/docs/python/overview.html"&gt;Python App Engine&lt;/a&gt;&lt;/b&gt; as the hosting platform, and &lt;b&gt;&lt;a href="http://www.djangoproject.com/"&gt;Django 1.0&lt;/a&gt;&lt;/b&gt; for the templates &amp; request handling. We embed the gadgets in the pages using the iGoogle Gadget Renderer (a deployed version of the &lt;b&gt;&lt;a href="http://shindig.apache.org/"&gt;open-source Shindig server&lt;/a&gt;&lt;/b&gt;), the gadgets communicate with the page using the Wave Gadgets JavaScript API (&lt;b&gt;&lt;a href="https://issues.apache.org/jira/browse/SHINDIG-1401"&gt;&lt;/b&gt;now open-sourced&lt;/a&gt;), and the page communicates with the server using the &lt;b&gt;&lt;a href="http://code.google.com/appengine/docs/python/channel/overview.html"&gt;Channel API&lt;/a&gt;&lt;/b&gt; (App Engine's approach to COMET). For AJAX processing and UI features, We use the &lt;b&gt;&lt;a href="http://code.google.com/apis/libraries/devguide.html#jquery"&gt;Google-hosted jQuery&lt;/a&gt;&lt;/b&gt;. For authentication, we use the &lt;b&gt;&lt;a href="http://dev.twitter.com/doc"&gt;Twitter API&lt;/a&gt;&lt;/b&gt;, &lt;b&gt;&lt;a href="http://developer.yahoo.com/social/rest_api_guide/social_dir_api.html"&gt;Yahoo API&lt;/a&gt;&lt;/b&gt;, and &lt;b&gt;&lt;a href="http://code.google.com/apis/buzz/docs/"&gt;Google Buzz API&lt;/a&gt;&lt;/b&gt;. For the comments and ratings in the gadgets gallery, we use &lt;b&gt;&lt;a href="http://www.disqus.com"&gt;Disqus&lt;/a&gt;&lt;/b&gt; threads.

&lt;p&gt;
By starting from scratch while reusing the relevant technologies out there, we were able to build the first version pretty quickly (within a few weeks), and we're also able to iterate quickly now (new releases every couple days). While the open-sourced codebase for Wave is around 250,000 lines of code, the codebase for Shared Spaces is now about 5,000. Wave is a complex technology encompassing multiple algorithms, backends, and interfaces, while Shared Spaces is a user-facing app that uses just one small part of that technology and is developed by a small team. If you pick the right tools for the right job, you can do a lot with a little. :)
&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8501278254137514883-7176266443973502358?l=blog.pamelafox.org' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.pamelafox.org/feeds/7176266443973502358/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=8501278254137514883&amp;postID=7176266443973502358' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8501278254137514883/posts/default/7176266443973502358'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8501278254137514883/posts/default/7176266443973502358'/><link rel='alternate' type='text/html' href='http://blog.pamelafox.org/2010/12/google-shared-spaces-how.html' title='Google Shared Spaces: How We Made It'/><author><name>Pamela Fox</name><uri>http://www.blogger.com/profile/15947664772001597300</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8501278254137514883.post-8557541167254748468</id><published>2010-12-28T12:41:00.000-08:00</published><updated>2010-12-28T16:03:00.695-08:00</updated><title type='text'>Google Shared Spaces: Why We Made It</title><content type='html'>&lt;p&gt;
Last week, just in time for the holidays, we released a Google Labs project called &lt;a href="http://sharedspaces.googlelabs.com/"&gt;Google Shared Spaces&lt;/a&gt;. "We" is actually just a few people working in our 20% time: &lt;a href="http://douweosinga.com/projects"&gt;Douwe Osinga&lt;/a&gt; - former Wave API tech lead, &lt;a href="http://twitter.com/tirsen"&gt;Jon Tirsen&lt;/a&gt; - former Wave contacts tech lead, &lt;a href="http://vadim.oversigma.com/"&gt;Vadim Gerasimov&lt;/a&gt; - former Gadgets API engineer, and myself - former Wave API developer advocate. As you can see, we all came from the Wave team, where we saw firsthand the ways that users used Wave and the ways that developers used the Wave APIs. Wave was a lot of things to many people, and there are a lot of directions that you could take the ideas in it. After Wave was cancelled by Google, a small team has been working on &lt;a href="http://waveprotocol.org/"&gt;open-sourcing it&lt;/a&gt; for the past 5 months, so developers can start building off the Wave technology stack, as a whole or as bits &amp; pieces, to take it in the direction of their vision.
&lt;/p&gt;
&lt;p&gt;
The four of us were personally interested in seeing what we could make with just the gadgets part of the stack. The &lt;a href="http://code.google.com/apis/wave/extensions/gadgets/guide.html"&gt;Wave Gadgets API&lt;/a&gt; is a simple but powerful API -- it combines the open-source &lt;a href="http://code.google.com/apis/gadgets/docs/dev_guide.html"&gt;gadgets API&lt;/a&gt; with a basic JavaScript API for modifying a shared state (hash map) &amp; retrieving participants information. With just a shared hash map, developers were able to make an astonishing array of gadgets - multi-player games, collaborative diagramming apps, date-picking utilities, even a Flash-like animation tool. In fact, developers made gadgets that were basically full-featured webapps, and they would take up the entirety of the Wave interface when you were using them. Developers weren't using Wave for its conversational abilities at that point -- they were just using it for the collaborative space that it enabled. Some of the developers even added a chat feature to their gadget, as users didn't want to have to scroll down past the gadget to converse with the other participants. 
&lt;/p&gt;
&lt;p&gt;The Diagram Editor gadget:&lt;br&gt;
&lt;img src="http://2.bp.blogspot.com/_TjPZfjV4gxc/S_GRQ_YbVFI/AAAAAAAAACE/eyeK1CKsI48/s1600/screenshot_full.png" style="width: 500px;"&gt;
&lt;/p&gt;
&lt;p&gt;
When we saw this happening while Wave was still an ongoing project, we thought of various ways we could improve the Wave UI for these app experiences: full-screen modes, split scrollbars, chat mode. But with Wave cancelled, we thought about how we could  start from scratch to create an experience that centered around these collaborative gadgets. At the same time, we wanted to experiment with other aspects of the Wave experience, like the sharing &amp; permissions model. And thus, Shared Spaces was born.
&lt;/p&gt;
&lt;p&gt;
Shared Spaces is entirely centered on the gadgets. The landing page is a list of featured gadgets, and each of them offers a button to "Create a space". Once you click that, you're prompted to login with either your Google, Yahoo!, or Twitter account. (We didn't see any reason to limit authentication to just Google, particularly since people might want to use Shared Spaces to collaborative with communities outside their Google sphere). You're then taken to a "space" with a list of participants (just you, to start), the selected gadget, a chat area, and a bunch of share buttons. Once you share the URL with other folks, whether via email, IM, or microblogging, you'll see the other participants show up in the list, and all of you can collaborate on the gadget together - whether that's a game of Sudoku, an RSVP gadget, or a drawing board. Much of the experience is similar to the Etherpad experience, where you can create a collaborative pad with one click, chat on the side, and share that pad by URL; I sometimes think of it as "Etherpad for gadgets."
&lt;/p&gt;
&lt;p&gt;The Yes/No/Maybe gadget:&lt;br&gt;
&lt;img style="width: 500px" src="http://1.bp.blogspot.com/_T1lquhCmKo8/TRpO3Ha4HsI/AAAAAAAADrw/N-Dj_As_WJI/google-shared-spaces-2.png" border="0"/&gt;
&lt;/p&gt;
&lt;p&gt;
We've launched Shared Spaces with what we deemed the minimal features necessary because this is very much an experiment; we want to see how users use this, what they want out of it, and what direction it may go in. Perhaps it will become a full product, or perhaps it will be integrated into existing Google products. And hey, maybe it will inspire non-Google companies to use similar technology in their products. The web is increasingly about collaboration, and I think it is always a good thing to experiment in how all of us can make collaboration easier. :)
&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8501278254137514883-8557541167254748468?l=blog.pamelafox.org' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.pamelafox.org/feeds/8557541167254748468/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=8501278254137514883&amp;postID=8557541167254748468' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8501278254137514883/posts/default/8557541167254748468'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8501278254137514883/posts/default/8557541167254748468'/><link rel='alternate' type='text/html' href='http://blog.pamelafox.org/2010/12/google-shared-spaces-why.html' title='Google Shared Spaces: Why We Made It'/><author><name>Pamela Fox</name><uri>http://www.blogger.com/profile/15947664772001597300</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://2.bp.blogspot.com/_TjPZfjV4gxc/S_GRQ_YbVFI/AAAAAAAAACE/eyeK1CKsI48/s72-c/screenshot_full.png' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8501278254137514883.post-2271119598537825317</id><published>2010-12-26T20:57:00.001-08:00</published><updated>2010-12-26T21:26:08.305-08:00</updated><title type='text'>The Costa Rica Surf Camp Experience</title><content type='html'>&lt;p&gt;I was born in California, but after an unfortunate decision from my dad, I ended up growing up in the cold confines of Syracuse, New York. I huddled for warmth in the glow of our many computers and eventually became a computer geek like my dad, but I often wondered what I would have become had I grown up in southern California instead -- and because it just looks so awesome in the movies, I always imagined myself as a surfer chick. I'm pretty happy as a computer geek these days, but I like to keep my options open, so I figured I should eventually take the first step to surfer chickdom: learning to surf. 
&lt;/p&gt;

&lt;p&gt;
Even though I've lived in California multiple times in my life, and lived in the surf kingdom of Sydney for the last two years, I somehow have never managed to get my ass on a surfboard. At one point, I figured it was just one of those things that I swore I'd always try and never actually do. (You gotta have a few of those). But in November, I serendipitously discovered that my colleague had the same wish -- and the same amount of vacation days -- and within a matter of weeks, we had arranged a weeklong trip to the &lt;a href="http://www.greeniguanasurfcamp.com/"&gt;Green Iguana Surf Camp&lt;/a&gt; in Costa Rica. We were deciding between Mexico, Australia, and Costa Rica, but eventually picked the latter because a friend recommended it, and because I've been to Costa Rica twice before &amp; have something of a massive crush on that country. (Plus, I miss speaking Spanish - it's a beautiful language and there aren't many opportunities to practice it in Sydney).
&lt;/p&gt;
&lt;p&gt;
We arrived in the surf camp in Costa Rica on December 12 and left on December 20th, and we had an amazing time in that week. We of course spent several hours each day &lt;a href="http://www.flickr.com/photos/pamelafox/5292278243/in/set-72157625553566813/"&gt;learning to surf&lt;/a&gt; -- practicing the basics of the "pop-and-hop" -- and washing off in the &lt;a href="http://www.flickr.com/photos/pamelafox/5292289929/in/set-72157625553566813/"&gt;local waterfalls&lt;/a&gt; after (they're as common as pubs are in Sydney). But we also spent a lot of time just enjoying the local culture, like:
&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;a href="http://www.flickr.com/photos/pamelafox/5292900676/in/set-72157625553566813/"&gt;
&lt;img src="http://farm6.static.flickr.com/5165/5292900676_472ebb0104_m.jpg" style="float:right"&gt;&lt;/a&gt;
&lt;b&gt;The food:&lt;/b&gt; We'd usually start our meals with an appetizer of &lt;a href="http://www.flickr.com/photos/pamelafox/5292898354/in/set-72157625553566813/"&gt;"patacones"&lt;/a&gt; (triple fried smashed plaintains) &amp; guacomole, then continue on with a "casado" (rice, beans, and a protein) or a &lt;a href="http://www.flickr.com/photos/pamelafox/5292900676/in/set-72157625553566813/"&gt;full fried red snapper&lt;/a&gt;. After surfing, we'd visit a street stand &amp; pick up a ceviche -- raw fish that cooks itself from the acids in a cup of lemon juice. On "Tuna Tuesday" at the local pub, we had &lt;a href="http://www.flickr.com/photos/pamelafox/5292300219/in/set-72157625553566813/"&gt;seared tuna in wasabi sauce&lt;/a&gt;, and it was the most delicious tuna that I've ever tasted - it melted in my mouth. Apparently Tuesday was the day they received the fresh tuna, and they wanted to sell it while it was fresh. It sure was! For snacks throughout the day, we'd walk up to our favorite fruit shop and have them cut up a pineapple (with sprinkled salt on it!) or a mango.&lt;/li&gt;
&lt;br&gt;
&lt;li&gt;
&lt;a href="http://www.flickr.com/photos/pamelafox/5294455441/"&gt;&lt;img src="http://farm6.static.flickr.com/5201/5294455441_3553c6ca91_m.jpg" style="float:right"&gt;&lt;/a&gt;
&lt;b&gt;The wildlife:&lt;/b&gt; We saw &lt;a href="http://www.flickr.com/photos/pamelafox/5294958514/in/set-72157625553566813/"&gt;lizards&lt;/a&gt; everywhere we went, including the largish "Ctenosaurs" which enjoy &lt;a href="http://www.flickr.com/photos/pamelafox/5294345355/in/set-72157625553566813/"&gt;sunning themselves on hotel &amp; restaurant roofs&lt;/a&gt; (and have an awesome dinosaur-sounding name). We also visited the local reptile park, Reptilandia, and wandered around it drinking &lt;a href="http://www.flickr.com/photos/pamelafox/5294253727/in/set-72157625553566813/"&gt;Rum &amp; Cokes from a can&lt;/a&gt; &amp; marveling in a rather tipsy way at the rather large reptiles ("OMG ANACONDA!"). Thankfully, we didn't actually see much sealife during the surfing lessons, besides the crabs scuttling to-and-from all the holes in the beach. I was happy to imagine that I was surfing in a scary-animal-free zone. :) During one visit to a fruit stand, we found ourself feeding all our banana to a very &lt;a href="http://www.flickr.com/photos/pamelafox/5294312617/in/set-72157625553566813/"&gt;adorable but aggressive Pizote&lt;/a&gt; (he showed us both his claws &amp; his puppy dog face). On our last day there, we went &lt;a href="http://www.flickr.com/photos/pamelafox/5294455441/in/set-72157625553566813/"&gt;horseback riding on a beach&lt;/a&gt;, and listened to the local birds calling in the trees (there's one that makes a sound like laughter, and it basically sounded like he was laughing at us the whole time.. as if I wasn't already lacking in confidence).
&lt;/li&gt;
&lt;br&gt;
&lt;li&gt;
&lt;a href="http://www.flickr.com/photos/pamelafox/5294914216/"&gt;
&lt;img src="http://farm6.static.flickr.com/5041/5294914216_387080c41c_m.jpg" style="float:right"&gt;
&lt;/a&gt;
&lt;b&gt;The nightlife:&lt;/b&gt; I was surprised to discover that our little town of Playa Dominical actually had a pretty thriving nightlife. Our first outing was to a Karaoke night, where the locals sang love ballad after love ballad (I say "love", but in fact most of the lyrics of the songs were much more about jealousy and rage), and we sang American classics, like "Total Eclipse of the Heart" and "I want to hold your hand". Our next outing was "Ladies Night," and the club was absolutely packed. The DJ, who we'd happened to befriend on our first day, played a mix of reggae, hiphop, house, reggaeton, and salsa. I loved dancing to that blend of genres, and I even had fun when a local led me in a salsa dance (I don't usually do partner dancing). We went out a few more times after that, and it was always a really fun atmosphere.
&lt;/li&gt;

&lt;p&gt;&lt;b&gt;And most importantly...&lt;/b&gt;&lt;/p&gt;
&lt;img style="float:right; width: 240px;" src="http://3.bp.blogspot.com/_T1lquhCmKo8/TRghNSULB0I/AAAAAAAADrc/AgtfCE6OoK8/s320/peoplepoza.PNG"&gt;
&lt;li&gt;&lt;b&gt;The people:&lt;/b&gt; Before we embarked on this experience, we thought it would mostly just be us two, and that we'd do a lot of solitary reflection and all that deep stuff. But pretty much as soon as we arrived there, we met the crew that would occupy our days going forwards: our fellow surf campers - about 7 people our age and a family with highly entertaining &lt;a href="http://www.flickr.com/photos/pamelafox/5295024182/in/set-72157625553566813/"&gt;8-yr-old&lt;/a&gt; &amp; 3 yr-old-boys, our surf instructors - 6 guys from ages 15 to 55, plus the family that runs the camp. We had a lot of fun learning to surf &amp; experiencing the local culture with that crew, but in addition to them, we also met many friendly locals -- like the boy that cut up our fruit every day or the taxi driver that snacked with us after our horseback ride. 
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;
In short, I loved every minute of the surf camp experience, even the ones where I was battling the saltwater in my eyes &amp; trying desperately to catch a wave, and I'm so thankful to the people of Playa Dominical that made it a warm &amp; welcoming place. 
&lt;/p&gt;
&lt;p&gt;
And, oh, yeah, I found out that I'm not that great of a surfer. Back to geeking I go! :)
&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8501278254137514883-2271119598537825317?l=blog.pamelafox.org' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.pamelafox.org/feeds/2271119598537825317/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=8501278254137514883&amp;postID=2271119598537825317' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8501278254137514883/posts/default/2271119598537825317'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8501278254137514883/posts/default/2271119598537825317'/><link rel='alternate' type='text/html' href='http://blog.pamelafox.org/2010/12/costa-rica-surf-camp-experience.html' title='The Costa Rica Surf Camp Experience'/><author><name>Pamela Fox</name><uri>http://www.blogger.com/profile/15947664772001597300</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://farm6.static.flickr.com/5165/5292900676_472ebb0104_t.jpg' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8501278254137514883.post-6352013053488466767</id><published>2010-12-05T01:40:00.000-08:00</published><updated>2010-12-05T01:42:08.982-08:00</updated><title type='text'>Reuseable HTML &amp; CSS Teaching Materials</title><content type='html'>&lt;p&gt;
When I decided to bring &lt;a href="http://meetup.com/girldevelopit-sydney/"&gt;GDI&lt;/a&gt; to Australia and kickstart it with an HTML &amp; CSS mini-course, I had a side goal: create reusable teaching materials. There are a huge number of online resources to help you learn web development, but there are few bundled sets of resources that can be used together to actually teach a topic to a class of students. (Or, atleast, few that I could find). I set out to make materials that I could CC-license and share with potential teachers, so that they could focus on customizing and delivering the materials instead of preparing them from scratch (which takes a surprising amount of time).
&lt;/p&gt;
&lt;p&gt;
Since delivering the materials a few months back, I have cleaned them up and theyre now online here, at a nice friendly URL:
&lt;br&gt;
&lt;a href="http://www.teaching-materials.org/htmlcss/"&gt;http://www.teaching-materials.org/htmlcss/&lt;/a&gt;
&lt;/p&gt;

&lt;p&gt;
To see what's there, you can click through the various lesson links. To actually get started re-using the material yourself, you can download the linked zip file, or if you want an easy way to host it online for your class, you can even download the &lt;a href="https://github.com/pamelafox/teaching-materials"&gt;website files from github&lt;/a&gt; and deploy them to App Engine or your own server. 
&lt;/p&gt;

&lt;p&gt;
If you do end up delivering the course (or some version of it), I would love to hear about it. We need more HTML &amp; CSS teaching in the world!  
&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8501278254137514883-6352013053488466767?l=blog.pamelafox.org' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.pamelafox.org/feeds/6352013053488466767/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=8501278254137514883&amp;postID=6352013053488466767' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8501278254137514883/posts/default/6352013053488466767'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8501278254137514883/posts/default/6352013053488466767'/><link rel='alternate' type='text/html' href='http://blog.pamelafox.org/2010/12/reuseable-html-css-teaching-materials.html' title='Reuseable HTML &amp; CSS Teaching Materials'/><author><name>Pamela Fox</name><uri>http://www.blogger.com/profile/15947664772001597300</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8501278254137514883.post-6857892585878760936</id><published>2010-11-26T23:10:00.000-08:00</published><updated>2010-11-27T00:08:50.280-08:00</updated><title type='text'>How I Bleach My Hair</title><content type='html'>&lt;p&gt;
As many people know, I am a fan of coloring my hair. It's a form of self expression and all that good stuff. Since my hair is naturally a thick dark brown (shh, don't tell my colleagues, they think I have no natural hair color), I have to bleach it before dying it most colors (except black). I'm not really a fan of salons because I don't like talking to strangers for hours, so I tend to do it myself. Since other people sometimes get inspired by my hair experimentations and want tips, I'm going to share my technique here.
&lt;/p&gt;
&lt;p&gt;First, when it comes to bleaching, I do &lt;b&gt;not&lt;/b&gt; use one of those kits with pretty people on the front. The kits are handy because they come with all the supplies you need and very specific instructions, but I find that they are not very strong - even the ones that purport to be the strongest.
&lt;/p&gt;
&lt;p&gt;
&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://4.bp.blogspot.com/_T1lquhCmKo8/TPC7XTEwMfI/AAAAAAAADps/wMTytwHxb3Q/s1600/bleachsupplies.PNG"&gt;&lt;img style="float:right; margin:0 0 10px 10px;cursor:pointer; cursor:hand;width: 227px; height: 320px;" src="http://4.bp.blogspot.com/_T1lquhCmKo8/TPC7XTEwMfI/AAAAAAAADps/wMTytwHxb3Q/s320/bleachsupplies.PNG" border="0" alt=""id="BLOGGER_PHOTO_ID_5544137150224675314" /&gt;&lt;/a&gt;
Instead, I start with bleach powder and 40 volume creme developer. The "volume" refers to the strength of the developer, and "40 volume" is the strongest that you'll find. I'm currently using Fudge brand developer and powder, which I got from the hair supplies shop at Harbourside Mall in Sydney, Australia. If you're in the US, you may want to check out &lt;a href="http://www.amazon.com/gp/product/B000G1JX38?ie=UTF8&amp;tag=amazonsimilar-20&amp;linkCode=as2&amp;camp=1789&amp;creative=390957&amp;creativeASIN=B000G1JX38"&gt;Manic Panic's 40 volume bleach kit&lt;/a&gt; instead.
&lt;/p&gt;
&lt;p&gt;I then put on cheap latex gloves and mix 1 part powder with 2 parts developer in a tupperware container (leftover from too much takeaway). If you don't mix enough, no worries, you can easily mix more later. 
&lt;/p&gt;
&lt;p&gt;Then I rub the mix over my hair, starting at the ends. Instructions always have you do the roots last, and as it turns out, that's because the chemicals process faster when they're close to the head, because your head is so warm and heats them up.
&lt;/p&gt;
&lt;p&gt;When I think that I've got everything covered (don't forget the back of your head), I go and watch a TV show for a half hour or hour. I'm used to the slight burning sensation of bleach so I tend to let it stay on for longer, but if it bothers you, you can rinse it out after just 30 minutes. 
&lt;/p&gt;
&lt;a href="http://dailybooth.com/pamelafox/10585818"&gt;
&lt;img src="http://cdn1.dailybooth.com/5/pictures/large/7a3ef929b1d5da98cad4b41db5ff29b3_10585818.jpg"&gt;
&lt;/a&gt;

&lt;p&gt;After I rinse it out and dry it, I check out how white it became, and if I missed any spots (not usually). 
&lt;/p&gt;

&lt;a href="http://dailybooth.com/pamelafox/10586764"&gt;
&lt;img src="http://cdn1.dailybooth.com/4/pictures/large/6f13216657be71af8b54edb4949d513d_10586764.jpg"&gt;
&lt;/a&gt;

&lt;p&gt;If it is still a bit yellow (as is natural with hair) and I am trying to dye it blue or just go for the very white look, then I wait for it to dry and then put a purple toner on it. A purple toner is basically a light purple hair dye that counters the natural yellow hues in human hair - so it does sometimes make your hair a bit purple-y if you overdo it (but I like that). I use one of two options these days: Fudge purple toner, or &lt;a href="http://www.consumer.schwarzkopf.com.au/index.php?id=11830"&gt;Schwarzkopf LIVE Color Silver toner&lt;/a&gt;. 
&lt;/p&gt;

&lt;a href="http://dailybooth.com/pamelafox/10591257"&gt;
&lt;img src="http://cdn1.dailybooth.com/5/pictures/large/0580f019d100dd563662a7e6edcd4a56_10591257.jpg"&gt;
&lt;/a&gt;

&lt;p&gt;If I really care about maintaining the whiteness of the color, then I sometimes invest in &lt;a href="http://www.amazon.com/gp/product/B000EVIUZC?ie=UTF8&amp;tag=amazonsimilar-20&amp;linkCode=as2&amp;camp=1789&amp;creative=390957&amp;creativeASIN=B000EVIUZC"&gt;toning shampoo&lt;/a&gt;, which is basically like shampoo with a little purple hair dye in it.
&lt;/p&gt;
&lt;p&gt;And that's it... happy bleaching!&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8501278254137514883-6857892585878760936?l=blog.pamelafox.org' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.pamelafox.org/feeds/6857892585878760936/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=8501278254137514883&amp;postID=6857892585878760936' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8501278254137514883/posts/default/6857892585878760936'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8501278254137514883/posts/default/6857892585878760936'/><link rel='alternate' type='text/html' href='http://blog.pamelafox.org/2010/11/how-i-bleach-my-hair.html' title='How I Bleach My Hair'/><author><name>Pamela Fox</name><uri>http://www.blogger.com/profile/15947664772001597300</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://4.bp.blogspot.com/_T1lquhCmKo8/TPC7XTEwMfI/AAAAAAAADps/wMTytwHxb3Q/s72-c/bleachsupplies.PNG' height='72' width='72'/><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8501278254137514883.post-6305020109148506446</id><published>2010-11-09T10:28:00.000-08:00</published><updated>2010-11-09T13:52:14.143-08:00</updated><title type='text'>GirlDevelopIt Sydney: Round 1, A Success!</title><content type='html'>&lt;p&gt;
As I &lt;a href="http://otherfancystuff.blogspot.com/2010/08/girl-develop-it-teaching-web.html"&gt;posted&lt;/a&gt; in August, &lt;a href="http://girldevelopit.com/"&gt;GirlDevelopIt&lt;/a&gt; is an initiative to increase the number of women in tech through low-cost programming workshops. It was created in New York and is thriving there (on their &lt;a href="http://www.meetup.com/girldevelopit/calendar/past_list/"&gt;27th class&lt;/a&gt; now!), and I wanted to try bringing it here to Sydney, Australia. 
&lt;/p&gt;

&lt;p&gt;
&lt;div style="float:right; text-align: center;"&gt;
&lt;a href="http://www.flickr.com/photos/katecar/5139317546/in/set-72157625170369763/"&gt;&lt;img src="http://farm5.static.flickr.com/4042/5139317546_57cfd5c679_m.jpg"&gt;&lt;/a&gt;
&lt;br&gt;Our tireless TAs
&lt;/div&gt;
We started here with the basics, a &lt;a href="http://imagine-it.org/gdi/curriculum.html"&gt;5-lesson course&lt;/a&gt; on HTML &amp; CSS, with the hope of expanding to more topics if there was enough interest. We ended up filling the room with &lt;strong&gt;40 eager female students&lt;/strong&gt; from varied backgrounds - like marketing, travel, advertising, and photography - plus &lt;strong&gt;6 super talented teaching assistants&lt;/strong&gt; of various expertise - like SEO, startups, and standards. At the end of the course, students put together their own personal website to show what they'd learnt, and it was awesome seeing the unique webpages that each of them put together.
&lt;/p&gt;

&lt;p&gt;
All in all, I would call this experiment a success, and I'm excited to see the momentum continue. We have an upcoming lecture with 30 RSVPs, we have a new offer of sponsorship (thanks to &lt;a href="http://www.thoughtworks.com/"&gt;ThoughtWorks&lt;/a&gt;), and more importantly, we have 60 members in &lt;a href="http://www.meetup.com/girldevelopit-sydney/"&gt;our meetup group&lt;/a&gt; who are all ready and willing to become women developers.
&lt;/p&gt;
&lt;p&gt;
So, if you're keen and looking to help, here's a wishlist for things that would be awesome:
&lt;/p&gt;
&lt;ul&gt;
 &lt;li&gt;We could use &lt;strong&gt;spare laptops&lt;/strong&gt; for the workshops, if you have any old ones lying around. They typically just need a web browser like Chrome and a text editor like Notepad++.
 &lt;li&gt;We would love for a hosting company to provide students in the courses with &lt;strong&gt;FTP accounts&lt;/strong&gt; and a teeny amount of disk space. We used my server for the last round, but we couldn't do more than 8 simultaneous logins on mine, so it was not ideal.
 &lt;li&gt;We can currently get 10 free books from O'Reilly for each course, but if we had a sponsor (like a bookstore) that would provide &lt;strong&gt;free books&lt;/strong&gt; for every student (~40), that would be just amazing.
 &lt;li&gt;We would love to have GDI branded &lt;strong&gt;t-shirts&lt;/strong&gt; to give to the students, to help them feel proud of their involvement and to spread the message.
&lt;/ul&gt;
&lt;p&gt;
We can always use more women students and teachers, of course, so join &lt;a href="www.meetup.com/girldevelopit-sydney"&gt;the group&lt;/a&gt; if you're keen to get involved. Onwards and upwards. :) 
&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Thanks to &lt;a href="http://katecarruthers.com/blog/about/"&gt;Kate Carruthers&lt;/a&gt; for the embedded photo.&lt;/em&gt;&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8501278254137514883-6305020109148506446?l=blog.pamelafox.org' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.pamelafox.org/feeds/6305020109148506446/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=8501278254137514883&amp;postID=6305020109148506446' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8501278254137514883/posts/default/6305020109148506446'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8501278254137514883/posts/default/6305020109148506446'/><link rel='alternate' type='text/html' href='http://blog.pamelafox.org/2010/11/girldevelopit-sydney-round-1-success.html' title='GirlDevelopIt Sydney: Round 1, A Success!'/><author><name>Pamela Fox</name><uri>http://www.blogger.com/profile/15947664772001597300</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://farm5.static.flickr.com/4042/5139317546_57cfd5c679_t.jpg' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8501278254137514883.post-336735781692215143</id><published>2010-11-01T05:49:00.000-07:00</published><updated>2010-11-01T05:57:08.447-07:00</updated><title type='text'>"No Boys Allowed"...And Why I Like It</title><content type='html'>&lt;p&gt;We just wrapped up our first Girl Develop It course in Sydney tonight. When I was first planning the course, I had males ask if they could be students and TAs, and after some consideration, I said no to them.
&lt;/p&gt;
&lt;p&gt;Part of me wanted to prove that we could pull it off with an all female ensemble. We ended up enrolling 40 female students, bringing us to full room capacity (daisy-chained power cords, ftw!), and enlisting the help of 6 highly skilled female teaching assistants, from web standards wizards to JS experts. I thus concluded that lack of "womanpower" was clearly not an issue.
&lt;/p&gt;
&lt;p&gt;The other part of me wanted to see if we could indeed have a better learning environment by having it be all female, as we suggest is the case on the &lt;a href="http://girldevelopit.com/sydney.html"&gt;Girl Develop It website&lt;/a&gt;. I was the teacher in this course, so I can only give my perspective from the front of the room. But, I have to say, I liked it. I am a straight woman, so when I am giving talks to the mostly all-male crowds at most tech events, I sense a small part of me is trying to impress a small part of them ("that way").  It's not something I'm very conscious of, as I'm usually fairly empassioned by the ideas my talk, but it is there nonetheless. When I am speaking to a group of all females, I am motivated only by the desire to educate them and not by any hidden desires. I played the part of the teacher in this course, but at the same time, I am also a student in an Afro-Brazilian dance class which is largely female. Similar to my reasoning for enjoying the absence of boys in the web dev course, I find that I enjoy the dance classes more when it is just us girls. I can shake my hips without worrying subconciously about impressing the boys in the class and having my performance affected by subsequent nervousness. 
&lt;/p&gt;
&lt;p&gt;
On a related note, it's nice to be in an environment where we can talk girl stuff and bring up "risque" topics without worrying about making boys feel awkward or wondering if they'll misinterpret our language. In dance class, we often make up rhymes about our "boobs", "hips", and "asses", and they help us learn the move... but it always feels a bit odd to teach them to boys too. That sort of thing doesn't happen as often in the web development course situation (well, maybe during the after-drinks :), but it's nice to have that kind of environment just-in-case.
&lt;/p&gt;
&lt;p&gt;
Finally, it's cool to meet local women. I have to admit that I'm not that great at making friends with girls (I grew up more around males), so I typically only make them when I'm forced to. Being in an entirely female room definitely helps as a forcing function. :) I met a bunch of awesome girls during this course and the dance class who I probably wouldnt've met otherwise, and I'm looking forward to seeing more of them.
&lt;/p&gt;
&lt;p&gt;
I know there are people who may argue that it is sexist to not allow boys into the classes, but I think that if you are going to go the "no boys" route, you should go all the way or you risk losing some of the benefits completely. This doesn't mean that I think every thing should be all girls - I will be actively encouraging the GDI students to come to mixed meetups, workshops, and user groups. It just means that I do see benefits to single-gender groups in some situations, atleast from my own personal perspective.
&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8501278254137514883-336735781692215143?l=blog.pamelafox.org' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.pamelafox.org/feeds/336735781692215143/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=8501278254137514883&amp;postID=336735781692215143' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8501278254137514883/posts/default/336735781692215143'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8501278254137514883/posts/default/336735781692215143'/><link rel='alternate' type='text/html' href='http://blog.pamelafox.org/2010/11/no-boys-allowedand-why-i-like-it.html' title='&quot;No Boys Allowed&quot;...And Why I Like It'/><author><name>Pamela Fox</name><uri>http://www.blogger.com/profile/15947664772001597300</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8501278254137514883.post-2693661568036924802</id><published>2010-10-21T17:58:00.000-07:00</published><updated>2010-10-21T18:16:47.214-07:00</updated><title type='text'>An Unofficial Guide to Geeking It Up Around Sydney</title><content type='html'>&lt;p&gt;Before I came to live in Sydney, I actually spent a day googling for information on the Sydney developer scene, learning about the local startups, user groups, and mailing lists. I didn't know anyone in Sydney, and I wanted to make sure I both had a way to get to know locals (make new friends!) and also figure out what sort of Google developer events I should organize. In just my first weekend in Sydney, I attended BarCamp Sydney 4 and met many of the people that I'm friends with today, and since then, I've attended something like 50 local meetups, "drink-ups", hackathons, and conferences.&lt;/p&gt;
&lt;p&gt;I think it's really fun to attend events from a get-to-know-others perspective and really useful to attend events from a learn-what-others-are-doing perspective, and I want to make sure every Sydney developer is aware of the events going on around them. So, for last night's Girl Geeks Dinner lightning talks, I put together a short preso on the local developer scene, and I've embedded it below. Hope to see you at an upcoming event!
&lt;/p&gt;

&lt;iframe src="https://docs.google.com/present/embed?id=dggjrx3s_373fv76p5gm&amp;size=m" frameborder="0" width="555" height="451"&gt;&lt;/iframe&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8501278254137514883-2693661568036924802?l=blog.pamelafox.org' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.pamelafox.org/feeds/2693661568036924802/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=8501278254137514883&amp;postID=2693661568036924802' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8501278254137514883/posts/default/2693661568036924802'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8501278254137514883/posts/default/2693661568036924802'/><link rel='alternate' type='text/html' href='http://blog.pamelafox.org/2010/10/unofficial-guide-to-geeking-it-up.html' title='An Unofficial Guide to Geeking It Up Around Sydney'/><author><name>Pamela Fox</name><uri>http://www.blogger.com/profile/15947664772001597300</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8501278254137514883.post-1767507178274711648</id><published>2010-10-13T23:42:00.001-07:00</published><updated>2010-10-14T00:05:48.881-07:00</updated><title type='text'>Sydney International Food Festival Maps</title><content type='html'>&lt;p&gt;
Every year, Sydney has this awesome &lt;a href="http://www.cravesydneyfoodfestival.com.au/index.php?="&gt;International Food Festival&lt;/a&gt; filled with food events and deals on meals at local restaurants. In particular, they have this &lt;a href="http://www.cravesydneyfoodfestival.com.au/events.php?intcategoryid=51&amp;linkid=101"&gt;"Lets do lunch"&lt;/a&gt; deal where you can get nice lunchtime meals at fancy restaurants for $35, and I usually like to get some colleagues together to hit up some of the restaurants. Unfortunately, they never have a map visualizing the locations of all the restaurants, and it's hard to find the places near my work.
&lt;/p&gt;
&lt;p&gt;
So, every year, I make a &lt;a href="http://imagine-it.org/letsdolunchmap.html"&gt;map&lt;/a&gt; of the restaurants. Per request of &lt;a href="http://twitter.com/MorselsMusings"&gt;@MorselsMusings&lt;/a&gt;, I've also made maps of the &lt;a href="http://imagine-it.org/cocktailsmap.html"&gt;Cocktails&lt;/a&gt;, &lt;a href="http://imagine-it.org/highteamap.html"&gt;High Tea&lt;/a&gt; and &lt;a href="http://imagine-it.org/sugarhitmap.html"&gt;Sugar Hit&lt;/a&gt; deals.
The deals last until the end of October, so check them out now while you have time!
&lt;/p&gt;
&lt;p&gt;
If you're a developer and wondering how I whipped these together, here's the short version: 1) I used &lt;a href="http://open.dapper.net"&gt;Dapper&lt;/a&gt; to get a CSV of the name, description, and link from the main page, 2) I converted those into a Google spreadsheet and used the &lt;a href="http://docs.google.com/support/bin/answer.py?hl=en&amp;answer=75507"&gt;importXML&lt;/a&gt; function to get the address from the individual restaurant page, 3) I published the sheets and got the latitude/longitude coordinates using my &lt;a href="http://gmaps-samples.googlecode.com/svn/trunk/spreadsheetsgeocoder/geocodespreadsheet.htm"&gt;Spreadsheets Geocoding&lt;/a&gt; tool, 4) I made the maps using my &lt;a href="http://gmaps-samples.googlecode.com/svn/trunk/spreadsheetsmapwizard/makecustommap.htm"&gt;Spreadsheets Maps API&lt;/a&gt; wizard. It is a bit of a process, but as I spend half my life doing this sort of thing, it doesn't actually take very long (&lt; hour).
&lt;/p&gt;
&lt;p&gt;Happy fooding!&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8501278254137514883-1767507178274711648?l=blog.pamelafox.org' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.pamelafox.org/feeds/1767507178274711648/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=8501278254137514883&amp;postID=1767507178274711648' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8501278254137514883/posts/default/1767507178274711648'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8501278254137514883/posts/default/1767507178274711648'/><link rel='alternate' type='text/html' href='http://blog.pamelafox.org/2010/10/sydney-international-food-festival-maps.html' title='Sydney International Food Festival Maps'/><author><name>Pamela Fox</name><uri>http://www.blogger.com/profile/15947664772001597300</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8501278254137514883.post-6447699800063773229</id><published>2010-10-13T22:29:00.000-07:00</published><updated>2010-10-13T22:45:59.708-07:00</updated><title type='text'>lscache: A localStorage-based, memcache-inspired library</title><content type='html'>&lt;p&gt;
Over the past few years, I've developed a fair few Python App Engine apps, and I've come to have a huge admiration for memcache. The &lt;a href="http://code.google.com/appengine/docs/python/memcache/"&gt;memcache API&lt;/a&gt; is incredibly simple, but at the same time, it's a very powerful way of making my apps scale better with increased user demand. The first time I wrote an &lt;a href="http://code.google.com/p/google-app-engine-samples/source/browse/trunk/simple-ajax-chat"&gt;App Engine app&lt;/a&gt;, it went over quota in the first 6 hours. After adding memcache support in, it never went over 1% of quota ever.  
&lt;/p&gt;
&lt;p&gt;
When I'm writing client-side apps, I find myself yearning for something like memcache to reduce my number of asynchronous server requests. HTML5 does offer the localStorage API for setting and getting key/value strings, but that API has no notion of an expiration date. It's great to be able to store copies of my data locally, but most of the time, I also want to be able to expire that data after some amount of time (5mins, 1hour, 1 day). So, I wrote a simple library called "lscache" that wraps on top of localStorage, but adds on the notion of expiration. Here's what it looks like to set and get some data:
&lt;/p&gt;

&lt;pre class="prettyprint"&gt;
lscache.set('somedata', {'name': 'Pamela'}, 60);
if (lscache.get('somedata')) {
  console.log(lscache.get('somedata').name);
}
&lt;/pre&gt;

&lt;p&gt;
The library lets you store pretty much anything, like a string, number, or object. The localStorage API only stores strings itself (though according to the spec, that should change soon), but the library uses JSON.parse and JSON.stringify to try to store non-string objects.
There are some objects that can't be stringified, like the Document object in an XMLHttpRequest, in which case you need to convert them to a simple JSON object yourself first.
&lt;/p&gt;

&lt;p&gt;
The library stores the expiration time in a separate key, and when you try to retrieve a key, it will only return it if the current time is before the expiration time (and will remove it otherwise). It calculates the time using the JavaScript &lt;code&gt;Date&lt;/code&gt; object, so it is subject to error if the user futzes with their clock - but if they do, it just means the objects will be cached for a bit less or a bit longer than expected, and the world probably won't fall over. And those silly people should stop futzing with their clock. :)
&lt;/p&gt;

&lt;p&gt;If the user's browser doesn't support localStorage, the library just won't store anything and will return null when trying to retrieve objects. This works wonderfully with the memcache style of coding, where you never assume that anything is stored, and always fall back to re-retrieving that data if it's not stored. People with "older" browsers will simply get a not-as-speedy performance.
&lt;/p&gt;

&lt;p&gt;
I've pushed the &lt;a href="http://github.com/pamelafox/lscache"&gt;lscache code&lt;/a&gt; to a github repo (my first!), and also published &lt;a href="http://pamelafox.github.com/lscache/lscache_demo.html"&gt;a demo&lt;/a&gt; of the functionality. I originally wrote lscache to speed up the performance of the XMLHttpRequests in a Chrome extension popup, but as that extension isn't published yet, I've also incorporated it into my public &lt;a href="http://www.ragetube.net"&gt;RageTube&lt;/a&gt; mashup to cache the JSON results of the Dapper and Youtube APIs. 
&lt;/p&gt;
&lt;p&gt;
Check out the library, and if you have any suggestions for improvements, feel free to fork. :)
&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8501278254137514883-6447699800063773229?l=blog.pamelafox.org' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.pamelafox.org/feeds/6447699800063773229/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=8501278254137514883&amp;postID=6447699800063773229' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8501278254137514883/posts/default/6447699800063773229'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8501278254137514883/posts/default/6447699800063773229'/><link rel='alternate' type='text/html' href='http://blog.pamelafox.org/2010/10/lscache-localstorage-based-memcache.html' title='lscache: A localStorage-based, memcache-inspired library'/><author><name>Pamela Fox</name><uri>http://www.blogger.com/profile/15947664772001597300</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8501278254137514883.post-5971518669708665155</id><published>2010-10-13T16:13:00.000-07:00</published><updated>2010-10-13T18:04:55.704-07:00</updated><title type='text'>SydJS: JavaScript Libraries Panel Roundup</title><content type='html'>&lt;p&gt;At last night's monthly meeting of &lt;a href="http://sydjs.com/"&gt;Sydney JavaScript&lt;/a&gt; developers, the organizers tried a different format: the panel. I will admit I was a little wary of the format choice, as I've heard a lot of commentary about panels not being so great (and I've attended SXSW, which seemed to re-inforce that) -- but I think it turned out quite well. The panel had a range of JS developers that represented different libraries, and articulated their differences in opinion in constructive ways. 
&lt;/p&gt;

&lt;p&gt;The panelists were:
&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;James McGill, Google, Maps API 
&lt;li&gt;Dan Nadasi, Google, Closure (&lt;a href="http://twitter.com/DanielNadasi"&gt;@DanielNadasi&lt;/a&gt;)
&lt;li&gt;Matthew Sain, Yahoo!7, YUI 2
&lt;li&gt;Tom Hughes Croucher, Yahoo!, YUI 3 (&lt;a href="http://twitter.com/sh1mmer"&gt;@sh1mmer&lt;/a&gt;)
&lt;li&gt;Dmitry Baranovskiy, Sencha, Raphael (&lt;a href="http://twitter.com/dmitrybaranovsk"&gt;@DmitryBaranovsk&lt;/a&gt;)
&lt;li&gt;Evan Trimboli, Sencha, Sencha
&lt;li&gt;Julio Ody Cesar, Awesome By Design, jQuery (&lt;a href="http://twitter.com/julio_ody"&gt;@julio_ody&lt;/a&gt;)
&lt;li&gt;Jared Wyles, Atlassian, AUI (&lt;a href="http://twitter.com/rioter"&gt;@rioter&lt;/a&gt;)
&lt;/ul&gt;

&lt;p&gt;
&lt;img src="http://farm5.static.flickr.com/4025/5078179080_82a081a64b.jpg"&gt;
&lt;br&gt;(Photo courtesy of &lt;a href="http://www.flickr.com/photos/halans/"&gt;halans&lt;/a&gt; - Check out his &lt;a href="http://www.flickr.com/photos/halans/tags/sydjs/"&gt;other SydJS pics&lt;/a&gt;.)
&lt;/p&gt;

&lt;p&gt;I typed up notes during the panel on the questions and answers, and am sharing a paraphrased version of those notes here. I didn't type anything word-for-word, and I missed some of the answers, so don't consider this to be 100% faithful. But perhaps it's useful for folks who want to remember what was discussed last night, or see the kind of questions that were asked at the panel.
&lt;/p&gt;


&lt;p&gt;&lt;b&gt;Q: Can your libraries be loaded asynchronously, and if not, how do you sleep at night?&lt;/b&gt;
&lt;br&gt;
&lt;em&gt;Tom&lt;/em&gt;: YUI was designed with that in mind from the beginning. It's the only way of loading it.
&lt;em&gt;James&lt;/em&gt;: The Maps API does it automatically - developer only includes the bootstrap and the API pulls the full library in after. All APIs should do it automatically, otherwise developers won't usually bother.
&lt;/p&gt;

&lt;p&gt;&lt;b&gt;Q: How do you test the Maps API offline?&lt;/b&gt;
&lt;br&gt;
&lt;em&gt;James&lt;/em&gt;: You must mock, and trust that we've designed our API in a way that makes for reliable mocks (we have). Check out the Closure mocking framework, based on EasyMock.
&lt;/p&gt;
&lt;p&gt;&lt;b&gt;Q: Why doesn't Google use Raphael for SVG?&lt;/b&gt;
&lt;br&gt;
&lt;em&gt;James&lt;/em&gt;: The Maps API only uses paths, and it isn't that hard to get paths working cross-browser. When you use a library, you're putting performance in someone else's hands, and the Maps API can't afford to do that.
&lt;/p&gt;
&lt;p&gt;&lt;b&gt;Q: What do you think of CoffeeScript?&lt;/b&gt;
&lt;br&gt;
&lt;em&gt;Julio&lt;/em&gt;: CoffeeScript is not equal to JavaScript. Different languages appeal to different people.
&lt;br&gt;
&lt;em&gt;Tom&lt;/em&gt;: I talked with Douglas Crockford, and he actually likes CoffeeScript, and thinks that maybe we should have done JS that way (if we could have). But now, even if we could reinvent JS, even if we could make it better, it would be a separate language. JS is winning right now, not because it's the best language ever, but because it's the language of the web. So we should stick with JS.
&lt;br&gt;
&lt;em&gt;Dmitry&lt;/em&gt;: There is real life, and there is play. I like to play- I like canvas- but I don't use canvas in real projects because it doesn't work in IE. It's not real life. It'd be sad if there was a CoffeeScript programmer that did not also know JavaScript.
&lt;/p&gt;

&lt;p&gt;&lt;b&gt;Q: What's the purpose of the Closure inspector?&lt;/b&gt;
&lt;br&gt;
&lt;em&gt;Daniel&lt;/em&gt;: It is easier to debug your Closure code before it has been obfuscated, and that's what you normally do. Some bugs, however, only occur after obfuscation, and the Closure inspector is useful for debugging the post-obfuscation bugs. Sometimes those happen when using the advanced compiler options with symbol exporting.
&lt;/p&gt;

&lt;p&gt;&lt;b&gt;Q: How will we develope JS in the future?&lt;/b&gt;
&lt;br&gt;
&lt;em&gt;Julio&lt;/em&gt;: We will see more modularization, where every page has its own miniframework, its own collection of modules used by the page.
&lt;br&gt;
&lt;em&gt;Jared&lt;/em&gt;: We will see JS in the server more.
&lt;br&gt;
&lt;em&gt;Evan&lt;/em&gt;: We will also see JS in the desktop.
&lt;br&gt;
&lt;em&gt;Dmitry&lt;/em&gt;: We will have better IDEs for developing JS.
&lt;br&gt;
&lt;em&gt;Tom&lt;/em&gt;: We will have better code, and new features of the language (like strict mode) that encourage developers to write better code.
&lt;/p&gt;

&lt;p&gt;&lt;b&gt;Q: Do you support touch events in your frameworks?&lt;/b&gt;
&lt;br&gt;
&lt;em&gt;All&lt;/em&gt;: Yes.
&lt;br&gt;
&lt;em&gt;James&lt;/em&gt;: Currently, it's not too difficult to support touch events since the mobile browsers all followed Apple's lead in implementing them and the API is the same. But, in 8 days, Microsoft is going to release Windows Phone 7, which bundles a ported version of the IE7 browser, and we don't have any idea what touch events will look like. Mobile development is going to get significantly more interesting; we're going from a 1 browser field to a 2 browser field.
&lt;/p&gt;

&lt;p&gt;&lt;b&gt;Q: What place do UI frameworks like Yuki and ExtJS have - should we be using them, and are they accessible?&lt;/b&gt;
&lt;br&gt;
 &lt;em&gt;Tom&lt;/em&gt;: ( Re accessibility) Frameworks should use ARIA for accessibility, which marks up the page to give screen readers additional info. The fact that most screen readers don't support JS is a technology failure. There's nothing inherent about JS which means it can't be supported. Current accessibility guidelines put the onus on the screen readers. Modern readers like Jaws 7 do support JS. Pick a framework that supports ARIA.
 &lt;br&gt;
 &lt;em&gt;Tom&lt;/em&gt;: (Re frameworks) Rebecca Murphy has written recently about the problems with using jQuery for enterprise sites. With libraries lik jQuery and Prototype, people tend to write DOM-focused code. With libraries YUI and Closure, people write component-based code. jQuery has done a good job of getting people started with JS and making it easy to get your site going,  but when you're building full apps, the component-based architecture with its inheritance and modules works better. DOM-style architecture gets ugly fast.
 &lt;br&gt;
 &lt;em&gt;Nadasi&lt;/em&gt;: Part of the reason we use component-based approach in Closure is because it works better at scale. In base.js, goog.inherits lets classes inherit from other classes easier. The ability to inherit is better for distributed development, for having many developers working off the same codebase. 
&lt;/p&gt;

&lt;p&gt;&lt;b&gt;Q: I come from a Java/C++ background, where tooling support is important. In moving to JS, I'm missing the tools. A lot of the times, I feel like I'm guessing-and-checking. Are you guys keeping secrets from us, or is that the way it is?&lt;/b&gt;&lt;br&gt;
  &lt;br&gt;
  &lt;em&gt;Julio&lt;/em&gt;: I work with Ruby as much as JS, and it has really nice testing tools - the best of any language I've seen. I hope JS will have similar tools somedays.
  &lt;br&gt;
  &lt;em&gt;James&lt;/em&gt;: Maybe you should check out Closure compiler. It lets you enforce static typing, which is like testing for a dynamic language - it will catch half the errors. But, in defense of JS, what other development environment lets you inspect your UI, change your UI on the fly, and reflect the changes back?
  &lt;br&gt;
  &lt;em&gt;Dan&lt;/em&gt;: Keep in mind that the cost of implementing static typing is that you lose dynamic typing. Static typing can be great for development at scale, but it deprives you of some flexibility.
  &lt;br&gt;
  &lt;em&gt;Tom&lt;/em&gt;: I recommend SpeedTracer from Google for performance checking, Firebug for Firefox, and Visual Studio Debugger for IE.
  &lt;br&gt;
  &lt;em&gt;Buchanan (audience)&lt;/em&gt;: We would love more tools for JS, but on the other hand, I've never lost a day of development due to my IDE refusing to work.
&lt;/p&gt;

&lt;p&gt;&lt;b&gt;Q: Do we need libraries now? Browsers are better, JS is easier cross-browser.&lt;/b&gt;
&lt;br&gt;
 &lt;em&gt;Julio&lt;/em&gt;: We're not at the stage yet where cross-browser isn't an issue. 
 &lt;br&gt;
 &lt;em&gt;James&lt;/em&gt;: When you're getting started with building an app, you can use libraries to take care of the hard parts for you. But once you start getting significant users, like we did with the Maps API, you'll understand their specific usage patterns, and you will find it better to write your own code that optimizes for their use case.
&lt;/p&gt;

&lt;p&gt;&lt;b&gt;Q: What was the design problem you were trying to fix when building your library?&lt;/b&gt;
&lt;br&gt;
 &lt;em&gt;Matthew&lt;/em&gt;: We designed YUI for the frontpage of yahoo.com, and then decided to open-source it for others to use.
&lt;br&gt;
 &lt;em&gt;Dmitry&lt;/em&gt;: IE has a problem with speed, it's very slow, and it has a problem with DOM, it's just fucked up.
&lt;/p&gt;

&lt;p&gt;&lt;b&gt;Q: Should we use jslint?&lt;/b&gt;
&lt;br&gt;
 &lt;em&gt;All&lt;/em&gt;: Yes.
&lt;/p&gt;

&lt;p&gt;&lt;b&gt;Q: What would you do better if you were starting over?&lt;/b&gt;
 &lt;br&gt;
  &lt;em&gt;Dan&lt;/em&gt;: With Closure, we would design API from the start instead of adding bits and pieces. The API is surprisingly consistent, likely due to having the same 2 code reviewers throughout, but it could be better. The documentation is shit. Michael Bolin's book fills in the gaps, but you shouldn't need to read a book to understand how to use it. 
  &lt;br&gt;
  &lt;em&gt;James&lt;/em&gt;: I would design the code to make it testable first, because it's hard to go back and make something testable. If I really wanted to hate my life, I would code everything in IE6 and get it working reasonable there, and *then* see how awesome it performed in other browsers.
  &lt;br&gt;
  &lt;em&gt;Evan&lt;/em&gt;: Augmenting the prototype of basic objects (Array, String, etc) was not a good idea.
&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8501278254137514883-5971518669708665155?l=blog.pamelafox.org' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.pamelafox.org/feeds/5971518669708665155/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=8501278254137514883&amp;postID=5971518669708665155' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8501278254137514883/posts/default/5971518669708665155'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8501278254137514883/posts/default/5971518669708665155'/><link rel='alternate' type='text/html' href='http://blog.pamelafox.org/2010/10/sydjs-javascript-libraries-panel.html' title='SydJS: JavaScript Libraries Panel Roundup'/><author><name>Pamela Fox</name><uri>http://www.blogger.com/profile/15947664772001597300</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://farm5.static.flickr.com/4025/5078179080_82a081a64b_t.jpg' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8501278254137514883.post-3086606601774948046</id><published>2010-10-07T22:17:00.000-07:00</published><updated>2010-10-07T23:22:28.833-07:00</updated><title type='text'>Generating Slides from a Spreadsheet</title><content type='html'>&lt;img style="float:right; margin:0 0 10px 10px;cursor:pointer; cursor:hand;width: 198px; height: 165px;" src="http://3.bp.blogspot.com/_T1lquhCmKo8/TK64cbGda8I/AAAAAAAADm8/TTuN2ITgj8Q/s400/sslides.png"/&gt;
&lt;p&gt;Lately, I've been playing around with the HTML5 slides deck from &lt;a href="http://slides.html5rocks.com"&gt;slides.html5rocks.com&lt;/a&gt;. A few months ago at the  GTUG campout, I hacked together an &lt;a href="http://otherfancystuff.blogspot.com/2010/08/5lide-html5-based-slides-maker.html"&gt;App Engine app&lt;/a&gt; for generating HTML5 slide decks. Last week, in preparation for my GDD Tokyo talk on Google's JavaScript APIs, I wrote a &lt;a href="http://pamelafox-samplecode.googlecode.com/svn/trunk/tokyotalk/slideshow.html#slide1"&gt;client-side mashup&lt;/a&gt; that generates an HTML5 slide deck based on data in a published Google spreadsheet, and used it both as my actual slides and as a demo for the talk. 
&lt;/p&gt;
&lt;br&gt;

&lt;p&gt;There are some definite benefits to writing your slide content in a spreadsheet:&lt;/p&gt;
&lt;ul&gt;
 &lt;li&gt;You can look at the revision history of just your content (instead of a confusing mix of code and content)
 &lt;li&gt;You can share the spreadsheet with other people, and collaborate on the content with them.
 &lt;li&gt;You can print the content for easy studying.
 &lt;li&gt;You can create alternate views of the same content, like differently themed slide  viewers or slide viewers that show additional columns of information.
&lt;/ul&gt;
&lt;p&gt;Of course, there are disadvantages as well - primarily the fact that Google Spreadsheets wasn't designed as a content management system, and it isn't terribly easy to author multi-line content in the cells.
&lt;/p&gt;

&lt;p&gt;In case any of you do want to try using a spreadsheet to build your slides, I've made a generalized version of the viewer that will work with any public spreadsheet.
&lt;/p&gt;
&lt;p&gt;To get started, create a spreadsheet with three columns, &lt;code&gt;'type'&lt;/code&gt;, &lt;code&gt;'title'&lt;/code&gt;, and &lt;code&gt;'content'&lt;/code&gt;. The type can either be &lt;code&gt;'intro'&lt;/code&gt;, &lt;code&gt;'normal'&lt;/code&gt;, or &lt;code&gt;'section'&lt;/code&gt;, and the title and content can be any text (inc. HTML tags). For example, check out this &lt;a href="https://spreadsheets.google.com/pub?key=0Ah0xU81penP1dHAxSklpQlI3Z3lLZ09LVU1EazRkX2c&amp;hl=en&amp;output=html"&gt;sample spreadsheet&lt;/a&gt;.
&lt;/p&gt;

&lt;p&gt;Next, publish that spreadsheet using the "Share -&amp;gt; Publish" menu in Google Spreadsheets, grab the key from the URL in the browser, and pass that as the key parameter to the &lt;a href="http://imagine-it.org/sslides/slideshow.html"&gt;generic slides viewer&lt;/a&gt;. For example, here's the URL for the sample spreadsheet:
&lt;br&gt;
&lt;a href="http://imagine-it.org/sslides/slideshow.html?key=tp1JIiBR7gyKgOKUMDk4d_g"&gt;
http://imagine-it.org/sslides/slideshow.html?key=tp1JIiBR7gyKgOKUMDk4d_g
&lt;/a&gt;
&lt;/p&gt;
&lt;p&gt;As a bonus feature, you can also include a 'narration' column in your spreadsheet, and display that narration below the slides by passing 'narration=on' to the viewer.   For example, here's the Japan talk with narration on:
&lt;br&gt;
&lt;a href="http://imagine-it.org/sslides/slideshow.html?key=0Ah0xU81penP1dDZWcmxjUjdhOTMyOGxxWXAxMnpKUWc&amp;narration=on"&gt;
http://imagine-it.org/sslides/slideshow.html?key=0Ah0xU81penP1dDZWcmxjUjdhOTMyOGxxWXAxMnpKUWc&amp;narration=on&lt;/a&gt;
&lt;/p&gt;

&lt;p&gt;As usual, I will keep experimenting with HTML-based slide viewers until I find the holy grail, so stay tuned! :)&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8501278254137514883-3086606601774948046?l=blog.pamelafox.org' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.pamelafox.org/feeds/3086606601774948046/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=8501278254137514883&amp;postID=3086606601774948046' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8501278254137514883/posts/default/3086606601774948046'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8501278254137514883/posts/default/3086606601774948046'/><link rel='alternate' type='text/html' href='http://blog.pamelafox.org/2010/10/generating-slides-from-spreadsheet.html' title='Generating Slides from a Spreadsheet'/><author><name>Pamela Fox</name><uri>http://www.blogger.com/profile/15947664772001597300</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://3.bp.blogspot.com/_T1lquhCmKo8/TK64cbGda8I/AAAAAAAADm8/TTuN2ITgj8Q/s72-c/sslides.png' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8501278254137514883.post-5931547411992560207</id><published>2010-10-05T05:04:00.000-07:00</published><updated>2010-10-07T18:33:51.019-07:00</updated><title type='text'>History of Client-side Web API Technology</title><content type='html'>&lt;p&gt;As part of GDD Tokyo last week, I gave a talk on &lt;a href="http://pamelafox-samplecode.googlecode.com/svn/trunk/tokyotalk/slideshow.html#slide1"&gt;Google's "client-side Web APIs"&lt;/a&gt;. That phrase is a bit of a mouthful (and not a common one), so here's what I mean by it: An "API" is a way for one piece of software to interact with another piece of software, a "Web API" is a way for one website to interact with another website, and a "client-side Web API" allows a website to interact with another website purely using client-side technology. For example, Google's client-side Web APIs include the Charts API (image-based), the AJAX Search APIs (JavaScript-based) and the Gadgets API (iframe-based).
&lt;/p&gt;
&lt;p&gt;
Both because I needed a way to explain the underlying technology behind our APIs and because I found it interesting, I started that talk with an intro to the history of client-side Web API technology -- the series of milestones in the evolution of the web that brought us to where we are today.
&lt;/p&gt;
&lt;p&gt;I was just a wee lass when the web was young, so I've cobbled this history together by reading old blog posts, mailing lists, tutorials, and press releases. (And yes, it is a bit Google-biased, since I have more access/knowledge of our history than others). I'm posting it here in hopes that others will learn from it &lt;em&gt;and&lt;/em&gt; others will teach me more about the early web. Please let me know in the comments if you have corrections or additions.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;It all started with...&lt;/strong&gt;&lt;/p&gt;
&lt;h3&gt;1990: HTML&lt;/h3&gt;
&lt;p&gt;In 1990, Tim Berners-Lee created the first prototype web browser and HTML page, and you can actually still view &lt;a href="http://www.w3.org/History/19921103-hypertext/hypertext/WWW/TheProject.html"&gt;that page&lt;/a&gt; today.
&lt;/p&gt;&lt;p&gt;
At this point, HTML was capable only of text and links, so we could link to other server's data, but we had no way of including it in our own page.
&lt;/p&gt;

&lt;h3&gt;1993: IMG&lt;/h3&gt;
&lt;p&gt;3 years later, Marc Andreesen was working on the &lt;a href="http://www.wired.com/thisdayintech/2010/04/0422mosaic-web-browser"&gt;NCSA Mosaic Browser&lt;/a&gt; and realized they wanted a way to include images on webpages - so he &lt;a href="http://diveintomark.org/archives/2009/11/02/why-do-we-have-an-img-element"&gt;proposed the IMG tag&lt;/a&gt;, implemented it, shipped the browser, and it's stayed to this day. That is a typical story for how HTML gains a new tag - someone needs it and implements it, others copy it, and eventually its considered part of the standard.
&lt;/p&gt;&lt;p&gt;
The IMG tag could point to image resources on external servers anywhere on the web, so it was actually the first way you could bring data from other servers onto your page, though the data had to be in image form.
&lt;/p&gt;&lt;p&gt;
Perhaps the first commonplace use of the IMG tag as an API of sorts was for "hit counters." People would put hit counters on their sites to track visitors, and each counter was actually just an IMG tag pointing at a server, passing in an ID parameter.
&lt;/p&gt;

&lt;h3&gt;1995: JavaScript&lt;/h3&gt;
&lt;p&gt;
In 1995, Netscape and Sun teamed together to &lt;a href="http://web.archive.org/web/20070916144913/http://wp.netscape.com/newsref/pr/newsrelease67.html"&gt;introduce JavaScript&lt;/a&gt;, a language they predicted would transform the web. At the time they introduced it, JavaScript could only really programmatically do the things you could already do in HTML - like programmatically creating IMG tags -- but it was an important step towards making client-side APIs more possible.
&lt;/p&gt;

&lt;h3&gt;1996: IFRAME&lt;/h3&gt;
&lt;p&gt;In 1996, Microsoft introduced the IFRAME element. The IFRAME element could embed another webpage on your page, which is one way of bringing in another server in a simplistic manner. It could also be hacked to bring data &lt;a href="http://www.pengoworks.com/index.cfm?action=articles:gatewayApip"&gt;asynchronously into a page&lt;/a&gt; from the same server, similar to what XMLHR would make possible later.
&lt;/p&gt;

&lt;h3&gt;1996: Flash&lt;/h3&gt;
&lt;p&gt;
In 1996, Macromedia launched the Flash Player plugin. The EMBED or OBJECT tags could now be used to embed a SWF file from anywhere on the web. Flash embeds meant we could embed something more interactive than just an image, like a game or animation.
&lt;/p&gt;

&lt;h3&gt;1999: XMLHttpRequest&lt;/h3&gt;
&lt;p&gt;In 1999, Microsoft innovated again by introducing the XMLHttpRequest object in JavaScript. XMLHttpRequest could make a request to your server, get data back from it, process the data, and render it into the page however it liked.
By default, you could only bring data in from your own server using XMLHttpRequest. With particular security settings in IE only, you could actually bring data in from other servers.
&lt;/p&gt;
&lt;p&gt;
XMLHttpRequest was important in getting people to think about getting data into webpages, and making them consider the possibility of getting data from servers other than their own.
&lt;/p&gt;

&lt;h3&gt;2004-5: GMail, Google Maps&lt;/h3&gt;
&lt;p&gt;
In 2004, Google &lt;a href="http://www.cnet.com.au/gmail-239145755.htm"&gt;launched GMail&lt;/a&gt;, the first popular web application that relied upon XMLHttpRequest/IFRAME for asynchronous data retrieval from the server, and really showed off what was possible with those technologies. In 2005, Google launched Google Maps, which used the same technology to transform online maps into an interactive experience.
&lt;/p&gt;


&lt;h3&gt;Feb. 2005: "AJAX"&lt;/h3&gt;
&lt;p&gt;Around the same time, Jesse James Garrett coined the term &lt;a href="http://en.wikipedia.org/wiki/Ajax_(programming)#History"&gt;"AJAX"&lt;/a&gt; to describe the new GMail-style of applications which fetch data asynchronously using XMLHR and reduce the time users spend waiting on page loads. 
After he coined the term and popular JS libraries built in support for XMLHR, it quickly rose in popularity amongst web developers as the new, right way to build web applications.&lt;/p&gt;
&lt;p&gt;
We were still limited to using AJAX to just getting data from our own domain, however.
&lt;/p&gt;

&lt;h3&gt;June 2005: Google Maps API&lt;/h3&gt;
&lt;p&gt;
A few months later, Google launched &lt;a href="http://googleblog.blogspot.com/2005/06/world-is-your-javascript-enabled_29.html"&gt;version 1 of the Google Maps API&lt;/a&gt;, the first JavaScript API by Google and also one of the first JS APIs by a big company. This first API was really a JavaScript library that would dynamically create IMGs for each map tile, position them with CSS, and make it easy to add control DIVs and marker IMGs. Developers would typically use the Maps API in conjunction with AJAX requests to get map data from databases on their server.
&lt;/p&gt;


&lt;h3&gt;Dec. 2005: "JSONP"&lt;/h3&gt;
&lt;p&gt;In December 2005, Bob Ippolitto wrote &lt;a href="http://bob.pythonmac.org/archives/2005/12/05/remote-json-jsonp/"&gt;a blog post&lt;/a&gt; describing a technique he named "JSONP", which used ("hacked") the SCRIPT tag to asynchronously bring data in from other servers.
&lt;/p&gt;
&lt;p&gt;
Finally, with JSONP, we had a way to bring data in from another server without using a server ourselves - as long as that server provides JSONP-compatible output.
&lt;/p&gt;

&lt;h3&gt;May 2006: Google AJAX Search API&lt;/h3&gt;
&lt;p&gt;Next year, Google &lt;a href="http://googlecode.blogspot.com/2006/05/mash-up-search-results-with-google.html"&gt;launched the Google AJAX Search API&lt;/a&gt;, which let you embed a Google search box on your site and display the results there, without ever having to leave the site. Since this API needed to get data from Google servers while being used on any domain, it used JSONP behind the scenes and wrapped it up in some JavaScript functions.
&lt;/p&gt;
&lt;p&gt;
This was one of the first APIs that used JSONP to let developers get data from other servers and include it on their site, and paved the way for others.
&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;And that bring us to...&lt;/strong&gt;&lt;/p&gt;

&lt;h3&gt;Present-day: Client-side Web API Technology&lt;/h3&gt;
&lt;p&gt;Thanks to the contributions to HTML/JS over the years, we now have these technologies to power client-side Web APIs:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Images
&lt;li&gt;Iframes
&lt;li&gt;JavaScript
&lt;li&gt;JSONP
&lt;li&gt;Flash 
&lt;/ul&gt;

&lt;p&gt;&lt;em&gt;Note: It has been pointed out in comments that other plugin technologies are also important in this history, and used as or inside APIs, like Java Applets and Silverlight. ActiveX scripting also has a part. We do not use these particular technologies in Google client-side Web APIs, but I will look into their history and update this when I have the chance.&lt;/em&gt;
&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8501278254137514883-5931547411992560207?l=blog.pamelafox.org' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.pamelafox.org/feeds/5931547411992560207/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=8501278254137514883&amp;postID=5931547411992560207' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8501278254137514883/posts/default/5931547411992560207'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8501278254137514883/posts/default/5931547411992560207'/><link rel='alternate' type='text/html' href='http://blog.pamelafox.org/2010/10/history-of-client-side-web-apis.html' title='History of Client-side Web API Technology'/><author><name>Pamela Fox</name><uri>http://www.blogger.com/profile/15947664772001597300</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8501278254137514883.post-818392285025061805</id><published>2010-09-22T20:43:00.001-07:00</published><updated>2010-09-22T20:58:29.495-07:00</updated><title type='text'>RageTube: Using APIs to Bring Music Video Playlists Online</title><content type='html'>&lt;p&gt;
As I've mentioned in other posts, I have a thing for music videos. Whenever I visit a new foreign country, I try to find the local music videos channel and learn about their culture entirely through hours glued to the channel (it kind of works!). In Australia, I eventually discovered &lt;a href="http://www.abc.net.au/rage/"&gt;Rage&lt;/a&gt;, a 6-hour long stretch of music videos that plays every Friday night, Saturday morning, and Saturday night (midnight to 6am!). I did my best to reorganize my life so that I could catch atleast one of the 6-hour stretches each weekend, but alas, I eventually acquired hobbies and the semblance of a social life. At the same time, I've been increasingly disappointed with my worktime music options here &amp;mdash; I can't use Pandora (US only), can't use Spotify (Europe only), and have had mixed success with Grooveshark. So, I decided to kill two birds with one stone, and make a mashup that'd let me watch Rage during the day in the form of Youtube music videos: &lt;a href="http://pamelafox-samplecode.googlecode.com/svn/trunk/ragetube/ragetube.html"&gt;RageTube&lt;/a&gt;!
&lt;/p&gt;
&lt;p&gt;
To use RageTube, you provide a URL to any playlist from the &lt;a href="http://www.abc.net.au/rage/playlist/" target="_blank"&gt;Rage archives&lt;/a&gt; and it will take care of finding music videos on Youtube for all of the songs and playing through the list one at-a-time. You can skip through songs you don't like with the "Next" button, or you can click ahead or back to videos that you want to watch immediately. Plus, if you want to remember what songs you liked (or hated!), you can click the "Yay", "Meh", or "Nay" ratings widget and see your rating displayed in the playlist. That makes it even easier to find favorite videos to skip to later.
&lt;/p&gt;
&lt;p&gt;
I wrote RageTube on a Monday morning and after sharing it on Twitter, I've discovered that there are quite a few Rage fans that are happy to have a way to enjoy Rage at work, including a few of my Australian colleagues abroad that never get the chance to watch Rage on TV anymore. I've added a few features since the initial version, like the ratings widgets, share-by-URL, and support for older playlists, but I still have much room to improve it, like by adding a playlist picker and playlist ratings.
&lt;/p&gt;
&lt;p&gt;
Now, I have to admit I didn't write RageTube just because I needed a better music option at work &amp;mdash; I also plan to use it as a demo in my upcoming GDD Tokyo Talk to showcase how much is possible with just the Google JavaScript APIs. The entire mashup is client-side - one HTML and 2 JS files - and it relies on 3 different JS APIs as well as some HTML5 functionality.
&lt;/p&gt;
&lt;p&gt;
For those interested, here's how it works behind the scenes:
&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;When you enter a URL, I send that URL through &lt;a href="http://open.dapper.net" target="_blank"&gt;open.dapper.net&lt;/a&gt;,  service that screen-scrapes websites and gives you the desired nodes in the format of your choice. I fetch the JSON format using a &lt;a href="http://www.nonobtrusive.com/2010/05/20/lightweight-jsonp-without-any-3rd-party-libraries/" target="_blank"&gt;lightweight JSONP library&lt;/a&gt;. I store the song and title in an internal JS array and render them out as a scrollable list.&lt;br /&gt;
&lt;pre class="prettyprint"&gt;
var dappUrl = 'http://open.dapper.net/transform.php';
var params = {'dappName': dappName, 'transformer': 'JSON', 'applyToUrl': playlistUrl}
JSONP.get(dappUrl, params, function(json) {
  ....
});
&lt;/pre&gt;
&lt;li&gt;
I then try to play the first song, and when I discover that there's no youtube ID stored in in the internal array (as will be the case for the first song), I use the &lt;a href="http://code.google.com/apis/youtube/2.0/developers_guide_jsonc.html" target="_blank"&gt;Youtube JSON-C API&lt;/a&gt; to find the first matching video.&lt;br /&gt;
&lt;pre class="prettyprint"&gt;
var query = song.artist + ' ' + song.title;
var searchUrl = 'http://gdata.youtube.com/feeds/api/videos';
var params = {'v': '2',  'alt': 'jsonc',  'q': query}
JSONP.get(searchUrl, params, function(json) {
  song.results = json.data.items;
  song.youtubeId = json.data.items[0].id;
  ...
});
&lt;/pre&gt;
&lt;li&gt;
The first time that I play a video, I embed the &lt;a href="http://code.google.com/apis/youtube/player_parameters.html" target="_blank"&gt;Youtube player SWF&lt;/a&gt; in the page using &lt;a href="http://code.google.com/p/swfobject/wiki/hosted_library" target="_blank"&gt;SWFObject&lt;/a&gt;, specifying a few parameters that will make it possible for me to use JavaScript to interact with that player later using the &lt;a href="http://code.google.com/apis/youtube/js_api_reference.html" target="_blank"&gt;Youtube Player API&lt;/a&gt;.&lt;br /&gt;
&lt;pre class="prettyprint"&gt;
var params = {allowScriptAccess: 'always', allowFullScreen: 'true'};
var atts = {id: 'youtubeplayer'};
swfobject.embedSWF('http://www.youtube.com/v/' + song.youtubeId +
 '?autoplay=1&amp;amp;fs=1&amp;amp;enablejsapi=1&amp;amp;playerapiid=ytplayer',
 'videoBlock', '425', '356', '8', null, null, params, atts);
&lt;/pre&gt;
&lt;li&gt;
Once I get programmatic access to the player, I &lt;a href="http://code.google.com/apis/youtube/js_api_reference.html#SubscribingEvents" target="_blank"&gt;register a callback&lt;/a&gt; so that I know whenever the player changes status (started/paused/ended).&lt;br /&gt;
&lt;pre class="prettyprint"&gt;
function onYouTubePlayerReady(playerId) {
  youtubePlayer = document.getElementById(playerId);
  youtubePlayer.addEventListener('onStateChange', 'onYouTubePlayerStateChange');
}
&lt;/pre&gt;
&lt;li&gt;
When the video ends, I play the next song. (I've already got the Youtube ID for the next song because I always search for the next video whenever I start playing a video.)&lt;br /&gt;
&lt;pre class="prettyprint"&gt;
function onYouTubePlayerStateChange(newState) {
  if (newState == 0) {
    currentSong++;
    playNext();
  }
}
&lt;/pre&gt;
&lt;li&gt;
To let users rate each video, I use a &lt;a href="http://pamelafox-samplecode.googlecode.com/svn/trunk/localstorage/localstoragelikerplus.html" target="_blank"&gt;localStorage-based doodad&lt;/a&gt; that I wrote for &lt;a href="http://otherfancystuff.blogspot.com/2010/09/putting-europopped-on-map.html" target="_blank"&gt;another music video mashup&lt;/a&gt;.&lt;br /&gt;
&lt;pre class="prettyprint"&gt;
likerCol.appendChild(LIKER.createLikerMini(song.id));
...
likerBlock.appendChild(LIKER.createLiker(song.id));
&lt;/pre&gt;
&lt;/ul&gt;

&lt;p&gt;Happy RageTube'ing!&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8501278254137514883-818392285025061805?l=blog.pamelafox.org' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.pamelafox.org/feeds/818392285025061805/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=8501278254137514883&amp;postID=818392285025061805' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8501278254137514883/posts/default/818392285025061805'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8501278254137514883/posts/default/818392285025061805'/><link rel='alternate' type='text/html' href='http://blog.pamelafox.org/2010/09/ragetube-using-apis-to-bring-music.html' title='RageTube: Using APIs to Bring Music Video Playlists Online'/><author><name>Pamela Fox</name><uri>http://www.blogger.com/profile/15947664772001597300</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8501278254137514883.post-7224055268336631089</id><published>2010-09-20T00:30:00.001-07:00</published><updated>2010-09-20T00:39:44.349-07:00</updated><title type='text'>Embedding Feed Gadgets in Google Sites</title><content type='html'>&lt;p&gt;Today, I spent a few hours re-organizing &lt;a href="http://waveprotocol.org" target="_blank"&gt;waveprotocol.org&lt;/a&gt; to be easier to navigate. As part of that re-org, I wanted to also make it clear to people visiting the site that the protocol is in active development by showing them the activity from our discussion group and code repository. Since both the group and project offer ATOM feeds, I figured I could just embed a gadget to show the latest posts from the feeds.&lt;br /&gt;
After spending a good half hour trying to find a gadget that would do just that, I gave up and wrote one myself. And now you can use the gadget yourself if you're in a similar situation. :)
&lt;/p&gt;

&lt;h3&gt;Using the Gadget&lt;/h3&gt;
&lt;p&gt;
Here's how you can actually embed the gadget on your site:
&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Put the target page in editing mode. Open the "Insert" menu and select the final "More gadgets" option. 
&lt;li&gt;Select "Add gadget by URL" in the sidebar of the dialog.
&lt;li&gt;Enter this URL in the input box:&lt;br /&gt;&lt;a href="http://pamelafox-samplecode.googlecode.com/svn/trunk/feedgadget/feedgadget.xml" target="_blank"&gt;http://pamelafox-samplecode.googlecode.com/svn/trunk/feedgadget/feedgadget.xml&lt;/a&gt;
&lt;li&gt;Enter the URL to your feed in the "Feed" input box in "Setup your gadget". The feed must be either an ATOM or RSS feed.
&lt;li&gt;Customize the width, height, and title as desired.
&lt;/ol&gt;
&lt;p&gt;
Tip: If you want to embed multiple gadgets next to eachother, change your page layout to a multi-column view and stick a gadget in each column.
&lt;/p&gt;

&lt;h3&gt;Finding Feeds&lt;/h3&gt;
&lt;p&gt;
Here are some tips for finding feed URLs for various Google properties:
&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;b&gt;Blogger&lt;/b&gt;: Scroll to the bottom of the blog and click "Posts (ATOM)" link. Here's an example blogger feed URL:&lt;br&gt;
&lt;a href="http://otherfancystuff.blogspot.com/feeds/posts/default" target="_blank"&gt;http://otherfancystuff.blogspot.com/feeds/posts/default&lt;/a&gt;
&lt;li&gt;&lt;b&gt;Google Groups&lt;/b&gt;: Click the orange "XML" image at the bottom of the group home. You can pick from various feeds - the "15 new messages" ATOM feed works well in my experience. Here's an example group feed URL:&lt;br /&gt;&lt;a href="http://groups.google.com/group/wave-protocol/feed/atom_v1_0_msgs.xml" target="_blank"&gt;http://groups.google.com/group/wave-protocol/feed/atom_v1_0_msgs.xml&lt;/a&gt;
&lt;li&gt;&lt;b&gt;Google Code Projects&lt;/b&gt;: Click the "Feeds" link on the sidebar of the project front page. You can pick from various feeds, depending if you want to show all activity or limit to just issues/downloads/etc. Here's an example project feed activity URL:&lt;br /&gt;&lt;a href="http://code.google.com/feeds/p/wave-protocol/updates/basic" target="_blank"&gt;http://code.google.com/feeds/p/wave-protocol/updates/basic&lt;/a&gt;
&lt;li&gt;&lt;b&gt;Google Sites&lt;/b&gt;: Each site has an associated feed for recent updates. There's not a good way to find the link to that feed, but you can construct it easily by adding "activity.xml" to the site URL. Here's an example site updates feed URL:&lt;br /&gt;&lt;a href="http://www.waveprotocol.org/activity.xml" target="_blank"&gt;http://www.waveprotocol.org/activity.xml&lt;/a&gt;
&lt;/ul&gt;

&lt;h3&gt;About the Gadget&lt;/h3&gt;
&lt;p&gt;For developers, here's some information about how the gadget works.
&lt;/p&gt;
&lt;p&gt;
The gadget uses the &lt;a href="http://code.google.com/apis/ajaxfeeds/" target="_blank"&gt;AJAX Feeds API&lt;/a&gt; and the &lt;a href="http://code.google.com/apis/ajaxfeeds/documentation/reference.html#FeedControl" target="_blank"&gt;google.feeds.FeedControl&lt;/a&gt; class, and of course, it uses the gadgets API.

It's actually a nice example of how to write a simple gadget that uses a Google API and user preferences:
&lt;/p&gt;
&lt;pre class="prettyprint"&gt;
&amp;lt;Module&amp;gt;
    &amp;lt;ModulePrefs title="Feed Control" height="400"/&amp;gt;
    &amp;lt;UserPref name="feedurl" display_name="Feed" default_value="https://groups.google.com/group/wave-protocol/feed/atom_v1_0_msgs.xml"/&amp;gt;
     &amp;lt;Content type="html"&amp;gt;&amp;lt;![CDATA[ 
     &amp;lt;div id="feed" style="font-size: small;"&amp;gt;&amp;lt;/div&amp;gt;
     &amp;lt;script type="text/javascript" src="http://www.google.com/jsapi"&amp;gt;&amp;lt;/script&amp;gt;
     &amp;lt;script type="text/javascript"&amp;gt;
     google.load("feeds", "1");
   &lt;br /&gt;
     function initialize() {
       var prefs = new gadgets.Prefs();
       var feedControl = new google.feeds.FeedControl();
       feedControl.addFeed(prefs.getString("feedurl"), "");
       feedControl.draw(document.getElementById("feed"), {});
     }
     google.setOnLoadCallback(initialize);
     &amp;lt;/script&amp;gt;
     ]]&amp;gt;
    &amp;lt;/Content&amp;gt;
&amp;lt;/Module&amp;gt;
&lt;/pre&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8501278254137514883-7224055268336631089?l=blog.pamelafox.org' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.pamelafox.org/feeds/7224055268336631089/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=8501278254137514883&amp;postID=7224055268336631089' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8501278254137514883/posts/default/7224055268336631089'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8501278254137514883/posts/default/7224055268336631089'/><link rel='alternate' type='text/html' href='http://blog.pamelafox.org/2010/09/embedding-rss-feed-gadgets-in-google.html' title='Embedding Feed Gadgets in Google Sites'/><author><name>Pamela Fox</name><uri>http://www.blogger.com/profile/15947664772001597300</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8501278254137514883.post-2676801654298218174</id><published>2010-09-15T01:36:00.001-07:00</published><updated>2010-09-21T04:19:37.601-07:00</updated><title type='text'>Using OAuth with Spreadsheets API on Django/AppEngine</title><content type='html'>&lt;p style="text-align: left;"&gt;
In a &lt;a href="http://otherfancystuff.blogspot.com/2010/08/importing-data-from-spreadsheets-to-app.html" target="_blank"&gt;previous blog post&lt;/a&gt;, I showed how to import a published spreadsheet feed into an App Engine datastore by just grabbing the JSON. For another project I'm working on, I need to be able to import a *private* spreadsheet into an App Engine datastore. Because of the need to authenticate the user (via the multiple steps of the ever-so-elegant OAuth dance), this importing requires much more finagling.
&lt;/p&gt;
&lt;p&gt;
With the help of my trusty colleague &lt;a href="http://www.vicfryzel.com/" target="_blank"&gt;Vic Fryzel&lt;/a&gt;, I've put together a set of Django views that use the &lt;a href="http://code.google.com/p/gdata-python-client/" target="_blank"&gt;Python GData Client Library&lt;/a&gt; and should run on both App Engine Django, and with some modification for token storage, other Django stacks. I'll walkthrough the views here.
&lt;/p&gt;
&lt;br&gt;

&lt;p&gt;
There are four URL handlers required, two for token requests, one for actually importing the spreadsheet, and one to manage the flow:
&lt;/p&gt;

&lt;pre class="prettyprint"&gt;
urlpatterns = patterns('',  
  (r'^get_oauth_token', 'importer.views.get_oauth_token'),
  (r'^get_access_token', 'importer.views.get_access_token'),
  (r'^import_spreadsheet', 'importer.views.import_spreadsheet'),
  (r'^$', 'importer.views.main_page'),
) 
&lt;/pre&gt;
&lt;br&gt;

&lt;p&gt;
When the user visits the main page, they are asked to login so that the app can remember their auth tokens, and if they are already logged in, they are redirected to the first token handler:
&lt;/p&gt;

&lt;pre class="prettyprint"&gt;
def main_page(request):  
  if not users.get_current_user():
    return HttpResponseRedirect(users.create_login_url(request.build_absolute_uri()))

  access_token = gdata.gauth.AeLoad(ACCESS_TOKEN)
  if not isinstance(access_token, gdata.gauth.OAuthHmacToken):
    return HttpResponseRedirect('/importer/get_oauth_token') 
&lt;/pre&gt;
&lt;br&gt;

&lt;p&gt;
In this first step of the OAuth dance, the app requests an oauth token for the specified scope (Spreadsheets), key/secret (anonymous, as I haven't &lt;a href="http://code.google.com/apis/accounts/docs/RegistrationForWebAppsAuto.html" target="_blank"&gt;registered my app&lt;/a&gt;), and a callback URL to my app. It saves that token to the App Engine datastore using a convenience function in the client library. Then it redirects the user to the authorization URL for that token, and the user is presented with the "Grant access" screen.&lt;br /&gt;&lt;br /&gt;
&lt;/p&gt;

&lt;pre class="prettyprint"&gt;
def get_oauth_token(request):
    oauth_callback_url = 'http://%s:%s/importer/get_access_token' %
        (request.META.get('SERVER_NAME'), request.META.get('SERVER_PORT'))
    request_token = client.GetOAuthToken(SCOPES, oauth_callback_url,
        CONSUMER_KEY, consumer_secret=CONSUMER_SECRET)
    gdata.gauth.AeSave(request_token, REQUEST_TOKEN)

    authorization_url = request_token.generate_authorization_url()
   return HttpResponseRedirect(authorization_url) 
&lt;/pre&gt;
&lt;br&gt;

&lt;p&gt;
When the user returns from the authorization screen to the callback handler, the app retrieves the original token, asks Google to upgrade that to an access token, and saves the access token to the App Engine datastore again.
&lt;/p&gt;

&lt;pre class="prettyprint"&gt;
def get_access_token(request):  
  saved_request_token = gdata.gauth.AeLoad(REQUEST_TOKEN)
  request_token = gdata.gauth.AuthorizeRequestToken(saved_request_token,
      request.build_absolute_uri())
  access_token = client.GetAccessToken(request_token)
  gdata.gauth.AeSave(access_token, ACCESS_TOKEN)
  return HttpResponseRedirect('/importer/') 
&lt;/pre&gt;
&lt;br&gt;

&lt;p&gt;
The user is then redirected to the main page, and since it sees that there is now an access token for the user, it shows the user an input box for providing a spreadsheets URL. When it knows the spreadsheets URL, it retrieves the list feed for that spreadsheet and saves each row as an entity in the datastore.
&lt;/p&gt;

&lt;pre class="prettyprint"&gt;
def import_spreadsheet(request): 
  import re
  import models

  client.auth_token = gdata.gauth.AeLoad(ACCESS_TOKEN)

  spreadsheet = request.GET.get('spreadsheet')
  if spreadsheet.find('google.com') &gt; -1:
    spreadsheet_key = re.search('key=([^(?|&amp;)]*)', spreadsheet).group(1)
  else:
    spreadsheet_key = spreadsheet
  worksheet_id = 'od6'
  list_feed = 'https://spreadsheets.google.com/feeds/list/%s/%s/private/values' %
      (spreadsheet_key, worksheet_id)
  feed = client.get_feed(list_feed,
                         desired_class=gdata.spreadsheets.data.ListsFeed)
  for row in feed.entry:
    firstname = row.get_value('firstname')
    lastname = row.get_value('lastname')
    email = row.get_value('email')
    person = models.Person(firstname=firstname, lastname=lastname, email=email)
    person.save()

  return HttpResponse('Saved %s rows' % str(len(feed.entry))) 
&lt;/pre&gt;

&lt;br&gt;

&lt;p&gt;Using that code, the end result is going from this spreadsheet...&lt;/p&gt;

&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;width: 397px; height: 82px;" src="http://4.bp.blogspot.com/_T1lquhCmKo8/TJCGHOH1zDI/AAAAAAAADfA/Zxhi1n04TK8/s400/si_spreadsheet.png"/&gt;

&lt;p&gt;
... to these datastore entities:
&lt;/p&gt;

&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;width: 400px; height: 134px;" src="http://4.bp.blogspot.com/_T1lquhCmKo8/TJCGVGUxfAI/AAAAAAAADfI/iAvZ0JEqgBE/s400/si_datastore.png"/&gt;

&lt;p&gt;
To see the full code (with inline comments), &lt;a href="http://pamelafox-samplecode.googlecode.com/svn/trunk/spreadsheetsimporter/" target="_blank"&gt;check it out from my repository&lt;/a&gt; or &lt;a href="http://code.google.com/p/pamelafox-samplecode/downloads/detail?name=spreadsheetsimporter.zip&amp;can=2&amp;q="&gt;download the zip&lt;/a&gt;.
&lt;/p&gt;

&lt;p&gt;
For simplicity's sake, this sample shows the simplest possible import. In my actual project, I am also creating an entity that represents the entire spreadsheet, and the entity for each row refer to that entity. In addition, I have code to convert from the spreadsheets strings to other model types like dates. &lt;br /&gt;&lt;br /&gt;
Hopefully this project can serve as a basis for other developers using spreadsheets as an import source for their apps. Enjoy!
&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8501278254137514883-2676801654298218174?l=blog.pamelafox.org' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.pamelafox.org/feeds/2676801654298218174/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=8501278254137514883&amp;postID=2676801654298218174' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8501278254137514883/posts/default/2676801654298218174'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8501278254137514883/posts/default/2676801654298218174'/><link rel='alternate' type='text/html' href='http://blog.pamelafox.org/2010/09/using-oauth-with-spreadsheets-api-on.html' title='Using OAuth with Spreadsheets API on Django/AppEngine'/><author><name>Pamela Fox</name><uri>http://www.blogger.com/profile/15947664772001597300</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://4.bp.blogspot.com/_T1lquhCmKo8/TJCGHOH1zDI/AAAAAAAADfA/Zxhi1n04TK8/s72-c/si_spreadsheet.png' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8501278254137514883.post-6713883156782179910</id><published>2010-09-12T16:58:00.000-07:00</published><updated>2010-09-19T13:36:41.818-07:00</updated><title type='text'>Porting from an App Engine RequestHandler to a Django View</title><content type='html'>&lt;p&gt;For whatever reason, I've found myself porting Python App Engine apps over from App Engine's "django-esque" webapp framework to true django 1.0 with views.py, urls.py, and the like.
&lt;/p&gt;
&lt;p&gt;
Besides learning about how urls.py and views.py work, I had to do some research to figure out how some of the webapp-isms translated to django-isms, so I thought I'd post my findings here in a table comparing the two:
&lt;/p&gt;
&lt;style&gt;
pre {
  white-space: pre-wrap;
}
td {
  border: 1px solid grey;
  font-size: 11px;
  vertical-align: top;
}
&lt;/style&gt;

&lt;table style="width:100%; border:1px solid" cellspacing="0"&gt;
 &lt;thead&gt;
  &lt;tr&gt;
   &lt;th&gt;Webapp&lt;/th&gt;
   &lt;th&gt;Django&lt;/th&gt;
  &lt;/tr&gt;
 &lt;/thead&gt;
 &lt;tbody&gt;
  &lt;tr&gt;
   &lt;td&gt;
&lt;pre&gt;
author = self.request.get('author') 
&lt;/pre&gt;
   &lt;/td&gt;
   &lt;td&gt;
    What you use depends on how specific you want to be about where parameter was passed:
&lt;pre&gt;
author = request.GET.get('author') 
author = request.POST.get('author')
author = request.REQUEST.get('author')
&lt;/pre&gt;
   &lt;/td&gt;
  &lt;/tr&gt;
  &lt;tr&gt;
   &lt;td&gt;
&lt;pre&gt;
class MyRequestHandler(RequestHandler):
  def get(self):
    # Do stuff
  def post(self):
    # Do other stuff
&lt;/pre&gt;
   &lt;/td&gt;
   &lt;td&gt;
&lt;pre&gt;
def handle_request(request):
  if request.method == 'GET':
    # do stuff
  elif request.method == 'POST':
    # do other stuff
&lt;/pre&gt;
   &lt;/td&gt;
  &lt;/tr&gt;
  &lt;tr&gt;
   &lt;td&gt;
&lt;pre&gt;
host = self.request.host
&lt;/pre&gt;
   &lt;/td&gt;
   &lt;td&gt;
&lt;pre&gt;
host = request.get_host()
&lt;/pre&gt;
   &lt;/td&gt;
  &lt;/tr&gt;
  &lt;tr&gt;
   &lt;td&gt;
&lt;pre&gt;
url = self.request.uri
&lt;/pre&gt;
   &lt;/td&gt;
   &lt;td&gt;  
&lt;pre&gt;
url = request.build_absolute_uri(request.path)
&lt;/pre&gt;
   &lt;/td&gt;
  &lt;/tr&gt;
  &lt;tr&gt;
   &lt;td&gt;
&lt;pre&gt;
query_string = request.query_string
&lt;/pre&gt;
   &lt;/td&gt;
   &lt;td&gt;
&lt;pre&gt;
query_string = request.META['QUERY_STRING']
&lt;/pre&gt;
   &lt;/td&gt;
  &lt;/tr&gt;
  &lt;tr&gt;
   &lt;td&gt;
&lt;pre&gt;
self.error(500)
&lt;/pre&gt;
   &lt;/td&gt;
   &lt;td&gt;
&lt;pre&gt;
return HttpResponse(status=500)
&lt;/pre&gt;
or
&lt;pre&gt;
from django.http import HttpResponseServerError
return HttpResponseServerError()
&lt;/pre&gt;
   &lt;/td&gt;
  &lt;/tr&gt;
  &lt;tr&gt;
   &lt;td&gt;
&lt;pre&gt;
self.redirect('/gallery')
&lt;/pre&gt;
   &lt;/td&gt;
   &lt;td&gt;
&lt;pre&gt;
from django.http import HttpResponseRedirect
return HttpResponseRedirect('/gallery') 
&lt;/pre&gt;
   &lt;/td&gt;
  &lt;/tr&gt;
  &lt;tr&gt;
   &lt;td&gt;
&lt;pre&gt;
path = os.path.join(os.path.dirname(__file__), 'index.html')
self.response.out.write(template.render(path, template_values))
&lt;/pre&gt;
   &lt;/td&gt;
   &lt;td&gt;
&lt;pre&gt;
from django.shortcuts import render_to_response 
render_to_response('index.html', path)
&lt;/pre&gt;
Or, if for some reason you need the in-between products of that shortcut (like the generated string), you can use the longer version:
&lt;pre&gt;
from django.template.loader import get_template
from django.template import Context 

t = get_template('index.html') 
html = t.render(Context(template_values))
return HttpResponse(html) 
&lt;/pre&gt;
   &lt;/td&gt;
  &lt;/tr&gt;
  &lt;tr&gt;
   &lt;td&gt;
&lt;pre&gt;
self.response.headers['Content-Type'] = 'application/atom+xml'
self.response.out.write(xml_string)
&lt;/pre&gt;
   &lt;/td&gt;
   &lt;td&gt;
&lt;pre&gt;
return HttpResponse(xml, mimetype='application/atom+xml')
&lt;/pre&gt;
   &lt;/td&gt;
  &lt;/tr&gt;
&lt;/table&gt;

&lt;p&gt;If you have suggestions for better "transformations", please let me know. I'm fairly new to Django and am happy to learn more about the right way to do things.
&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8501278254137514883-6713883156782179910?l=blog.pamelafox.org' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.pamelafox.org/feeds/6713883156782179910/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=8501278254137514883&amp;postID=6713883156782179910' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8501278254137514883/posts/default/6713883156782179910'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8501278254137514883/posts/default/6713883156782179910'/><link rel='alternate' type='text/html' href='http://blog.pamelafox.org/2010/09/porting-from-app-engine-webapp.html' title='Porting from an App Engine RequestHandler to a Django View'/><author><name>Pamela Fox</name><uri>http://www.blogger.com/profile/15947664772001597300</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8501278254137514883.post-4718804586400566378</id><published>2010-09-09T16:44:00.001-07:00</published><updated>2010-09-09T16:45:37.075-07:00</updated><title type='text'>Teaching &amp; Using Google Data APIs @ USYD</title><content type='html'>&lt;script type="text/javascript" src="https://blogspotty.appspot.com/static/post.js"&gt;&lt;/script&gt;
&lt;p style="text-align: left;"&gt;
As I've posted on other blogs, I always love the idea of teaching Web APIs to university students and finding ways to use them in class assignments. Today, I visited the University of Sydney (USYD) and saw multiple ways that they're using APIs in education, and I'd like to share them here.&lt;br /&gt;&lt;br /&gt;
First, I gave a guest talk to an &lt;a href="http://www.ee.usyd.edu.au/~rafa/elec5619/" target="_blank"&gt;Object-Oriented Frameworks&lt;/a&gt; class on &lt;a href="https://docs.google.com/present/view?id=dggjrx3s_370gf9tx7kq" target="_blank"&gt;"Google Data APIs &amp;amp; the Google Docs API"&lt;/a&gt;.  For the next two months, the students in that class will be working on group projects with an education theme and combining the technologies they've studied, and I hope to show up on their demo day and see some cool examples of API usage. &lt;br /&gt;&lt;br /&gt;
After the talk, I went to lunch with the professor's research team, and watched videos about some really neat education &amp;amp; API related projects they're working on: &lt;a href="http://www.weg.ee.usyd.edu.au/iwrite" target="_blank"&gt;iWrite&lt;/a&gt;, a system for submitting assignments as a doc &amp;amp; getting instructor feedback, and &lt;a href="http://www.weg.ee.usyd.edu.au/projects/glosser2" target="_blank"&gt;Glosser&lt;/a&gt;, a system for automatically creating questions about papers to make students think more about them; and for analyzing contributions of group members to a paper. Both of these use Google Data APIs in conjunction with the students' USYD Google Apps accounts, and are great examples of how research, APIs, and Google products can interact.&lt;br /&gt;&lt;br /&gt;
Though the Google Data APIs are not as "sexy" as our other APIs, they are incredibly useful and great teaching tools since they span across many Google products and build on existing web technologies like XML, ATOM, OAuth, and the HTTP protocol. They're also particularly useful for students at Google Apps enabled universities, since they can be used to create applications for accessing and modifying data in the Google Apps suite that they use daily. &lt;br /&gt;&lt;br /&gt;
When I was a TA at my old university (USC), we used Google docs and spreadsheets in our classes for keeping tabs on group work, and I used the APIs to automate processes for the professor. That was right before USC actually became a Google Apps domain -- if I was there as a TA or student now, I'd probably spend all day hacking on Google data APIs and App Engine to make cool apps for classes and clubs, and trying to get my classmates to join the fun.&lt;br /&gt;&lt;br /&gt;
Anyway, it was great to see how USYD is using our APIs across both their classes and research. Let me know if your university is up to anything similar! :)&lt;br /&gt;&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8501278254137514883-4718804586400566378?l=blog.pamelafox.org' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.pamelafox.org/feeds/4718804586400566378/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=8501278254137514883&amp;postID=4718804586400566378' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8501278254137514883/posts/default/4718804586400566378'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8501278254137514883/posts/default/4718804586400566378'/><link rel='alternate' type='text/html' href='http://blog.pamelafox.org/2010/09/teaching-using-google-data-apis-usyd.html' title='Teaching &amp; Using Google Data APIs @ USYD'/><author><name>Pamela Fox</name><uri>http://www.blogger.com/profile/15947664772001597300</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8501278254137514883.post-5734741665517966739</id><published>2010-09-03T16:22:00.001-07:00</published><updated>2010-09-03T16:22:24.048-07:00</updated><title type='text'>Putting Europopped on the Map</title><content type='html'>&lt;script type="text/javascript" src="https://blogspotty.appspot.com/static/post.js"&gt;&lt;/script&gt;
&lt;p style="text-align: left;"&gt;
After spending 3 years of my life making Maps API mashups, I now have a bit of an addiction. Whenever I see geographic information, I have this uncontrollable urge to visualize that information on a map. So when I started reading &lt;a href="http://Europopped.com" target="_blank"&gt;Europopped.com&lt;/a&gt;, a blog that chronicles awesome and awful music videos from European countries, I also started imagining how I could show those blog posts on a map. Last night, between episodes of Arrested development and True Blood (a balanced TV diet), I realized my fantasies: &lt;a href="http://pamelafox-samplecode.googlecode.com/svn/trunk/europopped/europopped.html" target="_blank"&gt;Europopped: On the Map&lt;/a&gt;. &lt;br /&gt;&lt;br /&gt;
Here's a step-by-step of how the mashup works:&lt;/p&gt;&lt;ul&gt;&lt;li style="text-align: left;"&gt;
It uses the JavaScript Maps API v3 to create a map centered on Europe.&lt;/li&gt;&lt;li style="text-align: left;"&gt;
It queries the Posterous API to retrieve all the tags and tag counts for the blog.&lt;/li&gt;&lt;li style="text-align: left;"&gt;
It creates markers for each of the tags, using latitude/longitude coordinates stored in the JS, and showing the tag count on top of each marker.&lt;/li&gt;&lt;li style="text-align: left;"&gt;
When you click on a particular country marker, it queries the Posterous API for all the posts for that tag.&lt;/li&gt;&lt;li style="text-align: left;"&gt;
It creates a sidebar of links for each post, and setting a click listener that embeds the video for each post in the infowindow.&lt;/li&gt;&lt;/ul&gt;&lt;p style="text-align: left;"&gt;&lt;br /&gt;
Here are some tips for how I made it quickly:&lt;/p&gt;&lt;ul&gt;&lt;li style="text-align: left;"&gt;
I used my &lt;a href="http://gmaps-samples.googlecode.com/svn/trunk/spreadsheetsgeocoder/geocodespreadsheet.htm" target="_blank"&gt;Spreadsheets Geocoder wizard&lt;/a&gt; to get the coordinates for all of the countries, and used a spreadsheet formula to generate JSON from my geocoded spreadsheet.&lt;/li&gt;&lt;li style="text-align: left;"&gt;
I used &lt;a href="http://getlatlon.com" target="_blank"&gt;getlatlon.com&lt;/a&gt; to find the ideal map center.&lt;/li&gt;&lt;li style="text-align: left;"&gt;
I used &lt;a href="http://www.google.com/url?sa=D&amp;q=http%3A%2F%2Fgmaps-utility-library.googlecode.com%2Fsvn%2Ftrunk%2Fmapiconmaker%2F1.1%2Fexamples%2Fmarkericonoptions-wizard.html" target="_blank"&gt;MapIconMaker Wizard&lt;/a&gt; to generate a template marker image URL for my markers, and passesd the tag count into that image URL to change the number for each country.&lt;/li&gt;&lt;li style="text-align: left;"&gt;
I used my &lt;a href="http://pamelafox-samplecode.googlecode.com/svn/trunk/europopped/centerbox.js" target="_blank"&gt;CenterBox control&lt;/a&gt; class from another project to create a centered info box instead of the typical infowindow.&lt;/li&gt;&lt;li style="text-align: left;"&gt;
I used &lt;a href="http://regexpal.com" target="_blank"&gt;regexpal.com&lt;/a&gt; to test the regular expression that extracted the Youtube URLs.&lt;/li&gt;&lt;li style="text-align: left;"&gt;
I used my &lt;a href="http://otherfancystuff.blogspot.com/2010/08/json-api-for-posterous.html" target="_blank"&gt;Posterous JSON API proxy&lt;/a&gt; for all of the API calls.&lt;/li&gt;&lt;/ul&gt;&lt;p style="text-align: left;"&gt;&lt;br /&gt;
That's why I love APIs and the web -- once you're aware of them, they make it possible to quickly create new ways to use and explore the data and sites that you love.&lt;br /&gt;&lt;br /&gt;
Happy EuroPopping! :)&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8501278254137514883-5734741665517966739?l=blog.pamelafox.org' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.pamelafox.org/feeds/5734741665517966739/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=8501278254137514883&amp;postID=5734741665517966739' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8501278254137514883/posts/default/5734741665517966739'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8501278254137514883/posts/default/5734741665517966739'/><link rel='alternate' type='text/html' href='http://blog.pamelafox.org/2010/09/putting-europopped-on-map.html' title='Putting Europopped on the Map'/><author><name>Pamela Fox</name><uri>http://www.blogger.com/profile/15947664772001597300</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8501278254137514883.post-8088120052529012757</id><published>2010-08-31T05:36:00.000-07:00</published><updated>2010-08-31T06:03:39.327-07:00</updated><title type='text'>How to Pretty-Print Code Snippets in Blogger</title><content type='html'>&lt;p&gt;I often want to include snippets of code in my instructional blog posts, so to make my blog posts easier to read, I decided to add syntax-highlighting to my blog tonight.
There are various syntax highlighting solutions out there, but we use &lt;a href="http://code.google.com/p/google-code-prettify/"&gt;google-code-prettify&lt;/a&gt; on code.google.com and it's worked well enough there, so I went with what I knew.
&lt;/p&gt;
&lt;p&gt;Here's how I added it to my Blogger blog:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Click the Design tab and "Edit HTML".
&lt;li&gt;After the &lt;code&gt;meta&lt;/code&gt; tab in the HTML, paste these two includes for the JS and CSS:&lt;br&gt;
 &lt;pre class="prettyprint"&gt;
&amp;lt;link href='http://google-code-prettify.googlecode.com/svn/trunk/src/prettify.css' rel='stylesheet' type='text/css'/&amp;gt;
&amp;lt;script src='http://google-code-prettify.googlecode.com/svn/trunk/src/prettify.js' type='text/javascript'/&amp;gt;
&lt;/pre&gt;
&lt;li&gt;Search for &lt;code&gt;script &lt;/code&gt; - for me, there's a script tag near the bottom of the page. In that script tag, put this javascript call:&lt;br&gt;
&lt;pre class="prettyprint"&gt;
prettyPrint();
&lt;/pre&gt;
If that tag doesn't exist, then just create a script tag at the bottom yourself.
&lt;li&gt;Now, whenever you're posting, add the prettyprint class to your pre or code tags:
&lt;pre class="prettyprint"&gt;
&amp;lt;pre class="prettyprint"&amp;gt;
var i = 2 + 4;
&amp;lt;/pre&amp;gt;
&lt;/pre&gt;
&lt;/ol&gt;

&lt;p&gt;To see examples of where I've used this, check out &lt;a href="http://otherfancystuff.blogspot.com/2010/08/json-api-for-posterous.html"&gt;JSON API for Posterous&lt;/a&gt; for Python snippets or the &lt;a href="http://otherfancystuff.blogspot.com/2010/08/google-apis-timeline-behind-scenes.html"&gt;Google APIs Timeline&lt;/a&gt; for JS snippets.
&lt;/p&gt;

&lt;p&gt;For more details on using the prettify library, see the &lt;a href="http://google-code-prettify.googlecode.com/svn/trunk/README.html"&gt;readme&lt;/a&gt;.
&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8501278254137514883-8088120052529012757?l=blog.pamelafox.org' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.pamelafox.org/feeds/8088120052529012757/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=8501278254137514883&amp;postID=8088120052529012757' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8501278254137514883/posts/default/8088120052529012757'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8501278254137514883/posts/default/8088120052529012757'/><link rel='alternate' type='text/html' href='http://blog.pamelafox.org/2010/08/how-to-pretty-print-code-snippets-in.html' title='How to Pretty-Print Code Snippets in Blogger'/><author><name>Pamela Fox</name><uri>http://www.blogger.com/profile/15947664772001597300</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8501278254137514883.post-3116727838040115786</id><published>2010-08-30T16:51:00.001-07:00</published><updated>2010-08-31T05:33:58.004-07:00</updated><title type='text'>A JSON API for Posterous</title><content type='html'>&lt;script type="text/javascript" src="https://blogspotty.appspot.com/static/post.js"&gt;&lt;/script&gt;
&lt;p&gt;
I recently became mildly obsessed with &lt;a href="http://Europopped.com" target="_blank"&gt;Europopped.com&lt;/a&gt;, a blog that highlights both really catchy &amp;amp; horribly tacky music videos from all over Europe, and I've started thinking up mashups to fuel my obsession. So, I looked up the API for &lt;a href="http://Posterous.com" target="_blank"&gt;Posterous.com&lt;/a&gt;, the blogging platform that powers Europopped, and discovered that its API is not quite as mashup-friendly as I hoped. They do offer an &lt;a href="http://posterous.com/api/reading"&gt;API for retrieving public feeds&lt;/a&gt; without authentication -- the first thing I looked for -- but the API result output is a custom XML format -- not optimal for client-side mashups. I was expecting to find an API output that was either ATOM-based, so I could pipe it through existing Feed-&amp;gt;JS proxies like the &lt;a href="http://code.google.com/apis/ajaxfeeds/"&gt;Google AJAX Feeds API&lt;/a&gt;, or even better, an API output in JSON with support for callback parameters. The documentation indicates the API is still under development, however, so hopefully they will soon go down one or both of those routes.
&lt;/p&gt;
&lt;p&gt;
But in the meantime, I decided to remedy their lack of a JSON output with a quick App Engine app to proxy API requests, convert the XML to JSON, and return it.
&lt;/p&gt;
&lt;p&gt;
&lt;strong&gt;First, the end result:&lt;/strong&gt;
&lt;/p&gt;
&lt;p&gt;
If I wanted to use the Posterous API to get the last 50 posts from the Europopped blog, I'd fetch this URL and it would return XML for each post:
&lt;pre&gt;
&lt;a href="http://posterous.com/api/readposts?hostname=europopped&amp;num_posts=50" target="_blank"&gt;http://posterous.com/api/readposts?hostname=europopped&amp;amp;num_posts=50&lt;/a&gt;
&lt;/pre&gt;
&lt;/p&gt;
&lt;p&gt;
To use my proxied JSON API to get those 50 posts, I'd fetch this URL:&lt;br /&gt;
&lt;pre&gt;
&lt;a href="http://posterous-js.appspot.com/api/readposts?hostname=europopped&amp;num_posts=50" target="_blank"&gt;http://posterous-js.appspot.com/api/readposts?hostname=europopped&amp;amp;num_posts=50&lt;/a&gt;
&lt;/pre&gt;
&lt;span style="font-style: italic;"&gt;Tip: Install the &lt;a href="https://chrome.google.com/extensions/detail/chklaanhfefbnpoihckbnefhakgolnmc" target="_blank"&gt;JSONView extension&lt;/a&gt; for Chrome to see the result pretty-printed.&lt;/span&gt;
&lt;/p&gt;
&lt;p&gt;
Notice that the only difference is the domain name -- I wanted the proxied API to mirror the actual API as much as possible, to make it easy to figure out the URLs to construct from the documentation, and to make it easy to port to an actual JSON offering from Posterous in the future, on the assumption that actually happens. :)
&lt;/p&gt;
&lt;p&gt;
If I want to get the same JSON wrapped in a callback, to use it inside a webpage, I'd fetch this URL:
&lt;/p&gt;
&lt;pre&gt;
&lt;a href="http://posterous-js.appspot.com/api/readposts?hostname=europopped&amp;num_posts=50&amp;callback=loadPosts"&gt;http://posterous-js.appspot.com/api/readposts?hostname=europopped&amp;amp;num_posts=50&amp;amp;callback=loadPosts&lt;/a&gt;
&lt;/pre&gt;

&lt;p&gt;&lt;strong&gt;Now, the code behind it:&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;
I've checked in the &lt;a href="http://pamelafox-samplecode.googlecode.com/svn/trunk/posterousjs/"&gt;two files&lt;/a&gt; it took to write the proxy on App Engine for Python, and I'll step through them here.
&lt;/p&gt;
&lt;p&gt;
First, I set up a URL handler to direct all /api requests to my api.py script:&lt;br /&gt;
&lt;/p&gt;
&lt;pre class="prettyprint"&gt;
application: posterous-js
version: 1
runtime: python
api_version: 1
handlers:
- url: /api/.*
  script: api.py
&lt;/pre&gt;

&lt;p&gt;
Then, in api.py, I directed all requests to be handled by ApiHandler, a webapp.RequestHandler class.In that class, I reconstruct the URL for the Posterous API request:
&lt;/p&gt;

&lt;pre class="prettyprint"&gt;
  url = 'http://posterous.com' + self.request.path + '?' + self.request.query_string
&lt;/pre&gt;
&lt;p&gt;
Then I check memcache to see if I've already fetched that request recently (in last 5 minutes):
&lt;/p&gt;
&lt;pre class="prettyprint"&gt;
   cached_result = memcache.get(url)
    if cached_result:
      dict = simplejson.loads(cached_result)
    else:
      dict = self.convert_results(url)
&lt;/pre&gt;
&lt;p&gt;
If I didn't find it in cache, then I'll call a function to fetch the URL and convert specified top-level tags in the XML to JSON:
&lt;/p&gt;
&lt;pre class="prettyprint"&gt;
  result = urlfetch.fetch(url, deadline=10)
  if result.status_code == 200:
      dom = minidom.parseString(result.content)
      errors = dom.getElementsByTagName('err')
      if errors:
        dict = {'error': errors[0].getAttribute('msg')}
      elif url.find('readposts') &amp;gt; -1:
        dict = self.convert_dom(dom, 'post')
      elif url.find('gettags') &amp;gt; -1:
        dict = self.convert_dom(dom, 'tag')
      elif url.find('getsites') &amp;gt; -1:
        dict = self.convert_dom(dom, 'site')
&lt;/pre&gt;

&lt;p&gt;
I convert from XML to JSON using the minidom library, converting each tag to a JSON key and recording  the text data or CDATA as the JSON value. This technique means that I don't actually convert any nested XML tags, but in the Posterous API, that only means that my output is missing the comments information for posts, which is the least interesting information for me.
&lt;/p&gt;

&lt;pre class="prettyprint"&gt;
 def convert_dom(self, dom, tag_name):
    dict = {}
    top_nodes = dom.getElementsByTagName(tag_name)
    nodes_list = []
    for top_node in top_nodes:
      child_dict = {}
      for child_node in top_node.childNodes:
        if child_node.nodeType != child_node.TEXT_NODE:
          child_dict[child_node.tagName] = child_node.firstChild.wholeText
      nodes_list.append(child_dict)
    dict[tag_name] = nodes_list
    return dict
&lt;/pre&gt;

&lt;p&gt;
Finally, after getting the JSON representing the API call, I output it to the screen with the appropriate mime-type and wrap it in a callback, if specified:
&lt;/p&gt;
&lt;pre class="prettyprint"&gt;
      json = simplejson.dumps(dict)
      memcache.set(url, json, 300)
      callback = self.request.get('callback')
      self.response.headers['Content-Type'] = 'application/json'
      if callback:
        self.response.out.write(callback + '(' + json + ')')
      else:
        self.response.out.write(json)
&lt;/pre&gt;

&lt;p&gt;
It's a quick hack and one that I hope to see replaced by the official Posterous API, but it's cool that it was so easy to do and now I can move on to actually making the Europopped mashup of my dreams. :)&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8501278254137514883-3116727838040115786?l=blog.pamelafox.org' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.pamelafox.org/feeds/3116727838040115786/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=8501278254137514883&amp;postID=3116727838040115786' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8501278254137514883/posts/default/3116727838040115786'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8501278254137514883/posts/default/3116727838040115786'/><link rel='alternate' type='text/html' href='http://blog.pamelafox.org/2010/08/json-api-for-posterous.html' title='A JSON API for Posterous'/><author><name>Pamela Fox</name><uri>http://www.blogger.com/profile/15947664772001597300</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8501278254137514883.post-6063165346954495425</id><published>2010-08-29T18:17:00.001-07:00</published><updated>2010-08-29T18:19:17.561-07:00</updated><title type='text'>Girl Develop It: Teaching Web Programming to Women</title><content type='html'>&lt;script type="text/javascript" src="https://blogspotty.appspot.com/static/post.js"&gt;&lt;/script&gt;
&lt;p style="text-align: left;"&gt;
A few months ago, &lt;a href="http://twitter.com/sarajchipps" target="_blank"&gt;Sara Chipps&lt;/a&gt; and I ended up on the same list of &lt;a href="http://mashable.com/2010/07/28/developer-hacker-women-twitter/" target="_blank"&gt;"Hacker Women on Twitter"&lt;/a&gt;, and I followed the link from her bio to the &lt;a href="http://girldevelopit.com/" target="_blank"&gt;Girl Develop it (GDI) project&lt;/a&gt;. The mission of GDI is to lessen the gender gap on the web by getting more women to develop software, and they're going about that by offering low-cost web programming courses to women in their local area (New York City). Some of those women might become web developers themselves, but even if most of them don't, they will hopefully inspire the women around them (like daughters and friends) to think about going down that road. Of all the various attempts to get more girls in computing, this one is my favorite.  It may take time -- it may even take generations -- but it's worth a shot.&lt;br /&gt;&lt;br /&gt;
So, I'm bringing GDI to &lt;a href="http://girldevelopit.com/sydney.html" target="_blank"&gt;Sydney&lt;/a&gt;, and kickstarting it with an introductory series on HTML &amp;amp; CSS, which will take place in 5 classes over 3 weeks at our local Google office. The series will be run like an actual course, in that students are expected to attend every class, to do homework, and to do a small final project (a personal website). &lt;br /&gt;&lt;br /&gt;
I'm currently in the midst of creating the curriculum, using my &lt;a href="http://otherfancystuff.blogspot.com/2010/08/5lide-html5-based-slides-maker.html" target="_blank"&gt;HTML5-based slides making application&lt;/a&gt;, and am hoping to make it fun, practical, and re-usable. :)&lt;br /&gt;&lt;br /&gt;
Here's where you come in:&lt;br /&gt;&lt;/p&gt;&lt;ul&gt;&lt;li style="text-align: left;"&gt;
If you're a local female looking to learn those topics, then you can read more and register from the &lt;a href="http://girldevelopit.com/sydney.html" target="_blank"&gt;GDI Sydney page&lt;/a&gt;. &lt;/li&gt;&lt;li style="text-align: left;"&gt;
If you're a local female that's keen to help others learn these topics, then we'd love to have you as a teaching assistant for the course. Just send me an email or wave (pamela.fox@).&lt;/li&gt;&lt;li style="text-align: left;"&gt;
If you're just curious to see how it goes, then subscribe to the main &lt;a href="http://girldevelopit.tumblr.com/" target="_blank"&gt;GDI blog&lt;/a&gt;. &lt;/li&gt;&lt;/ul&gt;&lt;p style="text-align: left;"&gt;&lt;br /&gt;
Thanks so much to Sara for supporting the Sydney version of GDI. I'm excited to see how this goes and to meet the first class of students!&lt;br /&gt;&lt;br /&gt;&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8501278254137514883-6063165346954495425?l=blog.pamelafox.org' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.pamelafox.org/feeds/6063165346954495425/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=8501278254137514883&amp;postID=6063165346954495425' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8501278254137514883/posts/default/6063165346954495425'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8501278254137514883/posts/default/6063165346954495425'/><link rel='alternate' type='text/html' href='http://blog.pamelafox.org/2010/08/girl-develop-it-teaching-web.html' title='Girl Develop It: Teaching Web Programming to Women'/><author><name>Pamela Fox</name><uri>http://www.blogger.com/profile/15947664772001597300</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8501278254137514883.post-8485808489630489285</id><published>2010-08-25T21:55:00.001-07:00</published><updated>2010-08-31T05:38:21.431-07:00</updated><title type='text'>Importing data from Spreadsheets to App Engine</title><content type='html'>&lt;script type="text/javascript" src="https://blogspotty.appspot.com/static/post.js"&gt;&lt;/script&gt;
&lt;p&gt;
Google App Engine provides the &lt;a href="http://code.google.com/appengine/docs/python/tools/uploadingdata.html" target="_blank"&gt;remote_api mechanism&lt;/a&gt; for uploading and downloading data from the datastore. It's handy and lets you import different types of data, but requires a certain amount of setup, and well, sometimes I'm lazy and don't feel like going through that setup. So, another way that you can easily import data into your datastore is to store it in a Google spreadsheet, publish the sheet, and write a handler to import the spreadsheet rows as datastore entities.
&lt;/p&gt;
&lt;p&gt;
For example, I created a &lt;a href="https://spreadsheets.google.com/pub?key=0Ah0xU81penP1dDNwSFROSU5KVlFRbmo5cERsTElKTGc&amp;amp;hl=en&amp;amp;output=html" target="_blank"&gt;spreadsheet&lt;/a&gt; to store information on Wave extensions, using one column for the URL and another column to indicate if they're featured or not.
&lt;/p&gt;

&lt;p&gt;
&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;width: 400px; height: 104px;" src="http://2.bp.blogspot.com/_T1lquhCmKo8/THXz9C6eLSI/AAAAAAAADeY/fN0qf3vSIU0/s400/screenshot_installerurls.png" border="0" alt="" id="BLOGGER_PHOTO_ID_5509577949237357858" /&gt;
&lt;/p&gt;
&lt;p&gt;
Then, I published that spreadsheet using the Share-&amp;gt;Publish menu, and constructed a URL for the JSON database-like output:
&lt;/p&gt;
&lt;a href="https://spreadsheets.google.com/feeds/list/0Ah0xU81penP1dDNwSFROSU5KVlFRbmo5cERsTElKTGc/od6/public/values?alt=json" target="_blank"&gt;https://spreadsheets.google.com/feeds/list/0Ah0xU81penP1dDNwSFROSU5KVlFRbmo5cERsTElKTGc/od6/public/values?alt=json&lt;/a&gt;
&lt;p&gt;To get the URL for your own public spreadsheet, just change the spreadsheet key (the long string there) and the worksheet ID (the first sheet is always 'od6').
&lt;/p&gt;
&lt;p&gt;
That JSON includes an array of entry objects, and each entry object contains an object for each of the columns, e.g.
&lt;/p&gt;
&lt;pre class="prettyprint"&gt;
[...
 gsx$url: {$t: "http://api.rucksack.com/hostelwithme.xml"},
 gsx$featured: {$t: "yes"}
..]
&lt;/pre&gt;

&lt;p&gt;
Note: Column headers are stripped of whitespace and lowercased when converted to keys in the JSON feed, so I always just start off with them that way in the spreadsheet to make it painless to find them in the JSON.
&lt;/p&gt;

&lt;p&gt;
Now, I write a simple handler that will pull in that JSON, parse each entry object, and convert them into datastore entities.
&lt;/p&gt;

&lt;pre class="prettyprint"&gt;
class ImportAppsActionHandler(BaseHandler):
 """ Handler for importing existing apps."""

 def get(self):
   user = users.get_current_user()
   # Need admin access to import
   if not user.is_current_user_admin():
     self.error(403)
   # Fetch JSON of published spreadsheet
   url = "http://spreadsheets.google.com/feeds/list/0Ah0xU81penP1dDNwSFROSU5KVlFRbmo5cERsTElKTGc/od6/public/values?alt=json"
   result = urlfetch.fetch(url)
   if result.status_code == 200:
     feed_obj = simplejson.loads(result.content)
     if "feed" in feed_obj:
       entries = feed_obj["feed"]["entry"]
       # Make an Application entity for each entry in feed
       for entry in entries:
         url = entry['gsx$url']['$t']
         featured = entry['gsx$featured']['$t']
         app = models.Application()
         app.url = url
         app.moderation_status = models.Application.MOD_APPROVED
         app.AddAuthor(user)
         app.AddMetadata()
         app.put()

   # Clear the memcache
   memcache.flush_all()
&lt;/pre&gt;

&lt;p&gt;
When I visit that handler, it imports the data, and works both on the local devapp server and the public server in the same way.
&lt;/p&gt;
&lt;p&gt;
There are various caveats to this technique, of course. First, your spreadsheet needs to be published. If you wanted to do it with a private spreadsheet, for more sensitive data, you would need to use the full spreadsheets API and &lt;a href="http://code.google.com/apis/spreadsheets/data/3.0/developers_guide_protocol.html#Authenticating" target="_blank"&gt;do an authentication dance&lt;/a&gt;. Second, your handler is limited to the typical 30 seconds limit for an App Engine request. If you wanted to use it to import many rows of data, you'd probably want to split it up across multiple requests by using the deferred &lt;a href="http://code.google.com/appengine/docs/python/taskqueue/" target="_blank"&gt;task queue&lt;/a&gt; or re-directing with pagination.
&lt;/p&gt;
&lt;p&gt;
But, hey, it was useful for my situation, so maybe it's useful for one more situation out there in the world. :)
&lt;p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8501278254137514883-8485808489630489285?l=blog.pamelafox.org' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.pamelafox.org/feeds/8485808489630489285/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=8501278254137514883&amp;postID=8485808489630489285' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8501278254137514883/posts/default/8485808489630489285'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8501278254137514883/posts/default/8485808489630489285'/><link rel='alternate' type='text/html' href='http://blog.pamelafox.org/2010/08/importing-data-from-spreadsheets-to-app.html' title='Importing data from Spreadsheets to App Engine'/><author><name>Pamela Fox</name><uri>http://www.blogger.com/profile/15947664772001597300</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://2.bp.blogspot.com/_T1lquhCmKo8/THXz9C6eLSI/AAAAAAAADeY/fN0qf3vSIU0/s72-c/screenshot_installerurls.png' height='72' width='72'/><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8501278254137514883.post-7900768871627078333</id><published>2010-08-24T14:13:00.001-07:00</published><updated>2010-08-24T14:13:26.509-07:00</updated><title type='text'>Tip for Networking at Conferences: Be a Speaker!</title><content type='html'>&lt;script type="text/javascript" src="https://blogspotty.appspot.com/static/post.js"&gt;&lt;/script&gt;
&lt;p style="text-align: left;"&gt;
Most people don't realize it, but I am incredibly shy -- they don't realize it because I've also spent a long time being shy, and have developed various "workarounds" because I know that it's healthy for me to interact with people and that it's not healthy for me to be a hermit (though tempting). &lt;br /&gt;&lt;br /&gt;
One of the situations where I find it quite easy for my shy-ness to take over is at conference, where I'm surrounded by hundreds of people that I don't know, and I think perhaps that some of them would be interesting conversational partners, but I haven't the slightest idea who, and how to approach them.&lt;br /&gt;&lt;br /&gt;
So, I work around it -- by being a speaker. By speaking at a conference, I make it so that there is atleast a room full of people that now have an excuse to talk to me, and I have something to talk with them about. That's a room-full more of people than when I was wandering around aimlessly through the halls before the talk! &lt;br /&gt;&lt;br /&gt;
Now, I know, it's not possible to be a speaker at every conference you go to. But, many conferences (atleast the cool ones) offer lightning talk sessions which can be signed-up for on the day of the event -- and many people have atleast one interesting or funny topic they can talk about for 5 minutes.&lt;br /&gt;&lt;br /&gt;
Whether you're a pre-slotted speaker or a lightning talk speaker, try to get your speaking slot on the first day. First, of course, that will mean you'll be able to relax after your talk and enjoy more of the conference, and second, that means that the room-ful of people will know of you sooner, and have more time to strike up a conversation with you.&lt;br /&gt;&lt;br /&gt;
And, hey, if any of you ever see me wandering around a conference (or sneaking into a bathroom to hide from all the intimidating people), stop by and say "hi". :)&lt;/p&gt;
&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8501278254137514883-7900768871627078333?l=blog.pamelafox.org' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.pamelafox.org/feeds/7900768871627078333/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=8501278254137514883&amp;postID=7900768871627078333' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8501278254137514883/posts/default/7900768871627078333'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8501278254137514883/posts/default/7900768871627078333'/><link rel='alternate' type='text/html' href='http://blog.pamelafox.org/2010/08/tip-for-networking-at-conferences-be.html' title='Tip for Networking at Conferences: Be a Speaker!'/><author><name>Pamela Fox</name><uri>http://www.blogger.com/profile/15947664772001597300</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8501278254137514883.post-3635157888215870243</id><published>2010-08-22T17:14:00.001-07:00</published><updated>2010-08-22T17:17:28.556-07:00</updated><title type='text'>5lide: HTML5-based Slides Maker</title><content type='html'>&lt;script type="text/javascript" src="https://blogspotty.appspot.com/static/post.js"&gt;&lt;/script&gt;

&lt;p style="text-align: left;"&gt;
At last week's &lt;a href="http://gtug-campout-2010.eventbrite.com/" target="_blank"&gt;GTUG campout&lt;/a&gt;, a 3-day long HTML5 hackathon, I signed up to be a TA for the weekend. That meant I spent most of my time wandering around answering random questions and helping developers debug their hacks. But, I can't be surrounded by a bunch of people hacking on cool shit and not join in myself -- it's just way too tempting. So, on Friday night, after coming home from the pitches and discovering that drinking 2 Dr. Pepper's was not in fact a good way to avoid jet lag, I stayed up into the wee hours hacking on an idea I'd been brewing for a few weeks.
&lt;/p&gt;
&lt;p&gt;
As some of you know from my posts about Prezi and Ignite, I am a fan of alternative slide formats and presentation techniques. In my work as both a student and a developer advocate, I have made a massive number of Powerpoint presentations, and I do believe there is much room for improvement and room for experimentation. So, whenever I spot a new slide format in the wild, I get excited to try it out myself. 
&lt;/p&gt;
&lt;p&gt;
Early last year, the HTML5 advocates started using &lt;a href="http://slides.html5rocks.com/" target="_blank"&gt;a set of slides&lt;/a&gt; that both showed off HTML5 features and were written in HTML5 - so they could do interactive samples and harness the power of HTML5 at the same time. (And by HTML5, I mostly mean rounded corners and CSS transitions :).  They recently created a generic stripped-down version for anyone to modify and use in &lt;a href="http://studio.html5rocks.com/" target="_blank"&gt;the HTML5 studio,&lt;/a&gt; but I wanted to take it a step further than that. I wanted to be able to store my slide data in a database and pull that into the slides template dynamically, so that I could work on my slide content separate from my presentation and easily create multiple slidesets without coding the base HTML each time. Thus began my hack!
&lt;/p&gt;
&lt;p&gt;
Since I had limited time to work on the app, I looked around for a sample application to start off with. One of the things I love about App Engine (well, atleast the Python version) is that when I find an open-sourced app similar to the one in my head, I can get it downloaded and deployed in just a few minutes. In the &lt;a href="http://code.google.com/p/google-app-engine-samples/" target="_blank"&gt;google-app-engine-samples&lt;/a&gt; project, I discovered the &lt;a href="http://code.google.com/p/google-app-engine-samples/source/browse/trunk/tasks" target="_blank"&gt;tasks app&lt;/a&gt; by the great &lt;a href="http://www.crunchbase.com/person/bret-taylor" target="_blank"&gt;Bret Taylor&lt;/a&gt;. The tasks app lets users sign in and create different task lists, where every list has a re-orderable set of tasks. The similarity to my app design was uncanny, and ridiculously convenient.  With some simple search and replace, the tasks app became a slides app, letting users create different slide sets, where every slide set has a re-orderable set of slides. (See what I mean?) Then I added the more slide-oriented features: I turned the generic HTML5 slide deck into a django template that pulled in the data, I added a "theme" option for each slide deck and used a different CSS for each theme ("party", "ballerina", and "android"), and I created a notion of a slide type for each slide (either the intro, transition, or body).
&lt;/p&gt;
&lt;p&gt;
&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;width: 500px;" src="http://3.bp.blogspot.com/_T1lquhCmKo8/THG9rTnW3HI/AAAAAAAADeQ/22lEbap8YJo/screenshot_slidemaker.png" border="0"/&gt;
&lt;/p&gt;
&lt;p&gt;
I demoed &lt;a href="http://5lide-maker.appspot.com/" target="_blank"&gt;the app&lt;/a&gt; in this form on demo night, and as usual, I haven't had time to add anything else to it since then. I'd like to add an "import from docs" as the next feature, as I have a few slidesets I want to bring over. I also think the slide editing interface could use some love and re-thinking, as it's really just a re-skinned task list editing interface right now. I have open-sourced all of the code &lt;a href="http://pamelafox-samplecode.googlecode.com/svn/trunk/slides/" target="_blank"&gt;here&lt;/a&gt;, as I'd love for other people to play around with it and maybe submit some patches (hint hint). 
&lt;/p&gt;
&lt;p&gt;Happy 5lide-ing! :)&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8501278254137514883-3635157888215870243?l=blog.pamelafox.org' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.pamelafox.org/feeds/3635157888215870243/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=8501278254137514883&amp;postID=3635157888215870243' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8501278254137514883/posts/default/3635157888215870243'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8501278254137514883/posts/default/3635157888215870243'/><link rel='alternate' type='text/html' href='http://blog.pamelafox.org/2010/08/5lide-html5-based-slides-maker.html' title='5lide: HTML5-based Slides Maker'/><author><name>Pamela Fox</name><uri>http://www.blogger.com/profile/15947664772001597300</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://3.bp.blogspot.com/_T1lquhCmKo8/THG9rTnW3HI/AAAAAAAADeQ/22lEbap8YJo/s72-c/screenshot_slidemaker.png' height='72' width='72'/><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8501278254137514883.post-8329878591539698399</id><published>2010-08-22T05:43:00.000-07:00</published><updated>2010-08-31T05:37:34.786-07:00</updated><title type='text'>Google APIs Timeline: Behind the Scenes</title><content type='html'>&lt;script type="text/javascript" src="https://blogspotty.appspot.com/static/post.js"&gt;&lt;/script&gt;
&lt;p style="text-align: left;"&gt;As part of my recent series of talks on the landscape of the Google APIs, I started off with a &lt;a href="http://imagine-it.org/google/apistimeline.html" target="_blank"&gt;timeline showing the history of our APIs&lt;/a&gt;, from just 10 APIs in 2005 to over 80 now, with many launches and a few deprecations along the way. That timeline, appropriately, is itself a quick mashup of our APIs, and I thought I'd spend a few minutes talking about how I made it here.
&lt;/p&gt;
&lt;p&gt;
First, I needed the data on our APIs over time. Unfortunately, we don't offer an API for querying our API existence over time (as awesomely meta as that would be), so I had to go the painstakingly manual route. I used the &lt;a href="http://web.archive.org/web/" target="_blank"&gt;Internet Wayback Machine&lt;/a&gt;, a website that lets you view cached versions of other websites at various times. We launched &lt;a href="http://code.google.com" target="_blank"&gt;code.google.com&lt;/a&gt; in March 2005 (and by we, I mean Chris Dibona), and the machine cached many versions since &lt;a href="http://web.archive.org/web/20050319051047/http://code.google.com/" target="_blank"&gt;that first version&lt;/a&gt;. By looking at a combination of the listings on the apis.html page and the launch announcements on the front page, I could figure out roughly which APIs we introduced when.
&lt;/p&gt;
&lt;p style="text-align: left;"&gt;
Next, I needed a place to store that data. Well, as some of you know, I'm a massive fan of using Google Spreadsheets as a lightweight database, so I created &lt;a href="https://spreadsheets.google.com/pub?key=0Ah0xU81penP1dE1TNnpscHdYYU5qSU5GZldLM1VMMVE&amp;hl=en&amp;output=html" target="_blank"&gt;a worksheet&lt;/a&gt; with a few columns (date, APIs added) and filled that in as I browsed the &lt;a href="http://code.google.com" target="_blank"&gt;code.google.com&lt;/a&gt; of yore (and got a bit nostalgic along the way).
&lt;/p&gt; 

&lt;p style="text-align: left;"&gt;
Finally, I wanted to visualize the data in a cool way. I had used the &lt;a href="http://code.google.com/apis/visualization/documentation/gallery/annotatedtimeline.html" target="_blank"&gt;Annotated Timeline&lt;/a&gt; from &lt;a href="http://code.google.com/apis/charttools/index.html" target="_blank"&gt;Google Chart Tools&lt;/a&gt; for the &lt;a href="http://googlewavedev.blogspot.com/2010/07/wave-visualizer-turning-trees-into.html" target="_blank"&gt;Wave Visualizer&lt;/a&gt; mashup last month, and I figured this was another good use of it. It's the same timeline that's used by Google Finance to show stock trends compared to news stories, and similar to the timeline used by Google Trends. Though the timeline itself is a Flash SWF, it is exposed via a Javascript API.
&lt;/p&gt;

&lt;p style="text-align: left;"&gt;
Now, to put it together, I just needed to pull in the spreadsheets data and feed that into the timeline. 
&lt;/p&gt;
&lt;p&gt;
I brought in the spreadsheets data using the &lt;a href="http://en.wikipedia.org/wiki/JSON#JSONP" target="_blank"&gt;JSONP&lt;/a&gt; technique, dynamically appending a script tag with the src attribute set to the JSON output of the &lt;a href="http://code.google.com/apis/spreadsheets/data/2.0/reference.html#ListFeed" target="_blank"&gt;spreadsheets API&lt;/a&gt;, and specifying a callback function to be passed the JSON data. Note that I used the &lt;a href="http://code.google.com/apis/spreadsheets/data/2.0/reference.html#Projection" target="_blank"&gt;"values" projection&lt;/a&gt; for the feed, as that treats the worksheet as a database and returns the named columns as values in the JSON.
&lt;/p&gt;

&lt;pre class="prettyprint"&gt;
function appendSpreadsheet() {
  var script = document.createElement('script');
  script.src = '&lt;a href="http://spreadsheets.google.com/feeds/list/0Ah0xU81penP1dE1TNnpscHdYYU5qSU5GZldLM1VMMVE/od6/public/values?alt=json-in-script&amp;callback=onSpreadsheetLoad" target="_blank"&gt;http://spreadsheets.google.com/feeds/list/0Ah0xU81penP1dE1TNnpscHdYYU5qSU5GZldLM1VMMVE/od6/public/values?alt=json-in-script&amp;amp;callback=onSpreadsheetLoad&lt;/a&gt;';
  document.body.appendChild(script);
}
&lt;/pre&gt;

&lt;p&gt;
In the callback function, I parse through the rows of the spreadsheets feed and add them as rows to a DataTable object. I then create the AnnotatedTimeline object and ask it to draw that data.
&lt;/p&gt;

&lt;pre class="prettyprint"&gt;
 function onSpreadsheetLoad(json) {
  var rows = json.feed.entry || [];
  var data = new google.visualization.DataTable();
  data.addColumn('date', 'Date');
  data.addColumn('number', 'Total APIs');
  data.addColumn('string', 'Changes');
  data.addRows(rows.length);
        
  for (var i = 0; i &amp;lt; rows.length; i++) {
    var row = rows[i];
    var year = parseInt(row['gsx$year']['$t']);
    var month = parseInt(row['gsx$month']['$t']);
    var day = parseInt(row['gsx$day']['$t']);
    var total = parseFloat(row['gsx$apitotal']['$t']);
    var info = row['gsx$info']['$t'];
    data.setValue(i, 0, new Date(year, month, day));
    data.setValue(i, 1, total);
    data.setValue(i, 2, info);
  }
        
  var annotatedtimeline = new google.visualization.AnnotatedTimeLine(
     document.getElementById('visualization'));
  annotatedtimeline.draw(data, {'displayAnnotations': true});
}
&lt;/pre&gt;

&lt;p&gt;
And with that (and some fiddling with the timeline options), I had an &lt;a href="http://imagine-it.org/google/apistimeline.html" target="_blank"&gt;interactive timeline&lt;/a&gt;:
&lt;/p&gt;

&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand; width:550px;" src="http://2.bp.blogspot.com/_T1lquhCmKo8/THEcIXI1JUI/AAAAAAAADeA/nSbDJc2QgJA/apistimeline.png" border="0"/&gt;

&lt;p style="text-align: left;"&gt;
It's a pretty simple mashup that only took a few hours to put together (99% of which was data collection), and an example of how you can easily combine a couple of our APIs in interesting ways. Happy mashing! :)
&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8501278254137514883-8329878591539698399?l=blog.pamelafox.org' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.pamelafox.org/feeds/8329878591539698399/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=8501278254137514883&amp;postID=8329878591539698399' title='3 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8501278254137514883/posts/default/8329878591539698399'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8501278254137514883/posts/default/8329878591539698399'/><link rel='alternate' type='text/html' href='http://blog.pamelafox.org/2010/08/google-apis-timeline-behind-scenes.html' title='Google APIs Timeline: Behind the Scenes'/><author><name>Pamela Fox</name><uri>http://www.blogger.com/profile/15947664772001597300</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://2.bp.blogspot.com/_T1lquhCmKo8/THEcIXI1JUI/AAAAAAAADeA/nSbDJc2QgJA/s72-c/apistimeline.png' height='72' width='72'/><thr:total>3</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8501278254137514883.post-1317877020833844563</id><published>2010-08-09T10:54:00.000-07:00</published><updated>2010-08-09T14:00:40.437-07:00</updated><title type='text'>Android Painting Apps: A Review</title><content type='html'>&lt;script type="text/javascript" src="https://blogspotty.appspot.com/static/post.js"&gt;&lt;/script&gt;
&lt;p style="text-align: left;"&gt;
Here is my preliminary review of 3 painting apps designed for the Android platform. Please suggest other ones or other opinions on these.&lt;br /&gt;&lt;br /&gt;
Note: I am not a professional artist, just an amateur doodler. :)&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;Differentiating Features:&lt;/span&gt;&lt;span style="font-weight: bold;"&gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;&lt;/span&gt;&lt;span style="font-weight: bold;"&gt;&lt;/span&gt;&lt;/p&gt;&lt;ul&gt;&lt;li style="text-align: left;"&gt;&lt;span style="font-weight: bold;"&gt;Paint Stroke Texture: &lt;/span&gt;Every app seems to implement their own stroking mechanism, so texture varies - and is important.&lt;/li&gt;&lt;li style="text-align: left;"&gt;&lt;span style="font-weight: bold;"&gt;Brush Size Picker: &lt;/span&gt;It's nice if you can quickly change/toggle sizes. You cycle through a lot of brush sizes when painting.&lt;/li&gt;&lt;li style="text-align: left;"&gt;&lt;span style="font-weight: bold;"&gt;Color Picker: &lt;/span&gt;It's important that you can pick shades of colors, like a human flesh tone.&lt;/li&gt;&lt;li style="text-align: left;"&gt;&lt;span style="font-weight: bold;"&gt;Undo/Redo:&lt;/span&gt; It's very easy to make mistakes while using a clunky finger on a small screen, so having an undo is essential to refining paintings.&lt;/li&gt;&lt;li style="text-align: left;"&gt;&lt;span style="font-weight: bold;"&gt;
Import (load from gallery): &lt;/span&gt;If you can bring in existing pictures from the gallery, then you can fork your previous paintings or paint on top of photos (like drawing moustaches on your colleagues).&lt;/li&gt;&lt;li style="text-align: left;"&gt;&lt;span style="font-weight: bold;"&gt;
Export (save to gallery): &lt;/span&gt;You always want to be able to save your paintings out, so you can keep an archive of them, tweet them, save them to your online photo albums, etc.&lt;/li&gt;&lt;/ul&gt;&lt;p style="text-align: left;"&gt;&lt;br /&gt;&lt;/p&gt;&lt;h3 style="text-align: left;"&gt;
FingerPaint Pro&lt;/h3&gt;&lt;p style="text-align: left;"&gt;&lt;/p&gt;&lt;ul&gt;&lt;li style="text-align: left;"&gt;&lt;span style="font-weight: bold;"&gt;Paint Stroke:&lt;/span&gt; Each stroke has a highlight + a shadow to it, like it's really a 3-dimensional stroke. It makes an interesting effect, but also makes it hard to do large blocks of color. I like the challenge of that though.&lt;/li&gt;&lt;li style="text-align: left;"&gt;&lt;span style="font-weight: bold;"&gt;Brush Size Picker:&lt;/span&gt; A nice UI that cycles between sizes with a single tap.&lt;/li&gt;&lt;li style="text-align: left;"&gt;&lt;span style="font-weight: bold;"&gt;Color Picker:&lt;/span&gt; A full H/S/V color picker with every color possible.&lt;/li&gt;&lt;li style="text-align: left;"&gt;&lt;span style="font-weight: bold;"&gt;Undo/Redo:&lt;/span&gt; Not supported.&lt;/li&gt;&lt;li style="text-align: left;"&gt;&lt;span style="font-weight: bold;"&gt;Import:&lt;/span&gt; Supported.&lt;/li&gt;&lt;li style="text-align: left;"&gt;&lt;span style="font-weight: bold;"&gt;Export:&lt;/span&gt; Supported.&lt;/li&gt;&lt;li style="text-align: left;"&gt;&lt;span style="font-weight: bold;"&gt;Conclusion:&lt;/span&gt; I find this paint texture so fascinating that I find myself using this the most. If this app implemented undo/redo, an eye dropper tool, and perhaps a bit of flexibility with the texture (to enable solid blobs of color), then it would really be my favorite app.&lt;/li&gt;&lt;/ul&gt;&lt;p style="text-align: left;"&gt;&lt;br /&gt;
Examples:&lt;br /&gt;&lt;/p&gt;
&lt;table align="center" cellpadding="0" cellspacing="0" style="margin-left: auto; margin-right: auto; text-align: center;"&gt;
  &lt;tr&gt;

&lt;td&gt;
  &lt;table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin: 0 .5em 0 .5em;"&gt;
    &lt;tbody&gt;
      &lt;tr&gt;
        &lt;td style="text-align: center;"&gt;
          &lt;a href="https://wave.googleusercontent.com/wave/attachment/2s8nx9x.jpg?id=kTZD4uQw2&amp;key=AH0qf5y8wslqhlqJLO6aLPFreCJQTfxTcA" imageanchor="1" style="margin-left: auto; margin-right: auto;"&gt;
            &lt;img border="0" src="https://wave.googleusercontent.com/wave/attachment/2s8nx9x.jpg?id=kTZD4uQw2&amp;key=AH0qf5y8wslqhlqJLO6aLPFreCJQTfxTcA" width="200" /&gt;
          &lt;/a&gt;
        &lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
        &lt;td class="tr-caption" style="text-align: center;"&gt;
          Eye of the Mummy
        &lt;/td&gt;
      &lt;/tr&gt;
    &lt;/tbody&gt;
  &lt;/table&gt;
&lt;/td&gt;
 
&lt;td&gt;
  &lt;table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin: 0 .5em 0 .5em;"&gt;
    &lt;tbody&gt;
      &lt;tr&gt;
        &lt;td style="text-align: center;"&gt;
          &lt;a href="https://wave.googleusercontent.com/wave/attachment/2vtekc8.jpg?id=kTZD4uQw5&amp;key=AH0qf5zSr8Xfv4cY4STrrULu4J5PvdsUPw" imageanchor="1" style="margin-left: auto; margin-right: auto;"&gt;
            &lt;img border="0" src="https://wave.googleusercontent.com/wave/attachment/2vtekc8.jpg?id=kTZD4uQw5&amp;key=AH0qf5zSr8Xfv4cY4STrrULu4J5PvdsUPw" width="200" /&gt;
          &lt;/a&gt;
        &lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
        &lt;td class="tr-caption" style="text-align: center;"&gt;
          Ice Cream in the Sky
        &lt;/td&gt;
      &lt;/tr&gt;
    &lt;/tbody&gt;
  &lt;/table&gt;
&lt;/td&gt;
 
  &lt;/tr&gt;
&lt;/table&gt;
&lt;p style="text-align: left;"&gt;&lt;/p&gt;&lt;h3 style="text-align: left;"&gt;
Kids Paint App&lt;/h3&gt;&lt;ul&gt;&lt;li style="text-align: left;"&gt;&lt;span style="font-weight: bold;"&gt;Paint Stroke:&lt;/span&gt; Each stroke is of a random thickness and color.&lt;/li&gt;&lt;li style="text-align: left;"&gt;&lt;span style="font-weight: bold;"&gt;Brush Size Picker:&lt;/span&gt; Not supported.&lt;/li&gt;&lt;li style="text-align: left;"&gt;&lt;span style="font-weight: bold;"&gt;Color Picker:&lt;/span&gt; Not supported.&lt;/li&gt;&lt;li style="text-align: left;"&gt;&lt;span style="font-weight: bold;"&gt;Undo/Redo:&lt;/span&gt; Not supported.&lt;/li&gt;&lt;li style="text-align: left;"&gt;&lt;span style="font-weight: bold;"&gt;Import: &lt;/span&gt;Not supported.&lt;/li&gt;&lt;li style="text-align: left;"&gt;&lt;span style="font-weight: bold;"&gt;Export:&lt;/span&gt; Supported.&lt;/li&gt;&lt;li style="text-align: left;"&gt;&lt;span style="font-weight: bold;"&gt;Conclusion: &lt;/span&gt;It is cute to play with, and it is interesting to see what one comes up with, but it will be frustrating for anyone with a particular goal in mind. (And I think most people acquire a goal after fiddling for a while, and a sudden change in stroke color can so easily squash goals here). I admire the different take, though.&lt;/li&gt;&lt;/ul&gt;&lt;p style="text-align: left;"&gt;&lt;br /&gt;
Example:&lt;br /&gt;&lt;br /&gt;&lt;/p&gt;
&lt;table align="center" cellpadding="0" cellspacing="0" style="margin-left: auto; margin-right: auto; text-align: center;"&gt;
  &lt;tr&gt;

&lt;td&gt;
  &lt;table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin: 0 .5em 0 .5em;"&gt;
    &lt;tbody&gt;
      &lt;tr&gt;
        &lt;td style="text-align: center;"&gt;
          &lt;a href="https://wave.googleusercontent.com/wave/attachment/4856492570_1e0f461b72_b.jpg?id=VzaGjPTb12&amp;key=AH0qf5zeNP4aUNjxOsRVLfBQUz-Lk2ODZw" imageanchor="1" style="margin-left: auto; margin-right: auto;"&gt;
            &lt;img border="0" src="https://wave.googleusercontent.com/wave/attachment/4856492570_1e0f461b72_b.jpg?id=VzaGjPTb12&amp;key=AH0qf5zeNP4aUNjxOsRVLfBQUz-Lk2ODZw" width="200" /&gt;
          &lt;/a&gt;
        &lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
        &lt;td class="tr-caption" style="text-align: center;"&gt;
          Eye
        &lt;/td&gt;
      &lt;/tr&gt;
    &lt;/tbody&gt;
  &lt;/table&gt;
&lt;/td&gt;
 
  &lt;/tr&gt;
&lt;/table&gt;
&lt;p style="text-align: left;"&gt;&lt;br /&gt;&lt;/p&gt;&lt;h3 style="text-align: left;"&gt;
Magic Marker&lt;/h3&gt;&lt;ul&gt;&lt;li style="text-align: left;"&gt;&lt;span style="font-weight: bold;"&gt;Paint Stroke:&lt;/span&gt; Each stroke is actually white, with a colored glow around it (for a neon effect).&lt;/li&gt;&lt;li style="text-align: left;"&gt;&lt;span style="font-weight: bold;"&gt;Brush Size Picker:&lt;/span&gt; Clicking on the current brush size pops up other sizes to pick from.&lt;/li&gt;&lt;li style="text-align: left;"&gt;&lt;span style="font-weight: bold;"&gt;Color Picker:&lt;/span&gt; 8 swatches and a basic wheel. Shades not supported.&lt;/li&gt;&lt;li style="text-align: left;"&gt;&lt;span style="font-weight: bold;"&gt;Undo/Redo:&lt;/span&gt; Supported.&lt;/li&gt;&lt;li style="text-align: left;"&gt;&lt;span style="font-weight: bold;"&gt;Import:&lt;/span&gt; Supported.&lt;/li&gt;&lt;li style="text-align: left;"&gt;&lt;span style="font-weight: bold;"&gt;Export:&lt;/span&gt; Supported.&lt;/li&gt;&lt;li style="text-align: left;"&gt;&lt;span style="font-weight: bold;"&gt;Conclusion:&lt;/span&gt; This app has a specific type of artistry in mind, and it delivers all the basic features needed to make the artists experience a good one. It would be great to see some additional pizazz in the future- like sparkles or brush shapes - but this is a great start for a unique vision.&lt;/li&gt;&lt;/ul&gt;&lt;p style="text-align: left;"&gt;&lt;br /&gt;
Example:&lt;br /&gt;&lt;/p&gt;
&lt;table align="center" cellpadding="0" cellspacing="0" style="margin-left: auto; margin-right: auto; text-align: center;"&gt;
  &lt;tr&gt;

&lt;td&gt;
  &lt;table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin: 0 .5em 0 .5em;"&gt;
    &lt;tbody&gt;
      &lt;tr&gt;
        &lt;td style="text-align: center;"&gt;
          &lt;a href="https://wave.googleusercontent.com/wave/attachment/2z7elnt.jpg?id=kTZD4uQw4&amp;key=AH0qf5zDZ0cQkLd-wG32UllXtKyxHGV8SQ" imageanchor="1" style="margin-left: auto; margin-right: auto;"&gt;
            &lt;img border="0" src="https://wave.googleusercontent.com/wave/attachment/2z7elnt.jpg?id=kTZD4uQw4&amp;key=AH0qf5zDZ0cQkLd-wG32UllXtKyxHGV8SQ" width="200" /&gt;
          &lt;/a&gt;
        &lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
        &lt;td class="tr-caption" style="text-align: center;"&gt;
          Magic Mercure
        &lt;/td&gt;
      &lt;/tr&gt;
    &lt;/tbody&gt;
  &lt;/table&gt;
&lt;/td&gt;
 
  &lt;/tr&gt;
&lt;/table&gt;
&lt;p style="text-align: left;"&gt;&lt;/p&gt;&lt;h3 style="text-align: left;"&gt;
DoodleDroid&lt;/h3&gt;&lt;p style="text-align: left;"&gt;&lt;/p&gt;&lt;ul&gt;&lt;li style="text-align: left;"&gt;&lt;span style="font-weight: bold;"&gt;Paint Stroke:&lt;/span&gt; You can pick a variety of different textures, and some of them produce a nice effect of varying thickness.&lt;/li&gt;&lt;li style="text-align: left;"&gt;&lt;span style="font-weight: bold;"&gt;Brush Size Picker:&lt;/span&gt; The stroke adjustment dialog lets you pick a "base width" and "tip width", as well as a transparency.&lt;/li&gt;&lt;li style="text-align: left;"&gt;&lt;span style="font-weight: bold;"&gt;Color Picker:&lt;/span&gt; You can basically pick any color ever, using two different types of pickers. You can also use an eyedrop tool to pick an existing color from the app.&lt;/li&gt;&lt;li style="text-align: left;"&gt;&lt;span style="font-weight: bold;"&gt;Undo/Redo:&lt;/span&gt; Not supported. :(&lt;/li&gt;&lt;li style="text-align: left;"&gt;&lt;span style="font-weight: bold;"&gt;Import: &lt;/span&gt;Supported.&lt;/li&gt;&lt;li style="text-align: left;"&gt;&lt;span style="font-weight: bold;"&gt;Export:&lt;/span&gt; Supported.&lt;/li&gt;&lt;li style="text-align: left;"&gt;&lt;span style="font-weight: bold;"&gt;Conclusion:&lt;/span&gt; This app is probably the best painting app, because you have so much flexibility in the paint stroke, from texture to color, and with enough layers and patience, you can create some quite detailed paintings. The huge missing feature is the Undo, and with the absence of that, it's hard to go from a good painting to a great painting.&lt;/li&gt;&lt;/ul&gt;&lt;p style="text-align: left;"&gt;&lt;br /&gt;&lt;/p&gt;
&lt;table align="center" cellpadding="0" cellspacing="0" style="margin-left: auto; margin-right: auto; text-align: center;"&gt;
  &lt;tr&gt;

&lt;td&gt;
  &lt;table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin: 0 .5em 0 .5em;"&gt;
    &lt;tbody&gt;
      &lt;tr&gt;
        &lt;td style="text-align: center;"&gt;
          &lt;a href="https://wave.googleusercontent.com/wave/attachment/4845380557_81221129eb_b.jpg?id=VzaGjPTb11&amp;key=AH0qf5wyQRoVqwLnUhyNp9yjrZ2uQ9wMEg" imageanchor="1" style="margin-left: auto; margin-right: auto;"&gt;
            &lt;img border="0" src="https://wave.googleusercontent.com/wave/attachment/4845380557_81221129eb_b.jpg?id=VzaGjPTb11&amp;key=AH0qf5wyQRoVqwLnUhyNp9yjrZ2uQ9wMEg" width="200" /&gt;
          &lt;/a&gt;
        &lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
        &lt;td class="tr-caption" style="text-align: center;"&gt;
          Alan
        &lt;/td&gt;
      &lt;/tr&gt;
    &lt;/tbody&gt;
  &lt;/table&gt;
&lt;/td&gt;
 
  &lt;/tr&gt;
&lt;/table&gt;
&lt;p style="text-align: left;"&gt;&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8501278254137514883-1317877020833844563?l=blog.pamelafox.org' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.pamelafox.org/feeds/1317877020833844563/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=8501278254137514883&amp;postID=1317877020833844563' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8501278254137514883/posts/default/1317877020833844563'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8501278254137514883/posts/default/1317877020833844563'/><link rel='alternate' type='text/html' href='http://blog.pamelafox.org/2010/08/android-painting-apps-review.html' title='Android Painting Apps: A Review'/><author><name>Pamela Fox</name><uri>http://www.blogger.com/profile/15947664772001597300</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8501278254137514883.post-8538391143583452617</id><published>2010-08-08T21:08:00.001-07:00</published><updated>2010-08-08T21:15:34.616-07:00</updated><title type='text'>How to pick &amp; prepare an Ignite talk</title><content type='html'>&lt;script type="text/javascript" src="https://blogspotty.appspot.com/static/post.js"&gt;&lt;/script&gt;
&lt;h1 style="text-align: left;"&gt;&lt;/h1&gt;&lt;p style="text-align: left;"&gt;&lt;br /&gt;
I am now somewhat of an Ignite veteran. I've given talks at multiple Ignites, including Ignite Spatial (for GIS folks) and Google I/O Ignite (for hard core developers). I don't necessarily give the best talk, but I usually give a talk that goes over well. So, I thought I'd share my personal technique for creating an Ignite talk, as it can be a bit different from typical talks.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;When I think of a topic for an Ignite talk, I look for one with the following characteristics:&lt;/span&gt;&lt;span style="font-weight: bold;"&gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;&lt;/span&gt;&lt;span style="font-weight: bold;"&gt;&lt;/span&gt;&lt;/p&gt;&lt;ul&gt;&lt;li style="text-align: left;"&gt;
Something that mixes humor, inspiration, information&lt;/li&gt;&lt;li style="text-align: left;"&gt;
Something I'm personally passionate about&lt;/li&gt;&lt;li style="text-align: left;"&gt;
Something that tells a story or has a narrative&lt;/li&gt;&lt;/ul&gt;&lt;p style="text-align: left;"&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;Then, once I've decided the topic, I need to actually create the talk. I typically take these steps:&lt;/span&gt;&lt;span style="font-weight: bold;"&gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;&lt;/span&gt;&lt;span style="font-weight: bold;"&gt;&lt;/span&gt;&lt;/p&gt;&lt;ul&gt;&lt;li style="text-align: left;"&gt;
Spend a week simply thinking about the topic, hearing yourself talk about it in my head. It's a great way to spend the morning commute, and a great way to make sure that the flow of the talk will be natural once it's down on paper.&lt;/li&gt;&lt;li style="text-align: left;"&gt;
Create a text document. I usually draft in Wave these days, so that I can share it with my friend and ask for comments, but otherwise any old editor will do - some folks even use real-life things like post-its. The important thing is that it should be a format that allows you to iterate easily. &lt;/li&gt;&lt;li style="text-align: left;"&gt;
Write down a list of all the bits of information you potentially want to communicate, and order them according to what feels natural. &lt;/li&gt;&lt;li style="text-align: left;"&gt;
See if you are at or around 20 bits of information, where a bit is about 2-3 sentences (you may want to time yourself to see what your personal pace of communication is, and calibrate that #). If you have too many, think about what point to cut, or what details to leave. If you have too little, think about what else you might communicate - maybe more backstory, a calls to action, or an anecdote.&lt;/li&gt;&lt;li style="text-align: left;"&gt;
Say this talk to yourself. Say it to a friend. See if it feels natural, that everything transitions together, and that it's similar to the way you might spontaneously tell these bits of information. That will make it easier to deliver. &lt;/li&gt;&lt;li style="text-align: left;"&gt;
Start thinking about the visualization of your information bits. If you've got 5 bits in a row that you have no idea how to visualize, you may want to re-think those bits. Eventually, each bit will need a picture.&lt;/li&gt;&lt;li style="text-align: left;"&gt;
Keep playing around with the talk, moving bits of information around, moving them in and out, until you get to a point where it just feels right, and you're at the right # of slides. &lt;/li&gt;&lt;li style="text-align: left;"&gt;
Create a powerpoint (or keynote) presentation. &lt;/li&gt;&lt;li style="text-align: left;"&gt;
Insert a text box on each slide that contains the text for that slide. Position it below the slides.&lt;/li&gt;&lt;li style="text-align: left;"&gt;
Start filling in the visuals. They might be photos that you've taken, images from the web (like iStockPhoto or CC-licensed Flickr pics), or hand-drawn doodles. Try and make them be something that jives with the audience, but also jives your memory about the content of the slide.&lt;/li&gt;&lt;li style="text-align: left;"&gt;
Add short headers to each slide, if you want. Position them near the top of the slide, as the bottom is often hard for the audience to see. Try to avoid adding any text besides a header  -- you don't want to distract audience members from what you're saying, and you don't want to make them feel they're reading off your talk.&lt;/li&gt;&lt;li style="text-align: left;"&gt;
Move the slide text up to the bottom of the slide.&lt;/li&gt;&lt;li style="text-align: left;"&gt;
Set the animation settings for auto-advance every 15 seconds.&lt;/li&gt;&lt;li style="text-align: left;"&gt;
Start practicing the talk. Since the slide text is visible, you get to view the text while practicing. After each practice, go back and make any tweaks to the text, change anything that didn't feel right, went too long, etc. &lt;/li&gt;&lt;li style="text-align: left;"&gt;
Once you feel comfortable, move the slide text below the slides, and practice the talk that way multiple times. This is the test that most nearly mimics the actual event characteristics.&lt;/li&gt;&lt;li style="text-align: left;"&gt;
Create a text document with all of your slide text, and print it out. You can now carry it around and practice it to yourself when you have the chance, like at the bathroom at the venue. :)&lt;/li&gt;&lt;li style="text-align: left;"&gt;&lt;span style="font-weight: bold;"&gt;Go to Ignite! Drink water. Give the talk. Be excited. &lt;/span&gt;&lt;/li&gt;&lt;span style="font-weight: bold;"&gt;&lt;/span&gt;&lt;li style="text-align: left;"&gt;&lt;span style="font-weight: bold;"&gt;&lt;/span&gt;Create a version of the slides that's consumable by non-Ignite attendees by moving the slide text box back onto the bottom of the slides. Upload it to Scribd, Slideshare, Google docs, and share it on Twitter, Facebook, etc. People love to read through these short slidesets, and with the transcript pasted on, the slides will actually make sense.&lt;/li&gt;&lt;/ul&gt;&lt;p style="text-align: left;"&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;My past Ignite talks:&lt;/span&gt;&lt;/p&gt;&lt;ul&gt;&lt;li style="text-align: left;"&gt;&lt;a href="http://www.slideshare.net/wuzziwug/flex-vs-html5-for-rias-presentation" target="_blank"&gt;Flex vs HTML5 for RIAs&lt;/a&gt; &lt;/li&gt;&lt;li style="text-align: left;"&gt;&lt;a href="http://otherfancystuff.blogspot.com/2009/05/ignite-io-growing-up-geek-my-dad.html" target="_blank"&gt;Growing Up Geek: My Dad, the Computer Scientist&lt;/a&gt;&lt;/li&gt;&lt;a href="http://otherfancystuff.blogspot.com/2009/05/ignite-io-growing-up-geek-my-dad.html" target="_blank"&gt;&lt;/a&gt;&lt;li style="text-align: left;"&gt;&lt;a href="http://otherfancystuff.blogspot.com/2009/05/ignite-io-growing-up-geek-my-dad.html" target="_blank"&gt;
 &lt;/a&gt;&lt;a href="http://otherfancystuff.blogspot.com/2009/10/world-of-words-and-me.html" target="_blank"&gt;A World of Words&lt;/a&gt;&lt;a href="http://otherfancystuff.blogspot.com/2009/05/ignite-io-growing-up-geek-my-dad.html" target="_blank"&gt; &lt;/a&gt;&lt;/li&gt;&lt;a href="http://otherfancystuff.blogspot.com/2009/05/ignite-io-growing-up-geek-my-dad.html" target="_blank"&gt;&lt;/a&gt;&lt;li style="text-align: left;"&gt;&lt;a href="http://otherfancystuff.blogspot.com/2009/05/ignite-io-growing-up-geek-my-dad.html" target="_blank"&gt;&lt;/a&gt;&lt;a href="http://www.scribd.com/doc/21396787/Collaborative-Mapping-with-Google-Wave" target="_blank"&gt;Collaborative Mapping with Google Wave&lt;/a&gt;&lt;a href="http://otherfancystuff.blogspot.com/2009/05/ignite-io-growing-up-geek-my-dad.html" target="_blank"&gt; &lt;/a&gt;&lt;/li&gt;&lt;a href="http://otherfancystuff.blogspot.com/2009/05/ignite-io-growing-up-geek-my-dad.html" target="_blank"&gt;&lt;/a&gt;&lt;li style="text-align: left;"&gt;&lt;a href="http://otherfancystuff.blogspot.com/2009/05/ignite-io-growing-up-geek-my-dad.html" target="_blank"&gt;&lt;/a&gt;&lt;a href="http://www.scribd.com/doc/27710281/I%25E2%2580%2599m-a-Barbie-Girl-in-a-CS-World" target="_blank"&gt;I'm a Barbie Girl in a CS World&lt;/a&gt; (or watch &lt;a href="http://igniteshow.com/videos/im-barbie-girl-cs-world"&gt;the video&lt;/a&gt;)&lt;/li&gt;
&lt;/ul&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8501278254137514883-8538391143583452617?l=blog.pamelafox.org' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.pamelafox.org/feeds/8538391143583452617/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=8501278254137514883&amp;postID=8538391143583452617' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8501278254137514883/posts/default/8538391143583452617'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8501278254137514883/posts/default/8538391143583452617'/><link rel='alternate' type='text/html' href='http://blog.pamelafox.org/2010/08/how-to-pick-prepare-ignite-talk.html' title='How to pick &amp; prepare an Ignite talk'/><author><name>Pamela Fox</name><uri>http://www.blogger.com/profile/15947664772001597300</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8501278254137514883.post-1841510507248857758</id><published>2010-08-06T08:17:00.000-07:00</published><updated>2010-08-06T08:26:38.059-07:00</updated><title type='text'>Why I Like Prezi</title><content type='html'>&lt;p&gt;In my life, I have given a *lot* of presentations. In high school, they were presentations on group projects. In university, they were presentations on research projects. At Google, they're presentations on how to use our APIs. When I first started giving presentations, I used Powerpoint, like everyone else. But I kept thinking there must be a better way, and I experimented with other options - flash interfaces, interactive Javascript apps. Then I discovered &lt;a href="http://prezi.com/"&gt;Prezi&lt;/a&gt;, and it has become my presentation tool of choice.
&lt;/p&gt;
&lt;p&gt;
Prezi is an online tool for creating presentations &amp;mdash; but it's not just a Powerpoint clone, like the Zoho or Google offering. When you first create a Prezi, you're greeted with a blank canvas and a small toolbox. You can write text, insert images, and draw arrows. You can draw frames (visible or hidden) around bits of content, and then you can define a path from one frame to the next frame. That path is your presentation. It's like being able to draw your thoughts on a whiteboard, and then instructing a camera where to go and what to zoom into. It's a simple idea, but I love it. Here's why:
&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
It forces me to "shape" my presentation. A slide deck is always linear in form, with no obvious structure of ideas inside of it. Each of my Prezis has a structure, and each structure is different. The structure is visual, but it supports a conceptual structure.  &lt;a href="http://prezi.com/oweoki7m572u/"&gt;One structure&lt;/a&gt; might be 3 main ideas, with rows of ideas for each one. &lt;a href="http://prezi.com/hgltotxorlot/"&gt;Another&lt;/a&gt; might be 1 main idea, with a circular branching of subideas.  Having a structure helps me to have more of a point to my presentations, and to realize the core ideas of them.
&lt;li&gt;
It makes it easy to go from brainstorming stage to presentation stage, all in the same tool. I can write a bunch of thoughts, insert some images, and easily move them around, cluster them, re-order them, etc. I can figure out the structure of my presentation by looking at what I have laid out, and seeing how they fit together. Some people do this process with post-its, but I like being able to do it with a digital canvas. 
&lt;li&gt;
It works well for explaining concepts that make more sense with a diagram, because you can basically make your entire presentation be the diagram &amp;mdash; and then you can just fly around that diagram, pointing out the flow and zooming into the important bits. For example, I used pseudo diagrams inside the &lt;a href="http://prezi.com/l5dtfctypd_3/"&gt;robots API&lt;/a&gt; and &lt;a href="http://prezi.com/oc884wp8tplr/"&gt;gadgets API&lt;/a&gt; prezis to explain the API &amp;lt;-&amp;gt; server interaction.
&lt;/ul&gt;

&lt;p&gt;
Prezi isn't perfect, of course. I've made several feature requests, and have a list of others. There are the small requests, like wanting higher quality images and a code style for embedded snippets, and there are also the big picture requests. I want to be able to link prezis inside of prezis, so that I can make "components" of presentations, and easily zoom from one to the other. I want to be able to create multiple paths for a given prezi, so that I can skip over bits for some audiences, and emphasize them for others. Hell, I'd love if I could have one canvas that had every bit of possible content on a topic, and I could use that one canvas for 20 different presentations. I don't know that Prezi will ever implement these ideas, but I have more faith in them doing so than any other presentation tool, since they are making a point of thinking different.
&lt;/p&gt;
&lt;p&gt;
Generally, I just love the fact that somebody is thinking different about presentation tools. There are so many people out there that are giving presentations every day, so as a society, we owe it to ourselves to invest more thought into how we do presentations. That's why I also like events like Ignite and Webjam, because they are challenging people to rethink the timing aspect of presentations. 
&lt;/p&gt;
&lt;p&gt;
(Not to talk about Wave all the time, but&amp;mdash;)
&lt;/p&gt;
&lt;p&gt;
My love for Prezi is similar to my love for Wave. Prezi is re-thinking presentations. Wave is re-thinking communication. Prezi gives me a blank canvas that can turn into a presentation of any shape. Wave gives me a blank wave that can turn into a document or conversation of any structure. Both of them are unfinished, but both have a bright future, and even if they don't succeed, they're successfully challenging the traditions of today.
&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8501278254137514883-1841510507248857758?l=blog.pamelafox.org' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.pamelafox.org/feeds/1841510507248857758/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=8501278254137514883&amp;postID=1841510507248857758' title='3 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8501278254137514883/posts/default/1841510507248857758'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8501278254137514883/posts/default/1841510507248857758'/><link rel='alternate' type='text/html' href='http://blog.pamelafox.org/2010/08/why-i-like-prezi.html' title='Why I Like Prezi'/><author><name>Pamela Fox</name><uri>http://www.blogger.com/profile/15947664772001597300</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>3</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8501278254137514883.post-7017675063242146125</id><published>2010-07-23T18:31:00.001-07:00</published><updated>2010-08-06T08:52:22.823-07:00</updated><title type='text'>How-to: 80s-ify your geek shirt!</title><content type='html'>I've created my first "instructable" on the technique I use for modding my t-shirts. &lt;a href="http://www.instructables.com/id/How-to-80s-ify-your-geek-t-shirt/"&gt;Check it out here!&lt;/a&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8501278254137514883-7017675063242146125?l=blog.pamelafox.org' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.pamelafox.org/feeds/7017675063242146125/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=8501278254137514883&amp;postID=7017675063242146125' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8501278254137514883/posts/default/7017675063242146125'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8501278254137514883/posts/default/7017675063242146125'/><link rel='alternate' type='text/html' href='http://blog.pamelafox.org/2010/07/how-to-80s-ify-your-geek-shirt.html' title='How-to: 80s-ify your geek shirt!'/><author><name>Pamela Fox</name><uri>http://www.blogger.com/profile/15947664772001597300</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8501278254137514883.post-5128537051202368095</id><published>2010-07-18T04:07:00.000-07:00</published><updated>2010-08-22T05:56:52.837-07:00</updated><title type='text'>Sydney MCA: Notable Artists</title><content type='html'>&lt;div id="waveframe" style="width:600px; height:600px;"&gt;&lt;/div&gt;

&lt;script src="http://www.google.com/jsapi"&gt;&lt;/script&gt;&lt;script type="text/javascript"&gt; google.load("wave", "1"); google.setOnLoadCallback(function() { new google.wave.WavePanel({target: document.getElementById("waveframe")}).loadWave("googlewave.com!w+iPUuNpBZB");}); &lt;/script&gt;

&lt;noscript&gt;
You need Javascript to view the embedded wave in this post.
&lt;/noscript&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8501278254137514883-5128537051202368095?l=blog.pamelafox.org' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.pamelafox.org/feeds/5128537051202368095/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=8501278254137514883&amp;postID=5128537051202368095' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8501278254137514883/posts/default/5128537051202368095'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8501278254137514883/posts/default/5128537051202368095'/><link rel='alternate' type='text/html' href='http://blog.pamelafox.org/2010/07/sydney-mca-notable-artists.html' title='Sydney MCA: Notable Artists'/><author><name>Pamela Fox</name><uri>http://www.blogger.com/profile/15947664772001597300</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8501278254137514883.post-8482645296165858737</id><published>2010-07-14T06:25:00.000-07:00</published><updated>2010-07-14T06:29:43.250-07:00</updated><title type='text'>GTUG Campout: A weekend of HTML5 in 11+ Cities!</title><content type='html'>&lt;p&gt;To quote the organizer:&lt;/p&gt;
&lt;p&gt;
"GTUG Campout is an annual weekend-long event where Google Technology User Group members have an opportunity to design, develop, and demo a complete application over the course of three days. This year, the theme will be HTML5. The event kicks off on Friday, August 13th, where ideas and teams will come together. Teams will then have the rest of the weekend to build their HTML5 applications before presenting their work to the public on Sunday evening."
&lt;/p&gt;
&lt;p&gt;
The campout is so far scheduled to happen in GTUGs in 11 cities:
&lt;/p&gt;
&lt;iframe src="http://www.meetup.com/everywhere/widget2/GTUG-Campout/?width=300" border="0" frameborder="0" height="390" width="300"&gt;&lt;/iframe&gt;

&lt;p&gt;I will be in the bay area around that time anyway, so I'm going to join in on the SF Bay meetup. As I've done other hacking weekends and seen Wave is pretty useful for these kind of things, I'm going to put together a Wave-based forum and team wikis for the weekend. If you're participating in the campout, stay tuned for details on those!
&lt;/p&gt;

&lt;p&gt;Hacking weekends are always a lot of fun, and HTML5 is freaking awesome, so I encourage you to join at the city nearest you, or hey, just reserve that weekend for hacking and join in virtually!
&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8501278254137514883-8482645296165858737?l=blog.pamelafox.org' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.pamelafox.org/feeds/8482645296165858737/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=8501278254137514883&amp;postID=8482645296165858737' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8501278254137514883/posts/default/8482645296165858737'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8501278254137514883/posts/default/8482645296165858737'/><link rel='alternate' type='text/html' href='http://blog.pamelafox.org/2010/07/gtug-campout-weekend-of-html5-in-11.html' title='GTUG Campout: A weekend of HTML5 in 11+ Cities!'/><author><name>Pamela Fox</name><uri>http://www.blogger.com/profile/15947664772001597300</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8501278254137514883.post-546732169571096406</id><published>2009-11-12T14:06:00.000-08:00</published><updated>2010-04-14T05:49:14.767-07:00</updated><title type='text'>Developer Relations Explained (The Nerdy Way)</title><content type='html'>&lt;p&gt;I often find it hard to answer the question, "So, what do you do at Google?" I find it hardest when that question is asked by someone completely outside the tech field, like a face-painter or a taxi driver, but it is hard even to explain to techies. It's not as simple as saying that I'm a tester, a software engineer, a product manager, or a support staff, because it's a crazy awesome combination of all the above. I'm in developer relations, and there are an awful lot of ways to relate to developers. We write articles and blog posts, create sample code and one-off projects, maintain open-source projects, respond to forum posts, triage bugs, speak at conferences, meet with partners, and generally do what needs to get done.&lt;/p&gt;
&lt;p&gt;One way of explaining our various roles in developer relations is to break it down into two parts: first, the type of developers that we support, and second, the particular developer product(s) that we support. For example, I generally support long-tail developers, and I supported the Maps APIs for the first 3 years, and now I'm supporting the Wave APIs. Some of my colleagues support our higher-touch partners or even our paying customers, and their role involves more 1-on-1 meetings and emails. You can play with the little app below to experiment with more configurations of products and developer types:
&lt;/p&gt;
&lt;iframe src="http://pamelafox-samplecode.googlecode.com/svn/trunk/devrelformula.html" width="600" height="150" frameborder="0"&gt;&lt;br /&gt;&lt;/iframe&gt;

&lt;p&gt;
Currently, in developer relations, we have one of two specific titles: "Developer Programs Engineer" and "Developer Advocate". Basically, the DPE supports the long-tail and the DA supports the high-touch partners. It doesn't really split as even as that in reality, but that's the basic idea.
&lt;/p&gt;
&lt;p&gt;So, that brings me to the real reason for this post. We are now hiring &lt;a href="http://sites.google.com/site/googdevreljobs/"&gt;DPEs and DAs&lt;/a&gt;. The jobs site only lists positions for Mountain View and New York, but there are also scattered positions around the world, in places like Australia, China, and India.  It's a fun challenge to figure out how best to relate to developers using our growing number of developer products (including the just-released &lt;a href="http://www.golang.org/"&gt;Go&lt;/a&gt; language), and we can always benefit from having a broad range of opinions and skills represented on our team. If you're interested, apply! :)
&lt;/p&gt;
&lt;!--
&lt;a target="_blank" href="https://wave.google.com/wave/wavethis?t=Developer+Relations+Explained&amp;amp;c=%22We+write+articles+and+blog+posts,+create+sample+code+and+one-off+projects,+maintain+open+source+projects,+respond+to+forum+posts,+triage+bugs,+speak+at+conferences,+meet+with+partners,+and+generally+do+what+needs+to+get+done.%22"&gt;
&lt;img style="cursor:pointer; border:1px solid grey; cursor:hand;width: 153px; height: 36px;" src="http://4.bp.blogspot.com/_T1lquhCmKo8/S8RLVEqN0iI/AAAAAAAADSE/l5dS_snHJcM/s400/wavethis.png" border="0" alt=""id="BLOGGER_PHOTO_ID_5459571473680028194" /&gt;
&lt;/a&gt;
--&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8501278254137514883-546732169571096406?l=blog.pamelafox.org' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.pamelafox.org/feeds/546732169571096406/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=8501278254137514883&amp;postID=546732169571096406' title='3 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8501278254137514883/posts/default/546732169571096406'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8501278254137514883/posts/default/546732169571096406'/><link rel='alternate' type='text/html' href='http://blog.pamelafox.org/2009/11/developer-relations-explained-nerdy-way.html' title='Developer Relations Explained (The Nerdy Way)'/><author><name>Pamela Fox</name><uri>http://www.blogger.com/profile/15947664772001597300</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>3</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8501278254137514883.post-1729915110768351059</id><published>2009-10-28T05:39:00.000-07:00</published><updated>2009-10-28T06:39:59.712-07:00</updated><title type='text'>Being a Girl in CS Doesn't Suck</title><content type='html'>&lt;span class="Apple-style-span"   style="font-family:arial, sans-serif;font-size:100%;"&gt;&lt;span class="Apple-style-span"  style="border-collapse: collapse; font-size:13px;"&gt;&lt;span class="Apple-style-span"  style="border-collapse: separate;  font-size:small;"&gt;&lt;p style="font-weight: bold; "&gt;&lt;span class="Apple-style-span" style="font-weight: normal; "&gt;When I posted last week about an experience with gender bias in "Should I Defend My Cred?", some of the re-tweets basically implied that post was proof that it sucks being a girl in CS. Well, I want to clarify that it doesn't suck. It's actually pretty freaking awesome.&lt;/span&gt;&lt;/p&gt;&lt;p&gt;
&lt;/p&gt;&lt;p&gt;&lt;/p&gt;&lt;p&gt;&lt;span x="y"  style=" font-weight: bold; font-size:1.33333em;"&gt;What rocks&lt;/span&gt;&lt;span style="-webkit-user-modify: read-only; "&gt;&lt;span style="-webkit-user-modify: read-only; white-space: pre-wrap; "&gt;&lt;/span&gt;&lt;/span&gt;&lt;span x="y"  style=" font-weight: bold; font-size:1.33333em;"&gt;:&lt;/span&gt;&lt;/p&gt;&lt;ul&gt;&lt;li&gt;&lt;span x="y" style="font-weight: bold; "&gt;Working with mostly guys&lt;/span&gt;. &lt;br&gt;I'm sorry, girls, but I've always gotten along better with guys, ever since I was in elementary school. It's probably because I didn't quite fit into the girl mold (or any mold) back then, and thus girls were hesitant to accept me, while guys didn't really care as long as I was willing to shoot cannons with them. I know a lot of other girls in CS who say the same thing - that they're mostly friends with guys - and actually, those are the girls that I get along with best. So, yes, I should learn how to get along better with girls. But in the meantime, I'll always feel more comfortable working with guys.&lt;/li&gt;&lt;li&gt;&lt;span x="y" style="font-weight: bold; "&gt;"Working" with mostly guys&lt;/span&gt;. &lt;br&gt;I once famously said "I only date guys who program in derivatives of ECMAScript". Well, it's kind of true. I prefer dating guys in tech because I have more stuff to talk about with them, so it's pretty handy that the tech industry is mostly guys. And yes, there is a bit of truth in the phrase often applied to guys in CS: "The goods are odd, but the odds are good"...but I'm pretty sure that the ratio of good guys is still in my favour. It's nice to be in an industry where I constantly encounter so many potential mates, and I don't have to rely on meeting random guys in a bar (which appears to be the dating preference of choice amongst adults, ick).&lt;/li&gt;&lt;li&gt;&lt;span x="y" style="font-weight: bold; "&gt;Being recognizable&lt;/span&gt;. &lt;br&gt; As a girl amidst a sea of guys, I'm pretty easy to find. At a conference, all someone has to say is "find the girl with the red|blue|pink hair", and they can make a positive match pretty quickly. This easy recognition means that I can connect with more of the developers that want to talk to me. It can sometimes cause problems when people remember me better than I remember them (there's a limit to the number of white guys I can store in my head at once), but they are usually quite forgiving.&lt;/li&gt;&lt;li&gt;&lt;span x="y" style="font-weight: bold; "&gt;Getting more opportunities&lt;/span&gt;. &lt;br&gt; Okay, I'm still not 100% sure how I feel about affirmative action.. except that I bet it's worked for me, and that I've probably benefited greatly from it. I remember asking my high school English teacher to review my college essay (which revolved around toilet flushing), and he glanced it over and said, "Well, you're applying as a girl in CS with a high SAT score, right? This shouldn't matter much." &lt;br&gt; When an employer or university is comparing 2 equally skilled people, it makes sense that they select the one that increases the diversity of their staff/student body/conference/etc. Diversity is a good thing for teams, and it just so happens that the easiest way to measure diversity is by looking at aspects like race or gender. Theoretically, affirmative action could also applied be to hobbies and interests, and I could be selected due to my intense passion for 80s music (which actually does come up surprisingly often in my talks and demos). Until that happens, I will take advantage of the opportunities that I get by being a girl, and trust that I am not being given opportunities that I don't deserve.&lt;/li&gt;&lt;/ul&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;
&lt;/div&gt;&lt;p&gt;&lt;/p&gt;&lt;h3  style=" ;font-family:arial, sans-serif;"&gt;&lt;span class="Apple-style-span"  style="font-size:medium;"&gt;What sucks:&lt;/span&gt;&lt;/h3&gt;&lt;ul&gt;&lt;li&gt;&lt;span x="y" style="font-weight: bold; "&gt;Not enough chick flicks&lt;/span&gt;. &lt;br&gt;I'm pretty sure I would have more excuses to watch romantic comedies if I hung out with more girls. But oh well, I'll just schedule a few more 12 hour trans-pacific flights.&lt;/li&gt;&lt;li&gt;&lt;span x="y" style="font-weight: bold; "&gt;Too little dancing.&lt;/span&gt; &lt;br&gt;Guys don't generally go out dancing as their night activity of choice, at least not guys in western cultures. They tend to prefer a night of tipsy talk at a pub. I sometimes wish that I was a rock star or celebrity, and got to spend every night clubbing in exotic places... but until I acquire any sort of stage talent whatsoever, I think I'll settle with tricking guys into going to pubs with good music.&lt;/li&gt;&lt;/ul&gt;&lt;div&gt;
&lt;/div&gt;&lt;p&gt;&lt;/p&gt;&lt;h3  style=" ;font-family:arial, sans-serif;"&gt;&lt;span class="Apple-style-span"  style="font-size:medium;"&gt;What really sucks:&lt;/span&gt;&lt;/h3&gt;&lt;ul&gt;&lt;li&gt;&lt;span x="y" style="font-weight: bold; "&gt;Being afraid to admit all that&lt;/span&gt;. &lt;br&gt;As a girl in CS, I am meant to have a very particular opinion about girls in CS. I feel that I risk being viewed as a traitor if I express other opinions. So, I generally try not to express any at all, and just go on my merry way. But, I now worry that other girls may feel the same fear, and that it is cowardly of me to keep my opinions to myself. Now, it's up to you to express your opinions, whatever they may be.&lt;/li&gt;&lt;/ul&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8501278254137514883-1729915110768351059?l=blog.pamelafox.org' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.pamelafox.org/feeds/1729915110768351059/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=8501278254137514883&amp;postID=1729915110768351059' title='12 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8501278254137514883/posts/default/1729915110768351059'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8501278254137514883/posts/default/1729915110768351059'/><link rel='alternate' type='text/html' href='http://blog.pamelafox.org/2009/10/being-girl-in-cs-doesnt-suck.html' title='Being a Girl in CS Doesn&apos;t Suck'/><author><name>Pamela Fox</name><uri>http://www.blogger.com/profile/15947664772001597300</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>12</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8501278254137514883.post-1726402806758815914</id><published>2009-10-21T17:17:00.000-07:00</published><updated>2009-10-21T19:23:52.588-07:00</updated><title type='text'>Joomla &amp; Google Wave: The Possibilities</title><content type='html'>&lt;p&gt;Last weekend, I presented a talk on &lt;a href="http://prezi.com/i6jilpzy79rh/"&gt;Google Wave&lt;/a&gt; to &lt;a href="http://sydney.joomladay.org.au/"&gt;Joomla Day Sydney&lt;/a&gt;, and then proposed various ways that Joomla and and the Wave APIs could be used together. I've summarized them below, and would love to hear ideas from Joomla developers on other types of integration.
&lt;/p&gt;
&lt;hr width="50%"&gt;
&lt;h3&gt;Using Wave to Produce Joomla Content&lt;/h3&gt;

&lt;h4&gt;Embedded Waves&lt;/h4&gt;
&lt;p&gt;
You might decide that instead of static HTML for a particular article, you want to embed a Wave and enable real-time collaboration. An enterprising developer has already written a &lt;a href="http://wavedemo.in-entwicklung.net"&gt;Joomla plugin&lt;/a&gt; that uses the Embed API and makes it easy to embed Waves in articles, so you can use that.
&lt;/p&gt;
&lt;p&gt;
For example, I can create &lt;a href="https://wave.google.com/a/wavesandbox.com/#minimized:nav,minimized:contact,minimized:search,restored:wave:wavesandbox.com!w%252BFspA8QgYA"&gt;a Wave&lt;/a&gt; with the content of the Joomla Day home page:
&lt;p&gt;
&lt;A href="https://wave.google.com/a/wavesandbox.com/#minimized:nav,minimized:contact,minimized:search,restored:wave:wavesandbox.com!w%252BFspA8QgYA"&gt;&lt;img src="http://2.bp.blogspot.com/_T1lquhCmKo8/St-lb1VNMAI/AAAAAAAACnc/6PF3x7-pd9c/s400/joomladay1" style="border:1px solid black"&gt;&lt;/a&gt;
&lt;/p&gt;
&lt;p&gt;
Then, in my Joomla instance, I can install the plugin and insert this code in an article:
&lt;/p&gt;
&lt;pre&gt;
{googlewave srv=http://wave.google.com/a/wavesandbox.com/|id=wavesandbox.com!w+FspA8QgYA|width=100%|height=600px|fsize=12px|bg=#FFF|ffamily=Georgia}
&lt;/pre&gt;
&lt;p&gt;
And then it would produce a page like &lt;a href="http://imagine-it.org/joomladay/index.php?option=com_content&amp;view=article&amp;id=19&amp;Itemid=27"&gt;this&lt;/a&gt;:
&lt;/p&gt;
&lt;p&gt;
&lt;a href="http://imagine-it.org/joomladay/index.php?option=com_content&amp;view=article&amp;id=19&amp;Itemid=27"&gt;&lt;img src="http://4.bp.blogspot.com/_T1lquhCmKo8/St-zFg1ENrI/AAAAAAAACns/Akjxzbyvf8U/s400/joomladay3" style="border:1px solid black"/&gt;&lt;/a&gt;
&lt;/p&gt;
&lt;p&gt;
Note: Only people with accounts for the embedded server will be able to view the Wave, and only if they are a participant or the Wave is public to that whole server. In the future, we hope to allow for another type of public waves that can be viewed anonymously.
&lt;/p&gt;
&lt;p&gt;
You may be creeped out by the idea of anyone being able to edit the Wave, and maybe you don't really want a full conversation on the page. That brings us to the second option.
&lt;/p&gt;

&lt;h4&gt;Exported Waves&lt;/h4&gt;
&lt;p&gt;
If you want to use the collaborative nature of Wave to create your articles, but then still use static HTML for your articles, then you could write a robot to export from Wave into Joomla or a Joomla-compatible format.
&lt;/p&gt;
&lt;p&gt;
For example, the &lt;A href="http://google-wave-resources.googlecode.com/svn/trunk/samples/extensions/robots/python/exporty/"&gt;Exporty bot&lt;/a&gt; listens for changes in a blip, extracts the contents of the root blip, and stores it in its App Engine datastore. Then, it renders that as HTML at a URL, and when someone requests that HTML, it displays the blip if its Wave was public, and otherwise it asks the user to sign in and checks if they are a participant of the Wave.
&lt;/p&gt;
&lt;p&gt;
So, I can create &lt;a href="https://wave.google.com/a/wavesandbox.com/#minimized:nav,minimized:contact,minimized:search,restored:wave:wavesandbox.com!w%252B7w-1O4JSA"&gt;a Wave&lt;/a&gt; with the content of the article, add the co-authors, and then add Exporty-bot:
&lt;/p&gt;
&lt;p&gt;
&lt;a href="https://wave.google.com/a/wavesandbox.com/#minimized:nav,minimized:contact,minimized:search,restored:wave:wavesandbox.com!w%252B7w-1O4JSA"&gt;
&lt;img src="http://4.bp.blogspot.com/_T1lquhCmKo8/St-93AQGFKI/AAAAAAAACn0/hHYtV0bQ824/s400/joomladay4" style="border:1px solid black"/&gt;
&lt;/a&gt;
&lt;/p&gt;
&lt;p&gt;
Then I can create an iframe pointing at the HTML in my article content:
&lt;/p&gt;
&lt;pre&gt;
&amp;lt;iframe src="http://exporty-bot.appspot.com/export?waveId=wavesandbox.com!w%252B7w-1O4JSA" width="100%" height="700" frameborder="0"&amp;gt;&amp;lt;/iframe&amp;gt;
&lt;/pre&gt;
&lt;p&gt;
And then it would produce a page &lt;a href="http://imagine-it.org/joomladay/index.php?option=com_content&amp;view=article&amp;id=18&amp;Itemid=27"&gt;like this&lt;/a&gt;:
&lt;/p&gt;
&lt;p&gt;
&lt;a href="http://imagine-it.org/joomladay/index.php?option=com_content&amp;view=article&amp;id=18&amp;Itemid=27"&gt;
&lt;img src="http://3.bp.blogspot.com/_T1lquhCmKo8/St--8vi7k0I/AAAAAAAACn8/lAhQ8CgkZ-U/s400/joomladay5" style="border:1px solid black"/&gt;
&lt;/a&gt;
&lt;/p&gt;
&lt;p&gt;
A more elegant solution would involve eliminating the iframe and baking the content into the page. But I will leave it to someone more experienced with Joomla to figure out best way to do that.
&lt;/p&gt;
&lt;hr width="50%"&gt;
&lt;h3&gt;Using Wave to Extract Joomla Content&lt;/h3&gt;

&lt;p&gt;
Using robots and gadgets, you can find ways to bring in content from your Joomla site.
&lt;/p&gt;
&lt;p&gt;
For example, a user of your site could use Wave to subscribe to changes in the site. The &lt;a href="http://wave-samples-gallery.appspot.com/about_app?app_id=30012"&gt;RSSy bot&lt;/a&gt; lets you specify an RSS feed and updates the Wave with blips for each new item in the feed.
&lt;/p&gt;
&lt;p&gt;
So, you can create a new wave, add RSSybot, and specify &lt;a href="http://sydney.joomladay.org.au/index.php?format=feed&amp;type=rss"&gt;the RSS&lt;/a&gt; from a Joomla site:
&lt;/p&gt;
&lt;p&gt;
The &lt;a href="https://wave.google.com/a/wavesandbox.com/#minimized:contact,minimized:search,restored:wave:wavesandbox.com!w%252BFspA8QgYH"&gt;resulting Wave&lt;/a&gt; looks like this:
&lt;/p&gt;
&lt;p&gt;
&lt;a href="https://wave.google.com/a/wavesandbox.com/#minimized:contact,minimized:search,restored:wave:wavesandbox.com!w%252BFspA8QgYH"&gt;
&lt;img src="http://3.bp.blogspot.com/_T1lquhCmKo8/St-_o0hWylI/AAAAAAAACoE/zlpmvoK9Vcg/s400/joomladay6"  style="border:1px solid black"/&gt;
&lt;/a&gt;
&lt;/p&gt;
&lt;p&gt;
This bot doesn't do the best job at handling the HTML in the feed, but you could improve that to insert iframes with the HTML, or convert the HTML into a Wave-compatible block of text with annotations for the styles. 
&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8501278254137514883-1726402806758815914?l=blog.pamelafox.org' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.pamelafox.org/feeds/1726402806758815914/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=8501278254137514883&amp;postID=1726402806758815914' title='4 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8501278254137514883/posts/default/1726402806758815914'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8501278254137514883/posts/default/1726402806758815914'/><link rel='alternate' type='text/html' href='http://blog.pamelafox.org/2009/10/joomla-google-wave-possibilities.html' title='Joomla &amp; Google Wave: The Possibilities'/><author><name>Pamela Fox</name><uri>http://www.blogger.com/profile/15947664772001597300</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://2.bp.blogspot.com/_T1lquhCmKo8/St-lb1VNMAI/AAAAAAAACnc/6PF3x7-pd9c/s72-c/joomladay1' height='72' width='72'/><thr:total>4</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8501278254137514883.post-2735051862906668529</id><published>2009-10-21T08:23:00.001-07:00</published><updated>2009-10-22T14:15:49.106-07:00</updated><title type='text'>Should I Defend My Cred? (...Yes)</title><content type='html'>&lt;p&gt;Tonight, I gave another Ignite talk on &lt;a href="http://www.scribd.com/doc/21396787/Collaborative-Mapping-with-Google-Wave"&gt;"Google Wave &amp; Collaborative Mapping"&lt;/a&gt;/. The talk went well, and it was a great opportunity to hear what other people are thinking of doing with Wave. But, something interesting happened after...
&lt;/p&gt;
&lt;p&gt;
I was asked by a speaker to basically defend my cred- as he looked at my appearance (a short green skirt &amp; t-shirt), saw that I gave a presentation that glossed over the technical details, and assumed that I wasn't that technical. When I explained to him that I actually do write code, he was fairly taken aback. He then recommended that I start off each presentation by clarifying my level of knowledge, and getting "respect" from the audience. His basic theory is that girls are not respected as technical peers until they sufficiently prove themselves, and apparently, particularly not if the girl is decent looking. Now, I want to explore that theory further (outside of the noisiness and distractions of the crowded pub).
&lt;/p&gt;
&lt;p&gt;
When I was in high school, I participated in MUN (Model United Nations), where high schoolers would be delegates for a particular country and argue position papers. At the conferences, I remember that I myself mentally discounted the ability of the female delegates when they went up to speak. I was willing to believe in them, but only after they really showed their stuff. I didn't have this same feeling with the guys, and I came to the conclusion that there are some areas where one gender garners  more of an immediate respect than others. I decided then that I would have to come off as incredibly confident (but not bitchily so) in order to win the respect of the MUN people, as I assumed that they would have that same accidental bias. The bias made sense to me in the area of speaking - men naturally have deep, confident voices, and so you just want to believe in that voice. I don't know how to describe women's voices, but it's certainly not like that.
&lt;/p&gt;
&lt;p&gt;
I think the respect bias may extend beyond debating in the tech world, however. When I look at the Twitter account for a self-professed "girl geek", I grow immediately suspicious of their geeky claims. When I see a girl go up to present on the stage, I usually assume they will talk about something less technical. Maybe this is because my suspicions are usually confirmed -- because we live in a world where we try to extend a geek label as far wide as possible, to try and sneakily get more girls "in CS." Maybe it's because girls naturally hate girls (a well documented phenomenom in women's magazines), and this is an extension of the phenomenon. 
&lt;/p&gt;
&lt;p&gt;
So, I'm biased, he's biased, and potentially others are as well. I don't know that we'll be able to eliminate our subconcious tendencies, but we can help people squash their own. 
&lt;/p&gt;
&lt;p&gt;
When you give a talk, always start off with an introduction slide that describes your background and experience. If you're an expert on the topic, admit it (humbly). If you're just learning and wanted to share your learnings, admit it.
&lt;/p&gt;
&lt;p&gt;
I think part of the reason that we try to rely on other (possibly incorrect) clues to help us form opinions is that people don't give us enough information about their credentials. And I don't think that we mind if someone is or isn't technical - we just want to know, one way or the other, and not feel like we're being misled. We respect people for who they are, but we don't respect people if we suspect that they're trying to be something they're not.
&lt;/p&gt;
&lt;p&gt;
Thoughts welcome, of course. :)
&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8501278254137514883-2735051862906668529?l=blog.pamelafox.org' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.pamelafox.org/feeds/2735051862906668529/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=8501278254137514883&amp;postID=2735051862906668529' title='24 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8501278254137514883/posts/default/2735051862906668529'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8501278254137514883/posts/default/2735051862906668529'/><link rel='alternate' type='text/html' href='http://blog.pamelafox.org/2009/10/should-i-defend-my-cred-yes.html' title='Should I Defend My Cred? (...Yes)'/><author><name>Pamela Fox</name><uri>http://www.blogger.com/profile/15947664772001597300</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>24</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8501278254137514883.post-1743843171133963060</id><published>2009-10-13T15:59:00.000-07:00</published><updated>2009-10-13T16:04:22.014-07:00</updated><title type='text'>Why I Sent You to a Group</title><content type='html'>&lt;p&gt;One aspect of my role as an API support engineer is making sure that developer's questions are answered. 
&lt;/p&gt;
&lt;p&gt;
So, when a developer personally emails me a question, you would think that I would rush to answer it.
&lt;/p&gt;
&lt;p&gt;
No. In fact, I usually ask them to post their question in the relevant group, and even if I know the answer to the question, I do not reveal it in my response.
&lt;/p&gt;
&lt;p&gt;
This is because another aspect of my role is making sure that developer's questions are answered in a scalable manner.
&lt;/p&gt;
&lt;p&gt;
If a developers emails me a question and I then answer it, that question and answer exist only inside our inboxes. They are absolutely undiscoverable by anyone else in the world, and basically useless to 99.9999999999999% of developers. However, if a developer posts a question in a forum and then receives an answer, that thread exists in the public group, it exists in the cached Google pages, it exists in the mail group archives - and most importantly, it exists in Google search results.
That means that when another developer has the same question and search for it, they will find an answer - without even having to post their question. So, potentially 100% of developers can benefit from the question and answer. Now, *that* is scalable.
&lt;/p&gt;
&lt;p&gt;
Now, a developer might think "But, I'm the only one with this question." This is nearly almost not the case, and it is not something that a developer can predict.
Better safe than sorry, and share the question with the world. 
&lt;/p&gt;
&lt;p&gt;
Another aspect of my role is making sure that questions are answered in a timely manner.
&lt;/p&gt;
&lt;p&gt;
If a developer emails me a question, and I happen to be quite busy then - with conferences, travel, launches, etc. - then I may not be able to respond  for a few weeks. However, if a developer posts that question in the group, all of the group members may see it, and the chances are that atleast one of them know the answer and happen to have the time to respond.  If they post in the group and don't get a response after a few days, it is fine protocol to ping the thread nicely, or hey, I don't even mind when a developer pings me personally and asks me to respond to the group thread.
&lt;/p&gt;
&lt;p&gt;
So, oftentimes, when I ask a developer to post in a group, it's because I want them to get an answer faster than I can provide, and I happen to know that the Group is the best way to guarantee that.
&lt;/p&gt;
&lt;p&gt;Basically, the only times that I *happily* respond to a one-on-one email (or wave) is when the matter concerns personal account information and must be worked out on a case-by-case basis - for example, requests for higher geocoding limits, or the recent problems with some sandbox users not getting wave preview invites.
&lt;/p&gt;
&lt;p&gt;
If you are a developer that I have sent to a group, please understand it is for your own good and the good of the world. Thanks for understanding!
&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8501278254137514883-1743843171133963060?l=blog.pamelafox.org' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.pamelafox.org/feeds/1743843171133963060/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=8501278254137514883&amp;postID=1743843171133963060' title='5 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8501278254137514883/posts/default/1743843171133963060'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8501278254137514883/posts/default/1743843171133963060'/><link rel='alternate' type='text/html' href='http://blog.pamelafox.org/2009/10/why-i-sent-you-to-group.html' title='Why I Sent You to a Group'/><author><name>Pamela Fox</name><uri>http://www.blogger.com/profile/15947664772001597300</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>5</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8501278254137514883.post-6788634989884002725</id><published>2009-10-08T05:54:00.000-07:00</published><updated>2009-11-15T02:22:56.118-08:00</updated><title type='text'>A World of Words.. And Me</title><content type='html'>&lt;p&gt;
Tonight, I gave a talk titled "A world of words" at Ignite Sydney, 
and I want to give a bit more information about why I gave that talk.
&lt;/p&gt;
&lt;p&gt;
As I said at the beginning of the talk, I have always had a thing for words.
When I was a wee lass, I had a favorite song called "Great Big Words"
and loved to finish crossword puzzles. In high school, I realized that 
I needed to study words in order to do well on the SATs, and I could get away
with more word geekery that way. I downloaded multiple flashcard programs on my PC, and I forced friends in my carpool to bring in words to discuss during each morning ride. Needless to say, I aced my test... and I was also no longer part of that carpool. Then, in university, I joined an honor society and suggested that we educate our peers by plastering the kiosks with "Word of the Week" posters. On each poster, I took great pleasure in coming up with a ridiculous sentence that used the word, and an overlay thorough description of its etymology. (See: &lt;a href="http://www.flickr.com/photos/pamelafox/3935869315/"&gt;poster for "diaphanous"&lt;/a&gt;)
&lt;/p&gt;

&lt;p&gt;
So, I realized I had an obsession, and I needed to make it legit.  I enrolled in a linguistics minor, and I was hooked. Everything about language was fascinating - why we make the sounds we do, why our sentences can become ambiguous, even stuff like why we can say "abso-fucking-lotely" and not "ab-fucking-solutely" (seriously, that was covered in &lt;b&gt;two&lt;/b&gt; classes). Inspired by my newfound knowledge, I applied for and was accepted into the John Hopkins Computational Linguistics summer workshop. There, I spent the summer working on a tool for visualizating the parse trees for sentences translated into multiple languages (See: &lt;a href="http://imagine-it.org/work_clsp_ilovemtv_g.jpg"&gt;screenshot&lt;/a&gt;). 
&lt;/p&gt;
&lt;p&gt;
That project got me thinking about the various ways that I could combine my 
computer science skills with my love for linguistics. I eventually concocted a project  that would use both those, &lt;b&gt;and&lt;/b&gt; my other minor, 3d animation, and convinced my advisors it was worthy of credit. It was entitled "A Computational Framework for Simulating Cross-Linguistic Acquisition of Spatial Prepositions", and it was basically an attempt to get a  computer script to learn prepositions (above/under/on) by analyzing a 3d-scene and given sentences. And, hey, it kind of worked. (See: &lt;a href="http://imagine-it.org/ling490/eposter.htm"&gt;e-poster&lt;/a&gt;). I was on a roll! 
&lt;/p&gt;
&lt;p&gt;
So, I was at the point where I was trying to figure out what was next in life. I knew what I loved, but couldn't decide what to do with what I loved. It was suggested that I apply for a Fulbright grant - a grant that would let me do research somewhere in the world - and I thought that was a mighty fine idea. I wrote up my proposal for an app that I had always fantasized about. It was called "A World Wide Web of Comparative Linguistics", and it would let user visualize and search through etymological history on a map-based interface. (See: &lt;a href="http://imagine-it.org/researchproposal.htm"&gt;proposal&lt;/a&gt;). In my opinion, the app would bring immediate world peace. How could you possibly fight with someone after you realized how connected your words were?
&lt;/p&gt;
&lt;p&gt;
Unfortunately, the Fulbright committee didn't see it that way, and I didn't get a grant. I instead went on to get a Masters degree and get hired by Google, and that's where I am today. I've been pretty busy supporting the Maps API for the past 3 years, but lately, I've started craving a bit of linguistics in my life. I started listing to word-of-the-day podcasts on my iPod during my morning commute, and it just gets my brain all tingly.
&lt;/p&gt;
&lt;p&gt;
So, I put together this talk as one way of satisfying that craving (or, more likely, making it much bigger), and also to share this bit of knowledge with others. It's a nice break from my typical web talks, and I think I surprised a few folks.
&lt;/p&gt;
&lt;p&gt;
You can see the talk embedded below or &lt;a href="http://www.slideshare.net/wuzziwug/a-world-of-words"&gt;on slideshare&lt;/a&gt;, complete with captions of what I actually said.
&lt;/p&gt;
&lt;div style="width:425px;text-align:left" id="__ss_2163507"&gt;&lt;a style="font:14px Helvetica,Arial,Sans-serif;display:block;margin:12px 0 3px 0;text-decoration:underline;" href="http://www.slideshare.net/wuzziwug/a-world-of-words" title="A World of Words"&gt;A World of Words&lt;/a&gt;&lt;object style="margin:0px" width="425" height="355"&gt;&lt;param name="movie" value="http://static.slidesharecdn.com/swf/ssplayer2.swf?doc=worldofwords-091008080023-phpapp02&amp;stripped_title=a-world-of-words" /&gt;&lt;param name="allowFullScreen" value="true"/&gt;&lt;param name="allowScriptAccess" value="always"/&gt;&lt;embed src="http://static.slidesharecdn.com/swf/ssplayer2.swf?doc=worldofwords-091008080023-phpapp02&amp;stripped_title=a-world-of-words" type="application/x-shockwave-flash" allowscriptaccess="always" allowfullscreen="true" width="425" height="355"&gt;&lt;/embed&gt;&lt;/object&gt;&lt;div style="font-size:11px;font-family:tahoma,arial;height:26px;padding-top:2px;"&gt;View more &lt;a style="text-decoration:underline;" href="http://www.slideshare.net/"&gt;presentations&lt;/a&gt; from &lt;a style="text-decoration:underline;" href="http://www.slideshare.net/wuzziwug"&gt;wuzziwug&lt;/a&gt;.&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;
&lt;p&gt;You can also watch the recorded talk below:&lt;/p&gt;
&lt;object width="560" height="340"&gt;&lt;param name="movie" value="http://www.youtube.com/v/CT7EiWYGkdM&amp;hl=en_US&amp;fs=1&amp;"&gt;&lt;/param&gt;&lt;param name="allowFullScreen" value="true"&gt;&lt;/param&gt;&lt;param name="allowscriptaccess" value="always"&gt;&lt;/param&gt;&lt;embed src="http://www.youtube.com/v/CT7EiWYGkdM&amp;hl=en_US&amp;fs=1&amp;" type="application/x-shockwave-flash" allowscriptaccess="always" allowfullscreen="true" width="560" height="340"&gt;&lt;/embed&gt;&lt;/object&gt;

For more resources on the topic, you can check out the &lt;a href="http://delicious.com/fkedupmonkey/worldwords"&gt;sites that I bookmarked&lt;/a&gt; while researching the talk, subscribe to the &lt;a href="http://podictionary.com/"&gt;podictionary podcast&lt;/a&gt;, or start looking up words in the &lt;a href="http://www.etymonline.com/"&gt;online etymology dictionary&lt;/a&gt;.
&lt;/p&gt;
&lt;p&gt;
And, of course, stay tuned to the blog to find out if I do ever create that etymology visualization app.. It would be a damn nifty thing indeed, even if it didn't bring world peace. :)
&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8501278254137514883-6788634989884002725?l=blog.pamelafox.org' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.pamelafox.org/feeds/6788634989884002725/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=8501278254137514883&amp;postID=6788634989884002725' title='10 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8501278254137514883/posts/default/6788634989884002725'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8501278254137514883/posts/default/6788634989884002725'/><link rel='alternate' type='text/html' href='http://blog.pamelafox.org/2009/10/world-of-words-and-me.html' title='A World of Words.. And Me'/><author><name>Pamela Fox</name><uri>http://www.blogger.com/profile/15947664772001597300</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>10</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8501278254137514883.post-6075095779062368513</id><published>2009-09-10T17:34:00.000-07:00</published><updated>2009-09-10T17:59:26.267-07:00</updated><title type='text'>How Google Wave Could Improve Education: Group Work</title><content type='html'>&lt;p&gt;Last night, at the Google Wave Sydney User Group, we brainstormed a lot of different ways that Google Wave could be used in a vast spectrum of fields. A recurrent theme was education, and we touched upon various ideas, and basically just agreed that Wave (and collaborative technology, generally) can have huge implications for education. One of those ideas we discussed was group projects, and I wanted to discuss that area in more detail here.&lt;/p&gt;

&lt;p&gt;
As a teacher, you often want to encourage group projects, since they can help students learn cooperation and teamwork, and since they can often have a synergistic effect and produce amazing results. But, there's always that same concern with group projects - someone will do all the work, someone will do none, and it's impossible to know who deserves the good grade. Well, Wave could potentially solve this, both in terms of knowing who to give credit to, and encouraging a better balance of work across group members.
&lt;/p&gt;

&lt;p&gt;Here's an example proposal based on my own experience:&lt;/p&gt;
&lt;p&gt;
You're a teacher running a game projects class, and you've divided the class into project teams for the semester. The first aspect of creating a game is writing a design doc for the game (describing gameplay, objective, characters, etc), and you make that the first assignment for each team. You create a Wave for each team that has the design doc template in it (headers), and you give them a week to work on it. You recommend that they use reply blips and inline blips to divy up the work, and tell them that you will be monitoring the project and will do a review of the first draft in a week, and grading of the final a week after that.  
&lt;/p&gt;

&lt;p&gt;
&lt;img align="right" src="http://2.bp.blogspot.com/_T1lquhCmKo8/SqmgXhqgpdI/AAAAAAAACfU/tivISJ6-tws/s400/screenshot_designdoc.png"/&gt;
When you review, you reply in the Wave and comment on what parts need work or clarification, and which parts look good. When it comes time for grading, you use the
playback functionality to see how everyone contributed. You see who took the lead and made decisions, who wrote up large sections, who revised sections for clarity, and who just sit back and watched. Now, hopefully, since every team member knows that you can see all the edits and attribute them to each of them, they will actually feel more motivation to contribute, and you won't have many students that just do nothing. But if you do, well, you can penalize them accordingly, and perhaps next time, they will learn that their actions (or lackthereof) are being watched. 
&lt;/p&gt;
&lt;p&gt;
You could even automate some aspects of this with robots. There could be a robot that counts the word count of each team member, and outputs that in a stats gadget at the end. This could feel a bit too strict for the students, but it can also serve as a nice "hey, you're not quite doing as much" reminder. That robot could also just monitor progress as a whole, making sure the team stays on progress. The gadget could list stats like "5 sections completed, 5 days left until final due". Then, those per-team-member stats just become another indicator of progress on the whole, and don't feel as accusatory. 
&lt;/p&gt;
&lt;p&gt;
One issue I see with this proposal is the tracking of "peer waving." Some students may sincerely find it more productive to sit at one computer and write up sections together - perhaps one giving the ideas, the other putting them into words. These words would only be attributed to one student, and the idea giver could be unfairly penalized. Possible solutions for this would be to annotate the text [Peer waved w/username@bla.com] or to recommend that students alternate between accounts 
when doing this.
&lt;/p&gt;
&lt;p&gt;
Another issue, of course, is that not all group projects are writing up a blob of text, and in fact, many of them are not. In computer science, many of them are actually writing code. You can already ask students to use SVN and monitor commits from each team member for less fine-grained monitoring, but you could potentially even have students write their code in a Wave, and use a robot to compile it out, for real-time monitoring. In other fields, many group projects involve the the creation of a physical (non-digital) object. Perhaps you could have students write a design doc for that physical object, or even use a collaborative gadget to sketch it out. 
&lt;/p&gt;
&lt;p&gt;
So, yes, this solution isn't perfect, and for non-text projects, involves a bit more creativity. But, I still think it's pretty damn good. If you're a teacher, try it out and report back!
&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8501278254137514883-6075095779062368513?l=blog.pamelafox.org' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.pamelafox.org/feeds/6075095779062368513/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=8501278254137514883&amp;postID=6075095779062368513' title='6 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8501278254137514883/posts/default/6075095779062368513'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8501278254137514883/posts/default/6075095779062368513'/><link rel='alternate' type='text/html' href='http://blog.pamelafox.org/2009/09/how-google-wave-could-improve-education.html' title='How Google Wave Could Improve Education: Group Work'/><author><name>Pamela Fox</name><uri>http://www.blogger.com/profile/15947664772001597300</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://2.bp.blogspot.com/_T1lquhCmKo8/SqmgXhqgpdI/AAAAAAAACfU/tivISJ6-tws/s72-c/screenshot_designdoc.png' height='72' width='72'/><thr:total>6</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8501278254137514883.post-31355163561432832</id><published>2009-09-08T06:08:00.000-07:00</published><updated>2009-09-08T06:23:42.881-07:00</updated><title type='text'>The Quest for Karaoke-able Slidesets</title><content type='html'>&lt;p&gt;
I'm a massive fan of karaoke, and I've often expressed my opinion that some songs are far more "karaoke-able" than others, and that someone/me/an entepreneur should create an app capitalizing on that. The app could let you rate the karaoke-ness of songs, upload video evidence, create karaoke playlists, and find lyrics for practicing. It'd be an awesome app to improve the karaoke experience, but somehow, people are surviving and managing to enjoy singing drunkenly without it.
&lt;/p&gt;
&lt;p&gt;
Well, perhaps traditional karaoke doesn't &lt;b&gt;need&lt;/b&gt; an app, but &lt;a href="http://en.wikipedia.org/wiki/Powerpoint-Karaoke"&gt;"Powerpoint Karaoke"&lt;/a&gt; definitely does. For the unfamiliar, Powerpoint Karaoke is yet another new style of presentation, and it basically involves having the speaker speak to a set of slides that he's never seen before, and that were originally delivered by someone else. It serves partially to make fun of the sometimes incomprehensible nature of slides, partially to just be damn funny as the surprised speaker deals with the surprise slides, and partially to improve the speaker's presentation skills. If you can present an arbitrary slideset and woo the audience, then you can present nearly anything. 
&lt;/p&gt;
&lt;p&gt;For our most recent set of internal lightning talks, I gave speakers the option of Powerpoint Karaoke instead of their own slideset, and one brave speaker (&lt;a href="http://twitter.com/jezfletcher"&gt;Jez&lt;/a&gt;) took on the challenge. And I, being the dumb-ass who suggested a format I have never done nor seen, was tasked with picking the slideset for him to present. Yes, I could have gone the route of randomly finding a slideset on the web as soon as Jez got on the stage, but considering that this was the first and only Powerpoint Karaoke that the office would witness that day, I wanted to make sure it went well. These were the approximate requirements I had in my head:
&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;The slideset should fit well into our lightning talk 5 minute format, with about 15-30 slides. Ideally, I could have the slides auto-advance, to challenge the speaker's reflexes further.&lt;/li&gt;
&lt;li&gt;The slideset should have a title and picture(s) on each slide, but not much else. If there was too much text, the speaker could just read that off and know the original intention of the slide. If there wasn't a title on any slide, then the speaker would have too much freedom in what he said.&lt;/li&gt;
&lt;li&gt;The slideset shouldn't offend anyone in terms of politics/religions/beliefs - I didn't want to pick a slideset with the clear intention to make fun of some group. It might offend, and that's too easy, anyway.
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;So, using &lt;a href="http://www.slideshare.net/"&gt;Slideshare&lt;/a&gt;'s search and browse features, my search began. I looked at the top slides in various categories for all time, I did searches for random topics, I looked for slides from speakers that I knew did the kind of slides I was looking for. After an hour of searching, I had nothing. Most slidesets were the wrong length, the wrong amount of textual content, or just plain spam (slidesets with 1 image advertising a product).  I then asked the office for suggestions of topics*, and used those random suggestions to seed my searches. After another half hour, I found 2 possibilities: &lt;a href="http://www.slideshare.net/loni12/how-to-defend-against-zombie-invasions"&gt;"How to Defend Against Zombies"&lt;/a&gt; and &lt;a href="http://www.slideshare.net/sawickipedia/how-i-learned-to-like-ballet-being-married-to-a-professional-ballerina-ignite-seattle-7"&gt;"How I learned to love ballet"&lt;/a&gt;. I picked the second one, as it had exactly 20 slides (Ignite format!), referenced the speaker's wife (Jez's wife works in the office too), and I thought it would be more humorous if Jez could turn ballet funny than if he could turn zombie invasions funny (since, well, they already are).
&lt;/p&gt;
&lt;p&gt;
How did it go? Jez took that slideset and freaking ran with it - he did more with it than I could have imagined. His best line was when he got to the slide about "Barre" (a position) and explained that was the Japanese pronunciation for "Ballet".
&lt;/p&gt;
&lt;p&gt;
But, I've learned now that it is much harder to find karaoke-able slidesets than karaoke-able songs, and it makes sense when you realize that the majority of songs are there are similar length &amp; lyrics density, whereas the slidesets in the world are a highly diverse species. So, I would like an app for finding suitable slidesets, or even better, I would like Slideshare to add the following features to their search: restrict by # of slides (a range?), restrict by text density (avg words per slide?). Then, everyone in the world can get on the Powerpoint Karaoke bandwagon, and it can be the next great (geek) thing.
&lt;/p&gt;
&lt;hr&gt;
&lt;p&gt;*And for your amusement pleasure, here are the list of topics that my colleagues proposed. I asked for these when I was contemplating actually creating the slideset myself with random images, but realized that isn't really the point of Karaoke, and used the ideas as keywords for slideshare searches. That could become an entirely new style of presenting though, especially if someone creates an app that can generate slidesets from just the titles - complete with images, graphs, and venn diagrams, of course. :)
&lt;ul&gt;
&lt;li&gt;"Lightning bugs"
&lt;li&gt;"Japanese pop culture from the 1980's"
&lt;li&gt;"Sesame Street and Alcoholism"
&lt;li&gt;"100 Things to do with Dwarves and Leather"
&lt;li&gt;"How to prepare for a zombie invasion"
&lt;li&gt;"Analytic and algebraic topology of locally Euclidean parametrization of infinitely differentiable Riemannian manifolds"
&lt;li&gt;"How Google could make billions through the power of hypnosis"
&lt;li&gt;"Early 20th century ballet and swimming pool repair"
&lt;li&gt;"Properly Disambiguated Java Generics"
&lt;li&gt;"How to bluff and give an insightful talk when you have to make it up on the spot with no prior warning"
&lt;li&gt;"Latin American Hedge Funds and You"
&lt;li&gt;"The Social and Economic History of the Grapefruit"
&lt;li&gt;"Care and Feeding of the Dugong"
&lt;li&gt;"Unicorns"
&lt;li&gt;"England Won the War of Independence - a counterfactual world history"
&lt;li&gt;"Keelhauling, Walking the plank, and other piratical forms of corporal punishment"
&lt;li&gt;"Why Robot Ninja Monkey Zombies are AWESOME"
&lt;li&gt;"A complete etymology of My Little Pony"
&lt;li&gt;"Zonkies: discuss"
&lt;li&gt;"The renovations that Start City *should* be making"
&lt;li&gt;"A 5-minute tutorial in interpretive dance"
&lt;/ul&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8501278254137514883-31355163561432832?l=blog.pamelafox.org' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.pamelafox.org/feeds/31355163561432832/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=8501278254137514883&amp;postID=31355163561432832' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8501278254137514883/posts/default/31355163561432832'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8501278254137514883/posts/default/31355163561432832'/><link rel='alternate' type='text/html' href='http://blog.pamelafox.org/2009/09/quest-for-karaoke-able-slidesets.html' title='The Quest for Karaoke-able Slidesets'/><author><name>Pamela Fox</name><uri>http://www.blogger.com/profile/15947664772001597300</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8501278254137514883.post-4167237924180331099</id><published>2009-06-05T21:07:00.000-07:00</published><updated>2009-06-05T21:22:58.469-07:00</updated><title type='text'>The Poem Store: "Write a Poem About Her Hair"</title><content type='html'>&lt;p&gt;&lt;a href="http://www.flickr.com/photos/88757125@N00/3589764865/"&gt;&lt;img src="http://farm4.static.flickr.com/3304/3589764865_58a6a49d0e_m.jpg?v=0" align="right"&gt;&lt;/a&gt;During the crazy week and a half that I was back in the states (after 8 months of being in Australia), I took a break from launching products and speaking at conferences to attend the Makers Faire with my old uni buddies from Los Angeles. The Faire was awesome - arts and crafts, fire-breathing objects, corn dogs, rockets, bicycle bands, sno cones, massive mouse traps, everything you could ever want in an amusement park for geeks. One of the really random things we encountered was a guy sitting under a tree, with a sign that said "POEM STORE: Your topic, Your price." That seemed like the coolest promise ever, so my friend Diana approached him and commissioned a poem on my behalf - about my hair. After I gave him a 2-minute recent history of my hair, he quickly typed up this on an old-school typewriter...

&lt;br clear="all"/&gt;

&lt;pre&gt;
sky blue
but nights
falling down
the plummets
spectrum doesn't
cover everything
but it does make
it darker than it
was last once weekly
dying now we survived
 our out last dead protein
             goes DEEP
&lt;/pre&gt;

&lt;p&gt;..which I think is awesome, even if I don't get all of it. We chatted with him more, and found out that he had offered the same service outside Google I/O, and that "web people gobble it up." Well, fine, we do. :) His name is &lt;a href="http://www.zachhouston.com"&gt;Zach Houston&lt;/a&gt;, and he's always looking for more places to show up. Shoot him an email if you've got a poem-hungry crowd at your disposal.&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8501278254137514883-4167237924180331099?l=blog.pamelafox.org' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.pamelafox.org/feeds/4167237924180331099/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=8501278254137514883&amp;postID=4167237924180331099' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8501278254137514883/posts/default/4167237924180331099'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8501278254137514883/posts/default/4167237924180331099'/><link rel='alternate' type='text/html' href='http://blog.pamelafox.org/2009/06/poem-store-write-poem-about-her-hair.html' title='The Poem Store: &quot;Write a Poem About Her Hair&quot;'/><author><name>Pamela Fox</name><uri>http://www.blogger.com/profile/15947664772001597300</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8501278254137514883.post-4649278152919922276</id><published>2009-05-31T22:14:00.000-07:00</published><updated>2009-08-15T20:52:25.383-07:00</updated><title type='text'>Ignite I/O - Growing Up Geek: My Dad, The Computer Scientist</title><content type='html'>&lt;p&gt;
&lt;a href="http://ignite.oreilly.com/"&gt;"Ignite"&lt;/a&gt; is a style of presentation: 5 minutes, 20 slides, 15 seconds each, auto-advance. It's probably the most challenging style of presentation out there (lightning talks are a breeze in comparison), which is why it intrigues me.  I did my first Ignite in Sydney a few months ago, with a talk entitled &lt;a href="http://otherfancystuff.blogspot.com/2009/01/html5-vs-flex-for-rias-ignite-style.html"&gt;"HTML 5 versus Flex for RIAs"&lt;/a&gt;. It went well, as I was able to remember all of my lines, and I managed to squeeze quite a bit of content into those 5 minutes. But I discovered that the best Ignite talks there weren't the informational ones, like mine - they were the narratives ones, the ones that told stories and left the audience feeling moved in some way. 
&lt;/p&gt;
&lt;p&gt;
So when I was asked by Brady Forrest to give an Ignite talk at Google I/O, I decided that I would find a story to tell, and hopefully one with a geeky twist. Thinking of how much my &lt;a href="http://jaoo.com.au/brisbane-2009/"&gt;JAOO Brisbane&lt;/a&gt; audience loved the slide in my &lt;a href="http://docs.google.com/Presentation?id=dggjrx3s_3452b5bndkd"&gt;App Engine talk&lt;/a&gt; about my dad not giving me allowance unless I'd programmed Java that week, I formulated my talk: "Growing up Geek:  My Dad, The Computer Scientist". I didn't have an exact outline for the talk when I proposed it, but I figured I had enough entertaining anecdotes about life with geeky parents (my mum ultimately became a computer scientist as well) that I could fill up 20 slides. 
&lt;/p&gt;
&lt;p&gt;
Creating the slides took ages, since my search for authentic pictures for the slides meant digging through our old archive of &lt;a href="http://www.new-npac.org/users/fox/homephotos/users/gcf/familyphotos/"&gt;5000 digitized family photos&lt;/a&gt; to find evidence of our myriad PCs, and using the &lt;a href="http://www.archive.org/web/web.php"&gt;Wayback Machine&lt;/a&gt; to capture screenshots of my original websites and Perl programs &amp;mdash; and man, nolstalgia is a bitch of a distractor. Soon, a real story began to emerge amongst the slides: the story of me wanting to do many things &amp;mdash; including programming, my dad disapproving of these non-programming activities, and me perservering on with my renaissance approach to scholarism and finally gaining his approval. The point I want to make with the talk is this: you should always encourage your kids to explore &lt;b&gt;everything&lt;/b&gt; that interests them. Yes, this may mean that they don't become a specialist, or that they don't become the particular profession you've set out in your heart for them &amp;mdash; but it means that they're doing what makes them happy, and people always excel the most at what makes them happiest.
&lt;/p&gt;
&lt;p&gt;
The final slides are embedded below, with my pre-scripted lines pasted in the slides (it's impossible not to script them, trust me). I've also entered the slides in a "Tell a Story" contest that Slideshare is running now, since they happen to tell a story; you can vote it up on Slideshare if you like. The video is now up on &lt;a href="http://www.youtube.com/watch?v=hcl3qmawY_0#t=13m50s"&gt;Youtube&lt;/a&gt;. Enjoy!
&lt;/p&gt;

&lt;div style="width:425px;text-align:left" id="__ss_1515285"&gt;&lt;a style="font:14px Helvetica,Arial,Sans-serif;display:block;margin:12px 0 3px 0;text-decoration:underline;" href="http://www.slideshare.net/wuzziwug/growing-up-geek-my-dad-the-computer-scientist?type=powerpoint" title="Growing up Geek: My Dad, the Computer Scientist"&gt;Growing up Geek: My Dad, the Computer Scientist&lt;/a&gt;&lt;object style="margin:0px" width="425" height="355"&gt;&lt;param name="movie" value="http://static.slidesharecdn.com/swf/ssplayer2.swf?doc=growingupgeek-090601001104-phpapp01&amp;stripped_title=growing-up-geek-my-dad-the-computer-scientist" /&gt;&lt;param name="allowFullScreen" value="true"/&gt;&lt;param name="allowScriptAccess" value="always"/&gt;&lt;embed src="http://static.slidesharecdn.com/swf/ssplayer2.swf?doc=growingupgeek-090601001104-phpapp01&amp;stripped_title=growing-up-geek-my-dad-the-computer-scientist" type="application/x-shockwave-flash" allowscriptaccess="always" allowfullscreen="true" width="425" height="355"&gt;&lt;/embed&gt;&lt;/object&gt;&lt;div style="font-size:11px;font-family:tahoma,arial;height:26px;padding-top:2px;"&gt;View more &lt;a style="text-decoration:underline;" href="http://www.slideshare.net/"&gt;OpenOffice presentations&lt;/a&gt; from &lt;a style="text-decoration:underline;" href="http://www.slideshare.net/wuzziwug"&gt;wuzziwug&lt;/a&gt;.&lt;/div&gt;&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8501278254137514883-4649278152919922276?l=blog.pamelafox.org' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.pamelafox.org/feeds/4649278152919922276/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=8501278254137514883&amp;postID=4649278152919922276' title='4 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8501278254137514883/posts/default/4649278152919922276'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8501278254137514883/posts/default/4649278152919922276'/><link rel='alternate' type='text/html' href='http://blog.pamelafox.org/2009/05/ignite-io-growing-up-geek-my-dad.html' title='Ignite I/O - Growing Up Geek: My Dad, The Computer Scientist'/><author><name>Pamela Fox</name><uri>http://www.blogger.com/profile/15947664772001597300</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>4</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8501278254137514883.post-195387163196123091</id><published>2009-05-17T04:34:00.000-07:00</published><updated>2011-02-11T23:20:52.431-08:00</updated><title type='text'>Google Spreadsheets + APIs = Interactive Flash Cards</title><content type='html'>&lt;p&gt;
For about 6 months in the Mountain View Google office, I went to a once-weekly hour-long German language class. Since I didn't have much time to really do homework outside of class, I looked for excuses to use Google APIs to give me different ways of learning German. My first attempt was &lt;a href="http://imagine-it.org/google/spreadsheets/ssImageSearch.html"&gt;a gadget&lt;/a&gt; that combined image search with a spreadsheet-stored German vocabulary wordlist. I liked the idea of using computer-generated hints for the words and wanted to make a more general solution for any topic/language.
&lt;/p&gt;
&lt;p&gt;
So, I made the interactive flash cards gadget. Each flash card has a hint and a form of guessing, with different options for hint generation and guessing strategy. The hints can come from the spreadsheet (e.g. user-entered definitions), Google translate (any supported language pair), Google image search, or Wikipedia (*currently down). The guesses can be entered in a simple text input, selected from multiple choices, or solved in a word jumble. Hopefully, these options are diverse enough for all types of learners. 
&lt;/p&gt;

&lt;p&gt;
Here are steps for using the gadget:
&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
Create a new spreadsheet, put a list of words in the first column, and put hints in the second column if you'd like to use that option. My sample spreadsheet has an animals wordlist:
&lt;br/&gt;
&lt;img src="http://pamelafox-samplecode.googlecode.com/svn/trunk/flashcards/screenshots/screenshot_flashcards_1_sheet.png"&gt;
&lt;/li&gt;

&lt;br/&gt;
&lt;li&gt;
Click on the "Insert" menu and then select "Gadget..." This presents you with various categories of gadgets to choose from (similar to the iGoogle directory). My gadget isn't yet in the gallery, so you'll need to select "Custom" and then type in &lt;a href="http://pamelafox-samplecode.googlecode.com/svn/trunk/flashcards/wordstudy.xml"&gt;the URL to the gadget&lt;/a&gt;: 
&lt;br/&gt;
&lt;img src="http://pamelafox-samplecode.googlecode.com/svn/trunk/flashcards/screenshots/screenshot_flashcards_2_add.png"&gt;
&lt;/li&gt;

&lt;br/&gt;
&lt;li&gt;
The gadget will appear embedded in the current worksheet, and it will prompt you to select a range of data to send to the gadget. Select whatever columns you've created (either just words, or words and hints), and you should see the Range text field update with the range. If it doesn't work, you can manually type it in. Click "Apply".
&lt;br/&gt;
&lt;img src="http://pamelafox-samplecode.googlecode.com/svn/trunk/flashcards/screenshots/screenshot_flashcards_3_range.png"&gt;
&lt;/li&gt;

&lt;br/&gt;
&lt;li&gt;
The flash cards gadget is designed to take up a bit more space, so it's best to move it into its own sheet. Click the menu in the upper left of the gadget and select "Move to own sheet".
&lt;br/&gt;
&lt;img src="http://pamelafox-samplecode.googlecode.com/svn/trunk/flashcards/screenshots/screenshot_flashcards_4_move.png"&gt;
&lt;/li&gt;
&lt;br/&gt;
&lt;li&gt;
You can now play with the different hint/guess options to find your favorite. Several combinations are shown below.
&lt;br/&gt;
&lt;p&gt;Image Search + Word Jumble&lt;/p&gt;
&lt;img src="http://pamelafox-samplecode.googlecode.com/svn/trunk/flashcards/screenshots/screenshot_flashcards_5_imagejumble.png" style="border:1px solid black"&gt;
&lt;br/&gt;
&lt;p&gt;Second Column + Multiple Choice&lt;/p&gt;
&lt;img src="http://pamelafox-samplecode.googlecode.com/svn/trunk/flashcards/screenshots/screenshot_flashcards_6_columnmultiple.png" style="border:1px solid black"&gt;
&lt;br/&gt;
&lt;p&gt;Translation + Type-in&lt;/p&gt;
&lt;img src="http://pamelafox-samplecode.googlecode.com/svn/trunk/flashcards/screenshots/screenshot_flashcards_7_spanishtype.png" style="border:1px solid black"&gt;
&lt;br/&gt;
&lt;/li&gt;

&lt;/ol&gt;

&lt;p&gt;You can play with my &lt;a href="http://spreadsheets.google.com/pub?key=p9pdwsai2hDNRUVOy6NAzbw"&gt;sample flash cards here&lt;/a&gt;. One day, I hope to add the ability to track your progress in learning the flash cards content... but if you're a developer, feel free to beat me to it!
&lt;/p&gt;

&lt;p&gt;If you're a developer and want to tweak this gadget further, you can grab the code from &lt;a href="http://pamelafox-samplecode.googlecode.com/svn/trunk/flashcards/wordstudy.xml"&gt;here&lt;/a&gt;. It's licensed under Apache 2.0, so feel free to tweak it and use it however you'd like. (And if you've got fixes, I'm happy to patch them back in).
&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8501278254137514883-195387163196123091?l=blog.pamelafox.org' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.pamelafox.org/feeds/195387163196123091/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=8501278254137514883&amp;postID=195387163196123091' title='18 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8501278254137514883/posts/default/195387163196123091'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8501278254137514883/posts/default/195387163196123091'/><link rel='alternate' type='text/html' href='http://blog.pamelafox.org/2009/05/google-spreadsheets-apis-interactive.html' title='Google Spreadsheets + APIs = Interactive Flash Cards'/><author><name>Pamela Fox</name><uri>http://www.blogger.com/profile/15947664772001597300</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>18</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8501278254137514883.post-9164864487218534518</id><published>2009-05-17T02:46:00.000-07:00</published><updated>2011-03-17T16:33:55.721-07:00</updated><title type='text'>Creating a Wordsearch using Google Spreadsheets</title><content type='html'>&lt;p&gt;
I'm a fan of alternative learning and testing techniques. Back when I was the teaching assistant for the "History of Video Games" class (yes, that's a real class), I gave the final exam as an illustrated crossword puzzle. It was surprisingly hard to find software for creating that crossword, so I hoped to make a Spreadsheets gadget to make it easier. Unfortunately, crossword-solving algorithms that run entirely in JavaScript are hard to find, and I gave up and went for second best: a wordsearch gadget. (A big thanks to Robert Klein for the &lt;a href="http://jswordsearch.sourceforge.net/"&gt;wordsearch JavaScript library.)&lt;/a&gt;
&lt;/p&gt;

&lt;p&gt;
Here are steps for using the gadget:
&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
Create a new spreadsheet, and put a list of words in the first column. (Or, alternatively, use an existing spreadsheet that has a column of words you're interested in). My sample spreadsheet has a simple animals wordlist:
&lt;br/&gt;
&lt;img src="http://pamelafox-samplecode.googlecode.com/svn/trunk/wordsearch/screenshots/screenshot_wordsearch_1_sheet.png"&gt;
&lt;/li&gt;
&lt;br/&gt;
&lt;li&gt;
Click on the "Insert" menu and then select "Gadget..." This presents you with various categories of gadgets to choose from (similar to the iGoogle directory). My gadget isn't yet in the gallery, so you'll need to select "Custom" and then type in &lt;a href="http://pamelafox-samplecode.googlecode.com/svn/trunk/wordsearch/wordsearch.xml"&gt;the URL to the gadget&lt;/a&gt;: 
&lt;br/&gt;
&lt;img src="http://pamelafox-samplecode.googlecode.com/svn/trunk/wordsearch/screenshots/screenshot_wordsearch_3_add.png"&gt;
&lt;/li&gt;
&lt;br/&gt;
&lt;li&gt;
The gadget will appear embedded in the current worksheet, and it will prompt you to select a range of data to send to the gadget. Select all the cells that contain the desired words, and you should see the Range text field update with the range. If it doesn't work, you can always manually type it in. 
&lt;br/&gt;
&lt;img src="http://pamelafox-samplecode.googlecode.com/svn/trunk/wordsearch/screenshots/screenshot_wordsearch_4_range.png"&gt;
&lt;/li&gt;
&lt;li&gt;
You can now customize the number of rows and columns. The default is 10 by 10, but if you have more words, you likely want a larger wordsearch. Click "Apply", and see the generated output. 
&lt;br/&gt;
&lt;img src="http://pamelafox-samplecode.googlecode.com/svn/trunk/wordsearch/screenshots/screenshot_wordsearch_5_apply.png"&gt;
&lt;/li&gt;
&lt;li&gt;
You have a few options for how you use the wordsearch. You can play with it immediately, inside that gadget, or you can use the option on the gadget menu to move the gadget to its own sheet and use it there. Note that each time you reload the spreadsheet, the wordsearch will be randomly generated with a new layout - so don't rely on it staying the same.
&lt;br/&gt;
&lt;img src="http://pamelafox-samplecode.googlecode.com/svn/trunk/wordsearch/screenshots/screenshot_wordsearch_6_play.png"&gt;
&lt;/li&gt;
&lt;br/&gt;
&lt;li&gt;
You can also publish your spreadsheet so that other people can play the wordsearch. Click "Share &gt; Publish" and you'll see the published URL, which you can share with friends. You can also use options on the gadget menu to embed the gadget in your iGoogle page or inside a normal webpage.
&lt;br/&gt;
&lt;img src="http://pamelafox-samplecode.googlecode.com/svn/trunk/wordsearch/screenshots/screenshot_wordsearch_8_publish.png"&gt;
&lt;/li&gt;
&lt;br/&gt;

&lt;/ol&gt;

&lt;p&gt;You can play with my &lt;a href="http://spreadsheets.google.com/pub?key=rs3ujkCznpqWr28UISGg-_A&amp;gid=1"&gt;sample wordsearch here&lt;/a&gt;. Enjoy, and hopefully one day, I'll have a gadget that makes crosswords too. 
&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8501278254137514883-9164864487218534518?l=blog.pamelafox.org' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.pamelafox.org/feeds/9164864487218534518/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=8501278254137514883&amp;postID=9164864487218534518' title='6 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8501278254137514883/posts/default/9164864487218534518'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8501278254137514883/posts/default/9164864487218534518'/><link rel='alternate' type='text/html' href='http://blog.pamelafox.org/2009/05/creating-wordsearch-using-google.html' title='Creating a Wordsearch using Google Spreadsheets'/><author><name>Pamela Fox</name><uri>http://www.blogger.com/profile/15947664772001597300</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>6</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8501278254137514883.post-3026070077074205772</id><published>2009-05-17T01:33:00.000-07:00</published><updated>2009-05-17T01:42:56.121-07:00</updated><title type='text'>How to Convert a Google Spreadsheet into JSON, XML, and MySQL</title><content type='html'>&lt;p&gt;As some people know, I have a huge fetish for Google Spreadsheets - maybe because I'm always dealing with small datasets, and Spreadsheets is perfect for tinkering with them. Often, I start with my data in Spreadsheets, and later want to move it into a different static format - like a JSON file, MySQL data, or XML file.  I originally did migration by concatenating column values together (e.g. ="&lt;name&gt;" &amp; A1 &amp; "&lt;/name&gt;"), but I decided to make the process easier by creating a generic converter gadget. Using my gadget, you can easily convert any spreadsheet into those formats. &lt;em&gt;
Note: I could get JSON and XML using the Spreadsheets data API, but then I would have to deal with alot of ATOM cruft when I'm only interested in the bare data.&lt;/em&gt;
&lt;/p&gt;

&lt;p&gt;Here are the steps for using the gadget:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Create a new spreadsheet, and put your data in columns. Give each column a name, and choose carefully. Since this name will be used for MySQL attribute names, JSON keys, and XML tag names, the best names are lowercase, whitespace-less, and descriptive. The image below shows a spreadsheet of geocoded pizza locations:
&lt;br/&gt;
&lt;img src="http://pamelafox-samplecode.googlecode.com/svn/trunk/spreadsheetsconverter/screenshots/screenshot_converter_1_sheet.png"&gt;
&lt;/li&gt;
&lt;br/&gt;

&lt;li&gt;Click on the "Insert" menu and then select "Gadget...": 
&lt;br/&gt;
&lt;img src="http://pamelafox-samplecode.googlecode.com/svn/trunk/spreadsheetsconverter/screenshots/screenshot_converter_2_insert.png"&gt;
&lt;/li&gt;
&lt;br/&gt;

&lt;li&gt;This presents you with various categories of gadgets to choose from (similar to the iGoogle directory). My gadget isn't yet in the gallery, so you'll need to select "Custom" and then type in &lt;a href="http://pamelafox-samplecode.googlecode.com/svn/trunk/spreadsheetsconverter/spreadsheetsconverter.xml"&gt;the URL to the gadget&lt;/a&gt;:
&lt;br/&gt;
&lt;img src="http://pamelafox-samplecode.googlecode.com/svn/trunk/spreadsheetsconverter/screenshots/screenshot_converter_3_add.png"&gt;
&lt;/li&gt;
&lt;br/&gt;

&lt;li&gt;The gadget will appear embedded in the current worksheet, and it will prompt you to select a range of data to send to the gadget. Select all the rows for the column with your address data, and you should see the Range text field update with the range. If it doesn't work, you can always manually type it in.
&lt;br/&gt;
&lt;img src="http://pamelafox-samplecode.googlecode.com/svn/trunk/spreadsheetsconverter/screenshots/screenshot_converter_4_range.png"&gt;
&lt;/li&gt;
&lt;br/&gt;

&lt;li&gt;You can now select either "JSON", "XML", or "SQL" from the dropdown, click "Apply", and see the generated output. To get the output in your clipboard, just double-click inside the frame, select all and copy.
&lt;br/&gt;
&lt;img src="http://pamelafox-samplecode.googlecode.com/svn/trunk/spreadsheetsconverter/screenshots/screenshot_converter_5_json.png"&gt;
&lt;br/&gt;
&lt;img src="http://pamelafox-samplecode.googlecode.com/svn/trunk/spreadsheetsconverter/screenshots/screenshot_converter_6_xml.png"&gt;
&lt;br/&gt;
&lt;img src="http://pamelafox-samplecode.googlecode.com/svn/trunk/spreadsheetsconverter/screenshots/screenshot_converter_7_sql.png"&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;br/&gt;

&lt;p&gt;You can see the &lt;a href="http://spreadsheets.google.com/pub?key=rxkw_khCxHvetWkGsRXmGtA"&gt;published example spreadsheet&lt;/a&gt;, and see the XML output of the gadget in the second sheet. I generally move gadgets to their own sheet to make my workspace cleaner.
&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8501278254137514883-3026070077074205772?l=blog.pamelafox.org' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.pamelafox.org/feeds/3026070077074205772/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=8501278254137514883&amp;postID=3026070077074205772' title='9 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8501278254137514883/posts/default/3026070077074205772'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8501278254137514883/posts/default/3026070077074205772'/><link rel='alternate' type='text/html' href='http://blog.pamelafox.org/2009/05/how-to-convert-google-spreadsheet-into.html' title='How to Convert a Google Spreadsheet into JSON, XML, and MySQL'/><author><name>Pamela Fox</name><uri>http://www.blogger.com/profile/15947664772001597300</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>9</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8501278254137514883.post-468818228023524505</id><published>2009-05-05T15:06:00.000-07:00</published><updated>2009-05-05T15:29:16.999-07:00</updated><title type='text'>How do you document an options Object?</title><content type='html'>&lt;p&gt;
In JavaScript APIs and libraries, you can make a constructor or function more flexible and easy to use by having developers pass in an object of additional options. 
&lt;/p&gt;
&lt;p&gt;
Here's an example of a badly designed constructor that doesn't take advantage of  this feature - the final 5 arguments are all optional, but yet, location must be passed in if the developer wants to specify hobbies.
&lt;/p&gt;
&lt;pre&gt;
EvilPerson(name:String, location?:String, age?:Number, job?:String, hobbies?:String);
&lt;/pre&gt;
&lt;p&gt;
When used, it's hard to understand what this constructor is doing:
&lt;/p&gt;
&lt;pre&gt;
var evilPerson = new EvilPerson("Taz the Haz", null, null, "Annihilator", "Blowing stuff up");
&lt;/pre&gt;

&lt;p&gt;
Here's an example of a well designed constructor that makes developers specify the 
absolute core information, and then pass everything else via an options object:
&lt;/p&gt;
&lt;pre&gt;
GoodPerson(name:String, options:Object);
&lt;/pre&gt;
&lt;p&gt;
When used, it's very obvious what options we're setting:
&lt;/p&gt;
&lt;pre&gt;
var goodPerson = new GoodPerson("Snuggly Muggly", {job: "Cuddler", hobbies: "Spooning"});
&lt;/pre&gt;
&lt;p&gt;
So, most people are in agreement that this is a good technique, but there's one problem: there's no standard on how these options objects should be documented. 
&lt;/p&gt;
&lt;p&gt;
In the JavaScript Maps API, we give the objects a class name, link to the class reference from the constructor, and then list the keys there. The advantage is that we can refer to these objects in the developer's guide or forum by name, the disadvantage is that we list a class in our reference that developers cannot actually instantiate, and that can be confusing.
&lt;/p&gt;
&lt;p&gt; The screenshots below are from the &lt;a href="http://code.google.com/apis/maps/documentation/reference.html#GMarker"&gt;GMarker&lt;/a&gt; and &lt;a href="http://code.google.com/apis/maps/documentation/reference.html#GMarkerOptions"&gt;GMarkerOptions&lt;/a&gt; reference.
&lt;/p&gt;
&lt;p&gt;
&lt;img src="http://4.bp.blogspot.com/_T1lquhCmKo8/SgC6E1jqhLI/AAAAAAAAB5Q/3tdt0_dH_fY/s400/screenshot_markerref.png"&gt;
&lt;/p&gt;
&lt;p&gt;
&lt;img src="http://2.bp.blogspot.com/_T1lquhCmKo8/SgC6Rg2tAmI/AAAAAAAAB5Y/LfZtQMO361o/s400/screenshot_markeroptionsref.png" /&gt;
&lt;/p&gt;

&lt;p&gt;
In the Maps API for Flash, we turned those name objects into actual classes that developers must instantiate. This is good for documentation, but does perhaps bloat our API and make constructors more verbose.
&lt;/p&gt;
&lt;p&gt;
The screenshots below are from the &lt;a href="http://code.google.com/apis/maps/documentation/flash/reference.html#Marker"&gt;Marker&lt;/a&gt; and &lt;a href="http://code.google.com/apis/maps/documentation/flash/reference.html#MarkerOptions"&gt;MarkerOptions&lt;/a&gt; reference.
&lt;/p&gt;
&lt;p&gt;
&lt;img src="http://4.bp.blogspot.com/_T1lquhCmKo8/SgC6ee1Qc8I/AAAAAAAAB5g/NPA_i6qu8gw/s400/screenshot_markerref_flash.png"&gt;
&lt;/p&gt;
&lt;p&gt;
&lt;img src="http://1.bp.blogspot.com/_T1lquhCmKo8/SgC6jmos8zI/AAAAAAAAB5o/t0LrEkgITLU/s400/screenshot_markeroptionsref_flash.png"&gt;
&lt;/p&gt;
&lt;p&gt;
In jQuery UI, every widget gets its own single-page documentation, with "Options" being a section along with "Events" and "Methods". There is no actual reference for the widget constructor itself, presumably because every widget's constructor takes only an options object. This likely works for jQuery UI developers as they're accustomed to this convention, but I personally found it confusing that there was no constructor reference.
&lt;/p&gt;
&lt;p&gt;
The screenshots below are from the &lt;a href="http://docs.jquery.com/UI/Dialog"&gt;Dialog&lt;/a&gt; reference and &lt;a href="http://docs.jquery.com/UI/Dialog#options"&gt;options&lt;/a&gt; section.
&lt;/p&gt;
&lt;p&gt;
&lt;img src="http://1.bp.blogspot.com/_T1lquhCmKo8/SgC6wPyqCeI/AAAAAAAAB5w/sR9fIYnV_EE/s400/screenshot_dialogref.png"&gt;
&lt;/p&gt;
&lt;p&gt;
&lt;img src="http://1.bp.blogspot.com/_T1lquhCmKo8/SgC60j2YzfI/AAAAAAAAB54/ZuNUolk2bMI/s400/screenshot_dialogref_options.png"&gt;
&lt;/p&gt;
&lt;p&gt;
In Dojo API, the reference for many of the Dijits specify that they take an Object for additional parameters, but they don't actually make it clear what can be passed into that object. My best guess is that the fields listed in the "Properties" section can all be passed in. This is probably once again a convention that seasoned Dojo developers are accustomed to, but arguably pretty confusing for a new Dojo developer.
&lt;/p&gt;
&lt;p&gt;
The screenshots below are from the &lt;a href="http://api.dojotoolkit.org/jsdoc/1.3/dijit.Dialog"&gt;Dialog&lt;/a&gt; reference and the 
&lt;a href="http://api.dojotoolkit.org/jsdoc/1.3/dijit.Dialog#Properties"&gt;properties&lt;/a&gt; section.
&lt;/p&gt;
&lt;p&gt;
&lt;img src="http://4.bp.blogspot.com/_T1lquhCmKo8/SgC6_XgM98I/AAAAAAAAB6A/avO172ChoC4/s400/screenshot_digitref.png"&gt;
&lt;/p&gt;
&lt;p&gt;
&lt;img src="http://3.bp.blogspot.com/_T1lquhCmKo8/SgC7EMqgGwI/AAAAAAAAB6I/9uwgRG9CIK0/s400/screenshot_digitref_props.png"&gt;
&lt;/p&gt;

&lt;p&gt;
In the Gears API, none of the constructors take a options argument, but there is something somewhat analagous: objects passed into event callbacks. In this case, Gears documents the object entirely inline with the reference. This technique has the advantage that everything about the function and the object are in one place - and the disadvantage that there's not a great way of referring to that specific event callback object elsewhere (besides saying "the object that the onerror function passes back").
&lt;/p&gt;
&lt;p&gt;
The screenshot below is from the &lt;a href="http://code.google.com/apis/gears/api_workerpool.html#workerpool_class"&gt;WorkerPool&lt;/a&gt; reference.
&lt;/p&gt;
&lt;p&gt;
&lt;img src="http://1.bp.blogspot.com/_T1lquhCmKo8/SgC7RbotUtI/AAAAAAAAB6Q/SV_pi-vDmi8/s400/screenshot_gearsref.png"&gt;
&lt;/p&gt;
&lt;p&gt;
All of these styles have their pros and cons - and there's no one technique that satisfy our goals, like being easy for newbies to understand easy to refer to elsewhere in the documentation. What do you think? Have you seen a documentation that does it better, or do you think one of these techniques is clearly superior?
&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8501278254137514883-468818228023524505?l=blog.pamelafox.org' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.pamelafox.org/feeds/468818228023524505/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=8501278254137514883&amp;postID=468818228023524505' title='3 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8501278254137514883/posts/default/468818228023524505'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8501278254137514883/posts/default/468818228023524505'/><link rel='alternate' type='text/html' href='http://blog.pamelafox.org/2009/05/how-do-you-document-options-object.html' title='How do you document an options Object?'/><author><name>Pamela Fox</name><uri>http://www.blogger.com/profile/15947664772001597300</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://4.bp.blogspot.com/_T1lquhCmKo8/SgC6E1jqhLI/AAAAAAAAB5Q/3tdt0_dH_fY/s72-c/screenshot_markerref.png' height='72' width='72'/><thr:total>3</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8501278254137514883.post-2560731693194456967</id><published>2009-04-25T21:44:00.000-07:00</published><updated>2009-04-25T22:02:27.910-07:00</updated><title type='text'>What is an API?</title><content type='html'>&lt;p&gt;
A game designer asked me the other day to explain the meaning of "API" - and I thought, wow, that is a good question, considering our massive (over?)use of the term on the web. Of course, the obvious meaning is "Application Programming Interface", but that's pretty damn non-helpful, particularly for a non-programmer. So here's what I told him:
&lt;/p&gt;

&lt;p&gt;
&lt;b&gt;There's the traditional meaning of "API" - &lt;/b&gt;
&lt;/p&gt;
&lt;p&gt;
Some programmer writes a library with lots of functionality in it, and
exposes the functionality as different functions, so that other
programmers can just call the functions.
&lt;/p&gt;
&lt;p&gt;
For instance, I could write a function that goes through all the
complex steps of making out:
&lt;/p&gt;
&lt;pre&gt;
function makeOut(passionLevel, partsOfBody) {
 for (each partOfBody in partsOfBody) {
   partOfBody.kiss(passionLevel);
   lookIntoEyes();
   sighDeeply();
 }
 moanDaintily();
 complainAboutPeopleWatching();
}
&lt;/pre&gt;

&lt;p&gt;
So if you want to have your code make out, then you could just call:
&lt;pre&gt;
makeOut(10, ["neck", "ear", "mouth"]);
&lt;/pre&gt;
&lt;/p&gt;
&lt;p&gt;
You don't have to worry about the "implementation details" - all that
code I wrote - you just know that it works.
&lt;/p&gt;
&lt;p&gt;
The "library" is the actual code, the "API" is what programmers need
to know in order to use it.
&lt;/p&gt;
&lt;p&gt;
So my API documentation would provide the minimal info needed to use the library, and it could look like this:
&lt;/p&gt;
&lt;pre&gt;
makeOut(passionLevel: Number, partsOfBody:Array)
&lt;/pre&gt;
&lt;p&gt;
For an example of actual API docs, Java has the online documentation for all of its common libraries here:
&lt;a href="http://java.sun.com/j2se/1.5.0/docs/api/"&gt;http://java.sun.com/j2se/1.5.0/docs/api/&lt;/a&gt;.
&lt;/p&gt;


&lt;p&gt;
&lt;b&gt;And then there are "Web APIs" - &lt;/b&gt;
&lt;/p&gt;
&lt;p&gt;
A Web API hosts all of its code on one server, and documents how other servers can call that code.
&lt;/p&gt;
&lt;p&gt;
There are JavaScript Web APIs, like the Google Maps API, where the
Javascript is publicly viewable but quite "obfuscated" (compressed,
hard to read).
&lt;/p&gt;
&lt;p&gt;
This is our actual code:
&lt;a href="http://maps.google.com/intl/en_us/mapfiles/148e/maps2.api/main.js"&gt;
http://maps.google.com/intl/en_us/mapfiles/148e/maps2.api/main.js
&lt;/a&gt;
&lt;/p&gt;
&lt;p&gt;
This is our API documentation:
&lt;a href="http://code.google.com/apis/maps/documentation/reference.html"&gt;
http://code.google.com/apis/maps/documentation/reference.html
&lt;/a&gt;
&lt;/p&gt;
&lt;p&gt;
Developers only need to know what the API looks like, they don't have
to figure out what all that crazy code means.
&lt;/p&gt;
&lt;p&gt;
Then there are HTTP APIs, which means that all of the code is hidden
on the server, and the code is executed when a programmer hits a
particular URL. Often times, these APIs will create new information on
the server for a user. All of our consumer products with user data
have HTTP APIs - like Google Spreadsheets, Google Calendar, Blogger,
etc. A programmer can hit a particular URL with an authentication
header, and either get or create more user data.
&lt;/p&gt;
&lt;p&gt;
One of the most popular HTTP APIs is the Flickr API, which can be used
to retrieve information, upload photos, create albums, etc.
Their API is documented here:
&lt;a href="http://www.flickr.com/services/api/"&gt;
http://www.flickr.com/services/api/
&lt;/a&gt;
&lt;/p&gt;
&lt;p&gt;
You can use the API without authenticating if you just want to do a
simple search:
&lt;/p&gt;
&lt;a href="http://api.flickr.com/services/rest/?method=flickr.photos.search&amp;api_key=4d12a2ccfa7400584c162bfc104bf682&amp;tags=fox"&gt;
http://api.flickr.com/services/rest/?method=flickr.photos.search&amp;api_key=4d12a2ccfa7400584c162bfc104bf682&amp;tags=fox
&lt;/a&gt;
&lt;/p&gt;
&lt;p&gt;
Notice the query parameters after the "?" like &lt;code&gt;method&lt;/code&gt;, &lt;code&gt;api_key&lt;/code&gt;, and
&lt;code&gt;tags&lt;/code&gt;. These are like the parameters to a function (like &lt;code&gt;passionLevel&lt;/code&gt;
and &lt;code&gt;partsOfBody&lt;/code&gt; from above). You could imagine that flickr has code on
their server that looks like:
&lt;/p&gt;
&lt;pre&gt;
function searchPhotos(api_key, tags) {
 ....
}
&lt;/pre&gt;
&lt;p&gt;
But once again, a developer never has to see the Flickr server code,
they can just use the API and get the results they want.
&lt;/p&gt;

&lt;p&gt;
&lt;b&gt;Above all, an API is a promise.&lt;/b&gt;
&lt;/p&gt;
&lt;p&gt; It's a promise that no matter how the author
changes the code (the implementation), the interface will remain the
same. You can always call that &lt;code&gt;makeOut&lt;/code&gt; function, and expect it to make out, even if it stops complaining about people watching.
&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8501278254137514883-2560731693194456967?l=blog.pamelafox.org' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.pamelafox.org/feeds/2560731693194456967/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=8501278254137514883&amp;postID=2560731693194456967' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8501278254137514883/posts/default/2560731693194456967'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8501278254137514883/posts/default/2560731693194456967'/><link rel='alternate' type='text/html' href='http://blog.pamelafox.org/2009/04/what-is-api.html' title='What is an API?'/><author><name>Pamela Fox</name><uri>http://www.blogger.com/profile/15947664772001597300</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8501278254137514883.post-7410631531219252417</id><published>2009-04-20T14:17:00.000-07:00</published><updated>2009-04-20T14:30:32.995-07:00</updated><title type='text'>Web09: Design, Code, Community.. and Maps!</title><content type='html'>&lt;p&gt;
Earlier in the year, I was invited to speak at &lt;a href="http://www.webstock.org.nz/"&gt;Webstock&lt;/a&gt;, an annual conference in Wellington, New Zealand. It was a fantastic conference filled with inspirational speakers from around the world who discussed the future of the web, ways in which it sucks now, what we could do to change it.
&lt;/p&gt;
&lt;p&gt;
This week, I had the opportunity to speak at &lt;a href="http://www.web09.org/"&gt;Web09&lt;/a&gt;, a similarly named conference in Auckland, New Zealand - just an hour flight north. I was a bit surprised that New Zealanders felt the need to hold 2 web conferences in a year, and wondered if this conference would be different from Webstock. Well, it was completely different - in a good way. Web09 was a cornocupia of real-world advice from both local developers - like &lt;a href="http://twitter.com/avon"&gt;Karl Von Randow&lt;/a&gt;'s talk about gaming the iPhone App store, and global evangelists - like &lt;a href="http://twitter.com/ryanstewart"&gt;Ryan Stewart&lt;/a&gt;'s talk about new Flex features. Some of my favorite talks were:
&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="http://twitter.com/danrubin"&gt;Dan Rubin&lt;/a&gt; gave us a variety of ideas for creating better designs, including adding noise to a background, using your own photographs as the
focal piece of a website, and scanning in every day objects to get web textures. In trying to define good design, he referenced &lt;a href="http://en.wikipedia.org/wiki/Donald_Norman"&gt;Don Norman&lt;/a&gt;
as the cognitive scientist who originally articulated the problem of doors that are so un-intuitively designed that they require signs - a problem that we have in our new Google building. Norman authored &lt;a href="http://www.amazon.com/Design-Everyday-Things-Donald-Norman/dp/0385267746"&gt;The Design of Everyday Things&lt;/a&gt;, which I've now put on my reading list.
&lt;/li&gt;
&lt;li&gt;&lt;a href="http://twitter.com/pburnett"&gt;Paul Burnett&lt;/a&gt;, Adobe Flash Evangelist, showed off various new features in Flash CS4 and its much better integration with AIR (now better than Flex Builder!). I was most impressed by the fact that Flash now supports adding bones (inverse kinematics) to shapes and graphics, and being able to set weights and properties and tweak the RTS graphs for every animation.
It takes me way back (2 years!) to futzing around with character animation in Maya and Max, and makes me want to get CS4 and try animating a few simple characters - zombie, whale, maybe even a &lt;a href="http://imagine-it.org/course_mult_walk.swf"&gt;streetwalker&lt;/a&gt;.
&lt;/li&gt;
&lt;li&gt;&lt;a href="http://twitter.com/davidkarp"&gt;David Karp&lt;/a&gt;, creator of Tumblr, described 5 areas of community building: engagement, use, negativity, change, feedback. Karp suggested that the reason
that people participate in communities is for the "promise" of something happening - like the people who upload to Youtube thinking they have a small hope that
one day their video will shoot to fame and they'll be a Youtube rockstar. Karp also described how Tumblr went from 1 support email a day to hundreds, and how they dealt with it. They categorized every support email as  both "type of user" plus the actual problem - with user type
ranging from paying customers and new customers to evangelist users. Visualizing the requests that way enabled them to decide what features were important to growth.
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;
I myself gave a talk called &lt;a href="http://docs.google.com/Presentation?id=dggjrx3s_153hdf2s6cm"&gt;"Avoiding Red Dot Fever: Tips for Improving Usability of Maps Mashups"&lt;/a&gt;. It was a series of tips for ways web developers could improve the maps on their sites, based on my experiences seeing many badly-designed maps over the past 2 years. The talk went over really well (so well I was asked to give it twice), and gave me an excuse to meet the web developers of many New Zealand mapping sites - Zoodle, Yellow Pages NZ, vodafoneNZ, EventFinder, etc. The slides are embedded below, and there should be a video up in a few weeks.
&lt;/p&gt;

&lt;iframe src='http://docs.google.com/EmbedSlideshow?docid=dggjrx3s_153hdf2s6cm' frameborder='0' width='410' height='342'&gt;&lt;/iframe&gt;

&lt;p&gt;Overall, it was a great conference, and I hope to see both Webstock and Web09 happen next year.&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8501278254137514883-7410631531219252417?l=blog.pamelafox.org' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.pamelafox.org/feeds/7410631531219252417/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=8501278254137514883&amp;postID=7410631531219252417' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8501278254137514883/posts/default/7410631531219252417'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8501278254137514883/posts/default/7410631531219252417'/><link rel='alternate' type='text/html' href='http://blog.pamelafox.org/2009/04/web09-design-code-community-and-maps.html' title='Web09: Design, Code, Community.. and Maps!'/><author><name>Pamela Fox</name><uri>http://www.blogger.com/profile/15947664772001597300</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8501278254137514883.post-4704899352055891348</id><published>2009-04-09T07:00:00.001-07:00</published><updated>2009-04-09T07:29:51.834-07:00</updated><title type='text'>Google Image Search + Color Restrict: Just look what you can find!</title><content type='html'>&lt;p&gt;
This week, Google &lt;a href="http://googleblog.blogspot.com/2009/04/search-rainbow.html"&gt;officially announced&lt;/a&gt; support for filtering by colors in Google Image search results.I don't actually know if this is actually a useful tool yet, but even if it's not - it's freaking fun. Here are some cool results from myself and the twitterverse.
&lt;/p&gt;
&lt;p&gt;
&lt;b&gt;You can find beautiful landscapes:&lt;/b&gt; &lt;a href="http://images.google.com/images?q=red&amp;gbv=2&amp;hl=en&amp;sa=G&amp;imgcolor=black"&gt;sky, red&lt;/a&gt;
&lt;/p&gt;
&lt;img src="http://pamela.fox.googlepages.com/screenshot_redsky.png"&gt;
&lt;p&gt;
&lt;b&gt;You can find your school logos:&lt;/b&gt; &lt;a href="http://images.google.com/images?q=usc&amp;hl=en&amp;sa=G&amp;imgcolor=red"&gt;usc, red&lt;/a&gt; 
&lt;br&gt;
(via &lt;a href="http://twitter.com/oglowo"&gt;@oGLOWo&lt;/a&gt;)
&lt;/p&gt;
&lt;p&gt;
&lt;img src="http://pamela.fox.googlepages.com/screenshot_redusc.png"&gt;
&lt;/p&gt;
&lt;p&gt;
&lt;b&gt;You can find a world covered in fail stickers:&lt;/b&gt; &lt;a href="http://images.google.com/images?q=fail&amp;imgcolor=red"&gt;fail, red&lt;/a&gt; 
&lt;br&gt;
(via &lt;a href="http://twitter.com/niick"&gt;@niick&lt;/a&gt;)
&lt;/p&gt;
&lt;p&gt;
&lt;img src="http://pamela.fox.googlepages.com/screenshot_redfail.png"&gt;
&lt;/p&gt;
&lt;p&gt;
&lt;b&gt;You can find a phrase that's lived up to its colors:&lt;/b&gt; &lt;a href="http://images.google.com/images?q=state&amp;hl=en&amp;sa=G&amp;imgcolor=blue"&gt;state, blue&lt;/a&gt; 
&lt;br&gt;
(via &lt;a href="http://twitter.com/manomarks"&gt;@ManoMarks&lt;/a&gt;)
&lt;/p&gt;
&lt;p&gt;
&lt;img src="http://pamela.fox.googlepages.com/screenshot_bluestate.png"&gt;
&lt;/p&gt;
&lt;p&gt;
&lt;b&gt;And one more of those:&lt;/b&gt; &lt;a href="http://images.google.com/images?imgcolor=yellow&amp;hl=en&amp;sa=1&amp;q=journalism&amp;btnG=Search+Images&amp;aq=f&amp;oq="&gt;journalism, yellow&lt;/a&gt; 
&lt;br&gt;
(via &lt;a href="http://twitter.com/KevinMarks"&gt;@KevinMarks&lt;/a&gt;)
&lt;/p&gt;
&lt;p&gt;
&lt;img src="http://pamela.fox.googlepages.com/screenshot_yellowjournalism.png"&gt;
&lt;/p&gt;
&lt;p&gt;
&lt;b&gt;You can find two colors at once:&lt;/b&gt; &lt;a href="http://images.google.com/images?imgcolor=black&amp;hl=en&amp;sa=1&amp;q=red&amp;btnG=Search+Images&amp;aq=f&amp;oq="&gt;red, black&lt;/a&gt;
&lt;/p&gt;
&lt;p&gt;
&lt;img src="http://pamela.fox.googlepages.com/screenshot_redblack.png"&gt;
&lt;/p&gt;
&lt;p&gt;
&lt;b&gt;And finally, you can find creatures you never thought existed:&lt;/b&gt; &lt;a href="http://images.google.com/images?q=dolphins&amp;imgcolor=pink"&gt;dolphins, pink&lt;/a&gt; 
&lt;br&gt;
(via &lt;a href="http://twitter.com/niick"&gt;@niick&lt;/a&gt;)
&lt;/p&gt;
&lt;p&gt;
&lt;img src="http://pamela.fox.googlepages.com/screenshot_pinkdolphins.png"&gt;
&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8501278254137514883-4704899352055891348?l=blog.pamelafox.org' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.pamelafox.org/feeds/4704899352055891348/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=8501278254137514883&amp;postID=4704899352055891348' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8501278254137514883/posts/default/4704899352055891348'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8501278254137514883/posts/default/4704899352055891348'/><link rel='alternate' type='text/html' href='http://blog.pamelafox.org/2009/04/google-image-search-color-restrict-just.html' title='Google Image Search + Color Restrict: Just look what you can find!'/><author><name>Pamela Fox</name><uri>http://www.blogger.com/profile/15947664772001597300</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8501278254137514883.post-4865694211514525768</id><published>2009-04-01T21:27:00.000-07:00</published><updated>2009-04-01T21:56:08.634-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='apidesign'/><title type='text'>API Design: Beautiful Interfaces</title><content type='html'>&lt;p&gt;&lt;em&gt;This is part of a series on Web API design. The intro post is &lt;a href="http://otherfancystuff.blogspot.com/2009/03/web-api-design-good-bad-and-ugly.html"&gt;here&lt;/a&gt;.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;
When some developers think about the Google Maps API, they may envision a sea of &lt;code&gt;GMarker&lt;/code&gt;s, &lt;code&gt;GPolygon&lt;/code&gt;s, &lt;code&gt;GScaleControl&lt;/code&gt;s, &lt;code&gt;GOverviewMapControl&lt;/code&gt;s, and the like. But really, it boils down to 2 things: &lt;code&gt;GOverlay&lt;/code&gt; and &lt;code&gt;GControl&lt;/code&gt;. 
&lt;/p&gt;

&lt;p&gt;
These two classes are interfaces in the API, and every class that is a visual item on the map extends from one of those two. Conceptually, a &lt;code&gt;GOverlay&lt;/code&gt; is something that moves when the map moves and is somehow related to latitude/longitude coordinates, and a &lt;code&gt;GControl&lt;/code&gt; is something that always stays in the same place, regardless of map movement. The screenshot below points to various examples in a standard maps mashup:
&lt;/p&gt;

&lt;img src="http://docs.google.com/File?id=dggjrx3s_2301fsp5kmfz_b"&gt;

&lt;p&gt;
To add one of these to the map, a developer just calls addOverlay or addControl:
&lt;/p&gt;
&lt;pre&gt;
map.addControl(new GScaleControl());
map.addOverlay(new GMarker(new LatLng(37, -122));
&lt;/pre&gt;
&lt;p&gt;To remove them, they call &lt;code&gt;removeOverlay&lt;/code&gt; or &lt;code&gt;removeControl&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;
There are some mapping APIs out there with calls like &lt;code&gt;addMarker&lt;/code&gt;, &lt;code&gt;addPolyline&lt;/code&gt;. This is is a bad idea for several reasons. It means you need an additional method each time you add a new visual class (bloating your API), and it likely also makes it hard for developers to extend the API. With generic methods like &lt;code&gt;addOverlay&lt;/code&gt; or &lt;code&gt;addControl&lt;/code&gt;, you can add a custom extension the *same way* you add a native class - so newbie developers don't have to learn a new syntax to add one to their map.
&lt;/p&gt;

&lt;p&gt;Along with using generic methods for adding stuff to the map, we can also take advantage of the interface to make our events more generic. A developer can listen to &lt;code&gt;"addoverlay"&lt;/code&gt; or &lt;code&gt;"removeoverlay"&lt;/code&gt; to find out when any overlay has been added to the map, and when they listen to a &lt;code&gt;"click"&lt;/code&gt; event on the map, their callback gets passed in whatever &lt;code&gt;GOverlay&lt;/code&gt; was clicked on. This means that whenever we add a new type of overlay to our API, the developer can continue using the same events they were before. We do often add specific events for each overlay later, but it's nice that the generic ones come for free.
&lt;/p&gt;

&lt;h3&gt;And something for the advanced developers...&lt;/h3&gt;

&lt;p&gt;
These interfaces make our API infinitely extensible in a standard way, and they're the reason I used the API for my personal and research projects even before working for Google.  If I have a fundamental aesthetic issue with our &lt;code&gt;GLargeMapControl3D&lt;/code&gt;, then I can simply create my own control (&lt;a href="http://gmaps-utility-library.googlecode.com/svn/trunk/extlargemapcontrol/"&gt;ExtLargeMapControl&lt;/a&gt;). If I want to visualize 5,000 markers, and &lt;code&gt;GMarker&lt;/code&gt; is simply too full-featured and heavyweight for the job, then I can create my own lightweight marker (&lt;a href="http://gmaps-samples.googlecode.com/svn/trunk/manymarkers/markerlight.js"&gt;MarkerLight&lt;/a&gt;). If I want to visualize my points as &amp;lt;div&amp;gt;-based bar graphs instead of &amp;lt;img&amp;gt;-based markers, then I can create my own overlay (&lt;a href="http://gmaps-samples.googlecode.com/svn/trunk/stockmap/baroverlay.js"&gt;Bar&lt;/a&gt;). 
&lt;/p&gt;
&lt;p&gt;
To extend the interfaces requires defining only a few minimal methods:
&lt;/p&gt;

&lt;pre&gt;GOverlay: initialize, redraw, remove&lt;/pre&gt;
&lt;p&gt;
The &lt;code&gt;initialize&lt;/code&gt; method, called when &lt;code&gt;addOverlay&lt;/code&gt; is invoked, should create DOM objects for the overlay and append them to the desired map pane (there are several). The &lt;code&gt;redraw&lt;/code&gt; method is called whenever the map moves, and it should re-position the overlay depending on the new latitude/longitude -&gt; pixel mapping. The &lt;code&gt;remove&lt;/code&gt; method, called when &lt;code&gt;removeOverlay&lt;/code&gt; is invoked, should clean up any DOM objects created by the overlay. More info and an example is in &lt;a href="http://code.google.com/apis/maps/documentation/overlays.html#Custom_Overlays"&gt;the docs&lt;/a&gt;.
&lt;/p&gt;

&lt;pre&gt;GControl: initialize, getDefaultPosition&lt;/pre&gt;
&lt;p&gt;
The initialize method, called when addControl is invoked, should create and return the div for the control.  The getDefaultPosition method should returns the recommended position for the control. There is no remove method, since the &lt;code&gt;initialize&lt;/code&gt; method returned a &amp;lt;div&amp;gt; that the map can remove whenever &lt;code&gt;removeControl&lt;/code&gt; is invoked. More info and an example is in &lt;a href="http://code.google.com/apis/maps/documentation/controls.html#Custom_Controls"&gt;the docs&lt;/a&gt;.
&lt;/p&gt;

&lt;p&gt;
Using just these methods and some JavaScript/CSS skills, a developer can create anything their hacker heart desires. Custom controls and overlays account for 15/20 of the libraries in our &lt;a href="http://gmaps-utility-library-dev.googlecode.com/svn/trunk/"&gt;official utility library&lt;/a&gt;, another 15 of the libraries listed in Mike William's list of &lt;a href="http://econym.org.uk/gmap/extensions.htm"&gt;3rd party extensions&lt;/a&gt;, and based on my experience, many more are likely floating around in developer's code on the web.
&lt;/p&gt;

&lt;h3&gt;Don't forget the actual API engineers...&lt;/h3&gt;

&lt;p&gt;
Along the same lines, these interfaces also make API development easier for internal developers. If they want to add a visual class to the API, they just need to figure out whether it's a control or an overlay, define the methods, document that the new class exists, and external developers will use their existing familiarity with &lt;code&gt;addControl&lt;/code&gt; or &lt;code&gt;addOverlay&lt;/code&gt; to add it to their map.
&lt;/p&gt;

&lt;h3&gt;It can't all be fluffy rainbows and unicorns...&lt;/h3&gt;

&lt;p&gt;
We've certainly made a few mistakes along the way with the interfaces - but this post is getting long, so I'll save those for later.
&lt;/p&gt;

&lt;h3&gt;To sum it all up...&lt;/h3&gt;

&lt;p&gt;
The interfaces are easy for newbie developers to understand, easy for advanced developers to extend, and easy for internal engineers to implement. Beautiful.
&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8501278254137514883-4865694211514525768?l=blog.pamelafox.org' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.pamelafox.org/feeds/4865694211514525768/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=8501278254137514883&amp;postID=4865694211514525768' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8501278254137514883/posts/default/4865694211514525768'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8501278254137514883/posts/default/4865694211514525768'/><link rel='alternate' type='text/html' href='http://blog.pamelafox.org/2009/04/api-design-beautiful-interfaces.html' title='API Design: Beautiful Interfaces'/><author><name>Pamela Fox</name><uri>http://www.blogger.com/profile/15947664772001597300</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8501278254137514883.post-1249302514678832236</id><published>2009-03-30T23:31:00.000-07:00</published><updated>2009-03-31T00:03:59.669-07:00</updated><title type='text'>Web API Design: The Good, The Bad, and the Ugly</title><content type='html'>&lt;p&gt;
Two recent events have prompted me to spend a lot more time thinking about API design: 1) A series of "Good, Bad, and Ugly" talks at the Google Sydney office which examine internal architectures and coding decisions, 2) An internal reading group starting with &lt;a href="http://oreilly.com/catalog/9780596517984/"&gt;"Beautiful Architecture"&lt;/a&gt;, a book of essays. Though the design of internal software (largely the focus of the talks and book) is important and should be done well, it's my opinion that the design of external-facing Web APIs is even more important, and yet, a much less discussed topic.
&lt;/p&gt;

&lt;p&gt;
Why? Web APIs have some unique challenges:
&lt;/p&gt;

&lt;p&gt;
&lt;b&gt;Flexibility:&lt;/b&gt; Web APIs are intended to by whatever random developer finds them useful, not by a restricted set of internal developers. And, I can tell you from experience, random developers do things that you never even realize was possible with your API - and then they beg for feature requests to make it easier for them - and you'll want to fulfill their requests because you'll think "hot damn, that was cool!" So, the easier it is to implement new and different features, the better.
&lt;/p&gt;
&lt;p&gt;
&lt;b&gt;Backwards-Compatibility:&lt;/b&gt; Web APIs have to stay around for a long, long time. Even if you threaten that you'll change your API every 2 years and you warn users 1 year ahead of time, you'll still have some developers use the old version of the API and write angry posts in your forum about their site breaking. Or, developers that have written code for client sites, moved on to bigger and better things, and left it with webmasters that have no idea how to upgrade it. Or, developers using wrapper libraries that abstract on top of the older version of the API, and have no notion of the underlying API. So, it's safe to assume that you can never really deprecate an API without breaking old sites, and you should design the API with that in mind (future-proof it). 
&lt;/p&gt;

&lt;p&gt;
.. and other challenges, like needing to be equally usable by both newbie and advanced developers, and needing to be a reasonable number of kilobytes (for client-side APIs). 
&lt;/p&gt;

&lt;p&gt;
In the land of Web APIs, the Google Maps API makes for an interesting case study. It is one of the most used Web APIs in the worlds (150,000 sites), the first interactive web mapping API, likely the first hosted JavaScript API, and it has grown from a simple API with just markers and zooming to a complex API with 90+ classes. It's also gone from version 1 to version 2, but the changes were primarily in terms of latency; the actual interface has remained largely the same. All these facts make it interesting to look at the Maps API from an architecture and design point of view, and point out the places where it went right - and where it went wrong. Of course, as an advocate of the Maps API and someone who uses it daily, I should point out that I still think we have the best Maps API in the world. But even gods can have their flaws (I hear Zeus had a weakness for mortal women).
&lt;/p&gt;
&lt;p&gt;
So, in an upcoming series of blog posts, I'll single out design decisions in our API that I think were good, bad, or ugly. To start it off on a good note, I'll start with something beautiful... stay tuned!
&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8501278254137514883-1249302514678832236?l=blog.pamelafox.org' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.pamelafox.org/feeds/1249302514678832236/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=8501278254137514883&amp;postID=1249302514678832236' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8501278254137514883/posts/default/1249302514678832236'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8501278254137514883/posts/default/1249302514678832236'/><link rel='alternate' type='text/html' href='http://blog.pamelafox.org/2009/03/web-api-design-good-bad-and-ugly.html' title='Web API Design: The Good, The Bad, and the Ugly'/><author><name>Pamela Fox</name><uri>http://www.blogger.com/profile/15947664772001597300</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8501278254137514883.post-281524596093898564</id><published>2009-03-30T04:08:00.000-07:00</published><updated>2009-03-30T04:39:12.017-07:00</updated><title type='text'>APUGS Round-Up: Bzoo, AIR, &amp; Eclipse</title><content type='html'>&lt;p&gt;Tonight, despite half of Sydney CBD being in a blackout (and zombies attacking the city), I attended the monthly &lt;a href="http://groups.adobe.com/posts/db02e98146"&gt;APUGS (Adobe Platform Users Group Sydney) meeting&lt;/a&gt;. 3 developers gave talks, and I learnt a great deal of random information. I realize that all of my Flex experience currently comes from supporting the Maps API for Flash - so, if a developer hasn't asked it, I've never learnt it - and apparently, developers haven't asked me all the questions in the world yet. Here's a roundup of the topics covered:
&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Developer Bachir El Khoury spoke about his AS3 library for creating a client-side database with full CRUD operations, called &lt;a href="http://code.google.com/p/bzoo"&gt;Bzoo&lt;/a&gt;. It can create the database from JSON, YAML, or ArrayCollections, and optionally, it can store the database persistently using Flash &lt;a href="http://livedocs.adobe.com/flex/2/docs/wwhelp/wwhimpl/common/html/wwhelp.htm?context=LiveDocs_Parts&amp;file=00001962.html"&gt;Shared Objects&lt;/a&gt;. Shared Objects are basically super cookies for Flash that are persistent across all browser sessions on a desktop, and can take up to 100 KB per domain. Cookies can be useful in Flash apps for remembering game configurations, backing up data before a save, or user sign-in state.
&lt;/li&gt;
&lt;li&gt;Developer &lt;a href="http://www.rebelspirit.com.au/"&gt;Andrew Muller&lt;/a&gt; showed off &lt;a href="http://www.bowernest.com"&gt;Bowernest&lt;/a&gt;, an AIR app he's creating for a client (&lt;a href="http://www.booktagger.com"&gt;BookTagger&lt;/a&gt;). It's a desktop app with a slick interface for managing books and other media. Andrew used the &lt;a href="http://code.google.com/p/mate-framework/"&gt;Mate (Mah-tay)&lt;/a&gt; RIA framework for creating the app, and the award-winning skin from &lt;a href="http://scalenine.com/blog/2008/10/16/and-the-winners-are/"&gt;ScaleNine&lt;/a&gt;'s contest. Cleverly, the app can import files from Shelfari and LibraryThing, the two big competitors to BookTagger, so its easier for users to switch over. It then stores all the data locally in an AIR SQLite DB, and offers the user the option to export back out to the Booktagger file format. As a heavy user of web-apps, I find it a bit shocking that the data isn't constantly backed up to a BookTagger user-account, but hey, apparently some users are into the whole desktop-only app thing. When I asked Andrew about other apps out there that were desktop-only, he showed us &lt;a href="http://www.balsamiq.com/products/mockups"&gt;Balsamiq Mockups&lt;/a&gt;, an awesome app for mocking up web prototypes in a sketchy way.
&lt;/li&gt;
&lt;li&gt;APUGS organizer Chris Velevitch showed some tips for working in Eclipse. I only work in FlexBuilder, but it was useful to see the similarities and differences to Eclipse development. Eclipse has a cool feature called &lt;a href="http://cephas.net/blog/2003/09/24/eclipse-local-history/"&gt;local history&lt;/a&gt;, which lets you see every version of the files in your project - for up to "9,999 days"! Also, in both Eclipse and FlexBuilder, you can right-click on a file tab and select "New Editor" to get the same file opened in two tabs. In FlexBuilder, you can then put one tab in Design mode and the other in Source mode, and drag one so it's below the other. Highly useful.
&lt;/li&gt;
&lt;/ol&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8501278254137514883-281524596093898564?l=blog.pamelafox.org' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.pamelafox.org/feeds/281524596093898564/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=8501278254137514883&amp;postID=281524596093898564' title='3 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8501278254137514883/posts/default/281524596093898564'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8501278254137514883/posts/default/281524596093898564'/><link rel='alternate' type='text/html' href='http://blog.pamelafox.org/2009/03/apugs-round-up-bzoo-air-eclipse.html' title='APUGS Round-Up: Bzoo, AIR, &amp; Eclipse'/><author><name>Pamela Fox</name><uri>http://www.blogger.com/profile/15947664772001597300</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>3</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8501278254137514883.post-2161375700923676299</id><published>2009-03-27T17:34:00.000-07:00</published><updated>2009-03-27T18:07:44.731-07:00</updated><title type='text'>BarCamp Canberra 2: Mapping the Fires</title><content type='html'>&lt;p&gt;I just spoke a few minutes ago at BarCamp Canberra 2 about our experience making a map of the Victoria BushFires. Here's a quick run-through of the presentation, with links:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;We woke up, saw there were crazy fires going on, and looked at how we could help.
The websites with the information were &lt;a href="http://www.dse.vic.gov.au/DSE/nrenfoe.nsf/childdocs/-05D409B0BFBBAD5BCA256DA600074990-DC25C965BDA0CAF5CA2573B400013504?open"&gt;DSE (Public Lands)&lt;/a&gt; and &lt;a href="http://www.cfa.vic.gov.au/incidents/incident_summary.htm"&gt;CFA (Private Lands)&lt;/a&gt;. The problem with the DSE site was the lack of an interactive map and the lack of an RSS feed. The lack of RSS feed meant that people were constantly reloading the page to see what had changed, and their server was crumbling under the load. The problem with the CFA site was the lack of a map -- and given all the number of small towns in Australia, it's very hard to visualize where the fires are happening in respect to where you or your loved. The problems with the RSS feed was that it lacked latitude/longitude coordinates, and the CFA website was struggling and producing corrupt feeds some of the time.
&lt;/li&gt;
&lt;li&gt;First we tried using &lt;a href="http://radar.oreilly.com/archives/2007/05/yahoo-pipes-add.html"&gt;Yahoo! Pipes&lt;/a&gt; to turn the RSS into a GeoRSS feed, but it didn't quite work correctly, and we were worried about relying on the service during an emergency.&lt;/li&gt;
&lt;li&gt;So then I set up a database on my server, ran a script geocoding any new locations every 2 hours, output the database as &lt;a href="http://imagine-it.org/mashplanet/display_fires2.php"&gt;an ActionScript object&lt;/a&gt;, copied and pasted it into my Flex app, and re-uploaded the SWF. It was ghetto and painful, but it worked.. provided I woke up every 2 hours. Sometimes, we had to manually find locations - like "DSE - 6KM ESE OF WARBURTON" - by using the distance measurer mapplet in Google Maps and eyeballing it. It sure would have been easier if CFA had done the geocoding for us!
&lt;/li&gt;
&lt;li&gt;So then we created &lt;a href="http://mapvisage.appspot.com/fires/FireMap.html"&gt;the map&lt;/a&gt;. We sent the RSS feed through Google App Engine, caching it every 5 minutes to avoid hitting the CFA web server (and to ignore corrupt feeds), parsed that feed in the Flash map, and displayed the fires as markers. We later added a legend, search box, and colored/sized markers, but we basically had our map up 4 hours after we started coding. Not bad! 
&lt;img src="http://www.edparsons.com/wp-content/uploads/2009/02/victoriafires.png"&gt;
&lt;/li&gt;
&lt;li&gt;
One important thing we did was make a gadget version of the map. This meant news agencies, blogs (like &lt;a href="http://mashable.com/2009/02/08/google-australian-fires/"&gt;Mashable&lt;/a&gt;, and random concerned folks could embed the map in their sites. A lot of people discovered the map through the gadget, and the news agencies benefited since they didn't have to create their own visual to complement their articles. 
&lt;/li&gt;
&lt;li&gt;The map got around 60 QPS at its peak - and App Engine handled it with no problems. It probably helped that we used our inside influence to raise all of our quotas to the absolute max (14 petabytes of bandwidth!). :)
&lt;/li&gt;
&lt;li&gt;After we had the map up, we wanted to make the geocoding less ghetto. We changed from doing the geocoding on my server to doing the geocoding on App Engine, and outputting the feed as &lt;a href="http://mapvisage.appspot.com/query/fire?agency=viccfa&amp;geocode=1"&gt;a GeoRSS feed&lt;/a&gt; instead. The great thing about GeoRSS is that it's a pseudo-standard, and there are multiple websites that can parse and display them (including &lt;a href="http://maps.google.com/maps?f=q&amp;source=s_q&amp;hl=en&amp;geocode=&amp;q=http:%2F%2Fmapvisage.appspot.com%2Fquery%2Ffire%3Fagency%3Dviccfa%26geocode%3D1&amp;ie=UTF8&amp;t=h&amp;z=9"&gt;Google Maps&lt;/a&gt;). The cool thing about outputting the data in this portable format was that one concerned guy was able to import the GeoRSS into a &lt;a href="http://maps.google.com/maps/ms?hl=en&amp;ie=UTF8&amp;msa=0&amp;msid=106748912741752087169.000462af2a083d89391ea&amp;ll=-37.913867,144.876709&amp;spn=2.348829,4.240723&amp;z=8"&gt;Google My Map&lt;/a&gt;, plot markers where his family members were located, and figure out if they were in trouble.
&lt;/li&gt;
&lt;li&gt;At this point, we were doing good things with the CFA data, but we still had no data for the public lands. DSE was unwilling to give us structured XML data, as they had various concerns about copyrights, attribution, and data distortion. We still wanted to represent public lands data though, and that's when we discovered that NASA takes satellite imagery of South Australia every 12 hours and &lt;a href="http://rapidfire.sci.gsfc.nasa.gov/subsets/?subset=FAS_SEAustra"&gt;makes them available&lt;/a&gt; in various standard formats. 
&lt;/li&gt;
&lt;li&gt;Using &lt;a href="http://www.maptiler.org/"&gt;MapTiler&lt;/a&gt;, an open-source GUI for the command line &lt;a href="http://www.gdal.org/"&gt;GDAL utilities&lt;/a&gt;, we converted the NASA GeoTIFF into map tiles. Those map tiles can be used in most APIs - Google, Microsoft, OpenLayers, etc. We, of course, overlaid them on our Google Flash Map, and let people toggle the imagery on. NASA does an automatic analysis of the imagery to look for fires, so you could actually see red outlines around the center of big lines of smoke. Since we're still serving the imagery from 25 days ago, you can still see that &lt;a href="http://mapvisage.appspot.com/fires/FireMap.html"&gt;on the website&lt;/a&gt;.
&lt;/li&gt;
&lt;li&gt;The aftermath of all of this is that we learned lessons about the issues with getting emergency data in a format that can be re-used, cached, syndicated, and visualized in useful ways. We wrote a white paper of sorts with recommendations for &lt;a href="http://docs.google.com/Doc?docid=dggjrx3s_153f9vbsdp&amp;hl=en"&gt;Emergency Data portability&lt;/a&gt; and we're consulting with various agencies to help them get their data up to snuff.
&lt;/li&gt;
&lt;/ul&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8501278254137514883-2161375700923676299?l=blog.pamelafox.org' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.pamelafox.org/feeds/2161375700923676299/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=8501278254137514883&amp;postID=2161375700923676299' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8501278254137514883/posts/default/2161375700923676299'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8501278254137514883/posts/default/2161375700923676299'/><link rel='alternate' type='text/html' href='http://blog.pamelafox.org/2009/03/barcamp-canberra-2-mapping-fires.html' title='BarCamp Canberra 2: Mapping the Fires'/><author><name>Pamela Fox</name><uri>http://www.blogger.com/profile/15947664772001597300</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8501278254137514883.post-535208143869891637</id><published>2009-03-24T15:15:00.001-07:00</published><updated>2009-03-24T19:44:56.029-07:00</updated><title type='text'>Ada Lovelace Tribute: A Q&amp;A with My Mum</title><content type='html'>&lt;p&gt;
A few months ago, I pledged to write a blog post for &lt;a href="http://findingada.com/"&gt;Ada Lovelace day&lt;/a&gt;. The hope is that atleast 1,000 bloggers will write about a woman in technology on today, March 24th, and that this will draw (good) attention to woman in technology. I don't necessarily know if we'll succeed in the objective, but hey, it's different and could work, so why not?
&lt;/p&gt;

&lt;p&gt;
&lt;img src="http://farm4.static.flickr.com/3607/3361430536_76258c5e34_s.jpg" align="right"&gt;
Since I don't actually know very many women in technology (I'm too distracted by all the tech boys?), I've done a Q&amp;A with my mum, &lt;a href="http://www.spectral.com/personnel.shtml#Rosemary"&gt;Rosemary Kennett&lt;/a&gt;. Mum studied Physics at Caltech, met and married my dad there (a professor! scandal!), had 3 kids, worked for NASA JPL, did physics research at SU and Cornell, taught Astronomy for a few years, and then moved on to her current job as a scientific programmer in Spectral Sciences. Here goes:
&lt;/p&gt;
&lt;br clear="all"&gt;
&lt;dl&gt;
&lt;dt&gt;&lt;b&gt;
Why did you choose to study Physics?&lt;/b&gt;&lt;/dt&gt;
&lt;dd&gt;I actually became fascinated in high school where I was taught by a
teacher who had just returned from a sabbatical at Oxford and was
intrigued by the new physics e.g. nuclear physics.  I remember that I
used to borrow her collection of popular scientific paperbooks.
&lt;/dd&gt;

&lt;dt&gt;&lt;b&gt;What was the first line of code that you wrote?&lt;/b&gt;&lt;/dt&gt;
&lt;dd&gt;I remember writing code to model an oscillating
violin string when I took an early math course involving programming as
an undergraduate (we did not have CS courses back then).  Most of the
early coding was in Algol 60 (which most people agree was a pretty
good language but somehow it died out)&lt;/dd&gt;

&lt;dt&gt;&lt;b&gt;What language have you programmed the most in?&lt;/b&gt;&lt;/dt&gt;
&lt;dd&gt;Fortran, then C/C++, then Java&lt;/dd&gt;
&lt;dd&gt;&lt;i&gt;(Hmm. Is Fortran kind of like 4chan? - PF)&lt;/i&gt;&lt;/dd&gt;

&lt;dt&gt;&lt;b&gt;What app are you proudest of creating?&lt;/b&gt;&lt;/dt&gt;
&lt;dd&gt;For the general public - there's a simple Java applet that often gets
referred to: &lt;a href="http://www.phy.syr.edu/courses/java/demos/kennett/Epicycle/Epicycle.html"&gt;Epicycle and Deferent Demo&lt;/a&gt;.&lt;/dd&gt;

&lt;dt&gt;&lt;b&gt;
You taught astronomy and ran the Syracuse Astronomical Club for a few
years. What's the most fascinating aspect of astronomy for you?
&lt;/b&gt;&lt;/dt&gt;
&lt;dd&gt;
How much we are learning about the distant past (likewise
through high energy physics experiments, which now are trying to mimic
conditions soon after the start of the universe!).  Also the number,
variation and beauty of objects in space, especially as observed using
the Great Observatories (Hubble, Chandra for X-Rays, Spitzer for IR
etc)
&lt;/dd&gt;

&lt;dt&gt;&lt;b&gt;
I always thought it was pretty cool to have a mum that worked at JPL. What were you doing there (besides rocket science, of course)?
&lt;/b&gt;&lt;/dt&gt;
&lt;dd&gt;
Actually the technical work of which I'm most proud was that done at
JPL.  One project was to check the performance of a new design of a
radar instrument called a scatterometer which measures oceanic winds
(strength and direction) by bouncing radar off the waves - the Bragg
effect means that the radar return depends on the roughness of the
waves, which is in turn influenced by the wind speed.  You do this
from different directions and you can tell the direction of the wind
also.  Anyway that style of scatterometer is now the standard,
although launches of these instruments are few and far between
&lt;/dd&gt;
&lt;dd&gt;
&lt;i&gt;(That's right, my mum's invention is orbiting space above your heads right now. Boo-yah! - PF)&lt;/i&gt;
&lt;/dd&gt;


&lt;dt&gt;&lt;b&gt;You have 3 kids, and two of them ended up in Computer Science. Do you credit/blame nature or nurture?&lt;/b&gt;&lt;/dt&gt;
&lt;dd&gt;Genes!&lt;/dd&gt;
&lt;dd&gt;&lt;i&gt;(Hmm. I'm pretty sure it was the fact that we had a T1 line before any other kids had the internet, and that we moved to cold, miserable upstate NY and I was forced to hibernate inside our well-supplied computer room. - PF&lt;/i&gt;
&lt;/dd&gt;
&lt;/dl&gt;

&lt;p&gt;&lt;b&gt;Bonus Factoid:&lt;/b&gt; My mum knows all the cool kids in CS: Steven Wolfram, because he was a student working with my dad on the Mathematica forerunner, Richard Feynman, because he was a Physics professor at Caltech, and Larry Page, because he attended a Hertz event and asked her a question about her research... I'm jealous!
&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8501278254137514883-535208143869891637?l=blog.pamelafox.org' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.pamelafox.org/feeds/535208143869891637/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=8501278254137514883&amp;postID=535208143869891637' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8501278254137514883/posts/default/535208143869891637'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8501278254137514883/posts/default/535208143869891637'/><link rel='alternate' type='text/html' href='http://blog.pamelafox.org/2009/03/ada-lovelace-tribute-q-with-my-mum.html' title='Ada Lovelace Tribute: A Q&amp;A with My Mum'/><author><name>Pamela Fox</name><uri>http://www.blogger.com/profile/15947664772001597300</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://farm4.static.flickr.com/3607/3361430536_76258c5e34_t.jpg' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8501278254137514883.post-2293078425486804932</id><published>2009-03-17T03:40:00.000-07:00</published><updated>2009-03-17T03:50:18.439-07:00</updated><title type='text'>Adelaide: More than OK, Actually</title><conte
