by Andreas

Remove action icons from text fields in Internet Explorer 10

Internet Explorer 10 introduced a new feature for input fields: the action icon. These certainly are user friendly, but introduces a problem with KnockoutJS which depends on changes being made to a field by key stroke (read more about forcing binding re-evaluation in one of my other blog posts). If you have a text field where you enter a value to filter the contents of a list, deleting the contents using the action icon will not trigger an update to the view model.

Here’s a text field displayed in Internet Explorer 10:

image

As you can see, the action icon is visible and will clear the contents of the text field when clicked. However, unless you add a custom binding your KnockoutJS view model will not re-evaluate its bindings and trigger an update of your filtered list. That will only happen if you start entering a new value in the text field, or change focus to a different control.

The quickest fix is to remove the action icon through CSS:

::-ms-clear {
      display: none;
}

Refresh your page and notice that the icon is now gone:

image

 

Note: this does not work when you’re running IE10 in IE7, IE8 or IE9 mode.

by Andreas

JQuery / KnockoutJS – define default button within a DIV

We’ve previously covered several aspects of using Default buttons in ASP.NET and Silverlight (the latter is in Norwegian, but should be semi-readable through an automagically translated version – sponsored by Google Translate).

This time I thought I’d show you how I did this without the need of server side controls. Why? First of all, adding server side controls adds unnecessary overhead by increasing the view state. Second, in my complex client side user interface I’ve stuck to clean HTML, javascript / jQuery and KnockoutJS. I didn’t want to clog it up, and since the solution was as simple as it turned out to be I am glad I stuck to my guns.

I had a look at what ASP.NET generates when a default button is defined for a Panel control. As you may or may not know, the server side Panel control is rendered as a DIV when the page is returned to the client browser. And as expected, Javascript is used to invoke the defined default button click event so I thought I’d just steal this javascript function and call it myself from within my pure HTML DIV element. Not surprisingly, this worked and why shouldn’t it? I just did the exact same thing as the .NET framework does, and there’s not much voodoo or black magic in that.

So, I wanted to invoke the click event for a “Save Changes” button displayed within a Fancybox dialog, simply by clicking ENTER. First, I added the javascript function that I stole from the .NET server control rendering engine (I am pretty sure that’s not what it’s called):

function WebForm_FireDefaultButton(event, target) {
    if (event.keyCode == 13) {
        // this variable has to be added
        var __nonMSDOMBrowser =
            (window.navigator.appName.toLowerCase().indexOf('explorer') == -1);

        var src = event.srcElement || event.target;
        if (!src || (src.tagName.toLowerCase() != "textarea")) {
            var defaultButton;
            if (__nonMSDOMBrowser) {
                defaultButton = document.getElementById(target);
            }
            else {
                defaultButton = document.all[target];
            }
            if (defaultButton && typeof (defaultButton.click) != "undefined") {
                defaultButton.click();
                event.cancelBubble = true;
                if (event.stopPropagation) event.stopPropagation();
                return false;
            }
        }
    }
    return true;
}

Note that I had to add the __nonMSDOMBrowser variable. This is usually added as a global variable on the page, but I saw no reason to do so because none of my other functions care about it.

Then, within my dialog box DIV element I make sure the onkeypress calls the new function with the ID of the button as a parameter:

<div id="addContactDialogBody" class="modal-body" onkeypress="javascript:return WebForm_FireDefaultButton(event, 'btnSaveContact')">
      <!-- This is my user input form, containing a couple of input text fields -->
</div>
<div id="addContactDialogFooter" class="modal-footer">
    <!-- dont be confused, the data-bind attribute is KnockoutJS related and has nothing to do with this example -->
    <input id="btnSaveContact" type="button" value="Save" data-bind="click: addNewContact, visible: true" />
    <input id="btnCancelContact" type="button" value="Cancel" onclick="javascript: $.fancybox.close();" />
</div>

 

When the focus is on an element within the first DIV (removed for clarty in the example code), pressing the enter Key will invoke the click event (or in my case, a KnockoutJS click binding) for the button with id btnSaveContact.

by Andreas

KnockoutJS – how to force binding refresh / re-evaluation

Observable bindings in KnockoutJS get re-evaluated when the focus is changed in a form, for instance when you click a button or use TAB to move from one input field to the next. When KnockoutJS is used in combination with an ASP.NET panel control where a DefaultButton is defined, re-evaluation of observable bindings is not performed when the user clicks ENTER to trigger the button click event. As a result of this, a value entered in an input field that is bound to the view model will not be registered if the user doesn’t navigate (move focus) away from the field first. 

A work-around for this is to use jQuery (or pure javascript) and programmatically set the focus to a different control, for instance the button itself when the event is fired.

self.addNewTimeRegEntry = function () {
    // set focus to button control to force re-evaluation
    $("#<%= btnAddRegEntry.ClientID %>").focus();

    ... // continue as normal

The button click event is bound to the addNewTimeRegEntry function above (through the KnockoutJS framework), and by moving the focus all variables will be refreshed before further processing is done.

by Andreas

Converting JSON date string to javascript date object

JSON dates come in a format that isn’t directly convertable to Javascript date objects (e.g. /Date(1349301600000+0200)/ ). This can cause a bit of headache, but there is a very simple way to convert this to a native date object.

After stripping off the initial “/Date” part using substr, parseInt will return only the integers and ignore the trailing “/”. The result is an integer value that can be used in the native javascript Date constructor.

This is what goes on under the hood:

1. Original JSON date

/Date(1349301600000+0200)/

 

2. After substr(6)

1349301600000+0200)/

 

3. After parseInt()

1349301600000

 

Finally I am using DatePicker from the jQuery UI library to format the date to a custom JSON date:

// parse JSON formatted date to javascript date object
var date = new Date(parseInt(jsonDate.substr(6)));

// format display date (e.g. 04/10/2012)
var displayDate = $.datepicker.formatDate("mm/dd/yy", date);

 

On the server side I recommend using the Json.NET framework by James Newton-King (available as a NuGet). It contains several settings for handling dates depending on what you’re running client side. If you’re using KnockoutJS for instance, the ko.toJSON method will return your date object in UTC format (which means the date might suddenly be a day off, with an offset set to +2 hours my current timezone).

My quick-fix using DateTime.ToLocalTime() will work, but I am sure there is a more elegant way of getting your local time directly in the Json deserialization process:

// parse JSON
var timeRec = JsonConvert.DeserializeObject<JSONTimeRecord>(jsonString, new JsonSerializerSettings { NullValueHandling = NullValueHandling.Ignore });
// convert date to local time
updatedRecord.Date = timeRec.Date.ToLocalTime();

 

At least that works fine – for now..

by Andreas

KnockoutJS debugging

One of the biggest challenges with KnockoutJS is debugging (to get started with this framework, have a look at an earlier blogpost). Finding out why your bindings don’t work or if your data have been populated can’t be done through normal javascript debugging. It would therefore be very helpful to see all your runtime values at least, and I found a great way to do this on StackOverflow in a reply from this fella. If you are running KnockoutJS 2.0 or earlier, replace or add the following code within the scope of your binding or variable:

<pre data-bind="text: JSON.stringify(ko.toJS($data), null, 2)"></pre>

Or, if you are running KnockoutJS v.2.1 and onwards use this one:

<pre data-bind="text: ko.toJSON($data, null, 2)"></pre>

 

This will give you a nice JSON formatted dump showing all your variables and their current value:

{
   "userId":"DEGREE\andreas",
   "timeRecords":[
      {
         "Id":1234,
         "Date":"/Date(1348783200000+0200)/",
         "CompanyId":348,
         "CompanyName":"Degree Consulting Group",
         "InternalNotes":""
      }
   ],
   "currentRecord":{

   }
}
by Andreas

Microsoft JScript error: jQuery.tmpl is too old

If you ever encounter the following error message when using string-based templates (or a component that uses it, like simpleGrid) for KnockoutJS:

Microsoft JScript runtime error: Your version of jQuery.tmpl is too old. Please upgrade to jQuery.tmpl 1.0.0pre or later.

you’d expect to just download the latest jQuery.tmpl plugin and get on with your life. This is not the case however, because from KnockoutJS version 2.0.0 jquery.templ are no longer supported. You’ve got two options:

1. Avoid using string-based templates (use native control flow bindings instead)

2. Download this version of jquery.tmpl: jquery-tmpl 1.0.0pre from github. And make sure you add the script reference before the knockout library:

<script src="../Scripts/jquery-ui-1.8.23.js"></script>
<script src="../Scripts/jquery.tmpl.js"></script>
<script src="../Scripts/knockout-2.1.0.js"></script>
<script src="../Scripts/knockout.simpleGrid.js"></script>
by Andreas

KnockoutJS – how to get started

imageKnockoutJS is a Javascript framework implementing the Model-View-ViewModel (MVVM) pattern. It’s purpose is to provide a way for developers “to create rich, responsive display and editor user interfaces with a clean underlying data model.” (Wikipedia). This is achieved by offering declarative bindings, dependency tracking and an automatic refresh of the UI upon changes to the data model.

Recently we have been using KnockoutJS in a fairly large web based document management system. We were replacing an existing desktop application and it was important to keep the system responsive and “non-web like”. We achieved this through substantial use of javascript based frameworks like jQuery and KnockoutJS. This blog post will help you get started with the setup and a very basic example, and hopefully you’ll see the potential of this great technology. Later I will add more blog posts about the advanced (and sometimes quirky) ways to use KnockoutJS.

First of all, fire up Visual Studio 2010 / 2012. Open or create your web project and install the KnockoutJS NuGet package.

image

Add a reference to knockoutjs (at the time of writing v. 2.1.0), define a simple data model containing an observable variable for name and occupation and some input and label fields. Take note of the declarative bindings (“data-bind”):

<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
    <title>Simple KnockoutJS test</title>
    <script src="Scripts/knockout-2.1.0.js"></script>
</head>
<body>
    <!-- input fields -->
    <p>First name: <input data-bind="value: firstName" /></p>
    <p>Occupation: <input data-bind="value: occupation" /></p>

    <!-- auto updated labels -->
    <p><label data-bind="text: firstName"></label> is a <label data-bind="text: occupation"></label></p>

    <script>
        function myViewModel() {
            self = this;
            self.firstName = ko.observable("Andreas"); // set default value
            self.occupation = ko.observable("Software Developer");
        }

        // initialize
        ko.applyBindings(new myViewModel());
    </script>
</body>
</html>

(Note: creating a self object in the data model is not necessary, but it has become a habit of mine to ensure a clear separation from the regular this reference).

imageThe above code will generate a page with two input fields and a text. The observable variables (firstName, occupation) in the data model are bound to the input fields and labels through the “data-bind” parameter. To test the binding run the project and see how changes to the input fields trigger the labels to be updated (when the cursor leaves the input field). This simple example shows the KnockoutJS declarative bindings and automatic UI refresh in action.

Now that you have a working example running on your computer I recommend going through the tutorials at the official Learn KnockoutJS site. Through their jsfiddle type GUI you can complete the basic steps as well as some more advanced examples, and then steal some code and ideas and transfer it into your own test project. This is the best way to prepare you before implementing the framework in your real world projects.