Knockout.js href Binding

I've been using this simple binding lately and I just thought I'd share. Sometimes I end up needing to construct URLs from viewmodel properties. Knockout has a built in binding that gets you there, attr.

With the built in binding, you have two options. First you can create a computed property on your viewmodel to do the concatenation and then bind the href attribute to that. The javascript looks something like this:

var viewmodel = {
    id:ko.observable('12345')
};
viewmodel.url = ko.computed(function(){
    return '/foo/'+this.id();
},viewmodel);

Then your binding will look like this:

<a data-bind="attr:{href:url}">Attr with computed</a>

It's not too bad on the binding side, but having to write that extra computed observable is tedious just to concatenate a couple of strings together. We can do better.

Your next option is to ditch the explicit computed observable and do the concatenation inside your binding. Knockout will create a computed on your behalf. That looks like this:

<a data-bind="attr:{href:'/foo/'+id()}">Attr with concat</a>

I like that we no longer need the extra computed, but that binding leaves a lot to be desired. There are a lot of things we can screw up in there. Let's fix this once and for all. First, let's look at the cleaned up binding.

<a data-bind="href:'/foo/:id'">Awesome</a>

That's more like it. Now, how do we make that happen?

ko.bindingHandlers.href = {
    update: function(element, valueAccessor, allBindings, viewModel, bindingContext) {
        var path = valueAccessor();
        var replaced = path.replace(/:([A-Za-z_]+)/g, function(_, token) {
            return ko.unwrap(viewModel[token]);
        });
        element.href = replaced;
    }
};

This binding takes advantage of overload of String.replace that allows you to pass a function to be evaluated when it comes time to resolve a replacement string. We then simply use that token and look up a property of the same name on our viewmodel to supply the replacement. Hopefully you will find it as useful as I have.

Setting up a Riak Development Cluster on Ubuntu 12.04

In order to explore and fully appreciate Riak, you're going to need to setup multiple nodes. Since not everyone has 3 extra boxes around, they've made it easy to setup the nodes on a single box. I'll walk you through the steps I took to setup a development Riak cluster on Ubuntu 12.04.

The first step is to get your dependencies installed:

sudo apt-get install build-essential libncurses5-dev openssl libssl-dev
sudo apt-get install erlang
sudo apt-get install git

Next, you'll need to grab the riak source:

git clone git://github.com/basho/riak.git && cd riak

Before we build our cluster, there are few things to change from the defaults. This will turn off authentication for the admin tool (I did say this was a development cluster ;)).

sed -i 's/{auth, userlist}/{auth, none}/g' ./rel/files/app.config

Next, let's turn on riak control and riak search:

sed -i 's/{enabled, false}/{enabled, true}/g' ./rel/files/app.config

Now we're ready to build a 3 node cluster from source:

make devrel DEVNODES=3 && cd dev

Next, start up all of the nodes and join them together:

find dev*/bin/riak -exec {} start \;
find dev[2-9]/bin/riak-admin -exec {} cluster join dev1@127.0.0.1 \;
dev1/bin/riak-admin cluster plan
dev1/bin/riak-admin cluster commit

And now you have a running 3 node cluster listening on a bunch of weird ports. Let's add haproxy in the mix to expose the cluster under standard (8098 for http and 8087 for protocol buffers) ports with roundrobin distribution. First, install haproxy:

sudo apt-get install haproxy

Next, create a configuration file for haproxy (I'll name mine dev.haproxy.conf) with the following contents:

#Mostly from OJ Reeves post: http://buffered.io/posts/webmachine-erlydtl-and-riak-part-2/
global
        maxconn 2048

defaults
        retries 3
        maxconn 1024
        timeout connect 3000

frontend riak_pb
        mode tcp
        bind *:8087
        default_backend riak_pb_cluster
        timeout client 1200000

backend riak_pb_cluster
        mode tcp
        balance roundrobin
        timeout server 1200000
        server riak1 127.0.0.1:10017 check
        server riak2 127.0.0.1:10027 check
        server riak3 127.0.0.1:10037 check

frontend riak_http
        bind *:8098
        mode http
        default_backend riak_http_cluster
        timeout client 1200000

backend riak_http_cluster
        mode http
        balance roundrobin
        timeout server 1200000
        option httpchk GET /ping
        server riak1 127.0.0.1:10018 check
        server riak2 127.0.0.1:10028 check
        server riak3 127.0.0.1:10038 check

Now run haproxy -f dev.haproxy.conf and you now have a cluster listening for connections. Fire up your web browser and point it at machine:8098/admin and you should see the web interface, Riak Control, displaying your cluster status. That's it! You're ready to start learning about Riak.

This is Happening Again

Less than 48 hours until my daughter is to be born, it just hit me. We're having another baby. I mean, I've known this has been coming. For some reason though, it just became real.

I've been covered up with projects at work. I've fixed up 3 rooms here at the house. I've been consumed with a construction project here too. Now it's all done and I'm here with nothing else to distract me. 9 months has withered away and we're about to have another human to keep alive.

I'm excited to meet my daughter. I'm relieved to see my wife not have to suffer through gestational diabetes. I'm nervous to see what adding another child to our family will be like. I'm scared.

Life is scary and awesome. I'm ready to stop being distracted and start focusing on the things that are important again. I have a feeling that baby Hannah will force me to slow down a bit. :)

Masked Input 1.3.1

A long overdue release of my Masked Input Plugin is available. This is a bugfix release that adresses some of the bigger issues out there:

  • jQuery 1.9 compatibility.
  • Fixed browser lockup when window loses focus.
  • Android issues.
  • No longer preventing event bubbling.
  • Making sure we call completed handler when pasting a value.
  • Fixed bug trying to set caret on hidden elements.
  • Fixed cursor positioning bug related to bounds check.

You can see everything in detail over at the 1.3.1 milestone on github.

I had planned to roll in more bugfixes, but jQuery 1.9 releasing forced my hand a bit. :) If you see any problems, please report them as a github issue. I also managed to get this published in the newly revamped jQuery plugins site. Thank you to everyone who reported issues and to those who submitted patches.

 

devLink 2012

I'm just winding down here from devLink 2012 and wanted to share my slides and take a moment to reflect. I was privileged to be given the opportunity to talk again this year on NoSQL. Unfortunately I think I reached a bit too far that late night when I pulled an abstract out of my rear for a yet to be written talk. Here, judge for yourself. This was the abstract I submitted:

Never has a technical buzzword produced such confusion as "NoSQL". Not all data stores are created equal. It's time to shine a light on the technology that claims to hold your big data, replicate it everywhere and be faster than its relational grandpa. This session will compare and contrast the popular NoSQL tools without subjecting you to fabricated benchmarks and meaingless jargon. It's time for a data store cage match!

It sounded good at the time, but it's lacking substance. What did I promise to deliver? A comparison without numbers and fancy words - okay, that's interesting I guess? The title implied there would be a winner and the tagline promised excitement, WWE style.

I feel like I delivered on comparing the technologies without numbers. I introduced some fancy words and concepts. Hopefully I explained them well enough. The video that the public will never see will tell the story there. In the end though, there was no real winner. Since I didn't show up dressed as a luchador, exciting was not a word you'd use to describe that talk.

I'm still new to this conference speaking thing and every experience, both good and bad, help me get better. I want to be great at this. I want to be able to deliver a talk that sticks in people's heads for weeks after the fact. I've learned my lesson and my next talk will be more focused - maybe a specific technology or pattern. No more of this I'm-going-to-show-you-the-meaning-of-life-in-an-hour type of thing. It's just not a good use of mine or the audience's time.

With all of that said, I'm glad to have that talk under my belt. It took me several months to compile all of that information and present it in a way that I felt was palatable in an hour format. NoSQL is a movement and there are a lot of options with more popping up every month. I felt like I had a firm grasp on the topic when I pitched the talk, but I learned so much more after having to research and build a few demos. In the end, that's knowledge I can take with me to build something awesome in the future. :)

My slides, notes and demos are up on github for your scrutiny. Thank you to devLink for having me. Thank you to those who attended both the talk and the preview talks - your feedback was invaluable. A big thank you to my friends and coworkers who continue to push me to be better at speaking, software, and life in general. It was great to see you all again. Now, let's all get some rest.

« Previous PageNext Page »