Ember and the Designer

For the last 7 years I’ve worked with User Experience designers and I have a huge respect for their craft. I’m also loving how designers are embracing HTML5 and CSS3, and how it is giving them ownership over the experience.

It’s affording deep collaboration between the designer and developer, and asserting the need for frameworks and tools to play to our respective crafts, and to be sensitive to the designer-developer-workflow.

With this in mind I struggled for a while with Ember. I wanted a clean separation between my HTML and my code. Ideally I didn’t want to change the HTML, and I really didn’t want to pollute it with proprietary code belonging to Ember (or any other framework).

I was really disappointed as the only solution offered up was to use Ember.TextField.

From:

<input type="text" id="firstName" placeholder="First" autofocus required>

To:

{{view Ember.TextField valueBinding="firstName"}}

It breaks the clean separation between designer and developer. It makes my code difficult to maintain. I loose the expressiveness of HTML5. Why?

I get the binding goodness it may bring, but…

At this point I did consider walking away from Ember, but I did persevere. In the end I opted to use plain old JQuery in my code. I’m intrigued to see how this plays out as I grow my codebase, but in the meantime it keeps my HTML as pure as it can be.

HTML:

<script type="text/x-handlebars" data-template-name="registration">
   <form autocomplete="on" id="registration" {{action createUser on="submit"}}>
      <label>Name</label>
      <input type="text" id="firstName" placeholder="First" autofocus required>
      <input type="text" id="lastName" placeholder="Last" required>
           
      <label>Email</label>
      <input type="email" id="primaryEmailAddress" placeholder="hello@mydomain.com" autocomplete="on" required><br>
           
      <label>Password <em>Minimum 6 characters</em></label>
      <input type="password" id="password" autocomplete="off" required pattern=".{6,}" title="Passwords must have a minimum of 6 characters."><br>
           
      <input type="submit" value="Create account" onmouseup="form.className='submitted';" />
   </form>
</script>

JavaScript:

App.UsersController = Ember.ObjectController.extend({
    
    createUser : function () {
        'use strict';
        
        var user = App.User.createRecord({
            firstName : $("#firstName").val(),
            lastName : $("#lastName").val(),
            primaryEmailAddress : $("#primaryEmailAddress").val(),
            password : $("#password").val()
        });
    }
});
Advertisements

Google Maps – “hello world” with RequireJS and jQuery

I’ve been looking at the Google Maps “hello world” tutorial in conjunction with HTML5 Boilerplate, RequireJS, and jQuery.

When you download and extract the boilerplate it already gives you jQuery. Given I am using RequireJS with Node (see node-reference-app) I also wanted to use on the client-side to modularize my code. It’s no big deal in itself, but I ran in to a few issues when I dropped in the Google Maps API. A search on Google soon revealed it was due to the async nature that the Google Maps API (and other Google APIs) loads its own code.

There are a number of posted solutions. The one I liked was the async plugin for RequireJS from Miller Medeiros.

Jump over to GitHub to look at the complete solution.

The basic map code is exactly as it appears in the Google Maps tutorial, however here’s a breakdown of how it fits in to HTML5 Boilerplate and RequireJS:

  • index.html – has the div for map_canvas, there is also a script tag with a data-main attribute that tells RequireJS the script to run, main.js, when the document is ready (read more here)
  • style.css – specifies the width and height for map_canvas
  • main.js – this is where the real work begins, we grab map_canvas from the DOM with the help of jQuery and call addMapToCanvas() on the google module
  • google.js – this is the heart of the solution to the async problem, if you look at the top you will see the URL is prefixed with async!, which causes the async plugin to be called

Note: to use the example make sure to obtain your own api key and add it to the URL in google.js where it says YOUR_KEY.