Windows 8, jQuery Geo, and toStaticHTML

I recently attended a Windows 8 DevCamp with the intention of installing Microsoft’s latest OS for the first time and getting jQuery Geo to work as a native app on top of WinJS.

What is jQuery Geo?

jQuery Geo ( http://jquerygeo.com ) is a JavaScript mapping API similar in concept to Bing Maps API and Google Maps API. It is open-source and uses open data by default but can consume any map and data service a developer wishes to use. It is well documented and the API design is inspired by the elegant style of jQuery itself. Write less, map more!

Did it work?

Yes!

Apart from $.ajax, jQuery works fine on WinJS’s Chakra engine. jQuery Geo does not use AJAX itself so this is not a problem.

The only change I had to make to jQuery Geo’s source code was to surround any HTML text used to dynamically create elements with a Windows 8 JavaScript method: toStaticHtml. This is required when you pass HTML to any jQuery manipulation method such as append.

Before:

.append( '<div />' )
 
After:

.append( toStaticHTML( '<div />' ) )
 
That’s all I had to change in the jQuery Geo source to get it working in Windows Store apps. Read on for more detail.

WinJS in Visual Studio 2012

WinJS in Visual Studio 2012 debugging a jQuery Geo Windows Store app (snapped to right) mapping tweets

Discussion

What about jQuery?

With Windows 8, it is possible to build Windows Store apps with HTML, CSS, & JavaScript. So, what about jQuery? The moment I got an empty WinJS project in front of me, I included it.

Since we are building a desktop app that can be installed from the Windows Store, we have to include jQuery’s minified script in our project and reference it locally.

In Visual Studio 2012, create a new project with:

FILE => New Project => Templates => JavaScript => Windows Store style => Blank App.

Then download a copy of 1.8.1 from http://jquery.com/download. Include it in the project’s js folder and add this to default.html:

<script src="/js/jquery-1.8.1.min.js"></script>
 
When you start the app, you will get three “Unable to add dynamic content” errors. This is jQuery/Sizzle feature detecting the JavaScript engine. The tests are based on dynamic content created using innerHTML. Windows 8 does not allow this without the toStaticHTML method so the tests will fail to correctly detect all WinJS features. However, I have not found issues with this when porting jQuery Geo and am hopeful that most of jQuery works as expected. If you find otherwise, you can download an un-minified version of jQuery and add toStaticHTML in these three places yourself.

HTML1701

Apart from jQuery’s initial tests, you will get the same error any time you use jQuery manipulation methods yourself (such as append). The full text of the error is:

HTML1701: 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.

The error message’s first suggestion is to wrap your HTML in a call to toStaticHTML. This includes any HTML sent to jQuery. The toStaticHTML method strips tags and characters that pose a security threat. For example, it will completely remove script and link tags as well as inline event handlers. I found some posts online stating that it also strips HTML5 data attributes but that has not been the case in my testing. jQuery Geo relies heavily on data attributes and wouldn’t work very well in Windows 8 without them.

The second suggestion is to use DOM methods such as createElement but, if you are creating fancy element hierarchies with data attributes and classes, this can get wordy and is not worth dropping the convenience of innerHTML.

Since jQuery Geo doesn’t append anything malicious, I chose to follow the first suggestion and wrap our dynamic HTML. We have eight calls which come to about an extra 112 characters. We can shrink that further using minification tricks.

Lastly, if you’re expecting a change in jQuery core to wrap HTML internally don’t get your hopes up. The jQuery team works toward web standards and this is neither web nor standard. It is more correct for developers to change how they call append when they know they’re writing a Windows Store app.

Only wrap text

When I first began adding toStaticHTML, I went overboard. I added it to every call to append and prepend in the library. The result was that all my maps had the string [object Object] at the top-left corner. I thought this was going to be a hard bug to track down.

The issue was that I was calling toStaticHTML on a jQuery collection. The collection represented elements I needed to move around in the DOM (using detach and append) rather than create dynamically. toStaticHTML‘s decision is to call toString on that object.
 

this._$existingChildren.detach( );   
this._$elem.html( '' );   
this._$elem.append( toStaticHTML( this._$existingChildren ) ); // don't use toStaticHTML here

 

Round trip

The toStaticHTML method is not new. It was introduced in IE8 as a first-pass security option to scrub user input. Web apps generally run in a sandbox and do not have much access to the system. Windows Store apps run on the desktop as the user, with various levels of access. It makes more sense in this context to require scrubbing in an attempt to prevent malicious actions such as deleting a user’s files.

It may seem like a pain to have to call this method any time you want to create dynamic elements with HTML text but I’m happy that this is all I had to do to port jQuery Geo to Windows 8. jQuery Geo 1.0b2 will support Windows Store apps.

References

Free book: Jump Start HTML5 Basics

Grab a free copy of one our latest ebooks! Packed with hints and tips on HTML5's most powerful new features.

  • http://www.d-mueller.de David Müller

    I’ve writte a post recently that is dealing with jQuery for Windows 8. It includes a ready-to-use version of jQuery for Windows 8 – http://www.incloud.de/2012/08/windows-8-using-jquery-for-app-development/

  • http://garsinfotech.com Anil Kumar

    Thanks Ryan for this valuable information.

  • http://www.nispaara.com Nispaara

    Very informative..