The best way to load external JavaScript

I found another post from Nicholas Zakas interesting:

 

The best way to load external JavaScript

http://www.nczonline.net/blog/2009/07/28/the-best-way-to-load-external-javascript/

 

default.html

<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8" />
    <title>Test page</title>
</head>
<body>



<script type="text/javascript" src="http://your.cdn.com/first.js"></script>
<script type="text/javascript">
    loadScript("http://your.cdn.com/second.js", function () {
        //initialization code
    });
</script>
</body>
</html>

first.js

function loadScript(url, callback) {

    var script = document.createElement("script")
    script.type = "text/javascript";

    if (script.readyState) {  //IE
        script.onreadystatechange = function () {
            if (script.readyState == "loaded" ||
                    script.readyState == "complete") {
                script.onreadystatechange = null;
                callback();
            }
        };
    } else {  //Others
        script.onload = function () {
            callback();
        };
    }

    script.src = url;
    document.getElementsByTagName("head")[0].appendChild(script);
}

The 4 JavaScript load opportunities

Interesting podcast by Scott Hanselman and Nicholas Zakas:

http://hanselminutes.com/383/enough-with-the-javascript-already-with-nicholas-zakas

 

It mentions the 4 JavaScript load opportunities:

  1. In the <head> tag
  2. Before the </body> tag
  3. After page load (windows.onload DOM ready function)
  4. On demand (when user clicks a button, mouse is 100px from button, user types first letter etc.)

 

For performance reasons, use 4, then 3, then 2 and if you can’t do without, use 1.

Kendo UI – jQuery and dataSource–transport–contentType

The way a kendo datasource retrieves data can be configured via the transport object.

This object contains configuration objects for specifying the way CRUD operations are executed.

Each of these configuration objects contain the properties

contentType (Type of the HTTP request)

dataType (Type of the HTTP response request)

 

The way you configure these properties defines the way how the C# REST Service code must be written. If you use the default contentType (application/x-www-form-urlencoded; charset=UTF-8). the data is sent inside the forms collection with the name "models" of the request, the name of this property is set in the parameterMap function:

var dataSource = new kendo.data.DataSource({
    transport: {
        update: {
            // The default HTTP request (send) type.
            contentType: "application/x-www-form-urlencoded; charset=UTF-8",
            // The expected HTTP response (receive) type.
            dataType: "json"    
        }
    },
    parameterMap: function (options, operation) {
        if (operation !== "read" && options.models) {
            return { models: JSON.stringify(options.models) };
        }
    }
});

C# code to handle this update request:

public List<MyDto> Post()
{
    string json = _request["models"];
    var records = new List<MyDto>();
    if (!string.IsNullOrWhiteSpace(json))
    {
        records = JsonConvert.DeserializeObject<List<MyDto>>(json);
        // Update data in database …
    }

    return records;
}

MyDto is just a POCO class.

 

If you want to sent the data as a parameter of the Post method, you should use "contentType:"application/json"":

var dataSource = new kendo.data.DataSource({
    transport: {
        update: {
            // The default HTTP request (send) type.
            contentType: "application/json",
            // The expected HTTP response (receive) type.
            dataType: "json"    
        }
    },
    parameterMap: function (options, operation) {
        if (operation !== "read" && options.models) {
            return { models: JSON.stringify(options.models) };
        }
    }
});

C# code to handle this update request:

public List<MyDto> Post(List<MyDto> records)
{
    // Update records in database ...

    return records;
}

How to use a password field in a Kendo grid

The demo at http://demos.kendoui.com/web/grid/editing-custom.html shows how to create a custom editor function. We can use this function to show a password field as editor in a Kendo grid.

function passwordEditor(container, options)
{
    $('<input type="password" required data-bind="value:' + options.field + '"/>').appendTo(container);
};

In the column that should be used as password, use:

$("#grid").kendoGrid({
    dataSource: dataSource,
    pageable: true,
    height: 430,
    toolbar: ["create"],
    columns: [
        { field: "ProductName", title: "Product Name" },
        { field: "Category", title: "Category", width: "160px", editor: categoryDropDownEditor, template: "#=Category.CategoryName#" },
        { field: "UnitPrice", title: "Unit Price", format: "{0:c}", width: "120px" },
        { field: "UserPassword", title: "Password", editor: passwordEditor, template: "…" },
        { command: "destroy", title: " ", width: "90px" }],
    editable: true
});

 

The template: "…" ensure no data is shown to the user, when the password is changed.

 

An example would be:

image

Wrapping the MSApp.execUnsafeLocalFunction

Microsoft’s MSApp.execUnsafeLocalFunction can be used to dynamically add potentially unsafe code to the DOM. If you want to use this function in a cross platform HTML 5 app, you might want to wrap the function like:

if ("undefined" === typeof Utilities)
{
    Utilities = {};
}

Utilities.executeUnsafe = function (func)
{
    if ("undefined" !== typeof MSApp)
    {
        MSApp.execUnsafeLocalFunction(function ()
        {
            func();
        });
    }
    else
    {
        func();
    }
};

Now you can call a potentially unsafe function, like:

Utilities.executeUnsafe(App.myFunction);

Where App.myFunction should be replaced by your function.

How to add dynamic html content with jQuery 2.0.0 to a Windows Store app.

If you directly append html to the DOM that contains HTLM 5 data attributes or event handlers, like the onclick event to a Windows store app, you might get the exception during runtime:

 

Unhandled exception at line 5, column 18611 in ms-appx://3bce315e-3d91-43e6-8149-06d6377f04a1/js/libraries/jquery-2.0.0.min.js

0x800c001c – JavaScript runtime error: Unable to add dynamic content. A script attempted to inject dynamic content, or elements previously modified dynamically, that might be unsafe. For example, using the innerHTML property to add script or malformed HTML will generate this exception. Use the toStaticHTML method to filter dynamic content, or explicitly create elements and attributes with a method such as createElement.  For more information, see http://go.microsoft.com/fwlink/?LinkID=247104.

 

This exception even crashes my Windows Store app, because it is not caught anywhere in the code.

 

In my case this was caused by the following code:

var content = "";
content += ' <ul data-val="users" onclick="console.log(\'Clicked on users list.\');"> ';
content += ' <li>User1</li> ';
content += ' </ul> ';

var container = $('#content');
container.empty();
container.append(content);

This can be fixed by using jQuery document fragments:

var ul = $('<ul>', { 'data-val': 'listOfNames', 'onclick': 'console.log("Clicked on users list.");' });
ul.append('<li>' + 'User1' + '</li>');

var container = $('#content');
container.empty();
container.append(ul);

 

For more information on globally killing this exception, without changing the code (not recommended), see

http://blog.jonathanchannon.com/2013/01/24/using-angularjsbackbonejs-in-windows-8-javascript-app/

It uses jQuery.isUnsafe = true; so all calls to .append and appendTo are wrapped with Microsoft’s MSApp.execUnsafeLocalFunction.

Convert a date object to a string in JavaScript

If you want to convert a date object to a string in JavaScript and you use jQuery, then you can use the function $.datepicker.formatDate.

 

The following QUnit test will succeed:

/// <reference path="Scripts/qunit.js"/>
/// <reference path="Scripts/jquery-1.8.3.js"/>
/// <reference path="Scripts/jquery-ui-1.9.2.js"/>
"use strict";

test('JsTest', function ()
{
    
    var input = new Date(2012, 10, 28); // Note: months start at zero!
    var expected = '2012-11-28';
    var actual = $.datepicker.formatDate('yy-mm-dd', input);
    ok(expected == actual,
        'Dates are not equal. Expected:' +
        expected + ' _ Actual:' + actual);
});

Convert string to date in JavaScript

If you want to convert a string to a date object in JavaScript and you use jQuery, then you can use the function $.datepicker.parseDate.

 

The following QUnit test will succeed:

/// <reference path="Scripts/qunit.js"/>
/// <reference path="Scripts/jquery-1.8.3.js"/>
/// <reference path="Scripts/jquery-ui-1.9.2.js"/>
"use strict";

test('JsTest', function ()
{
    var text = '2012-11-28';
    var expected = new Date(2012, 10, 28); // Note: months start at zero!
    var actual = $.datepicker.parseDate('yy-mm-dd', text);
    ok(expected.getTime() == actual.getTime(),
        'Dates are not equal. Expected:' +
        expected.toISOString() + ' _ Actual:' + actual.toISOString());
});