Video of my YUIConf talk about open web app development

yuiconf-wfwalkerThe YUIConf folks have just posted their recording of a talk I gave there last year. I had planned to talk generally about the Firefox Marketplace, how it differs from other app stores, and how those differences create an overall apps ecosystem unlike other app ecosystems. All true, and all important.

I ended up giving a completely different talk. I decided I really wanted to show to use the Firefox developer tools to test, deploy, and debug an open web app running live on a Firefox OS phone. I had a lot of fun demoing live, including use of my patent pending cardboard and WebRTC ELMO replacement.

Take a look, I hope you enjoy it!

http://www.yuiblog.com/blog/2014/02/24/yuiconf-2013-bill-walker-on-firefox-marketplace-breaking-the-stranglehold-of-app-stores/

Posted in HTML5, Mozilla, Trip Reports | Leave a comment

Replacing Google Image Charts with D3.js

[When I'm not in the office, I'm often out birding and photographing birds. To keep track of my life list and bird photos I wrote a Ruby on Rails site hosted at birdwalker.com; you can see all the source on github. This post is about some recent improvements to that code]

When I first discovered Google Image Chart API, I had written little JS and was excited about how easily I could create decent-looking bar charts without including big libraries or writing a lot of code. I added a method in my Rails ApplicationHelper class to generate a URL for the Google Image Chart API by encoding my parameters and data values into the expected format:

def counts_by_month_image_tag(totals, width=370, height=150) 
  monthly_max = 10 * (totals[1..12].max / 10.0).ceil

  stuff = {
    :chco => 555555,
    :chxt => "y",       
    :chxr => "0,0," + monthly_max.to_s,
    :cht => "bvs",
    :chd => "t:" + totals[1..12].join(","),
    :chds => "0," + monthly_max.to_s,
    :chs => width.to_s + "x" + height.to_s,
    :chl => Date::ABBR_MONTHNAMES[1..12].join("|")
  } 

  chartString = ("http://chart.googleapis.com/chart" + "?" + 
    stuff.collect { |x| x[0].to_s + "=" + x[1].to_s }.join("&")).html_safe

  ("<img src=\"" + chartString + "\" alt=\"Totals By Month\" width=\"100%\"/>").html_safe
end

I started using this helper from my various page templates and all was well. Time went by.

Eventually, I became disenchanted with this solution. I can develop and test the rest of the site locally on my laptop, but the external image URL’s like those aren’t reachable offline. The Google chart images are statically sized, so they’re ill-suited to responsive design frameworks like Twitter Bootstrap. And, rendering charts as images doesn’t allow for any interactivity. [note: Google addressed these deficiencies in a subsequent version of their Chart API, which does most of the work client-side, and adds a lot of scope for interactivity].

Meanwhile, I became more comfortable with JS and began to create more of birdwalker.com using it. After attending a conference talk about D3, I decided to copy a sample bar chart and adapt it for my purposes. I put the finished code in a Rails partial called _species_by_month.html.erb

D3.js code works by chaining many function calls together. Each call has a very specific purpose, and the calls can generally go in any order. By chaining them together, you get the overall behavior you want. For example, to create the bars in my bar graph I do this:

var bars = svg.selectAll("rect").remove().data(sightingData).enter()
  .append("rect")
  .attr("x", function(d, i) { return x(d.month); })
  .attr("y", function(d, i) { return y(d.count);})
  .attr("height", function(d, i) { return height - y(d.count); })
  .attr("width", function(d, i) { return x.rangeBand(); })
  .attr("class", "bargraph-bar"

The calls to attr() specify the location and size of an SVG rectangle and assign it a CSS style name. By calling data() you can iterate over an array of data; by calling enter() you can create new SVG nodes for each item in the array. In this case, we iterate over twelve numeric values representing birding activity during each month of the year and create twelve rectangles.

These new graphs resize nicely as elements within my Bootstrap layout. And I was able to create a tooltip when mousing over each bar like this:

svg.selectAll("rect").on("mouseover.tooltip", function(d){
    d3.select("text#" + d.month).remove();
    svg
    .append("text")
    .text(d.count)
    .attr("x", x(d.month) + 10)
    .attr("y", y(d.count) - 10)
    .attr("id", d.month);
});

And remove the tooltip on mouse exit like this:

svg.selectAll("rect").on("mouseout.tooltip", function(d){
    d3.select("text#" + d.month).remove();
});

The tooltips are styled with CSS just like the other graph elements.

So far, my experience with D3 has been really great. I now have graphs that work well in a responsive layout, don’t require external image links, and have some interactivity. Suggestions and code reviews welcome!

-Bill

Posted in HTML5, Ruby on Rails | Leave a comment

DevCon5 — on learning from games, Monty Sharma, Mass Unity

Monty Sharma gave a great talk this morning at DevCon5 about the current trends in games and what the rest of us can learn from them. He centers on three big ideas:

  • Free-to-Play. Find a way to let dedicated users pay more to get more stuff, but offer free functionality to everybody who asks
  • Compulsion Loops. Find ways to get people hooked into coming back to your software in order to satisfy some compulsion
  • Engaged Communities. Give up some control to bring your users into a community with one another.

I was really interested in his retelling of the EVE Online community responding to something called GoonSwarm. I can’t quite follow the internal politics of the game, but I can see that thousands of users organized themselves into highly effective ad hoc groups in order to battle one another within the game. Are your users that passionate and engaged?

Posted in Trip Reports | Leave a comment

jsEverywhere: Apathy is the Enemy of Awesome by Nancy Lyons

Nancy Lyons of geekgirlsguide gives a real end-of-day pep talk about how failed communication and collaboration can kill projects. I’ll put in a few of her zingers and how I understand them:

  • Learn how to talk about what you do to people who have no idea what you’re talking about.

Her evangelical zeal is very refreshing; I can imagine her listening to all these tech talks and thinking, “none of this is going to save you if your team can’t talk to each other.”

  • Don’t drop truth bombs

She urges us to imagine what non-technical clients who haven’t thought about iterations and known bugs will hear when you talk about bugs.

  • Don’t define scope in a consulting proposal

Instead, define the requirements collaboratively alongside the client. You have no idea what you’re talking about when you start!

Posted in Uncategorized | Leave a comment

jsEverywhere: PhoneGap CLI and PhoneGap Build Steve Gill, Adobe

Steve Gill is demoing “Cordova Client”, in which you have command-line tools to build, deploy, and manage Cordova-based applications on Blackberry, Android, and iOS. This is still in beta. It’s at github.com/filmaj/cordova-client. It requires Node.js, should be available in npm.

Posted in Uncategorized | Leave a comment

jsEverywhere: From Continuous Integration to Continuous Delivery by Morten Nielsen

Morten‘s presentation is a hilarious, compelling fable of what happens when a .NET shop relying on manual processes becomes a victim of its own success and ends up with an exploding number of software versions in the field. The fable ends happily using Hudson and Jenkins for repeatable, automated deployments. Whew.

Posted in HTML5, Trip Reports | Leave a comment

jsEverywhere: End-to-End W3C APIs by Alexandre Morgaut

Alexandre is giving a great overview of the history of JavaScript, popular API’s, and the role of W3C and other standards bodies. He gives a shoutout to Kevin Dangoor for CommonJS, then proposes the idea that remote CommonJS processes can be thought of as remote Web Workers. Wakanda makes big use of CommonJS.

Posted in HTML5, Trip Reports | Leave a comment