Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Building a Windows 8 Metro app with jQuery

I am just starting out with Windows 8 development using HTML/JS. I've spent the last few months immersed in jQuery development for apps targeting vehicle head-units and televisions.

Jumping into this, I thought the transition would be simple. I have the design and structure of my site all figured out for the most part and was hoping to follow some of the practices I had been using for my previous work.

That is, I want to essentially create a single page app. The main default.html file will house the top navigation/title and one other div. The other div will be used to load in all the other pages, all separate HTML files within the project.

All of the global functions and major functionality will reside in a javascript file, application.js. Then any page-specific javascript will reside at the top of each HTML file.

I'm quickly realizing that this is a problem. Using jQuery.load() to load in my pages causes security errors in my app.

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.

I was really hoping to avoid having to learn a bunch of Microsoft-specific stuff. I think it's great that they've provided a lot of tools and what not, and maybe I just haven't used them enough, but everything just feels too rigid for me and for what I'm trying to do or can already be accomplished with jQuery. I'm one who likes to know EXACTLY what is happening and have full control over it.

Also looking through the templates and sample projects, I really don't like all the repeated code. For instance, every single HTML file declaring all the same references. I want to write my references and sections like my title bar just once, and not have to copy/paste that code all over my project.

Is there a way to do things the way I was hoping, and create a single page app? Do they have their own substitute for jQuery's .load()?

Any help pointing me in the right direction would be much appreciated!

EDIT 8/14/2012:

I have tried using the fix from this question: Using jQuery with Windows 8 Metro JavaScript App causes security error

This gets rid of the security warning and I can load in HTML using jQuery.load(). However, looking at DOM explorer, my HTML is being stripped of my scripts.

I have also tried wrapping my .load() call inside of MSApp.execUnsafeLocalFunction(), but yet again my file still gets stripped of all scripts. What gives?

like image 577
Danny Avatar asked Aug 14 '12 07:08

Danny


3 Answers

I fixed by simply changing the line of jQuery that was causing the error.

jQuery-1.8.0, line 5566:

    append: function () {
        return this.domManip(arguments, true, function (elem) {
            if (this.nodeType === 1 || this.nodeType === 11) {
                self.appendChild(elem);  // problem line
            }
        });
    },

Changed to:

    append: function () {
        return this.domManip(arguments, true, function (elem) {
            if (this.nodeType === 1 || this.nodeType === 11) {
                var self = this;
                MSApp.execUnsafeLocalFunction(function () {
                    self.appendChild(elem);
                });
            }
        });
    },
like image 143
Danny Avatar answered Oct 03 '22 09:10

Danny


There is a "formal" way to do what you are seeking.
WinJS.Navigation is provided to support "single page apps". For example, the default.html would contain a markup that would represent where the dynamically loaded page content would go:

<div id="contenthost" 
    data-win-control="Application.PageControlNavigator" 
    data-win-options="{home: '/pages/home/home.html'}">
</div>

In the example above, the actual content page loaded is at /pages/home/home.html

In event handlers, you can simply do the following to load or navigate to another page:

WinJS.Navigation.nav("/pages/other/page.html");

True, it is not jQuery, but it works great :)

like image 39
Michael Palermo Avatar answered Oct 03 '22 09:10

Michael Palermo


Depending on your app, if you are not intending to access any WinRT components, you can navigate your page to ms-appx-web which will change the security policy around the page, but you can't specify this from start up. You would have to do a navigate, and leverage that new securyt context.

The other option you have it to wrap the calls to JQuery with msWWA.execUnsafeLocalFunction function, which will enable all that unsafe code be pushed into the DOM

like image 41
Dominic Hopton Avatar answered Oct 03 '22 10:10

Dominic Hopton