Showing posts with label HTML 5. Show all posts
Showing posts with label HTML 5. Show all posts

Sunday, March 4, 2012

Adding navigation to WinRT JavaScript

In the previous post we looked at the anatomy of a basic WinRT JavaScript navigation application. In this post we will add 2 additional pages and navigate between them. I will use the same fragment navigation as used in default.html and homePage.html.

First thing I'll do - just to spare me some typing work - is make two copies of homePage.html and call these page2.html and page3.html. Next, I'll alter the default content of homePage.html (there where it says 'content goes here') and replace it with two link tags. I'll add the same content to page2 and 3 as well, so as to easily navigate between all three pages.

<section role="main" aria-label="Main content">
    <p>
        <div>Navigate to: &lt;/div>
        <div>
            <a href="page2.html">Page 2</a>
            <a href="page3.html">Page 3</a>
        </div>
    </p>
</section>

When you try this out, you can actually navigate to page2 and 3. That wasn't too hard to do, now was it. Only downside with this app is, that the back button is not functioning (it stays disabled both on page2 and page3). The appbar as well is not popping up when you click your right mouse button. Also, when you look at it, the contents of pages 2 and 3 are not shown right, they are shown too far to the left. Obviously we need to add some extra code to fix all this.

So I started to play around with this little application, to see what could be done to get it functioning correctly. First thing I did, was add some breakpoints to the default.js file's navigated function. This showed me that, when clicking the page2 or page3 link, the navigated event was not being hit. Apparently, using a simple a tag with an href attribute doesn't trigger navigation. This had to be done some other way then.

For this I added some extra code to the homePage.js file.

function fragmentLoad(elements, options) {
    WinJS.UI.processAll(elements)
        .then(function () {
            // TODO: Initialize the fragment here.
            var page2Nav = document.getElementById('page2Nav');
            if (page2Nav) {
                page2Nav.addEventListener('click', function () {
                    WinJS.Navigation.navigate('/html/page2.html');
                }, false);
            }
        });
}

The fragmentLoad function is called when the homePage gets loaded. When this happens, we get hold of the page2Nav element (I added an id to the link element). If we find this element, we add an eventlistener for its click event. When clicked, we should navigate to page2.html. A similar piece of code can be added to navigate to page3.

After adding this, you will notice that after you click the page2 link, the navigated event in default.js is being hit. That's what we wanted. But wait, as it gets hit, the application doesn't find our back button, its value stays null. That's not right, it should be able to find the back button.

The thing that's wrong here is the fact I added an href to my a tags. If you remove this and let WinJS just handle all of the navigation, you will see the back button is being found. Now, if you land on page2, the back button can be used to navigate back to the homePage. Even the appbar is functioning as expected.

As cool as this is (hey, I can navigate), the downside of using these techniques is that you get an awfully big buy-in into the WinRT way of building apps. When you choose to develop your applications with HTML5 and JavaScript, I think one of the reasons for your choice is portability, the fact that you can take this same code and run it on a different machine with minimal effort. That is why you should think twice when using WinRT functionality. Or, you'd better start writing wrappers for platform specific libraries. But than still ... Hey, I can navigate.

Saturday, March 3, 2012

Navigating with WinRT JavaScript

I am currently playing around with WinRT JavaScript applications. Starting out with a navigation application written from scratch, just to find out how it all fits together. The MSDN library is actually quite scarce when it comes to resources on WinRT. They give you the overall picture of how Metro style apps work, but, for JavaScript applications, the actual information is a bit meager. So I thought it would be nice to dissect a Metro style navigation app and see what code you need to get it up and running. Also beware that the information I will be giving here is based on the first developer preview of Windows 8 and Visual Studio 2011 Express Edition. Things are still very likely to change in the next couple of months.

What I did, was create two Metro style JavaScript applications, one based on a blank project template and one based on the navigation application project template. Let's first see what the navigation application gives us.



When you look at the project of the navigation application, you will see it gives you a couple of predefined html, JavaScript and css files. There are two html files present, a default.html and a homepage.html file. First let's take a look at the homepage.html file. In the head section it includes the JavaScript files you find in the solution, so nothing new or fancy there. In the body there is a div defined with content.

<!-- The content that will be loaded and displayed. -->
<div class="fragment homePage">
    <header role="banner" aria-label="Header content">
        <button disabled class="win-backbutton" aria-label="Back">&lt;/button>
        <div class="titleArea">
            <h1 class="pageTitle win-title">Welcome to NavApp!&lt;/h1>
        </div>
    </header>
    <section role="main" aria-label="Main content">
        <p>Content goes here.&lt;/p>
    </section>
</div>

The main div has a couple of classes defined on it, fragment and homePage. The fragment class we will come back to later on, when we take a look at the JavaScript files of the project. Just remember that it's there on the main div of the homepage.

Within the main div there is a header tag defined. This shows that WinRT JavaScript applications make use of new HTML5 features. The header tag has a role attribute, with a value of banner. There is also a role defined on the section tag a bit further down the homepage, with a value of main. These role attributes are primarily used as selectors in the css and JavaScript files. There is no real functionality associated with them.

The last peculiar attribute values can be found on the button and the h1 tags. Their classes are set to win-backbutton and to win-title respectively. With WinRT JavaScript applications you will find there are a lot of these win-something attribute values. You would think these give you out of the box functionality. Well, they don't. You will find that all magic is really just JavaScript doing it's thing. Those win-something attributes again, are just selectors for the css and JavaScript files. When you run the appication, you will see that the win-backbutton is actually an arrow with a circle around it. That's just plain css:

.win-backbutton::before
{
    font-family: "Segoe UI Symbol";
    content: "\E0D5";
    vertical-align: 50%;
}

So, let's take a look at the default.html page. The header again is just JavaScript and css file includes. The body is more interesting.

<body data-homePage="/html/homePage.html">
    <div id="contentHost">&lt;/div>
    <div id="appbar" data-win-control="WinJS.UI.AppBar" aria-label="Command Bar" data-win-options="{position:'bottom', transient:true, autoHide:0, lightDismiss:false}">
        <div class="win-left">
            <button id="home" class="win-command">
                <span class="win-commandicon win-large">&#xE10F;&lt;/span>&lt;span class="win-label">Home&lt;/span>
            </button>
        </div>
    </div>
</body>

There is a data-homePage attribute on the body tag and it is set to our homePage.htm file. You will also find a contentHost and appbar div. The contentHost makes you suspect that the default.html page is actually the start page of your application and that other html pages will actually be loaded as fragment into it. That is indeed the case here. But then, why, as you run the application, don't I see the appbar that is defined at the bottom. You do get to see all the content of the homePage, but the appbar is nowhere in site. The reason is that, to see the appbar, you need to swipe up, or, if that doesn't work on your device, perform a right mouse click. There's the appbar for you.


So, where does all the magic happen? In the JavaScript files of course. Let's first take a look at the default.js file. There are a couple of functions defined here. Let's not start at the top, but at the bottom.

WinJS.Navigation.addEventListener('navigated', navigated);
WinJS.Application.start();

An eventlistener for the navigated event gets added and the application is started. That's simple, right. Right above these two statements we find the handler for activating the mainwindow.

WinJS.Application.onmainwindowactivated = function (e) {
    if (e.detail.kind === Windows.ApplicationModel.Activation.ActivationKind.launch) {
        homePage = document.body.getAttribute('data-homePage');

        document.body.addEventListener('keyup', function (e) {
            if (e.altKey) {
                if (e.keyCode === WinJS.Utilities.Key.leftArrow) {
                    WinJS.Navigation.back();
                }
                else if (e.keyCode === WinJS.Utilities.Key.rightArrow) {
                    WinJS.Navigation.forward();
                }
            }
        }, false);

        WinJS.UI.process(document.getElementById('appbar'))
            .then(function () {
                document.getElementById('home').addEventListener('click', navigateHome, false);
            });

        WinJS.Navigation.navigate(homePage);
    }
}

This code says as much as, when we launch the application, do the following things:
  • Our homepage is set to the attribute value of the data-homePage attribute of the body element.
  • If a user presses the alt key and the left or right button, navigate forward and backward. 
  • Find the appbar and attach a click handler to the home element. The navigateHome function is defined at the top of the JavaScript file and contains pretty straightforward code.
  • And last, but not least, navigate to the homePage.
Right abobe this function, you will find another function definition. 

function navigated(e) {
    WinJS.UI.Fragments.clone(e.detail.location, e.detail.state)
        .then(function (frag) {
            var host = document.getElementById('contentHost');
            host.innerHTML = '';
            host.appendChild(frag);
            document.body.focus();

            var backButton = document.querySelector('header[role=banner] .win-backbutton');
            if (backButton) {
                backButton.addEventListener('click', function () {
                    WinJS.Navigation.back();
                }, false);
                if (WinJS.Navigation.canGoBack) {
                    backButton.removeAttribute('disabled');
                }
                else {
                    backButton.setAttribute('disabled', 'true');
                }
            }
            WinJS.Application.queueEvent({ type: 'fragmentappended', location: e.detail.location, fragment: host, state: e.detail.state });
        });
}

This tells us what happens when we navigate (remember, the previous function actually navigated to the homePage, so this gets called at the start of the application).

  • It clones the current fragment state (I am guessing this remembers where we are coming from and in what state the page is at the moment).
  • And, hey, next bit is some asynchrony. After the cloning is done, a function gets executed for the fragment.
  • It finds the contentHost on the default.html page and appends the fragment to it. There you have masterview (default.html)- detailview (homePage.html) behavior.
  • The backbutton also gets some extra functionality. Based on the fact whether we can go back or not, the button gets disabled or enabled and the click handlers get attached.
  • Last bit is queuing the fact that the fragment got appended, so the WinRT runtime can do its thing.
On the one hand, that's all simple JavaScript code. On the other hand, if you are used to working with the regular .NET languages, this seems like quite some code you need to write for some basic functionality. 

Let's find out, in a next post, what we need to do to navigate to a new page in our application. 

Tuesday, July 12, 2011

Going to the Opera

I recently installed the Opera browser on my laptop. Main reason for this was the fact that I thought the Opera guys gave some really good HTML 5 talks during this years' NDC conference. And they just looked like really nice guys (I'm allowed to judge people on nicety). The Opera browser is also pretty far in implementing HTML 5 features as well, so might be interesting to try it out.

So, after installing this browser, I only used it for a day or so. Good points were its speed, which is faster than IE, faster then Firefox and faster than Chrome, this last one, up until now, being the fastest browser I used thus far. Bad points however are the way it treats shortcut keys. Ctrl click, opens a new tab, like Chrome, but also immediately places focus on this tab, unlike Chrome. To open the tab in the background on Opera, you need Ctrl Shift click, something I am not used to. This, sadly enough, was actually the main reason to have me use Opera only for a day. On a side note, one thing to always keep in mind when designing user interfaces: don't change the way things look and feel for a user too much (did you hear me, Office guys?), they get scared and run.

But then recently I gave it another shot. I primarily tried it out again because my laptop while running an instance of Visual Studio, a VM and Chrome with a couple of tabs opened, was getting really, really really slow. Looking at my CPU usage I saw that Chrome was actually using more resources than my Visual Studio while compiling. Some googling showed me that Chrome uses a sandbox for each tab, which also means it uses the same amount of resources for each tab, since resources are not shared. This has the advantage that when one tab crashes, it doesn't crash your other tabs. A phenomenon I haven't really experienced yet (in my case my other tabs actually did crash as well. not good!). This has the disadvantage of eating CPU cycles like a madman if you like to have many tabs open all the time.

So I reconfigured Opera as my default browser and immediately got annoyed again by the missing ctrl click. There are some workarounds for this (google them, you'll find them), but they didn't really work for me. Altering your shortcuts in the advanced preferences didn't do the trick. And the JavaScript solution that you can add didn't work either (my clicks stopped working altogether). I do find the fact that you can add your own JavaScript code to this browser pretty cool, though. Anyhow, while trying this out, I restarted my browser a couple of times and during my last restart I got the message that there was an update ready to install. This, I must say, I didn't really like, I like the fact that Chrome installs updates in the background and that I'm not bothered by this. My initial annoyance with update windows probably stems from the iTunes app that starts nagging about updates every friggin' time you start it.

So I installed the update, reopened the Opera browser and as a miracle I now have ctrl click open tabs in the background. I went from version 11.11 to 11.50, so I skipped a few versions as well, it seems. I suppose this is a new feature, I have no idea, but I'm happy with it. And the most important thing: my laptop doesn't become overly slow while I leave some browser tabs open all day. And apart from this, Opera offers pretty much the same features as Chrome. So for now, I'm sticking with it!

---

On a side note: I have been using Opera now for a week or two. I am still very happy with its performance (read this as: the performance of the rest of my system). But there are some drawbacks, though. Not all CSS is rendered as it should be. My own blog for instance doesn't render correctly using Opera and when I watch my blogs' statistics, they are just not shown in Opera. Also, yesterday, I was editing a new blog post, only to find out today that the autosave or Ctrl + S, which works just fine in Chrome, didn't function in Opera. I lost my changes, which I don't like! I'm going to keep using it for a couple of weeks (not for blog editing) and re-evaluate again.

Sunday, June 12, 2011

NDC 2011

Last week some colleagues and I went to the NDC conference in Norway.



Apart from the weather, which was crappy, it was an awesome conference. I've seen some great talks and am looking forward to watching some of the talks I missed (because I was in another session) online. I also went home with some new great ideas for books I want to read:

  • Introducing HTML 5, by Bruce Lawson and Remy Sharp. They gave the HTML 5 talks during the second day of the conference in a small and very crowded room. They convinced me even more of the amazing things you can do for web pages with the new upcoming standard. It was a relieve as well to hear someone from the Opera browser team talking about HTML 5 instead of the standard Microsoft talks I heard thus far. 
  • Test-Driven JavaScript Development, by Christian Johansen. Too bad his talk was given simultaneously with Rob Ashton's (Document databases with ASP.NET MVC), Kevlin Henney and Anders NorĂ¥s's (Introducing The FLUID Principles) and Hadi Hariri's (Dynamic in a Static World). I went to this last session, which was very good. It gave me some ideas and examples of more things I can start doing with dynamic. I would really like to try to get a DSL written with it (I would probably start off by copying a Ruby example, since it is not easy stuff). The talk about the FLUID principles was very good as well, my colleagues went to that one and it is one of the talks to catch on rerun, once they put the videos up. I did follow the talk about the SOLID principles, which was nice to refresh again. I went to the RavenDB by Example talk on day  3 of the conference. It was a good thing the speaker also mentioned some of the problems he had with a document database, having to rethink the design of your data as opposed to relational databases.
  • The Joy of Closure, by Michael Fogus and Chris Houser. I didn't get to catch any of the Closure and F# talks and it would be nice to get up to speed with this. Also something to watch on rerun and see what we can do with it
  • 97 Things Every Programmer Should Know, by Kevlin Henney and 97 Things Every Software Architect Should Know, by Richard Monson-Haefel. I only went to Kevlin's talk about the 101 things he learned in architecture school, which was light, but enlighting. His other two talks apparently were very good as well, as my colleague went to those.
  • Specification By Example, by Gojko Adzic. His talk wasn't so good, but I think a lot can be learned from this book. One thing I will really remember from the conference is the multiple question marks that speakers had with BDD, DDD and agile. While they are all good techniques, they have their flaws and the software community really needs to figure out how we can do these things even better. Gojko's post on his blog about one of these talks really explains the problem a bit as well. He also mentioned our Cronos colleagues from iLean in his talk, which I think was pretty cool. And he is also one of the creators of cuke4ninja, a port of cucumber for .Net.


Apart from those books and talks I already mentioned, I also followed some of the talks on mobile development. The ones about multi platform development were really informative. The MonoTouch and MonoDroid projects have moved from Novell to Xamarin and are planning on a next release in the coming months. Biggest take-away there was: use the latest MonoTouch and MonoDroid builds for now and switch to the Xamarin builds once they are published. Jonas Follesoe's talk on this topic was great, if you're doing mobile, catch it on rerun! 

I also really liked the AOP talks given by the PostSharp people. They have a great framework for doing AOP, which is really powerfull and which gives you a lot of cool features for keeping your code nice and, well, sharp. They also mentioned some other AOP frameworks, which I think is a nice gesture, since they are not the only ones out there.

The CQRS talk by Fredrik Kalseth was inspiring as well, although he only mentioned one part of CQRS. It was explained really well and can be used as a basis on future projects. I also learned in his talk that JetBrains have a Ruby IDE which I didn't know about. As I look at their site now, I see they're also working on an Objective-C IDE. 



So, all in all, a very good conference, which I hope to catch again next year, and hopefully without the rain. I learned a lot and have now a whole lot of stuff to read and learn even more about. Too bad there's only 24 hours in a day (of which I really need 9 to sleep, since I'm a sleepy head).

Thanks as well to my colleague, Guy, for providing some very nice pictures. You can find the entire collection here.

Monday, May 30, 2011

HTML 5 Feature Support

I recently prepared a chapter about HTML 5 for our QFrame bootcamp. The main thought for this chapter was: is it already possible to implement HTML 5 sites without all users having to upgrade to the newest browser versions. Most talks and sites about HTML 5 only tell you how great it is, using HTML 5, and how many cool new features you can now use. But still, I, as a developer, need to make sure that everyone who visits the sites I create, can view them more or less the same way. In this post I will show you my findings on the new HTML 5 features support. A next post will handle how you can make your sites HTML 5 compatible, even for older browsers.

So, I tried to get an idea of how far all browsers are already implementing the new HTML 5 spec. The html5test site gives you a good idea of which features a browser supports. You open this site in a browser of your choice and you get an overall score (the maximum score is 400) and an overview of which features are supported and which features are not. If you use the latest version of chrome for instance, you get a total score of 293, which is pretty good, almost 75 percent of the spec is supported.
The features that are not supported in chrome are:

  • MPEG-4 support, when using the new video tag
  • some new form field types 
  • microdata
  • the FileWriter API (FileReader is supported)
  • ...
All in all this is a short list and thus the high score for Google Chrome.

I also ran this test for Firefox. At the time I took the test I was still using version 3.6.3, which is a pretty old one. I have to admit I am pretty content with chrome's speed of showing web pages and haven't returned to Firefox since I installed the Google browser. Still, version 3.6.3 of Firefox still got a score of 155, which is less than half, but still pretty good for a pretty old version.
Since this was a lower score, I also tested for the latest version of Firefox (4.0.1) and off course got a much better score of 240, which is closer to the chrome score.
But now, the big question was, what about IE 9? Ever since Microsoft released their newest version of IE they have also been promoting their HTML support. Keeping this in mind, I was expecting a really high score here. But, alas, the actual result was quite disappointing. IE9 scores an overwhelming (mind the pun) 130 points. That is even less than my old Firefox version gets!
I also tested some more browser versions using the SuperPreview tool that is included in the Expression Suite. This tool allows you to test web sites in different browser versions. The tool uses the browser versions that it can find on your operating system and also offers some on-line browsers. This makes it possible, for Microsoft geeks like me, to, for instance, test sites in Safari. Version 4 scores 139 (more than IE9 again), version 5 scores 228.

I must say it is a pretty handy tool, but it comes with some restrictions. For instance, not all JavaScript always runs as it should. And the on-line chrome version for instance, gets a lower score for the html5test site. I'm thinking they don't have the latest chrome version installed at Microsoft. 
But still, I was able to get a score for IE6 up untill IE8. Not that it were high scores, 17 and 32 respectively. 

Which really makes you think whether you can already start using HTML 5 features today. I am pretty sure that for normal people (not geeks like you and me) not everyone has upgraded to IE9 yet. 
The last test I executed, was using the web browser of my new Windows Phone 7. Here I also got a score of 17. Pretty low, if you ask me. The good news is that with the new Mango update for Windows Phone 7, there will also be a IE9 browser. The bad news is, on the iPhone and Android devices you can already get a score of 132 and 182 respectively. 
I hope this gives you a nice view as how far browsers are in implementing the new HTML 5 spec. Still, The question remains 'can I start using HTML 5 features today'. I will already answer this for you: yes you can! Even if some browsers score low in a feature test for HTML 5. In a next post I will show you which parts of the spec you can start using and how you can implement fallbacks for older browsers.