April 4, 2013
HTML5 Date input

Thus, whither the jquery-ui datepicker?

It sounds like the HTML5 date type for inputs has been around for a while but I just found out about it during today’s announcement of Chrome Beta 27.

    `Best Day Ever: <input type="date" name="best-day" value="2009-01-02">`  

Best Day Ever:

January 20, 2013
Pairing Tour: Chris Peak and Sprites

Day eight of my pairing tour took me to a client site to pair with one of 8th Light’s design craftsman, Chris Peak. The 8th Light team he’s working with just finished a major milestone for the client so Chris had a list of housekeeping tasks to tackle. We started off writing a little CoffeeScript and Jasmine specs, made some tweaks to the database config, and wrapped the day working with Image sprites in CSS.

There wasn’t much to report on regarding the CoffeScript or database config tweaks— however, the sprite stuff was really cool and it was great to watch Chris quickly flip between Photoshop and his CSS file to get the icons just right.

Like many people, my introduction to sprites was primarily through Twitter Bootstrap. By just attaching a class name like class = “icon-home” to an element a cool little pre-made “home” icon would show up. I knew that all of these icons came from one single image sheet but had never dug into the “magic” behind them.

Well, as it turns out there really isn’t that much magic, it’s just a clever use of the width, height, background-image and background-position attributes.

Here’s a look at the relevant attributes from inspecting the elements of the icons page in Twitter’s own Bootstrap guide:

.icon-home {
    background-position: 0 −24px;
    background-image: (“../img/glyphicons-halflings.png”);
    width: 14px;
    height: 14px;
}

The first two lines of this block include the png file that has all of the icons (as seen here) and then positions it accordingly. By positioning it −24 pixels along y-axis it shifts the focus of the image down the “sheet” of images. Since the home-icon is positioned all the way to the left there is no adjustment necessary for the x-axis. The width and height attributes are simply the constraints that they want to put on the background image. The home-icon is only 14 pixels x 14 pixels so that is all that they need to include.

An easy way to experiment with sprites in “real-time” is to head over to the aforementioned Twitter Bootstrap icon section, right click on an icon to inspect it, and then start playing around with the CSS attributes to see how each adjustment affects the image. Happy sprit-ing.

January 17, 2013
Pairing Tour: Eric K - Working with iOS Touch Events

On Tuesday I had the chance to pair with Eric Koslow on the client project that I worked on with Brian Pratt last week. Eric did his apprenticeship during mine so we’ve paired quite a bit together. He’s a quick thinker who seems to know something about every toolset out there so I invariably learn something new every time we work together.

He was continuing to work on the JavaScript for the iPad web app, which meant tracking down some unexpected behavior and getting the app to respond to touches and swipes the way that it should.

The secret to handling touch events in Safari on iOS is that the mobile browser provides unique DOM elements that you can interact with. The ones that we worked with most were the targetTouches and touchEvent object. Apple’s documentation explains it best:

The system continually sends touchEvent objects to an application as fingers touch and move across a surface. A touch event provides a snapshot of all touches during a multi-touch sequence, most importantly the touches that are new or have changed for a particular target. A multi-touch sequence begins when a finger first touches the surface. Other fingers may subsequently touch the surface, and all fingers may move across the surface. The sequence ends when the last of these fingers is lifted from the surface. An application receives touch event objects during each phase of any touch.

So, in a nutshell, what happens is that targetTouches ends up being an array of touchEvent objects. These events are things like touchstart, touchmove and touchend, and can be mapped to the mouse events mousedown, mousemove and mouseup. These touchEvents have various properties, such as the X and Y coordinates of each event.

Unfortunately all the code we worked on is in the client repo so I’m going to need to update this post with some better examples after I follow up with Eric, but here’s a quick and dirty example:

Let’s say that you wanted to track how far a touch moved along the X- or Y-axis. Normally a touch that moved further along the X-axis would just move the page around on the mobile browser (and snap back into place), but you want to intercept it and do something like a “page swipe” so that you can advance to the next slide in an HTML presentation or the next photo in a web gallery.

function pageSwipe(event) {
    event.preventDefault();
    var movementThreshold = 100;    
    var xDistanceMoved = event.targetTouches[0].pageX - startX;
    var yDistanceMoved = event.targetTouches[0].pageY - startY;
    if (xDistanceMoved > yDistanceMoved && xDistanceMoved > movementThreshold)
        advanceToNextPage;
};

All this function does is grab the first element out of the targetTouches and ask what its X and Y coordinates are (pageX and pageY). By subtracting the starting X and Y values we can then determine just how far it moved. If the X distance is greater than Y and also greater than the “accidental movement” threshold, then you trigger the page swipe. (Again, not the greatest example, so I’ll definitely update the post with more).

I feel like Eric and I just “touched” on the tip of the iceberg when it came to event handling in mobile browsers. As so much web consumption moves to mobile I’m looking forward to learning more about it.

January 15, 2013
Pairing Tour: Working with Presenters

I kicked off the second week of my pairing tour with Skim, who’s been working on a big app upgrade for a client for the better part of the past year.

In the morning we updated a set of attributes from previously assigned values to a new range of values. This meant we also needed to update the way queries were made on those values, but the previously written tests guided us pretty well. It was the first time I’d ever seen elastic search in action and a great intro to both the power and complexity of it.

In the afternoon we helped one of the client’s designers update a view and it was my first chance to work with presenters in Rails. I’d read about presenters in various articles and seen them in one of 8th Light’s internal apps, but I never quite understood them. It’s amazing how much easier it is understand something when you have a guide along the way. Within a few minutes of working on it with Skim I was able to get a feel for how presenter’s work and why it makes sense to use them. Here’s a very over-simplified example of one:

In a traditional Rails controller you could have an action like this to set up variables for your views:

def show
    @user = current_user
    @course = current_user.courses.last
    render :show
end

Then in your views you might have some logic like this:

<% if @user.freshman? %>
    “Welcome to your first year”
<% elsif @user.senior %>
    “Congrats on your final year”
<% end %>

This class is offered by the <%= @course.department.name %> department.

However, by using the presenter pattern you could strip the logic out of your view, limit the amount of digging into an object a view needs to do, and also slim down your controller. What the presenter boils down to is an object that encapsulates what you actually need for your view. Here’s how it would look:

#in the controller
def show 
    @presenter = CoursePresenter.new(@user)
    render :show
end

#in the view
<%= @presenter.welcome_message %>

This class is offered by the <%= @presenter.course_department_name %>

Again, this is a very over-simplified example and wouldn’t necessarily call for creating an entirely new CoursePresenter class. However, if you found yourself setting a lot of variables in your controller action and/or using a lot of logic in your views hopefully it helps illustrate how you could use a presenter

January 14, 2013
Pairing Tour Day 5: Upgrading To The Asset Pipeline

I wrapped up last week by pairing with my mentor Mike on an upgrade to our 8th Light University app. It’s a straightforward Rails app that we needed to update to take care of the recently discovered Rails vulnerability. Mike also wanted to use it as an opportunity to make the jump up from Rails 3.0.10. That meant a leap to the asset pipeline and I wanted to document the steps we took in order to get everything working.

Update Rails and mySql

We have a pretty spartan Gemfile and use mySql2 so the only two things we needed to do to start were update the versions of these two gems:

gem 'rails', '~> 3.1.10'
gem ‘mysql2’, ‘0.3.11’

In the first run through of this upgrade we had some problems with mySql so I decided to lock it to version ‘0.3.11’. After this we did a bundle update.

’rake rails:update’

I’d never heard of rake rails:update before but I came across it in this post after hitting some initial troubles and decided to give it a shot. What it does is goes through and updates your necessary files, but prompts you along the way so that you know what will be overwritten. Below is my terminal output as an example, which also includes what files I decided to overwrite and which I didn’t.

Whenever it prompted me to overwrite a file I loaded it in MacVim first, then allowed it to override, then selected ‘load file’ from the OS X dialog, then toggled between ‘undo’ (u) and ‘redo’ (r) to make sure I wanted to apply the changes:

identical  config/boot.rb
exist  config
conflict  config/routes.rb
Overwrite ~/projects/university/config/routes.rb? (enter "h" for help) [Ynaqdh] n
        skip  config/routes.rb
    conflict  config/application.rb
Overwrite ~/projects/university/config/application.rb? (enter "h" for help) [Ynaqdh] Y
    force  config/application.rb
identical  config/environment.rb
    exist  config/environments
    conflict  config/environments/development.rb
Overwrite ~/projects/university/config/environments/development.rb? (enter "h" for help) [Ynaqdh] Y
    force  config/environments/development.rb
    conflict  config/environments/production.rb
Overwrite ~/projects/university/config/environments/production.rb? (enter "h" for help) [Ynaqdh] Y
    force  config/environments/production.rb
    conflict  config/environments/test.rb
Overwrite ~/projects/university/config/environments/test.rb? (enter "h" for help) [Ynaqdh] Y
    force  config/environments/test.rb
    exist  config/initializers
identical  config/initializers/backtrace_silencers.rb
identical  config/initializers/inflections.rb
identical  config/initializers/mime_types.rb
    conflict  config/initializers/secret_token.rb
Overwrite ~/projects/university/config/initializers/secret_token.rb? (enter "h" for help) [Ynaqdh] n
        skip  config/initializers/secret_token.rb
    conflict  config/initializers/session_store.rb
Overwrite ~/projects/university/config/initializers/session_store.rb? (enter "h" for help) [Ynaqdh] n
        skip  config/initializers/session_store.rb
    create  config/initializers/wrap_parameters.rb
    exist  config/locales
    conflict  config/locales/en.yml
Overwrite ~/projects/university/config/locales/en.yml? (enter "h" for help) [Ynaqdh] Y
    force  config/locales/en.yml
    exist  script
identical  script/rails

Moving the Assets & Creating Application files

Before the asset pipeline all of the images, stylesheets and javascripts were stored in the ‘public’ directory. Now all of those should be moved to app/assets/images, app/assets/javascripts’ and app/assets/stylesheets. These three simple commands should do the trick (depending on the structure of your directories):

mv public/images app/assets/
mv public/stylesheets app/assets/
mv public/javascripts app/assets/

I also needed to add an application.js and application.css file that required my other files. The application.js file looked like this (note the order of the files you are requiring!):

#app/assets/application.js
//= require jquery  
//= require jquery_ujs  
//= require_self  
//= require_tree .

and the application.css file looked like this (again, pay attention to order!):

#app/assets/application.css
/*
*= require reset
*= require_self
*= require_tree .
*/

Add the Asset Gems

Next, add this group to your Gemfile, followed by a bundle update command:

group :assets do  
  gem 'sass-rails', " ~> 3.1.0"  
  gem 'coffee-rails', " ~> 3.1.0"  
  gem 'uglifier', '1.0.4'  
end 

Changing the config files:

Update or add the following lines in their corresponding files:

#config/development.rb
config.action_view.debug_rjs = true

#config/production.rb
config.serve_static_assets = true

Update your views and CSS

You can fire up your server to see how things are coming along- but most likely you’ll have some broken images and javascript that doesn’t work. This is because prior to the asset pipeline it was common to use things like a standard img src="public/assets/gangnam-style.gif"tag— but now we use an image tag like . You’ll have to go in and change each of these image links manually.

We also need to update the headers of our ’layout.html.erb’ file to include our new application.js and application.css files. The old links probably looked something like:

<%= stylesheet_link_tag 'reset.css', 'jquery.css', '8thlightu.css' %>
<%= javascript_include_tag 'custom/application.js' %>

which can be replaced with:

<%= stylesheet_link_tag 'application.css’ %>
<%= javascript_include_tag 'application.js’ %>

Jasmine YML Update

At this point all of our RSpec and Cucumber tests were passing (and things looked good when we fired up our server) but none of our Jasmine specs passed. We realized that our spec/javascripts/support/jasmine.yml file still pointed to the old assets. In that file we were able to replace this entire block of lines:

src_files:
  - public/javascripts/prototype.js
  - public/javascripts/effects.js
  - public/javascripts/controls.js
  - public/javascripts/dragdrop.js
  - public/javascripts/application.js
  - public/javascripts/**/*.js

with these two lines:

src_files:
  - assets/application.js 

The End

If everything went according to plan then congrats, you’re done! Things should look great and all of your Specs, Features and Jasmine Tests pass… Of course, I realize that may not be the case and there might be a hiccup or two along the way. If anyone has experience with alternate upgrade paths, questions, or feedback I’d love to hear it.

January 11, 2013
Pairing Tour Day 3 & 4: Craftsman & Their Tools

The last two days I’ve been pairing with Brian Pratt on another client project. The client has an existing application and 8th Light is helping to build out an iPad optimized web app for their content. It’s built almost entirely in JavaScript and has a really impressive user experience. Although it’s only been a month since my last dive into JavaScript, it feels like a long time ago so it’s been a good review.

One lesson of working with all the crafstmen this week is to see how adeptly they use their toolset and how their small investments in learning more about them can result in bigger and bigger payoffs.

For example, when working with Eric in IntelliJ (which he hasn’t spent much time with) he would spend a few extra moments searching down a keyboard shortcut to avoid reaching for the mouse. That research interrupted his workflow the first few times he had to do it, but just a few minutes later he was instantly firing off commands. I’m a huge keyboard-shortcut fan, but I think too often I choose to do something the “long” way because I don’t want to interrupt my workflow.

When working with Brian he showed some serious git-, tmux-, and vim-Fu. Most of his moves were things I’d seen before, but his speed and aptitude when sailing through different git commands- branching, checkouts, bisects, etc…- was particularly impressive. Git is such a powerful tool that I always take a pause with any commands beyond the basics. Both Brian and Eric definitely showed me how valuable it is to invest more time into learning about the tools we use.

Brian did my first Vim macro with me yesterday too. Let’s say I have a bunch of text I want to format into an array. For example, I want this:

#987    #398    LabelA
#876    #234    LabelB
#765    #543    LabelC

To look like this:

[[#987, #398, LabelA], [#876, #234, LabelB],[#765, #543, LabelC]]

I can use a macro to format the first line and then use one keystroke to format the rest. Here’s how it’s done:

1) Move your cursor to the beginning of the first line, and then while still in select-mode hit "q"     to start recording mode.
2) Hit the key you'd like to assign the macro to. I'll use "2"
3) Do the Macro exactly like you want for the first line*
4) Next, type q to quit the recording.
5) Now, go to the next line you'd like to apply the macro to (if you're not already there)
6) Type @, then 2 (the key you assigned the Macro to)
8) The line should be formatted exactly like the first, and you can continue to type @, then 2 for all the other lines you'd like to apply the macro to.

*For the example line I would do something this:

- I (Enter Insert mode)
-  Type [, then type "
- Esc, e, a (Exit insert mode, go to end of word, append word)
- Type ", then type ,
- Esc, n, i (Exit insert mode, go to next word, enter insert mode)
- Type "
- Esc, e, a (Exit insert mode, go to end of word, append word)
- Type ", then type ,
- Esc, n, i (Exit insert mode, go to next word, enter insert mode)
- Type "
- Esc, e, a (Exit insert mode, go to end of word, append word)
- Type ", then type ]
- Esc, j, 0 (Exit insert mode, go to next line, go to beginning of line)

January 9, 2013
Pairing Tour Day 2: Eric Meyer

The second stop on my pairing tour was with Eric Meyer, who was 8th Light’s first official apprentice. Eric has been embedded with a client for at least the past year and it’s a pretty big company. Pairing with him was an opportunity to get a glimpse of a large code base and also witness how a company of that size operates.

The first thing that jumped out at me was the broad range of skill sets and positions of all the people that attend each meeting. Each person or team is responsible for a certain section of a product, but then it seems like each person reports to, works with, and maybe even manages more people. However, the important lesson that jumped out at me was the amount of trust that everyone has to have in the other members of the company. To this company’s credit, it seemed like the level of trust was very high and it was impressive to see how efficiently members of different teams and from different specialities could come together, communicate and move through a topic.

If the first day of my pairing tour was all about writing then the second day was definitely more about reading. Eric and I spent a good portion of the day working on tracking down some unexpected behavior that users had reported. It was great watching Eric quickly read through a large and complex app: he confidently navigated through the different classes and quickly parsed the necessary methods to track down what he was looking for. I know that this is a skill that simply takes time to develop- but it was a good reminder that I should find as many opportunities as I can to read through other people’s code.

To finish off the day Eric paired with me on making my HTTP Server pass the latest Cob Spec test that Will added in. It was great to do a pretty typical ping-pong pairing session where one of us wrote the test and the other person made it pass. The new Cob spec also lead us in to some refactoring that allowed me to work on yesterday’s lesson: deleting!

January 9, 2013
Pairing Tour Day 1: I Should Delete More

Nothing kicks off a pairing tour like spending the day with the CEO. Paul was first on my list and we spent the entire day writing and refactoring- but rather than working with code we were working with text. As the CEO Paul is constantly working-on and iterating-over ways to help the company, so I was able to work with him while he wrote some thoughts down and then see how he organized them. I used the word “refactoring” because Paul approaches his writing in what feels like a very TDD way.

He starts out by writing down sections and blocks of sentences of what he wants to say. This builds momentum and he doesn’t have to spend time thinking about form. Then he shifts that block of writing towards the bottom of the page (or screen) and takes a shot at rewriting those thoughts into new sentences— or if he’s happy with how he said something the first time then he’ll pull it to the top.

He rapidly moves through this process of rewriting and moving sentences around until he’s satisfied- but there’s one other step to his workflow that I need to be better at: he fearlessly deletes sentences and even entire sections. If he’s rewriting a sentence and doesn’t feel the words are clearly stating what he wants- he’ll delete it before spending too much time on it. If he rewrites a new concise sentence that get his point across- he’ll immediately delete all of his brainstorming text at the bottom of the page. If the delete was a mistake there’s always the undo-key, but otherwise he knows that his next run at the thought will probably be better anyway.

I’ve definitely been feeling like I need to delete a lot more code. When starting out with JavaScript and Java on the last two projects I was so nervous that I’d forget how I did something that I ended up leaving in code that in hindsight almost feels like a spike (I say almost because I did write tests first). Now when I go back and look at the code I wrote a couple of months ago I know that it would be trivial to rewrite most of the methods- especially if I already have a test in place.

The past few weeks the phrase that’s been bouncing around my head is Uncle Bob’s saying: “the only way to go fast is to go well”, but with the addendum ” …and fearlessly”. We can all go faster by going well and being confident that each refactoring, each revision, or even a complete rewrite will most likely be better than our previous attempt.

January 7, 2013
The Value of Blogging

I haven’t done much blogging the past few months and I miss it terribly. After posting almost daily for five months as a requirement of my apprenticeship, I got a pass to only post a couple times a week… which I let slide to once a week… and then slid to just twice a month. I kept wanting to write posts and even have a list of topics to tackle, but because I felt crunched for time I kept pushing blogging down the priority list. First there was a client project on deadline, then there was a series of apprenticeship tasks I needed to finish, then the holidays started… it was easy to just kept putting it off. I definitely learned a lot during the past few months, but there is a noticeable difference in how I feel about my learning when I blog about it compared to when I don’t— and there is enough value in that difference that I’m making it a priority again.

Dave Hoover and Ade Oshineye’s Apprenticeship Patterns book made a huge impression on me during my introduction to the world of software craftsmanship, and I’m going to use it to frame why blogging is valuable.

Hitting the Patterns

A quick look through the Pattern List of the book reveals that blogging hits at least eight patterns in one fell swoop:

  • Confront Your Ignorance: Writing about a topic for public consumption always makes me confront the gaps in my knowledge- and in an effort to at least sound like I know what I’m talking about I take action to fill in the gaps.

  • Create Feedback Loops: Although my blog audience is relatively small I still often get a tweet, email or comment from someone at the office that provides valuable feedback on something I wrote.

  • Dig Deeper: While confronting my ignorance I always end up researching a little bit more on something I’m going to write, even if it’s just reading another article or two.

  • Expose Your Ignorance: Nothing exposes my ignorance like putting it out to the internet.

  • Kindred Spirits: The aforementioned emails, tweets and comments from coworkers on a post always have a positive effect. They often result in either someone reaching out to me to better understand the topic I wrote about or offering to help me better understand it.

  • Record What You Learn: There are a few posts (especially the technical ones) that I consistently go back to for reference. It also helps to be able to just Google ‘site:mikeebert.tumblr.com whatever-i’m-looking-up’ when I know that I wrote about something I want to review.

  • Unleash Your Enthusiasm: Nothing shows passion like the faceless posting of random thoughts on the internet with excessive punctuation and run-on-sentences, right?!?!?

Reflection:

The pattern I left out of the list above is the one that has affected me most since I stopped posting, and also the one that I think is most important to maintaining a learning mindset: Reflect As You Work.

Although many of my posts end up being technical in nature, I’ve also written several posts where I muse about how or why I’m learning something. These posts tend to be very personal and I always feel a little weird about publishing them. However, the act of publishing both the personal and technical posts force me to think about an audience— which then makes me think very differently about the topics rattling around inside my head.

Blogging forces me to reflect and then provide some structure to those thoughts. It’s the structure that makes the thoughts much more tangible, and I think it’s this “tangibility” to my learning that I’ve missed during the months I did little-to-no blogging. Although my rate of learning has continued to increase and I can think about all of the things I’ve done the past few months, that knowledge feels much more scattered and less concrete than when I blogged about the experiences.

Just Write

Sometimes when I think about all of these reasons to blog… and an audience… and deadlines… it gets a bit overwhelming and becomes just one more reason to de-prioritize writing. But after my unintended experiment of the past few months, I’ve learned that the value of regularly posting far outweighs whatever the cost is.

December 16, 2012
Working With jQuery Tokeninput

During the project I was working on the past month we decided to incorporate jQuery Tokeninput as an autocomplete & token solution. We came across some big +’s and -’s that I wanted to share for anyone considering using it.

Pros:

  • Simple to set up. Michael worked on this with me and we had the basics up and running pretty quickly. We already had an endpoint that served up JSON for autocomplete suggestions, so then we just needed to include the Tokeninput JS and CSS files and add the following javascript:

    $(“#input-selector-to-bind-to”).tokenInput('api/endpoint_serving_json’, {
      queryParam: 'term',
      resultsLimit: 10
    })
    
  • Pretty good out of the box configurability. You can set options like the number of suggestions returned, the value you’d like to pass on submit, if you want suggestion text, and even if you want to format the returned result in special HTML (which is very handy for styling).

  • Pretty good documentation The project’s main page has a lot of good info and there’s also a solid demo page with a lot of additional details.
  • Some handy callbacks & add/remove methods. If you want to trigger something when a token item is added or removed then Tokeninput includes onAdd and onDelete methods (among others). For example, we used the onAdd callback to update a recommendation box based on the token they’d selected. You can also use the tokenInput(“add”, {your_item}) method to populate your input field. For example, if a user wanted to keep track of previous searches in order to refine an earlier search, you could use tokenInput to add in these previous terms.

Cons:

  • ”Hidden” Data Once you start adding items via tokenInput they can be pretty well abstracted away from you. Although the items have an tokenInput id and a name, those attributes aren’t reflected on the page’s source code and they aren’t easy to work with.
  • tokenInput brings its own DOM elements tokenInput muscles it’s own DOM elements into your code. Although you’re attaching the tokenInput action to a DOM element you create, tokenInput stores the items it adds in its own containers and attaches its own slightly-confusing class names. Our personal favorite: ‘token-input-input-token’
  • It’s a little too good We eventually figured out how to use underscore and some DOM tomfoolery to dig into tokenInput’s data stores and do all sorts of things like attach dynamic ratings to search tokens that users could update. It made for some really slick UI- however, this code could start to get ugly and fragile very quickly so we really had to be careful.

Verdict

jQuery tokenInput is a pretty easy and powerful tool and the next time I need an autocomplete/token solution I’ll look into using it again. However, I’ll also be pretty careful with it and be sure to get a lot of acceptance test coverage around it as we learned it can get hairy pretty quickly.

Liked posts on Tumblr: More liked posts »