Hello, is it me you’re looking for?

May 6th, 2013 § Comments Off on Hello, is it me you’re looking for? § permalink

TL;DR: I consolidate all of my thoughts on Twitter.

Oh, you want more? You got it.

Here’s a list of things that are different:

  • Got a new job.
  • Stopped writing JavaScript
  • Started writing CoffeeScript
  • Stopped working on my Backbone library
  • Started working around Batman.js (and contributing to fix broken things)
  • Became the most knowledgeable among my friends and coworkers about testing in JavaScript and associated environments
  • Stopped working on front-end development
  • Started working on iOS development again
  • Became the most knowledgeable among my friends and coworkers about testing in iOS
  • Fired up a personal project and got neck-deep in Angular.js and more familiar with Node.

That’s really all there is to say of interest. If that’s not enough, get in touch with me on Twitter. I’m still doing freelance work and I’m sure I can do something very helpful for your team.

The dude abides

July 24th, 2012 § Comments Off on The dude abides § permalink

Man, when did forms get so complex? Oh, right, always.

Backbone.js is great because it lets me structure my app how I see best and gives me the tools to do so efficiently. Well, most of the tools. It’s not very good at dealing with handling multiple forms submitting over AJAX and orchestrating those submissions under a parent view. Nor should it be. However, I needed that functionality so I wrote some code.

I give you Abide

Abide is an extension of a Backbone.View that has hooks for checking model validation, dealing with multiple jQuery.Deferred promises (be they AJAX or not) and orchestrating the whole submission process in one place.

Just have your view extend Abide instead of Backbone.View…

var parentView,
    firstChild,
    secondChild,
    redhadedStepChild;

//Create up your parent view and extend Abide instead of Backbone.View
parentView = Backbone.Abide.extend({
    promises: function() {
        // Gather child view save promises
    }
}
});

//Create child views as well. These can be regular views or more Abide parents.
firstChild = Backbone.View.extend({ /* ... */ });
secondChild = Backbone.View.extend({ /* ... */ });
redhadedStepChild = Backbone.View.extend({ /* ... */ });

//Then instantiate the parent, passing in which views it should parent
new parentView({ views: [firstChild, secondChild, redhadedStepChild] });

…and override the promises method to return your view’s promises…

var sweetAbideView = Backbone.Abide.extend({
    promises: function() {
        var promises = [],
            self = this;

        _.each(self.views, function(view) {
            promises.push(view.model.save());
        });

        return promises;
    }
});

…and you’re good to go!

There’s more information on github. Fork and submit pull requests!

How I used backbone.js in Lifesquare to make for a better signup progress

June 21st, 2012 § Comments Off on How I used backbone.js in Lifesquare to make for a better signup progress § permalink

This year has been interesting. When not working the day job or finding time to brew I’ve been working hard on getting Lifesquare‘s consumer website off the ground. Lifesquare centers around QR codes that people attach to things that are always with them (e.g. bike helmet, wallet, iPhone, car insurance) and in the event of an accident an EMS team can use the Lifesquare app (available only to EMS professionals) to scan your QR code to find out any information they might need to know in an emergency. This is great because every second counts in a first responder situation and if you’re unable to communicate to the EMS team they might not know to avoid certain medications that could cause serious allergic reaction. It’s a fantastic idea and their product definitely adds to the betterment of humanity – two things that I pretty much require when working for someone.

All of the mobile app and server stuff was pretty much taken care of when I was brought on board; what was needed was a consumer side where people could sign up, create patient accounts and enter information about those patients. Sounds like something that has been done before but the team at Lifesquare threw in some fun twists that helps them stand out from generic, boring data entry workflows.

Level up backbone.js

I was given pretty much free reign on the front-end code so I based my work on backbone.js. The absolute best part of using backbone is that you don’t have to subscribe to any one way of doing anything. The tools are given to you to assemble an application in whatever way makes most sense for you. There are some basic things I like to do when starting any backbone-based app to augment the framework and create a bit cleaner architecture.

Organize further

Backbone provides structure but not much in the way of namespacing. A little bit of memoization takes care of that, however. I use a memoized base object that automatically adds a Views object but nothing else. I’ve had projects that create multiple types of memoized objects from full backbone views/models/collection groups to plain object literals. I find the Views addition takes care of what’s needed for Lifesquare.

var module = function () {
	var modules = {};

// Create a new module reference scaffold or load an existing module.
	return function (name) {
		if (modules[name]) {
			return modules[name];
		}
		return modules[name] = { Views: {} };
	};
}();

var Home = module('home');
Home.Views.SplashImages = Backbone.View.extend({ ... });

No matter where you are in the app’s code you simply call module(‘featureNameGroup’) and you get the fresh object or a reference to the one being used by everyone else. Especially handy when passing modules in to immediately invoked function expressions.

(function(Home) {
	Home.Views.coolNewView = Backbone.View.extend({
		...
		initialize: function() { ... }
		...
	});
}(module('home'));

Add magic to getters/setters

While we all wait for ES6/Harmony and the getters and setters we deserve there’s Backbone.Mutators to do the heavy lifting for you. It gives you hooks for existing or arbitrary model values that can run transformations, mutations or whatever else you like on the get or set of any value.

My favorite use in Lifesquare was accepting a free text date field value, analyzing the string and finding the true date, creating a date mask to match the user input, saving that mask to a field and saving the full date in another field in the database and still retaining the user format in the field. This happens every time a date is entered into a field in Lifesquare. The storage of full date as YYYY-MM-DD HH:II:SS allows for better reporting and sorting on the admin side while the saved user mask allows us to display the date just as entered. This took some work to get right but it’s still not bug free. Free text dates are not a solved problem yet in JavaScript, despite moment.js and date.js.

A simple example is format conversion. Lifesquare is currently targeted toward American users but we store everything in metric so I needed to accept weight in pounds but convert to kilograms.

(function (Patient) {
	"use strict";

	Patient.Model = Backbone.Model.extend({
		mutators: {
			imperialWeight: {
				get: function() {
					var pounds = Math.round(this.weight * 2.20462262)
					return pounds > 0 ? pounds : undefined;
				},

				set: function(key, value, options, set) {
					var matches = value.match(/([0-9\.]+)/);
					if(matches !== null) {
						var pounds = value,
							kilos = pounds * .45359237;

						this.set('weight', kilos, options);
					} else {
						this.set('weight', '', options);
					}
				}
			},
		...
	});
}(module('patient'));

Speaking of matching strings…

With all the input happening it’s inevitable that some validation was required. Nobody likes doing front end validation. Thankfully there’s backbone.validation to make things easier. It works with your model structure to provide hooks for default rules, custom regex tests and even custom validation functions. I use all three of those features extensively and it has been great.

What hasn’t been great is the validation execution path. Maybe I just don’t grok the intended workflow but it’s less than smooth in practice. What I ended up doing was the moment a view accepts a model the .validation object is duplicated as validationRules and the validation object is reset to an empty object literal. Then, as each field is blurred/selected the validation rule for that field is applied to the validation object (from the cloned validationRules) and that’s where the model-wide validation is run. Clunky, for sure, but it works pretty well in practice. Binding the validation rules to the fields, though, is a bummer. I ended up using data- attributes and name attributes. If anyone has integration tips I’m all ears.

Stick to the defaults

When development initially began the server interfaces would not accept requests if data had values outside of what was expected in the model. Given that the Backbone.Mutators were adding those fields to the model during JSON serialization (something for which I am eternally grateful) there were issues. Although the server rules eventually relaxed and just threw away the unnecessary fields I had to write a stripper in the interim. Pretty simple stuff but maybe someone will find it useful. Just plop this into your custom Backbone.Model extension or in any single model as it’s needed and call before/after sync().

//Removes values that shouldn't be sent back during a sync
evictIllegals: function() {
	var self = this,
		allowed = _.keys(this.defaults);
	_.each(self.attributes, function(value, key) {
		if(!!~allowed.indexOf(key) === false) {
			delete self.attributes[key];
		}
	});
}

Wait for the big show

Okay, so now you have some great building blocks. Let’s write some data entry!

Wait. There are multiple groups of data on each page that need to go to different services and all must finish before you can consider the page “submtted”? No problem.

Enter Backbone.Abide

Abide is a small addition to backbone that I wrote during development of Lifesquare. What this dude does is orchestrates the submission of multiple AJAX requests, monitors their completion status and when everything is done will throw an event to anyone who cares to listen. He also will run validation on any models submitted, disable submit buttons and update their text with submitting/finishing/done status messages.

Right now there are hooks to warn the user if leaving a page where values have been modified and monitor the session timeout to throw “hey you’re about to time out and you haven’t submitted anything” events to subscribers but those will be refactored out in future revisions.

Just extend Abide when creating a view and subscribe to the events and you should be good to go.

(function(Home) {
	Home.Views.AwesomeForm = Backbone.Abide.extend({

		initialize: function(options) {
			_.bindAll(this);

			//I like to use "self" because it compresses well
			var self = this;

			self.on('validating', function() {
				//Clear out previous validation warnings
			}).on('validationFailed', function(e) {
				//Tell the user there has been something wrong and identify where
			}).on('done', function(e) {
				//All AJAX done. Navigate the page somehow (pushState, document.location.href, change views, etc.)
			}).on('fail', function(jqXHR, textStatus, errorThrown) {
				//AJAX submission has failed somehow. Show error.
			}).on('sessionExpired', self.renewSession).on('sessionTimeoutWarning', self.warnTimeout);

			$(window).on('beforeunload', function(e) {
				if(self._dirty === true) {
					//Abide provides the _dirty flag if the data has been manipulated by the user. Warn about mods here
				}
			});
		}
}(app.module('home'));

Who is this, really?

One of my favorite features to work on was the image uploading. Users can drop an image on the page (or, if you’re old school, pick one from the file picker) and crop the selection to the desired area. I did some really fun work on the cropper, making it intuitive and allowing re-edits. A picture is work a thousand words, right?

Of course it’s recommended you use an actual picture of your face so EMS professionals can correctly identify you. Unless you’re Worf. Then you use this picture.

The kitchen sink and more

I haven’t even gotten to occurance.js, the natural date parser helper I wrote to accompany moment.js, the autocomplete work with jQuery UI, how to deal with deeply nested backbone views sharing collections and more. All in good time.

What I missed

You can’t get everything right in an app and what I did miss this time around was using an event aggregator, like postal.js. This would have cleaned up a lot of the weird events I push and bubble through backbone and let me decouple things a bit better. In the future I’d like to spend more time getting Postal in but it works for now and like any startup it’s important to ship quickly and refactor on the go.

For now head on over to Lifesquare and check it out. Heck, you should sign up if you live in Marin County, CA. It really is a great idea that could save your life one day.

Calculating Levenshtein distance for fun and profit

April 16th, 2012 § Comments Off on Calculating Levenshtein distance for fun and profit § permalink

JavaScript has some pretty weak tools for strings. What method would you use to compare simliar-but-different strings? Say, for example, you have a signup form and when someone is typing in their email address you want to be helpful and check to see if they may have typed “gmial.com” instead of “gmail.com” or “em.com” instead of “me.com”. I give you the Levenshtein distance!

The Levenshtein distance is an oft-used algorithm for determining the similarity of two strings, measured in the number of changes you’d have to make to one string to make it into the other. So strings a distance of 5 would require five letter changes to be the same, a distance of 7 would need seven edits and so on.

For reference, I have used Carlos Rodrigues’ implementation of the Levenshtein distance in previous projects with great success. Yes, it is attached to the String prototype. No, I don’t have a problem with that, nor should you. Arguments about prototype purity will be saved for another day.

Levenshtein, how does it work?

In practice finding the distance between two strings is easy. Just do this:

var barDiff = 'bar'.levenshtein('baz');
console.log('difference: ' + barDiff);
//Outputs: "difference: 1"
var jsDiff = 'javascript'.levenshtein('JavaScript');
console.log('difference: ' + jsDiff);
//Outputs: "difference: 2"

Did you see that? Yes, Levenshtein is a case-sensitive comparison, just like the rest of JavaScript. Keep that in mind and sanitize/mutate your comparisons accordingly.

That’s it! Take this information and go write something clever and useful for your users. Also, keep an eye on my GitHub account for a Backbone extension that will automatically suggest proper email provider spellings for you users.

Way more action, much less to read!

April 16th, 2012 § Comments Off on Way more action, much less to read! § permalink

Blog posts are such a huge investment for me.

If you want to see the day-to-day stuff I’m working on, come find me on my Twitter.

Side note: If you think something basic like natural date parsing in JavaScript is a) simple and b) not yet solved you are wrong on both counts.

Don’t tell me what to focus on, I’ll tell you!

October 27th, 2011 § Comments Off on Don’t tell me what to focus on, I’ll tell you! § permalink

After a frustrating interaction with a form I whipped up a quick jQuery plugin for developers who don’t want to think about form field focus.

I present to you…

Polite Focus!

It’s a simple idea – use document.activeElement to determine if an existing field has focus. If not, give your field focus. Otherwise, leave the focus where it is, where someone else (user or previous programmer) decided it should be.

That’s it.

Go forth and use wisely

I’ve created a repo on GitHub so you kids can branch and comment as much as you like.

Go clone the plugin on GitHub. Now.

Using document fragment when rendering a backbone view

October 27th, 2011 § 1 comment § permalink

Backbone.js is pretty fun to use. Right out of the box it makes app development quick and organized. Fully grokking how to adapt to using view controllers is a bit of a change and the event system is happily powerful, yet blending it with jQuery events doesn’t seem immediately obvious. All the same it does a great job of giving great tools for organization and structure while staying out of your way.

One drawback to using a library that does magic is that if you’re not careful you can miss some important details. In this case I’m talking about injecting your views into the DOM. Blindly following the create view/render into element pattern as described in the documentation is usually fine. However, if you are using a view to render a list of children the $(this.el).append(view.render().el) quickly becomes costly.

For my needs I wanted to add an arbitrarily-long list of elements to an ordered list. Instead of blindly looping over models, creating views and shoving them into the list one at a time I decided to add all rendered views into a document fragment in memory and then append that fragment on to my list. Clean code for rendering, only one DOM adjustment for speed.

Example Code!

var containerView = Backbone.View.extend({
//... snip
	render: function() {
		var template = _.template($('#regular_ol_template').html()),
			self = this;

		$(self.el).html(template(self.model.toJSON()));

		self.list = $('.list', self.el);

		var frag = document.createDocumentFragment();
		_.each(self.model.things.models, function(thing) {
			frag.appendChild(self.createThing.call(this, question).render().el);
		});
		self.list.append(frag);

		return self;
	},

	createThing: function(thing) {
		return new ThingView({model:thing});
	}
//... snip
});

But why make a separate function?

What you’re not seeing is another method named addThing which uses createThing and does more work – to my model, spinning up other views, etcetera. It’s also good not to bind the creation of elements solely into your render method. You want to be able to add more things to your list without fully re-rendering it. That way, should someone else decide to use my model or view in the app, elements in the list can be adjusted without the performance overhead of creating the whole list again.

Result

There you have it! You have now rendered your Backbone.js views into memory and appended them to the DOM in one fell swoop. Instead of abusing the DOM in your loop cycle you’ve speedily created them in memory. Isn’t that much kinder to the DOM? The answer is yes, yes it is.

What do you think? How would you change this? Comments!

Your blog post is cool and imma let you finish but first…

October 20th, 2011 § Comments Off on Your blog post is cool and imma let you finish but first… § permalink

Having great code but not being able to share it is rough.

For many years I’ve either been working on boring enterprise integration stuff or amazing tech that I’m not allowed to yet share with the world. That makes for a fairly silent blog and twitter feed. Unless, of course, you want me to talk about the sandwich I had for lunch and omigod how annoying are drivers in [your local commute path]?

But things have changed! I’ve been working on some awesome code, projects and platforms lately and I have some neat code that I think should be shared with the programming community.

Thankfully I’m seeing some progress here from management towards openness and embracing the community. That means not only do I get to talk about some of the crazy stuff I’ve done here but also start open sourcing our code!

Bam. It’s going to be cool. But hold on to your knickers cause enterprises are slow moving beasts. Patience, kids…

Emulating the native shadow on UIMenuController

August 22nd, 2011 § Comments Off on Emulating the native shadow on UIMenuController § permalink

I’m an iOS developer! I still love and will continue doing front-end dev for web but I’m adding another feather to my cap in the way of working on some pretty cool iOS apps. One app I’ve worked on is Constellation, an eBook reader developed for Ashford Education. It’s pretty cool.

One of the things we do is emulate the UIMenuController with our own more powerful view controller. And one of the neat things about a UIMenuController is that you get a slick, subtle drop shadow wherever it is placed. Being the guy I am I spent some time to analyze the drop shadow in Photoshop and do my best to emulate it. Here’s what I came up with. Have a better solution? Tell me in the comments!

- (void) viewDidLoad
{
	[super viewDidLoad];
	
	self.view.layer.shadowColor = [[UIColor blackColor] CGColor];
	self.view.layer.shadowOffset = CGSizeMake(0, 2.0f);
	self.view.layer.shadowOpacity = .55f;
	self.view.layer.shadowRadius = 2.0f;
	self.view.layer.shouldRasterize = YES; 
}

Using CSS transforms to mimic Safari’s find word selection

May 26th, 2011 § Comments Off on Using CSS transforms to mimic Safari’s find word selection § permalink

Here’s a quick one for you kids. I’ve just started playing with CSS3 and I needed something simple but useful to implement. Say what you will about Safari as a browser but I think its find feature has the best UI for showing matching results on the page and what item is currently selected. Wait, you don’t use Safari? Okay, check out the picture below.

See what I’m saying? Fade out what isn’t important, lighten all matches, put some special pizazz on the current item. As an added bonus each time you switch the current item it “pops” a bit to help pull your eye to where the next item is. Pretty slick.

I set out not to duplicate the styles but to get a feel for CSS3 animation and transitions. With that in mind the animation tweens and colors aren’t exact but they’ll work for the project I have in mind. If you have improvements go ahead and share them in the comments.

[Ninja edit] I forgot to mention that in order for CSS transformations to be hardware accelerated by devices that do so you have to include the “translate3d” property. If you don’t need to translate, use the meaningless zeroed out setting like I did below.

[Ninja edit 2} Also, I didn’t bother putting in all the different vendor prefixes. If you’re interested in this code your Google-fu will be strong enough to look up the different vendor settings and adjust accordingly.

@-webkit-keyframes pulseFocusedOverlay {
	0%, 100% {
		-webkit-transform: scale(1) translate3d(0px, 0px, 0px);;
	}
	15% {
		-webkit-transform: scale(1.35) translate3d(0px, 0px, 0px);;
	}
}

.searchMatch {
	display: inline-block;
	padding: 0 4px;
	margin: 0 -3px;
	-webkit-box-shadow: 0 1px 5px #333;
	box-shadow: 0 1px 5px #333;
	color: #222;
	background-image: -webkit-gradient(linear, left bottom, left top, color-stop(.5, rgb(222, 222, 222)), color-stop(1, rgb(255, 255, 255)));
}

.searchMatch_selected {
	display: inline-block;
	padding: 0 4px;
	border-radius: 5px;
	border: 1px solid #EFDB13;
	margin: -1px -4px;
	-webkit-box-shadow: 0 1px 3px #333;
	box-shadow: 0 1px 5px #333;
	color: #000;
	-webkit-animation: pulseFocusedOverlay 185ms ease-in-out 0;
	background-image: -webkit-gradient(linear, left bottom,left top,color-stop(.5, rgb(238, 207, 0)),color-stop(1, rgb(242, 237, 19)));
}