Windows 8 – Using jQuery for app development

Windows 8 – Using jQuery for app development

The incredibly practical Javascript-library jQuery is the favored tool for lots of web developers. Since Windows 8 supports app development using the standard webtechniques, jQuery immediatly suggests itself. But because Microsoft has integrated a new security model in Windows 8, jQuery has to be modified slightly in order to be usable for app development.

The background

Microsofts security model comes into play when one of the standard Javascript functions innerHTML, outerHTML or document.write are used. Try the following code

1
2
3
4
<div id="test"></div>
<script>
    document.querySelector("#test").innerHTML = "<a onclick='document.body.style.backgroundColor=\"#F00\"'>Something evil</a>";
</script>

You will see a Javascript runtime error that terminates the app, because dynamic content is injected via Javascript.

The solution

Microsoft provides the method execUnsafeLocalFunction with which you can explicitly disable the security model and tell Windows “I know what I’m doing”. Of course, this should only be done when you control the executed code and are sure that no security problems could potentially happen. You have to wrap the code within the execUnsafeLocalFunction construct and let it execute for you. The following code works without problems:

1
2
3
4
5
<script>
MSApp.execUnsafeLocalFunction(function () {
    document.querySelector("#test").innerHTML = "<a onclick='document.body.style.backgroundColor=\"#F00\"'>Something evil</a>";
});
</script>

When pulling in potentially unsafe content from an external source, you might want to consider using the toStaticHTML method (further documentation here) or creating your nodes via DOM – but this is another topic, we don’t want to cover in this post.

The problem with jQuery

jQuery itself comes with lots of checks for the sake of browser compatibility. These checks contain code, that is considered to be potentially malicious and Visual Studio shows 3 warnings when using jQuery 1.8 (at the time of this post, version 1.8 is the latest).

Even if these are “only” warnings, we are going to get rid of them when using jQuery with Windows 8.

Making jQuery ready for Windows 8 – step by step

We will use the development version of jQuery 1.8 for this blogpost that can be found here.

Starting from the bottom of the file, the first necessary change is to wrap the contents of the assert block starting at line 5025 up to line 5040 within a execUnsafeLocalFunction block:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
assert(function( div ) {

    MSApp.execUnsafeLocalFunction(function () {
        // Opera 10-12/IE9 - ^= $= *= and empty values
        // Should not select anything
        div.innerHTML = "<p test=''></p>";
        if (div.querySelectorAll("[test^='']").length) {
            rbuggyQSA.push("[*^$]=" + whitespace + "*(?:\"\"|'')");
        }

        // FF 3.5 - :enabled/:disabled and hidden elements (hidden elements are still enabled)
        // IE8 throws error here (do not put tests after this one)
        div.innerHTML = "<input type='hidden'/>";
        if (!div.querySelectorAll(":enabled").length) {
            rbuggyQSA.push(":enabled", ":disabled");
        }
    });
});

The next target is the assertUsableName function – same principle as above. Change lines 3808 to 3826 to this:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
assertUsableName = assert(function( div ) {

    return MSApp.execUnsafeLocalFunction(function () {
        // Inject content
        div.id = expando + 0;
        div.innerHTML = "<a name='" + expando + "'></a><div name='" + expando + "'></div>";
        docElem.insertBefore(div, docElem.firstChild);

        // Test
        var pass = document.getElementsByName &&
            // buggy browsers will return fewer than the correct 2
            document.getElementsByName(expando).length ===
            // buggy browsers will return more than the correct 0
            2 + document.getElementsByName(expando + 0).length;
        assertGetIdNotName = !document.getElementById(expando);

        // Cleanup
        docElem.removeChild(div);

        return pass;
    });
}),

The next and last necessary change is the jQuery.support function that starts at line 1239 and goes all the way down to line 1507. The stripped down function looks like this:

1
2
3
4
5
6
jQuery.support = (function() {

    //...
   
    return support;
})();

This self executing function has to be wrapped like this:

1
2
3
4
5
6
jQuery.support = MSApp.execUnsafeLocalFunction(function() {

    //...
   
    return support;
});

Be sure to remove the last paranthesis because execUnsafeLocalFunction already executes the function for you – no need for a self executing function any more.

Further optimization

When you know what you are doing and can be sure that all the executed code is controlled by you, it makes sense to apply one last change to the core of jQuery which is handling the html() method among some others like append. After having applied the modification, you will be able to execute code like this without an error:

1
$("#test").html("<a onclick='document.body.style.backgroundColor=\"#F00\"'>Something evil</a>");

Change line 6115 from

1
div.innerHTML = wrap[1] + elem + wrap[2];

to our new favourite contruct

1
2
3
MSApp.execUnsafeLocalFunction(function() {                         
    div.innerHTML = wrap[1] + elem + wrap[2];
});

$(“windows8″).ready();

All the modifications have been included in this modified version of jquery-1.8.0. Download, include in your Windows 8 App and have fun! If a new jQuery version has come out in the meantime, you know where to apply your changes. Watch out for innerHTML and maybe some time, the jQuery team will release a Windows 8 ready version. Let’s hope together!

Update 2012-10-02: Eric pointed out an encoding issue with the original file causing applications with the modified, old jQuery version contained to fail the WACK test. This has now been fixed, the links are updated accordingly. Thanks Eric!

Download patched version of jQuery 1.8.0 for Windows 8

13 Kommentare zu Windows 8 – Using jQuery for app development

  • […] Windows 8 – Using jQuery for app development – Englischer Artikel, Verwendung von jQuery in Windows 8 – Apps […]

  • Eric

    have you tried to run Windows App Certification Kit (WACK) with this version of your customized jquery ? It gives errors like this … any ideas to get it passed ?

    ===
    Performance test

    FAILED
    Bytecode generation

    Error Found: The bytecode generation test detected the following errors:◦File \\?\C:\Program Files\WindowsApps\xxxxxxx\js\jquery-1.8.0-windows8-ready.js has JavaScript syntax or other problems.


    Impact if not fixed: As a performance optimization to accelerate JavaScript execution time, JavaScript files ending in the “.js” extension generate bytecode when the app is deployed. This optimization significantly improves start-up and ongoing execution times for JavaScript.


    How to fix: You may need consider one or more of these steps to fix the issue:
    – Ensure that event logging is enabled
    – All JavaScript files are syntactically valid; otherwise exclude the respective files from the package
    – Please note that you should uninstall all previous versions of the app before deploying
    Otherwise exclude the respective files from the package.

    ===
    File encoding

    FAILED
    UTF-8 file encoding

    Error Found: The UTF-8 file encoding test detected the following errors:◦File C:\Program Files\WindowsApps\xxxxxxx\js\jquery-1.8.0-windows8-ready.js is not properly UTF-8 encoded. Re-save the file as UTF-8 (including Byte Order Mark).


    Impact if not fixed: HTML, CSS, and JavaScript files must be encoded in UTF-8 form with a corresponding byte-order mark (BOM) in order to benefit from bytecode caching and to avoid other runtime error conditions.


    How to fix: Open the affected file, and select “Save As…” option from the File menu in Visual Studio. Select the drop-down control next to the Save button and select “Save with Encoding”… option. From the Advanced save options dialog, choose the “Unicode (UTF-8 with signature)” option and click the OK button.

    Hope you have an idea on this as I cannot find any resources on the internet…

    Eric

  • David Müller

    Hey Eric, thank you very much for your comment and sorry for the little longer response time. I was able to reproduce the problem and uploaded a “fixed” version of the modified jQuery-file which is located here (and also in the blog post). I tracked the error down to an encoding issue.

    Visual Studio demands UTF-8 encoded Javascript Files without a BOM (Byte Order Mark). The uploaded, pervious version had a byte order mark, whatsoever. I packed the “new” version in a Zip-File because the encoding problem seemed to be upload-related. Be sure to double check with Notepad++ that the encoding is UTF-8 without BOM:

    This new version passes the WACK test without problems. Thanks again for pointing this out, Eric.

  • Josh

    Hello and thanks for all your hard work. I’ve used this successfully when working from a blank app, but when I try to integrate it deeper into Windows 8, such as within a WinJS.Binding.Template, I can’t get jQuery to work on those elements. For example, I want a grid element to open in a modal view.

    Is this an inherent conflict with the Windows 8 JS framework? If so that’s OK, and I’ll try to work around it.

    • David Müller

      Hey Josh, could it be that you are trying to operate on elements, that are not loaded yet? The same is true for the windows Charm Bar – be sure to apply your event handlers and other jQuery stuff in the corresponding “onLoaded” function or whatsoever the name might be.

      • Josh

        I suppose that’s possible, but I haven’t had issues with the Charm Bar (though I haven’t tried that with jQuery). I quickly added a listener for the “loaded” event to force my jQuery function to fire. No luck on that yet. I’m having trouble figuring out where the problem might be (using one of the app templates provided in Visual Studio.

      • Josh

        So specifically, jQuery is not firing in WinJS.Binding.Template elements on my page. It’s a video that opens up in a lightbox. When I take that video and place it outside of the element, it works. I’ve verified as best I can that I’m loading the jQuery stuff after all the elements have loaded. Any ideas?

  • Martin

    Hi

    This worked for me, it’s the 1.8.3 jQuery version with adapted code for Windows 8 apps
    Hope it helps someone: http://bit.ly/12GwT63
    Good luck and let me know if it works.

  • Anony Mouse

    For those interested, you can get the updated jQuery Win8 version from the below github page:

    https://github.com/appendto/jquery-win8

    ‘appendto’ will manage and update it for us.

  • David Müller

    Thanks for contributing, Martin and Anony!

  • […] You can make jQuery ready for Windows 8 using instructions in this blog. […]

  • E. Schmidt

    Best. Blog post. Ever. The code snippets and commentary that you provided helped me to make the required changes to jQuery 1.9.1 really quickly.

    Thank you so much!

  • […] The jquery library used is a modified version: http://www.incloud.de/2012/08/windows&#8230; […]

Schreiben Sie einen Kommentar

Kommentar senden