Category Archives: Javascript

KnockOut 2.1.0, the SELECT Binding, and No Initial Value Displayed

0
Filed under Javascript, KnockOut, Web

Fair warning; this post doesn’t have a lot to do with the Feng Shui of VB, or does it…. <g>

I’ve been recently playing quite a lot with Javascript, and various frameworks and libraries that really turn the browser into a client development platform in its own right.

To me, that combination just rings truer than the use of server-side html-generating frameworks like ASP.net, etc. But that’s philosophy for another discussion.

In this case, I’m using JQuery, JQueryMobile, and Knockout to build a mobile capable app that can run on various devices via single source, and hopefully be deployed via PhoneGap, but still look relatively native on each device.

If you’re not already aware of these libraries/frameworks (it can be difficult to tell exactly where each of these fits in the grand spectrum of browser client side development):

  • JQuery : the granddaddy of client side browser libraries. Even Microsoft is supporting this one out of the box now. This thing really makes working with the DOM and client side development a joy.
  • JQueryMobile : A UI kit running on top of JQuery that renders almost native looking UI across a broad spectrum of mobile devices (think one source set running on everything from iPhones, to Kindles, to Android phones, to Win7 Phones).
  • KnockOut : a framework for doing client-side data binding between DOM elements (text boxes, select lists, spans, etc), and Javascript JSON objects.

I wanted to bind a SELECT list to the equivalent of  a .net ENUM in Javascript (which doesn’t technically have ENUMs, so I had to create a class to support something similar).

Here’s the KnockOut View Model:

var userProfileViewModel = {
    timeToTrack : ko.observable(SecondsEnum.secs15),
    secondsEnum : ko.observableArray(SecondsEnum.toArray())
}

The toArray function is just a convenience function to convert my ENUM class into a typical Javascript array that KnockOut can work with. Eventually my plan is to construct a KnockOut Custom Binding that would do all this automatically . But that’s for another post…

The HTML to actually view and bind to that model looks like this:

<span data-bind='text: timeToTrack'></span>
<select name="selTimeToTrack" id="selTimeToTrack" data-mini="true" data-bind="
        options: secondsEnum,
        optionsText: 'desc',
        optionsValue: 'value',
        value: timeToTrack">
</select>

Everything worked great, except for one nasty bit. When the displayed page first comes up, the select lists are empty. You can see the effect here.

image

Notice how the 15 that’s highlighted DOES populate properly (the value of the bound property is 15 in the view model), but the dropdown list value is empty.

Interestingly, if I click the dropdown, the resulting list does show the proper initial value (15 seconds):

image

After days of Google searching for answers, I finally got a few hours of free time and decided to just roll up my sleeves and start tracing through the KnockOut unminified debug version.

Eventually, I fell into this function (in KnockOut.2.1.0.js):

function ensureDropdownSelectionIsConsistentWithModelValue(element, modelValue, preferModelValue) {
    if (preferModelValue) {
        if (modelValue !== ko.selectExtensions.readValue(element))
            ko.selectExtensions.writeValue(element, modelValue);

    }

    // No matter which direction we're syncing in, we want the end result to be equality between dropdown value and model value.
    // If they aren't equal, either we prefer the dropdown value, or the model value couldn't be represented, so either way,
    // change the model value to match the dropdown.
    if (modelValue !== ko.selectExtensions.readValue(element))
        ko.utils.triggerEvent(element, "change");
};

Something didn’t quite look right about this.

If the first block of IF’s ends up true, the modelValue (the value of the property from view model) is going to be set as the initial value of the select DOM element, which is what we want.

BUT, if that happens, the next IF will ALWAYS be false (because the code just set the two value equal), so the “change” event will not be triggered in this case. The problem is, if it’s not triggered, the select DOM element won’t get updated to reflect that value that just got written.

My suspicion is that this was an attempt to circumvent having two lines of code to trigger then change element, but the logic just doesn’t seem to work.

So, I made a subtle change:

function ensureDropdownSelectionIsConsistentWithModelValue(element, modelValue, preferModelValue) {
    if (preferModelValue) {
        if (modelValue !== ko.selectExtensions.readValue(element))
            ko.selectExtensions.writeValue(element, modelValue);
            // DWH added this to correct problem with the change not firing on initial population
            ko.utils.triggerEvent(element, "change");

    } else {
        // No matter which direction we're syncing in, we want the end result to be equality between dropdown value and model value.
        // If they aren't equal, either we prefer the dropdown value, or the model value couldn't be represented, so either way,
        // change the model value to match the dropdown.
        if (modelValue !== ko.selectExtensions.readValue(element))
            ko.utils.triggerEvent(element, "change");
    }
};

Here, you can see the “change” event is triggered in both situations (whether the ModelValue is preferred or not).

Once I made the change, I run the page and now I get the much more reasonable:

image

Notice how each dropdown list is initially populated with the current value from the view model.

The Take Away

Javascript (and dynamic languages in general) are a huge departure from static languages like VB ( and all the .net languages). Whether that’s a good thing or not is debatable, but the fact is, there is a tremendous amount of flexibility available because of the dynamic nature of Javascript. And frameworks like JQuery and KnockOut really bring some fantastically clean functionality to client-side browser development.

But, as with most code, these frameworks aren’t bug free. I’m not saying that this is definitively a bug in the KnockOut code, yet, though. I’ve posted to the KnockOut forums and am awaiting a reply.

In the meantime, though, this is a quick and easy fix to a vexing problem.

So if you’ve run into similar problems with KnockOut, it might be worth investigating.

Using Arbitrary Fonts In a Web Page

0
Filed under Fonts, Javascript, Web

image I’ve written here about how to embed arbitrary fonts in a flash file. This approach works, but it has several downsides.

  1. You have to have Flash. It’s not necessarily cheap.
  2. You have to go through a pretty arduous process to embed the fonts.
  3. You end up with a swf file that can be quite large, especially if you have a lot of fonts you need to embed. This can have a very negative impact on your bandwidth and the user’s experience with your site.

I understand that SilverLight has a method for using embedded fonts as well, though I’ve found very little information on it.

But I did recently come across True Font Family.

It’s not a 100% solution, since it essentially replaces specifically styled text on your site with dynamic images of that text in the font of your choosing. But, it’s got some great benefits.

  • It’s cheap, as in 27$, no royaties
  • It’s easy. Just a simple Javascript include, and a little CSS markup.
  • It’s double plus easy. You just upload the fonts you need to use as TTF files to your webserver somewhere. No messing with conversions of any kind. And since the fonts you use can be locked up in a secure spot on your server, there’s no worries of font use violations that might come from allowing end users to actually download the fonts you need for your site.

Plus, they’ve got a newer version coming out sometime in the fall that’ll do all sorts of special effects on the text as it’s rendering it.

Depending on your needs, this might be a very viable alternative to Flash.