Notes from the Interview Front

Interrogation Room #5

Sadly, I won’t be sharing a bunch of funny anecdotes from my time on the interview trail. While that might be fun, there are some bigger trends that I wanted to talk about after having reviewed dozens of job descriptions and talking to dozens of people at one level or another over the month of March.

AngularJS is the new boss

At least in terms of green field development it seems like no one is talking about anything other than AngularJS right now. My year and a half’s worth of Angular experience set off alarm bells for many recruiters. Backbone comes up, but not with as much frequency. Several people were moving from Backbone to Angular. Nothing else in the MV* space was really in the running.

Lots of smart people (including many that I know) are still pouring a lot of time and effort into Backbone, so it’s clearly not going anywhere. It is weird, however, as Angular seems to be winning developer mind share no matter what the regular front end engineering taste-makers might think about it. I’ve had a lot of conversations with people (including some big names) where they’re completely flabbergasted that anyone is even using Angular, forget about the fact that it’s storming the castle.

It’s definitely storming the castle.

In the course of writing this post, I saw a bell clear sign of Angular’s rise. I saw an “Angular expert” job posting from a company who had spent a ridiculous amount of time and money (hundreds of thousands of dollars worth of developer hours) crafting a “perfect” Backbone based application development stack. I’m sure they’re still quite fond of Backbone, but it was interesting to see them hedging their bets, trying to get some Angular expertise on staff.

Start-ups are spreading like wildfire.

The Boston start-up scene is pretty nuts. I’m not generally interested in start-ups, but as part of my “talking to everyone” thing I ended up talking to a few of them. I remain mostly uninterested from a full-time perspective, although I did get up to the brink with one group that seemed pretty cool.

There is a lot of opportunity out there for someone like me to help them out on a short-term basis, however, so in my new life as an indie consultant, I might go back into the fray.

Start-up Geography

At this point start-ups are no longer crowding around South Station. They’re in South Boston proper. It’s a walk to get over there these days.

Bocoup might be leading a smart charge over to North Station.

Agency vs. Startup/Product

When I interview at agencies I don’t do tech screens. No one has asked me to do anything like that in 4 years. The shared experience of the agency existence and the number of people I usually have in common with agency folks means that the “tech” portion of interviews usually doesn’t go beyond philosophy and general experience. For most agency people knowing the level I’ve been at the places I’ve worked is a pretty good indicator that I know what I’m doing.

Product people, on the other hand, are super wary of my experience. They seem to think that because I’ve been a manager and been in charge of teams that I don’t know how to code. Some of them have even made the assumption that I don’t want to code (yes, I do open source software to torture myself.)

Interviewer: “So you’ve been a manager, running teams for a while. You haven’t really been coding since 2007 then?”

Rob: “No, unless today is opposite day. I’ve worked on probably 20 sites or applications in that time. Some with thousands of lines of JavaScript and incredibly complex UIs.”

Let me set the record straight on that assumption. Being an engineering manager at some companies might include no coding/all meetings, but at an agency the pendulum usually swings way too far in the other direction.

A technology manager at an agency will probably be doing coding/architecture most of the time and will not have any time officially allotted to do anything strategic or to work with their team on anything other than project work. .

Even if their target allocation is something like 60% billable work, they will probably be fully allocated to client work. Occasionally, they will be over-allocated to a client (or two.) Oftentimes, soft-skills “manager stuff” happens in hours 40 and above (or 80 and above.)

Personally, at one point a couple of years ago I was allocated 100% to two separate divisions at the same investment bank for six weeks. Not a lot of time to get soft when you’re scheduled to work 80 hours a week :)

This is actually a systemic problem at agencies. There’s not a lot of room for people at even the director level and above to really nurture staff. There are exceptions, of course. If you look around and spot stable teams at different agencies you can usually spot a guy or gal at the top who makes a point of keeping their staff happy, but the pressure to do that is not coming from up on high. The pressure from up on high is to keep your billable rate as high as you possibly can in order to justify your continued presence at the agency.

To that end, senior people at agencies are constantly getting their hands dirty. No one is hiding. I know start-up people think their experience is special, and in a lot of ways it is, but the experience on the agency side isn’t any easier.

To be perfectly honest, looking at someone from an agency with a good engineering culture and thinking they’re going to be soft is insane. That person has probably built up and torn down more architectures than most people do in a career in the product world.

There is a reverse bias

Agency people don’t want to hire people who don’t have agency experience. This is undeniably true. There’s a fear that you will hire someone, they will walk in the door, see the maelstrom and walk back out the door.

That happens, so it’s a valid concern, even if I don’t put as much weight into it as some people do. For my money, I’d rather have people get the shot and fill the role than play gatekeeper just because someone is coming from another industry. Sometimes it turns out really well.

Front-end engineering isn’t, universally, a first class discipline (although it’s getting closer to being one)

Something similar to the following happened twice when interviewing for very senior architect positions (including one that was titled something like “Front End Architect.”)

Hiring manager: “We want an architect whose focus is on the front end. You’ll lead projects, working with other developers and vendors, but we really want someone who can make a difference with the user interface layer. We see it as a game changer for us. ”

Me: “Sure, great. I’d love to come in”

Rob interviews

Feedback: “Rob was really strong on the front end, but he wasn’t as strong as we want him to be with Java/C#”

(So you actually want a Java guy? You want a Java guy who’s also an expert with JavaScript? Does such an unholy chimera even exist? )

The thing that drives me crazy about this scenario (beyond the fact that it’s a waste of my time) is that I’ve worked with architects who knew so little about JavaScript that they didn’t know enough to leave the JavaScript alone. I’ve seen very smart people completely break the UI because they were completely clueless about JS and didn’t even realize the depth of their cluelessness.

Up until they start breaking things, I’m cool with this. As long as folks delegate I don’t want or expect someone to be an expert across the whole system or to be able to code the whole system. I wouldn’t trust many of the absolute geniuses I’ve worked with to code the front end of any system. Just like they wouldn’t trust me to code up the services layer or come up with a database schema. But yet, in many organizations, you are simply not allowed to be in charge if you don’t have significant back-end experience. It doesn’t matter that the heavy lifting is happening in the browser now. It doesn’t matter that the potential advantage is in the user interface because there’s still an incredible shortage of strong front end engineers. It doesn’t matter than getting people to be effective at their jobs is a skill that stretches across technology domains. If you’re not a Java or C# expert, in some places at least, you still can’t straddle domains and run the show.

It is getting better

The good news is, the previous used to be universal. It’s no longer. I did interview for two general technology leadership roles (Director/VP) and those were judged on their own merits. No one once gave me the stink eye because I’m not a reformed Java developer.

Random notes

The Interrogation

  • I don’t like people who do tech screens like it’s an affront to their honor that you would even think you are good enough to work at their company. This doesn’t happen too often, but it does happen and I fill up with quiet rage pretty quickly when I encounter one of these people. When I run tech screens, I want to fill the role. I’m not happy when people aren’t up to snuff. I’m truly disappointed. It seems to me like these people would be happier to keep the role unfilled. That’s the absolute wrong way to approach the interview process. My reaction is invariably: “You don’t want me here? Cool, I won’t work here.”
  • I’ve been contacted by 28 separate recruiters in six weeks for various jobs at one company. I want to opt-out permanently please? I wish there was a central registry to opt out of contact by company.
  • I’ve got a hint for people who have been trying to fill roles for a six months or a year and can’t find anyone. Pay more money. Instead of losing out on some opportunity waiting to get someone at a 50th percentile wage and fitting it into some budget, push the pay envelope by 10% or more and people will be a lot more receptive. There are very few job descriptions I’ve seen in the Boston area, at any level, that had an aggressive (for the level) salary attached. There are some, but not many (maybe 10%.) Everyone else seems to think that being able to use new technology and getting free soda and coffee should be enough of a selling point to get you to choose them in the middle of one of the hottest skill sectors in the job market. The salaries seem to slot into very clear strata and there are few outliers. I know people are afraid because money is money and front-end developers should be worth $xxx. But if you have a need now, paying aggressively is one way to fill it that’s within your control. Everything else is outside of your control. Pay more than your competitors. Everyone is using Angular or other modern architecture. Everyone gives out free snacks and coffee and all that crap. You can’t win with that stuff.


And that’s it for now. I may add onto this as other trends percolate around in my brain. For the most part I enjoyed the conversations I had even if nothing turned out to be a perfect fit for me and I hope that people on the other side of the desk felt the same.

Posted in Web | Tagged , , | 1 Comment

Current Status: Independent Consultant

As many of you know, my run at Wellington ended at the end of February. My contract wasn’t renewed for reasons beyond my control and that was that.

No more suits, sadly.*

One of the big problems with that contract ending was that the timing of it was a little abrupt. I found out just a couple of hours before I got on stage to speak at jQuery conference which was, in turn, just over two weeks away from what would turn out to be my end date. Since the time frame was compressed and I wasn’t really in the “new job” mindset to begin with, I ended up going into the first month of my job search with the wrong attitude. That wrong attitude was that it was okay to talk to people because, at the end of the day, I wasn’t working anyway, so why not hear people out?

It turns out that talking to as many people as I talked to in March is actually a pretty crummy idea. While I had good conversations with a few companies and actually got pretty close on a couple of roles that made some sense for me at this stage of my career I ended up burning myself out on the interview process before the month was over.**

In hindsight, I should have chosen my conversations more wisely, written a bunch and done a ton more open source work. Oops.

Anyway, in the back of my mind, as I was doing all of this interviewing and listening to everyone who wanted a moment of my time I was nurturing the thought that I would be happier just doing my own thing as an independent consultant for a while. I’ve always threatened to start my own agency and while this isn’t the way I imagined doing it, it is a way to do it, so the option was one that I’d thought about for a long time. It might not be my own version of Sterling Cooper Draper Pryce (even if I’ve been know to dress like a modern Don Draper), but it’s still an opportunity to help clients with tough problems and do so under my own banner. That’s pretty cool by itself and if it turns into something bigger down the road, then even better. And if it doesn’t work out? That’s cool too. At least I gave it a shot.

So, to make a long story short, unless someone blows me away with a great role I’m going to be a sword-for-hire for the foreseeable future. Sure, I will listen to people that have really great engineering leadership roles, but I’m going to focus more on doing consulting and training on my own. To start, as I’ve already got an engagement that will keep me busy for the next few weeks, I’ve got a small page outlining the services I provide. I’ll be creating a more official presence as time allows, but for now that page is good enough to give you a sense of what I’m available to do.

So, hire me if you’ve got the need.


* Stated without irony. I like the suits.

** I actually had some help on that, but more on that in a subsequent post. I’ve got a couple of anecdotes to share about the interview process as I’ve witnessed it, but that will come in the next couple of weeks.

Posted in Web | Tagged , | Leave a comment

I Made a Scatter Plot Data Visualization with AngularJS and SVG. Here’s How I Did It.

This post is a longer examination of the new scatter plot visualization I added to my upcoming data visualization presentation for jQuery Conference. As with the other Angular examples I’ve posted recently, this one is based on the data I keep about the world’s most valuable comics. This particular visualization lives on the page I keep detailing record comic book sales. Take a look. It’s pretty cool, especially if you’re fascinated by comic books that have sold for more than $100,000.

For reference, it looks like the following. It’s 20 years of comics sales plotted horizontally with their sale prices (ranging from $100,000 to $2,500,000) plotted vertically. You can see a couple of clusters of activity based on different events in the marketplace.

chart

So, how did I do it? And why did I do it this way? D3 actually has a few scatter plot examples out there, so I could have used one of those, but as I thought about it I decided I wanted to do something hand-rolled. A scatter plot is actually pretty easy to map out and, as an added bonus, I could lay out the basics of the chart in Illustrator, which allowed me to demo the fact that SVG can be authored like any image by a graphic designer and then manipulated with JavaScript and CSS.

So let’s take a look at the particulars.

First we’ll start with the markup. This is Angular, after all. I’ve simplified the markup a bit, taking out some of the elements representing grid lines. Check the source on Github for all the details.

The interesting bits, from the Angular perspective, happen around line 30. The core of the visualization is in the circle element. It’s an ng-repeat that goes through the items collection in the controller’s scope. It’s filtered by the venues property.

Take note of the prefixes on the next set of attributes. For starters, as I normally do, I prepend data-* to Angular attributes as that’s the way custom attributes are defined in the spec. I like to play by the rules. You’ve probably seen that before. What’s probably not so familiar is the use of the additional ng-attr-* prefix. If you’re familiar with Angular you know you should just be able to do fill="{{colorPicker(it.venue)}}" and Angular should evaluate the results of the colorPicker method and insert it in as the value of the fill attribute. This doesn’t work with SVG elements. Some browsers will parse the entire SVG element before Angular has a chance to evaluate the SVG attributes. So if you put n Angular expression inside an SVG attribute it will throw an error. ng-attr solves this by binding the attribute solely to Angular’s discretion. Here, I’m using this pattern three times. The fill attribute, which provides the color coding for the different venues s these comic books have sold (with the handy colorPicker method that accepts the it.venue as an argument) , and the cx and cy attributes which indicate the center of the circle.

The cx and cy attributes are passed through custom filters which transform the data into usable x and y coordinates. I’ll talk about those in the section on the Angular filters. Following the filters there are two mouse events used to show and hide a simple (svg) tooltip.

The tooltip is in the next section. Doing boxes in SVG isn’t quite the same thing it is with HTML. You can’t just throw a box in there and have text flow inside the box like you can with a DIV or something, so this would have been easier with an HTML tooltip. That said, I wanted to do this in SVG so it’s all in SVG. In this case I’m doing it with a solid box with several text elements layered on top. All of these tooltip elements show based on the tooltip model on the scope. If the price is truthy, the tooltip shows. Otherwise, it's hidden. For each text element and the rect element, I'm using x and y coordinates generated with the same Angular filters in use on the circles and using the transform attribute to move the element around based on that common x/y. Each of the text elements also expose the data from the model.

Following the tooltip code, in the 'legend' g element there are several rect elements which allow for quick filtering by sales venue. ng-mouseover and ng-mouseout are used to update the venues filter.

That's the markup. SVG isn't that scary, is it?

 <div data-ng-app="comicsApp">
  <div data-ng-controller="chartCtrl">
    <svg version="1.1" xmlns="http://www.w3.org/2000/svg"
    xmlns:xlink="http://www.w3.org/1999/xlink"
    width="980" height="600" viewBox="0 0 980 600" xml:space="preserve">
      <g id="lines">
        <line fill="none" stroke="#000000" stroke-miterlimit="10"
         x1="90.828" y1="-8" x2="90.828" y2="579.297"/>
        <line fill="none" stroke="#B5B5B6" stroke-miterlimit="10"
         x1="0" y1="579.297" x2="981.996" y2="579.297"/>
        <line fill="none" stroke="#595858" stroke-miterlimit="10"
         x1="734.275" y1="49.246" x2="734.275" y2="579.161"/>
        <!--about 50 lines cut-->
      </g>
      <g id="text">
        <text x="10" y="16">price in USD</text>
        <text x="71" y="574">$0</text>
        <text x="480" y="595">2003</text>
        <text x="78" y="595">1993</text>
        <text x="881" y="595">2013</text>
        <text x="25" y="553">$100,000</text>
        <text x="25" y="468">$500,000</text>
        <text x="16" y="363">$1,000,000</text>
        <text x="16" y="256">$1,500,000</text>
        <text x="16" y="151">$2,000,000</text>
        <text x="16" y="45" >$2,500,000</text>
      </g>
      <g id="dynamic">
        <circle  data-ng-repeat="it in items | filter : venues"
         opacity="0.8"
         data-ng-attr-fill="{{colorPicker(it.venue)}}"
         data-ng-attr-cx="{{it.date | xDate}}"
         data-ng-attr-cy="{{it.price | yPrice}}"
         data-ng-mouseover="updateTooltip(it)"
         data-ng-mouseout="updateTooltip(0)" r="7" />
        <rect data-ng-show="tooltip.price" data-ng-model="tooltip"
         transform="translate(-55,-100)"
         data-ng-attr-x="{{tooltip.date | xDate}}"
         data-ng-attr-y="{{tooltip.price | yPrice}}"
         width="150" height="80"
         fill="white" style="filter:url(#drop-shadow)" />
        <text data-ng-show="tooltip.price" data-ng-model="tooltip"
         transform="translate(-45,-90)"
         data-ng-attr-x="{{tooltip.date | xDate}}"
         data-ng-attr-y="{{tooltip.price | yPrice}}">
         {{tooltip.title}} {{tooltip.issue}}</text>
        <text data-ng-show="tooltip.price" data-ng-model="tooltip"
         transform="translate(-45,-75)"
         data-ng-attr-x="{{tooltip.date | xDate}}"
         data-ng-attr-y="{{tooltip.price | yPrice}}" >
         {{tooltip.pedigree}}{{tooltip.collection}}{{tooltip.provenance}} {{tooltip.grade_src | srcFilter}} {{tooltip.grade}}</text>
        <text data-ng-show="tooltip.price" data-ng-model="tooltip"
         transform="translate(-45,-60)"
         data-ng-attr-x="{{tooltip.date | xDate}}"
         data-ng-attr-y="{{tooltip.price | yPrice}}" >
         {{tooltip.price|currency}}</text>
        <text data-ng-show="tooltip.price" data-ng-model="tooltip"
         transform="translate(-45,-45)"
         data-ng-attr-x="{{tooltip.date | xDate}}"
         data-ng-attr-y="{{tooltip.price | yPrice}}" >
         {{tooltip.date}}</text>
        <text data-ng-show="tooltip.price" data-ng-model="tooltip"
         transform="translate(-45,-30)"
         data-ng-attr-x="{{tooltip.date | xDate}}"
         data-ng-attr-y="{{tooltip.price | yPrice}}" >
         {{tooltip.venue}}</text>
      </g>
      <g id="legend">
        <rect x="125" y="5" width="15" height="15" fill="#D95B43"
         data-ng-mouseover="venues='comic connect'"
         data-ng-mouseout="venues=''"></rect>
        <text x="145" y="15" class="legend">Comic Connect</text>
        <rect x="245" y="5" width="15" height="15" fill="#ECD078"
         data-ng-mouseover="venues='heritage'"
         data-ng-mouseout="venues=''"></rect>
        <text x="265" y="15" class="legend">Heritage</text>
        <rect x="325" y="5" width="15" height="15"
         fill="#C02942" data-ng-mouseover="venues='comiclink'"
         data-ng-mouseout="venues=''"></rect>
        <text x="345" y="15" class="legend">ComicLink</text>
        <rect x="405" y="5" width="15" height="15" fill="#542437"
         data-ng-mouseover="venues='pedigree'"
         data-ng-mouseout="venues=''"></rect>
        <text x="425" y="15" class="legend">Pedigree</text>
        <rect x="485" y="5" width="15" height="15" fill="#53777A"
         data-ng-mouseover="venues='metropolis'"
         data-ng-mouseout="venues=''"></rect>
        <text x="505" y="15" class="legend">Metropolis</text>
        <rect x="565" y="5" width="15" height="15" fill="#69D2E7"
         data-ng-mouseover="venues='jp'"
         data-ng-mouseout="venues=''"></rect>
        <text x="585" y="15" class="legend">JP/Mint</text>
        <rect x="645" y="5" width="15" height="15" fill="#FA6900"
         data-ng-mouseover="venues='mastronet'"
         data-ng-mouseout="venues=''"></rect>
        <text x="665" y="15" class="legend">Mastronet</text>
        <rect x="725" y="5" width="15" height="15" fill="#FE4365"
         data-ng-mouseover="venues='pgc'"
         data-ng-mouseout="venues=''"></rect>
        <text x="745" y="15" class="legend">PGCMint</text>
        <rect x="805" y="5" width="15" height="15" fill="#666666"
         data-ng-mouseover="venues='unknown'"
         data-ng-mouseout="venues=''"></rect>
        <text x="825" y="15" class="legend">Other/Unkown</text>
      </g>
    </svg>
  </div>
</div>

Now let's take a look at the JavaScript. First up is the controller. This is pretty simple as far as these things go. $scope.items is first populated with data provided by an Angular factory. The factory is a simple $http.get so I'm not showing it here. I just organized the data request into a factory so two controllers could share the same code for getting comics data. Following that, the $scope.tooltip model is set with a single property, price set to zero. This falsy value ensures that the tooltip we previously defined in the HTML isn't shown by default. Following that is a small method designed to update the tooltip model with data representing the currently selected comic book. Finally, there's a small method and related array used to choose colors for the different venues. The method accepts a string argument and matches against a list of known venues, returning the proper color.

That's the whole controller.

angular.module('comicsApp.controllers', ['comicFilters','comicsFactories']).
  controller('chartCtrl', ["$scope",'dataService',function( $scope, dataService )  {
    $scope.items = dataService;
    $scope.tooltip = {
      price:0
    }
    $scope.updateTooltip = function(it) {
      $scope.tooltip = {
        price:it.price || 0,
        venue:it.venue,
        date:it.date,
    	 	title:it.title,
    		issue:it.issue,
    		pedigree:it.pedigree,
    		collection:it.collection,
    		provenance:it.provenance,
    		grade_src: it.grade_src,
    		grade : it.grade
      }
    }
    $scope.colorPicker= function( venue ){
      switch (venue) {
        case "Heritage":
          return $scope.colors[0];
        case  "Comic Connect":
          return $scope.colors[1];
        case "Comiclink":
          return $scope.colors[2];
        case  "Pedigree":
          return $scope.colors[3];
        case "Metropolis":
          return $scope.colors[4];
        case  "JP The Mint":
          return $scope.colors[5];
        case "Mastronet":
          return $scope.colors[6];
        case  "PGCMint":
          return $scope.colors[7];
        default:
          return $scope.colors[8];
       }
    }
    $scope.colors = ["#ECD078","#D95B43","#C02942","#542437","#53777A","#69D2E7","#FA6900", "#FE4365","#666666"];
  }
]);

Now let's take a look at the filters. As I mentioned earlier, this particular visualization isn't generic, so these are only useful in the context of this particular implementation. Which is fine. I'm not doing a million of these.

The first, xDate, defines the x axis. It takes the date (in the form yyyy-mm-dd) and splits it into and array containing the years, months and days. I calculate the total number of months from 1993 by subtracting 1993 from the year and then multiplying that number by 12. I then adding that number to the number of months from the original date array. After that the numbers of months is fudged into a pixel measurement as the offset of the left of the chart, 90, is added to the number of months multiplied by 3.3333, which is a rough "month" unit on this particular chart.

The y axis filter is easier. It calculates a pixel representation of the book's value (the value divided by 4700, the number of dollars per pixel) and that number is subtracted from 579, which is the offset from the top of the SVG element to the baseline of the chart.

If you were doing a generic chart that could take any similar data and produce a scatter plot, you would have to do these calculations on the fly. Getting the minimum and maximum values out of the data and creating a range and scales depending on the specific data. Since I defined the data and parameters for this before I wrote a line of code.

Yay for lazy.

angular.module('comicFilters', []).filter('xDate', function () {
    "use strict";
    return function (input) {
        if (input !== undefined) {
          var date = input.split("-");
          var years = date[0] - 1993;
          var months = (years * 12) + parseInt(date[1]);
          return 90 + months * 3.3333;
        }
    };
}).filter('yPrice', function () {
    "use strict";
    return function (input) {
      if (input !== undefined){
        return 579 - (input/4700);
      }
    };
})

And there you have it. Check out the $100,000 club repo for all the source code from this visualization and keep your eyes peeled for my jQuery Conference presentation where I'll be talking about this as well as D3, the canvas element (with the web audio API) and Google Maps.

Posted in JavaScript | Tagged , , , | Leave a comment

I’m Going to be Presenting at jQuery Conference. It’s in San Diego. You Should Go, Too.

It was announced last week, so I can now share the fact that I’m going to presenting on Data Visualization in the Browser at jQuery Conference in February. Because it’s a new year and because the presentation time is so tight (30 minutes!) I’m going to redo the existing dataviz presentation I’ve been giving entirely. I’ve got a new branch and everything.

I’m thinking of using World Bank data. At minimum, I’ll be doing something interesting and meaningful and, at best, I might end up on the World Bank data visualization tumblr.

I’m also super happy to be going to San Diego in February.

Posted in JavaScript | Tagged , , | Leave a comment

Late Notice: I’m Presenting on Canvas Tomorrow at HTML5 Boston

I tweeted about it but I never added it my public calendar and… never posted about it here. Anyway, I’m going to present on canvas tomorrow night at HTML5 Boston. It will be great.

It’s also at the Arsenal complex (at Harvard Business Review), which means I’ll be having Isobar flashbacks. It also means I’ll be running the western end of the Charles River for the first time in a while. Super fun.

Here are the slides.

Posted in HTML | Tagged , , , | Leave a comment

I’m Giving Away a Copy of My Book, Beginning HTML and CSS

beginning-html-css

Want a free copy of my book? Sure you do. This month, I’m giving away a copy of my book right here on the blog (on this very post.)

The rules of this contest are simple, simply share an interesting/funny anecdote about your experience interviewing for a technology or agency position (no names or companies needed, blind items are fine.) At the end of October, I’ll pick the best one and you get a free copy of my book, Beginning HTML and CSS. I can’t tell you what kind of story will win, but if you’ve got an interview story that’s funny, creative, cool, inspirational, or whatever share it and you might get some free stuff. This contest is open to anyone in the world with an address. If I can send you a copy of my book using the US Postal Service, you’re eligible.

And heck, even if you’re already an expert and don’t have need of a beginner book, you can certainly hand it off to someone looking to make their own site for the first time or to an engineer from another technology discipline looking to get introduced to the joys of web technology.

Posted in HTML | Tagged | 4 Comments

The Project (soon to be) Formerly Known as ng-grid

I’ve go a bunch of small updates to share (and one big one.) I’m starting with this one since it fits with the Angular kick I’ve been on.

I’ve recently gotten involved with the ng-grid project housed under the Angular UI banner. We’re using it at work, so it makes sense for me to pitch in to help keep the project humming along as best it can.

We had a meeting last week and hatched plans to rewrite the core of the project in order to juice performance and ease development going forward. Working in financial services, grids are a big deal for me and I’ve never been a huge fan of any of the ones out there. I’m hoping this project will end up being the quality grid I’ve always been looking for as a consumer.

On the name

While it’s called ng-grid at the moment, it’s going to get a name change for 3.0, in order to better fit with the rest of the Angular UI stable. I’m not 100% sure of this, since we haven’t followed up since the meeting, but it will likely be UI Grid.


So, yeah. If you’re an Angular type and are looking for a data grid, I’ve got your back.

Posted in JavaScript | Tagged , | 7 Comments

And… @roblarsenwww

I’m finally going to start using @roblarsenwww. I’ve had the account for a couple of years and have long had the plan to use it for tech tweets. As I’ve basically given up editing my other interests on @robreact, I figured now as as good a time as any to try to separate out the accounts. If you’re interested in technical subjects you’re not all that well served by @robreact and I’m enjoying the content I’ve been sharing there, so I’m not interested in changing what that looks like any time soon.

So, if you currently follow me @robreact, that account probably won’t change much. I don’t really talk about technical subjects there very often, so very often will just turn into never. @roblarsenwww will be only be about technical subjects. It’s basically content I don’t share at present. IF you’re interested in that stuff, follow me there.

Now you know.

It will look something like this:

Posted in Web | Leave a comment

Help Wanted: Please Test the New @h5bp Ant Build Script Image Optimization Flow

I reworked the way images are optimized in the Ant Build Script. After all the work I’d done to get it to 1.0 I discovered that a lot of the features we added to the image optimization process, coupled with a few hacks I threw in there myself, had made the image optimization tasks wonky on the Mac and on Linux. To that end, I reworked them, making them much simpler logically. I think the new changes are pretty foolproof (me, being the fool) but I need as many people as possible to test it to make sure I’ve really solved the problem. With these image issues fixed, I would release 1.1.0 and then sit back and see how things go. I’m really looking at getting the project to a nice stable place where I can just let it chill out and do its thing without me worrying about having stupid open bugs staring me in the face.

Which is where I am now.

Anyway, the branch is new-image-optimization.

To test you need some PNGs and JPGs in the img folder in an HTML5 Boilerplate structured project. Importantly, you need to test your version of OptiPNG. If it’s less than 0.7.0 and you can’t upgrade for some reason* you need to uncomment line 189 in your project.properties. If it’s above, just run ant and holler if your images aren’t getting optimized.

This is the issue to track issues with the new flow.

If this works, I can close like 6 bugs and release the patch** version. Which is the bee’s knees.

* This is some Mac thing. I’ve never quite understood why people just can’t upgrade their tools, but apparently something about the Mac stops you from being able to update a stupid little utility.
** I’m wondering if this should be a minor version since there’s a lot of “private” code rewritten to change the image optimization flow. 1.1.0? Maybe.

Posted in Performance | Tagged , , | 1 Comment

Easy Autocomplete with the datalist Element, the list Attribute and AngularJS’s ng-repeat Directive

Continuing to write about some Angular features I’ve been working with recently, I thought it would be interesting to show off one of the little conveniences I was able to put together using just a couple of Angular’s core features. This example leverages basically two basic features of Angular and two HTML5 features to create an easy, live autocomplete widget.

The pieces we’re going to use are:

  • Angular models This demo shows how easy it is to use Angular’s models. While they can get more complicated, this example shows the base case of simply binding to a variable in scope, creating dynamic links that update the UI when the data is updated with minimal or no JavaScript interaction.
  • ng-repeat Obviously if you’ve worked with Angular for any length of time you’ll be familiar with this directive. Here, it’s used here to iterate over a collection and create a dynamic datalist element.
  • datalist and list The datalist element and the list attribute are the two new HTML features that bind up the autocomplete functionality. In short, the datalist element defines a list of autocomplete entries. The list attribute binds the datalist to an input using an id reference. This combination is available in Chrome, Opera and Firefox with buggy support in IE10+

Let’s see how it all goes together.

First up, since this is Angular, let’s look at the markup.

To get started you need to define an Angular controller. This one is named MainCtrl. Since this is just a simplified demo to illustrate the autocomplete widget, it doesn’t do much, but the code it’s pulled from is a form used to add information about individual comic books to a simple database. Many of those comics are from the same titles (Amazing Spider-Man, Action Comics, etc.) so it’s handy to have an autocmplete list in order to improve data entry efficiency.

The input itself has two pieces to note, the data-ng-model attribute and the list attribute.

Note: As always, I append data- to Angular attributes in order to follow the HTML spec’s directions on custom attributes. That’s just me. You might want to let it all hang out. Fair play.

The data-ng-model attribute defines the model for the input as the title property of variable named item bound to the controller’s scope. Interestingly, this variable doesn’t exist at run-time. Instead of erroring with a warning about item being undefined Angular handles the creation of it once the form is submitted. This is a great example of how casual Angular is with their models. There’s no ceremony here. Add the data-ng-model attribute and the binding is done for you. If the variable exists in scope, the input is bound to it. If it doesn’t exist, Angular creates it. That’s pretty sweet.

The list attribute references the datalist element that the input should look for in order to build value hints. The value of the attribute is the id of the datalist you want to use.

The button at the end of the form is the next interesting piece of markup. On that input we’re using data-ng-click in order to bind the addItem function to click events on the form. Angular will look for addItem in the global namespace and in the controller’s scope. As you’ll see in the JavaScript example, we’re safely binding the method to the controller’s scope. If you click this button after adding a new title the title will be immediately added to the autocomplete list.

Finally, there’s the datalist element which uses data-ng-repeat to build out the list of autocomplete options. This directive is bound to the titles property of the controller scope. Since Angular models are bidirectional, once you update $scope.titles this list will be updated with new values. Pretty sweet. As you can see, this datalist element has the id we referenced earlier in the list attribute of the input.

<body data-ng-controller="MainCtrl">
    <form>
      <div>
        <label>title</label>
        <input type="text" data-ng-model="item.title" list="comicstitle">
      </div>
      <div>
        <input type="Button" value="Add" data-ng-click="addItem(item)">
      </div>
    </form>
  </div>
  <datalist id="comicstitle">
    <option  data-ng-repeat="ttl in titles" value="{{ttl}}">
  </datalist>
  </body>

Now that you’ve seen the markup, let’s look at the JavaScript that binds it all together. It’s actually pretty simple. Most of the wiring is done in the markup so the JavaScript is pretty sparse. That said, there are some interesting things so let’s look at it in-depth.

For starters we’re defining the starter list of titles as a variable on the controller’s scope. It’s a simple array bound to $scope.titles.

Have I mentioned that data binding is one of my favorite things about Angular? There’s absolutely no ceremony with creating a model. It’s just a variable on the controller’s scope (or even the global scope if you’re super lazy.)

After the model, the only other thing on the controller is a function called addItem.

This function is the method referenced in the data-ng-click attribute in the markup. It does a couple of things. The first is that is pushes the new value to $scope.titles. This example uses lodash’s contains function to test whether or not the title already exists in the array before it’s added. That keeps the list unique.

The next bit is another neat illustration of Angular models. Since the item we created when we added a title, setting it the object to an empty object is a shortcut to clearing the values out of the form. In this case there’s just the one form element, but if there were fifty or five hundred form elements with their data-ng-model attributes bound to properties of item this single line would clear all the values out of every bound form element.

app.controller( 'MainCtrl' , function( $scope ) {
  $scope.titles = [ "Action Comics" , "Detective Comics" , "Superman" , "Fantastic Four" , "Amazing Spider-Man" ];
  $scope.addItem = function( item ) {
    if ( !_.contains( $scope.titles , item.title ) ){
      $scope.titles.push( item.title );
    }
    $scope.item = {};
  }
});

Check it out, in action, with this plunker.


And there you have it. Let me know if you have any questions, comments or corrections in the comments. I’ve got at least one more Angular

Posted in JavaScript | Tagged , , , | 6 Comments