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?
Did it work?
$.ajax, jQuery works fine on WinJS’s Chakra engine. jQuery Geo does not use AJAX itself so this is not a problem.
toStaticHtml. This is required when you pass HTML to any jQuery manipulation method such as append.
.append( '<div />' )
.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 debugging a jQuery Geo Windows Store app (snapped to right) mapping tweets
What about jQuery?
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:
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:
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.
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
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
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.