JavaScript
7 Reasons I Still Love JavaScript
For many reasons, I still love developing Windows 8 apps using HTML, CSS, and JavaScript. I have extensive C# experience and always want to be able to say “I’m a C# developer”, but I’d like to add that “I’m a JavaScript developer” as well.
Some months ago I was a little pained to make even a short term commitment to write more JavaScript than C#. It felt a little like when I was learning French and found myself hesitant to start trying to think in French as if I would lose my English. Of course, that won’t happen, and we shouldn’t be afraid even of immersing ourselves in other languages. In fact, I’m a big advocate of the polyglot theory of intentionally moving into other languages spaces to expand our own scope, our value, and our perspective.
Becomes a way of thinking
I’m sure most development languages become a “way of thinking,” but I think JavaScript does even more so because it’s so dynamic and so light.
It’s the language of the web
Mashups are a breeze when you’re ingesting HTML and JSON data into and app that’s made with HTML and JavaScript. The WinJS.xhr() method can make web requests with a request type of “document” and then immediately act on the results just like it would any other in-app content. Blob images can be consumed and repurposed. JavaScript objects can be created instantly out of JSON data. Yada yada yada. It’s very convenient.
CSS selection of elements is great
Selectors are one huge strengths of the HTML/CSS that take advantage of the fact that HTML markup goes all the way to the client as XML-like syntax. Even on the client (at run-time) CSS can select very specific portions of the UI in order to affect it with styles or layout. JavaScript can take advantage of selectors too (using document.querySelector and .querySelectorAll) and that allows our logic to act on very specific portions of the UI.
One with the masses
There are a LOT of people writing JavaScript. A StackOverflow search on the [javascript] tag returns 300k+ questions on the matter (actually [c#] returns almost 400k!). It’s good to have camaraderie in writing code. It’s good to have employers looking for your skillset. It’s good to have others asking questions on StackOverflow that you can benefit from. It’s good to be one with the masses.
Standards driven
3JavaScript is broadly adopted and is broadly and inherently appealing because it’s based on web standards. The ECMAScript standard that is JavaScript, along with CSS and HTML, are governed by the World Wide Web Consortium (W3C) and that makes developers feel good. It’s very democratic and very social and has very high likelihood of moving forward and moving in good directions.
Don’t reinvent the wheel
There are a lot of JavaScript libraries out there. A lot. If you want to track faces or get fancy with date calculation or recognize touch gestures or implement IoC or pub/sub or manage Entity Framework data or edit images or any of a plethora of other things, there’s a JavaScript library waiting for you.
A full stack of script
When you write C#, you don’t usually just write C#. We find the client/server model everywhere and you don’t send server code to the client, but you can send script. Whether you’re writing an ASP.NET app or a client app, these days it seems you’re inevitably going to be interacting with some HTML or even some JSON somewhere… whether you’re using REST web services or scraping HTML screens. Having JavaScript on both the server end and the client end just tends to make you smile.
I like exploring languages. I am a veteran of VB. Like I have said, I’m a huge fan of C#. I have huge respect for C++ (though I haven’t knocked on that door since college). I am exploring Erlang. Nevertheless, today I am having a blast writing JavaScript, and if you’re writing JavaScript, I don’t think you’ll be hurting for work anytime soon!
Happy coding!
Using WinJS.xhr to Fetch This and That
You know the story. A call to a website used to be little more than a single request with its single response. But times have changed. The web is all grown up and any given visit to a website is often accompanied by multiple requests for more atomic bits of data.
The popular thing to do now, in fact, is to implement websites using a single page architecture where the user does one primary request and response to get the core document, and then the rest of his or her time spent in the app consists only of these tiny requests/response cycles that bring just what’s necessary.
This is how Windows 8 apps using HTML/JS work - they are single page apps. And to play in this sandbox, you need to get good at using WinJS.xhr(). WinJS.xhr() is not a fancy function. It doesn’t do a lot more than any of the other libraries do when they wrap the XmlHttpRequest. It makes for good, simple, elegant though and I like that.
Watch this screencast of the xhr() function in action and enjoy.
A JavaScript Library for Everything
Windows 8 is one of those environments that’s just fun and expressive to develop in. So is JavaScript. The convergence of the two is just rockin’.
One of the great things about JavaScript is the enormous amount of code that other people have already written and put up on the web for your consumption. Do you want to wrap local storage (store.js), detect faces (liuliu), implement lightweight pubsub (minpubsub), or load JavaScript asynchronously (include.js)? You can do it by simply including a library in your Windows 8 project.
To find a library, you can always Bing (did you know that Bing results are preferred to Google 2:1 in blind taste tests?) for the functionality you need or you can try something here…
- microjs.com
- Hanselman’s post
- List of JavaScript libraries (Wikipedia)
Random Tile Colors
This tip is quite short and simple, but worth a post I think. If you want to colorize some tiles like the start screen does, here’s one simple way to do it.
var demos = [ |
This is some code from a project I have that showcases some simple code demos, so I have an array of each of these objects. Then I create a quick array of some of the color codes used on the start screen. Finally, I simply do a forEach on the demos array adding a new tileColor property to each which is a randomly selected color from the color array.
This ability to just throw another property onto an object without mucking with the class and affecting all of the other instances, is in my opinion one of the nicest things about a dynamic language like JavaScript, and I take advantage of it quite a lot.
Now to actually use this color for the tiles, it’s a simple matter of adding it to the databinding statement like this…
<div id="itemTemplate" data-win-control="WinJS.Binding.Template"> |
Notice the style.backgroundColor:tileColor term. That’s all it takes.
Using Promises
If you’re developing Windows 8 apps using JavaScript, then you’re likely familiar with the WinJS.Promise
object. You can hardly get by without using one, because a lot of the API in WinJS and WinRT is asynchronous and for JavaScript apps they return a Promise.
I’m going to share with you what I have learned about promises so far in increasing order of sophistication.
Consuming a Promise
Everybody and their uncle is going to use this one. If you need to make a call to WinJS.xhr()
for instance, you’re going to get a WinJS.Promise in return. They’re quite easy to deal with actually and you may already know this.
When you get a promise from a method, you simply hang a .then
or a .done
method off of it and provide a function that you want to run when the asynchronous method is complete.
WinJS.xhr({url:"http://someuri.com/service"}) |
The call to .xhr comes back really quickly and you and your code go about your day even though the service hasn’t responded yet. Then when the service finally does come back to you, everything inside the done method runs. The promise that .xhr returns contains a payload as well. That’s why we’re able to declare our done function with function(xhr)
and then access whatever it is the service returned.
So this is super handy for keeping our UI fast and fluid. But let’s move past merely consuming promises and get a bit more advanced.
Passing a Promise
You’ve seen how to consume a promise so that you can avoid a blocking call to a relatively long running or potentially long running method call. Sometimes you want to write a method yourself that calls an asynchronous method and you want to give your method caller the ability to call it asynchronously.
In this case, all you have to do is return the promise given to you by the asynchronous method you’re calling. So, for example, let’s wrap the example call to .xhr
above with our own method call…
function myMethodAsync() { |
There we go. Now I can call myMethodAsync (and by the way, adding Async
to the method name is a convention to indicate that it is an asynchronous method) like this…
myMethodAsync() |
And notice that I can still specify the xhr parameter for my done function and access the payload.
That’s how we pass along a promise from one asynchronous method to another. Sometimes, however, you need to start from scratch and create your own promise.
Creating a Promise
If I want to create my own method and allow callers to call it asynchronously then I need to return to them a promise. That’s simply the pattern in JavaScript.
Creating a promise is pretty easy, but you need to understand the concept because sometimes things can start to feel messy and it’s really helpful to understand what’s going on (not that I do entirely yet).
In Windows 8 JavaScript development we have the WinJS.Promise
. You create it like this…
new WinJS.Promise(function(c,e,p) { |
The c
, e
, and p
are parameters that are themselves functions. Within the function body, then, I can actually call c()
when I want to complete the promise, call e()
when I want to report an errant case, or call p()
when I want to report progress.
Study this method I wrote that makes sure a file exists and if it doesn’t then it creates it…
function assureFileAsync() { |
There are a few things going on here, so let’s dissect.
First, I did use the Async
suffix to indicate to the caller that this is going to be an asynchronous method. I create and return a new WinJS.Promise
and the bulk of the logic here exists in the function declaration for that promise.
If a file called applicationData.json
exists (fileExists
is another function I wrote), then we don’t need to do anything and this promise should be considered complete, so we simply call c()
. If we wanted our promise to carry a payload (like the xhr
method does), then we could put that here by calling c(myResult)
. In this case, however, we don’t need that.
If the file does not exist, then we want to create it. Notice that this creation is itself an asynchronous call and in the .then
there’s even another one. Finally, after we have made certain the file exists and contains my starterData
, then we call the c()
to indicate that this promise is complete.
There’s plenty more insinuated by this, but I’m going to leave it there for now in the interest of simplicity.
Saving a Promise
Now this trick I just figured out recently and it’s very handy.
Let’s say that in one part of my code I want to do something (call it Action A) that may take some time, and then in another place I want to do something else (call it Action B) but Action B should not occur until Action A has successfully completed.
I could let Action B call Action A asynchronously because then I could hang the .then
or .done
on that call. Sometimes, though, I don’t want Action B to be the initiator.
Let’s look at a more concrete example. This is the case where I ended up discovering this pattern.
When my application loads I want to load all of the data from file. When you user lands on the home page, I want to show the loaded data. Obviously I can’t show the user the data until it’s loaded, but I want to initiate the data load in the app’s activated event not in the home page.
So here’s what we do. We initiate the data load from the app’s activated event and save the resulting promise somewhere where it will be accessible to the home page. I just added it dynamically onto the WinJS.Application
object (not sure if that’s recommended or not, but it works great :) Then from the home page, we simply access that object and hang a .done on it. Easy.
Here’s the data load call from my app activated event…
WinJS.Application.dataLoadedPromise = Data.initializeAsync(); |
…and here’s where I want to start work on my home page data, but only after the data is loaded…
var hubItemsList = new WinJS.Binding.List(); |
Now getHubItemsAsync (itself another asynchronous call, but that’s coincidental) will only get called once the dataLoadedPromise is complete.
Conclusion
There’s much more to promises that I didn’t include here - for brevity in part, but also because I haven’t discovered it yet, but keep an eye on this blog. As I turn over new leaves, I’ll post it here - I promise.
Page Navigation in Windows 8 JavaScript Apps
I’d like to talk a bit about navigating in Metro apps using HTML/JavaScript. There are a few options for doing so, and as you probably know whenever there’s more than one way to do things, then you the developer have power but not necessarily clarity. The latter is what I hope to offer here.
First of all, the HTML/JavaScript that Metro apps are based on are identical to the HTML/JavaScript that websites are based on. It is entirely based on the standards. This is good because proprietary things are bad - generally speaking. This means that you can navigate exactly like you do in websites, but don’t. I’ll explain why not.
So you could navigate from default.html to page2.html
like this…
<a href="page2.html">link to page 2</a> |
But again… you should usually do this. Doing so changes the “top level document location”. This navigation looks something like this…
Where the user is no longer on the default.html
page. For websites, it’s just fine to jump around by navigating the top level like this because you’re usually not too concerned about state, but in a full-fledged application, you usually are concerned with state and you can make your life easier by using the built-in navigation features that are provided by the VS2012 templates.
When you use the navigation functionality, a navigation looks more like this…
Notice that the user is still on default.html
, but the contents of the second page have simply been loaded into what is called the contenthost
. Now, if you loaded a bunch of script and styles on default.html
and even declared some variables and set some state, you still have all of that, even though to the user it appears that you’ve navigated to a second page.
Implementing this is pretty straight-forward. Follow these steps…
Get the navigate.js script file that comes with the Navigation Application project template in VS2012. You can either start with the Navigation Application project template and notice that navigate.js is already in your js folder, or you can create a throw-away Nav project and steal that file.
Reference the navigate.js from your default.html file…
Add a contenthost to your default.html file
And that’s it. After this has been implemented, then you are free to do things in your JavaScript like this…
WinJS.Navigation.navigate("/pages/page2/page2.html"); |
And you have the chance to pass some parameters without having to resort to query string parameters which can be cumbersome and restricting. To do this, you can pass a second parameter to the navigate function like this…
WinJS.Navigation.navigate("/pages/page2/page2.html", myDoohicky); |
…where myDoohicky can be any JavaScript object you want.
Now, when might we actually perform this navigation? Well, in many cases it will be on some user action. For instance, let’s say the user is going to click a button and we want to navigate them to page2.html
. Let’s see what that would look like…
HTML
<button id="myButton">go to page2</button> |
JavaScript
ready: function (element, options) { |
Now let’s look at a bit more pragmatic example. Let’s say we are working in a grid (WinJS.UI.ListView
technically) and when the user touches one of the tiles, we want to navigate to a second page with more details about that element.
This can be wired up much like the simple button example above, but likely the elements in our grid are data bound from some list that we have. In that case, perhaps the easiest way to implement this is by adding a function to the list and then bind the click function just like any of the data elements are bound. Here’s an example of that…
HTML
<div id="headertemplate" data-win-control="WinJS.Binding.Template"> |
JavaScript
ready: function (element, options) { |
Now, there’s a lot going on in the JavaScript file there, so let me break it down for you. First of all, I pulled this example from another post I did on creating a Netflix browser app utilizing their OData feed. If you want to know what’s going on with the call and the data binding, go check that out.
I added to it though. I changed what happens in the forEach
loop. The reason I did is to illustrate how to bind to a function like you bind any other data property. Look in the HTML at the div
just below the one with the id of template
. I’m binding the onclick
attribute to the clickFunction
. That clickFunction
is what I created in the forEach
loop of the JavaScript. Notice, though, that there’s one funny thing we need to do to it. Since we are using this in the HTML it could be exploited and so we turn on strictProcessing
for our app and that requires us to set _supportedForProcessing_
on any functions that we are going to call from the HTML. So, we set that to true
for our function and we’re good to go.
I hope this brings the concept home for you. If you have questions, leave a comment below and I’ll be glad to try to help.
I give you my word...
I’m excited about what I just implemented. I’m always excited when I figure something out or learn something big. This one is big for me. Hopefully this post will add some value to your life as well.
First the problem statement…
Here’s what I wanted to do. I am working on a Windows 8 Metro app using HTML/JavaScript.
I have a data.js file that represents (for now, until I put the data in the cloud) my data service. I am loading data up from a roaming file that contains simple JSON data. Actually, is “simply JSON” redundant. JSON just IS simple, right?
My hub page then needs to make sure that the application data is loaded and then it needs to request some. I can’t just directly request the data as is though because it needs to be massaged into the right shape to back the hub view. My application has items of Type A and Type B and I need to essentially flatten that into a super type that my hub will represent in different groups.
So I need to fetch some data and it needs to happen in an async fashion.
I’ve consumed objects that follow the Promise pattern plenty, but here I need to create my own Promise and get all custom about when it is considered complete and what it returns as its payload.
So I have two methods that I need to make asynchronous: loadAppDataAsync() and getHubItemsAsync(). The former is internal to my data.js function, but the latter is “exposed” to the rest of the app using a WinJS.Namespace called “data”.
loadAppDataAsync
This method, as I said, is “internal” to my data.js file. That is, it’s defined inside the modular function that encapsulates everything on my data.js file and thus is not available anywhere else in the application. The purpose of the function is to read the applicationData.json file and populate some arrays with the results. Here’s the method definition…
function loadAppDataAsync() { |
I added the Async suffix to the method name because this method not only calls an async method, but also acts asynchronously itself. Here’s how that’s implemented.
If I just wanted to wrap up the getFileAsync method call, then I could simple return the result of that call, but I need to add a little bit of my own logic. I only want to make the getFileAsync call in the condition that my data has not already been loaded. So I return a new WinJS.Promise specifying its function (which receives complete, error, and progress attributes that I’ve called c, e, and p). In the function, if the data has already been loaded I call the complete method c (passing no attributes) immediately indicating that we’re done loading app data (because it’s already loaded). If the data has not been loaded, however, we have some work to do and we will not complete (by calling c) until we’re done with it (that’s why it’s in the .then).
This one is pretty simple. Let’s move on to the next method that we use to get the hub items after the application data has already been loaded. Here’s the code…
WinJS.Namespace.define("data", { |
This one is defined in a Namespace so that we can call it from elsewhere in our app - namely from hub.js. What this method does is a little different from the former. Like before, we are returning a new Promise. Unlike before, after we populate our result (hubItems), we complete the promise with a result by calling c(hubItems).
Passing a value to the complete function makes that value available to the caller like this…
data.getHubItemsAsync().then(function(hubItems) { |
Simple, eh? That’s the way it’s supposed to be. I want to get then items and then I want to push each of the results into my WinJS.Binding.List (here called hubItemList).
Now the grid on my hub is bound to a List that gets populated with data after the application data has been loaded and after the getHubItemsAsync method has projected the application data to look how we want it to look.
Phew! This JavaScript stuff is pretty crazy. It’s pretty awesome though.
Happy promise keeping!
Query Selector Helper for Metro Apps
I wrote a post sometime back about selecting DOM elements in your Metro apps. I have since written myself a helper method that I find quite useful and perhaps you will too. It looks like this…
function q(query, context) { |
I just drop it in the global namespace (handslap) so I don’t have to worry about qualifying it with a namespace prefix. So, more specifically, I just add it outside of the function on the default.js page, and that makes it available to all of the pages in my app.
The original goal was to make it easier to type then things like…
var fredDiv = document.querySelector("div#fred"); |
…or…
var allDivs = document.querySelectorAll("div"); |
But I subsequently decided to combine the selection of single elements and multiple elements. The logic dictates that if multiple results are found, then they are all returned, but if just one is found then that one is returned. Furthermore, you can see that I am turning the NodeList result that comes back in the case of multiple results into a standard JavaScript array using a slice. This way I can use array methods like .map, .filter, etc.
It accepts a context which if it’s omitted will default to the document object. If provided, however, then the selection is done below the DOM element specified. Therefore this…
var allDivs = q("div"); |
…will find all div elements in the entire document, but…
var footer = q("div#footer"); |
…will find all div elements underneath the div called “footer”.
Use it if you like it. Happy selecting.
Creating an Observable Object in Windows 8 JavaScript
Living in the JavaScript world for a while will help you to appreciate the offerings of C# for sure. Many concepts like classes, inheritance, observable collections, list extensions (LINQ) are simply absent and so a creative alternative has been created either in WinJS or just in recommended practice.
One of these is in the area of data binding.
First of all, I recommend Stephen Walther’s excellent article on Metro: Declarative Data Binding. He’s much more thorough than I intend to be here. I only want to relay my experience with following the instructions on dev.windows.com – specifically the article entitled How to bind a complex object, and following the sample project entitled Programmatic binding sample. If you want to learn a lot more about Windows 8 development using HTML and JavaScript, you can check out Stephen’s book Windows 8.1 Apps with HTML5 and JavaScript.
Here are the steps I took to get a very simple object to bind well.
- Write a simple class
- Add an _initObservable method
- Mix it
- Instantiate it
- Bind the properties
- Change a property to test
That’s it. I’ll elaborate a bit on each point.
Write a simple class
Here’s the rocket science class I wrote. It has a single property – name.
var Widget = WinJS.Class.define( |
Add an _initObservable method
var Widget = WinJS.Class.define( |
This is necessary so that “the observablility implementation is completed properly”.
Mix it
WinJS.Class.mix(Widget, |
This adds the necessary bindability to your custom class. If you only want a select few of your properties, you can specify a subset of properties in the parameter for the expandProperties method call. See the Programmatic binding sample to see what I mean.
Instantiate it
Now you’re ready to instantiate your object.
var widget = new Widget("Widget1"); |
Bind the properties
What you’re doing in the binding is specifying a function that you want to run whenever a property is changed.
widget.bind("name", function (newValue, oldValue) { |
Change a property to test
Now, somewhere in your code, change value of that property like this…
widget.setProperty("name", "Hi, Mom!"); |
And there you have it. The simplest possible example I could come up with for data binding a complex object by turning it into the JavaScript version of an observable object.
Happy binding!
navigator.js
If you create a blank JavaScript application in Windows 8, you get just that – a blank application. You don’t get page references to the WinJS library, you don’t get a grid or a list or any other navigation structure, and you don’t get the navigation code to implement the Microsoft recommended navigation method – single page navigation.
If you want to implement navigation, you can obviously just create a new application from the Navigation Appliction template (built-in), but if you’re like me, it’s nice to add in all of a given piece of functionality from scratch for understanding’s sake.
Follow these steps to add navigation to a blank application. And I encourage you to actually type all of the code instead of just copying and pasting. If you type it, your brain will pick it up better.
- In Visual Studio 11, create a new Blank Application using JavaScript
- Add an html folder at the root of your project
- Right click on the html folder and Add | New Item…
- Choose Page Control and call your new item page1.html
Note: You’ll see that you got your new .html file as well as a .css and a .js - Drag the .css file into the css folder and the .js file into the js folder
- Modify the css link reference and js script reference on your html file changing “page1.js” to “/js/page1.js” and “/css/page1.css”
- Grab a copy of navigator.js from any other sample app or template app. You can create a throw-away project from the Navigator Application to get a copy of this file if necessary.
- Modify the navigator.js file changing the name of the namespace to the project name of your application. For instance…
WinJS.Namespace.define("YourProjectName", { ...
- Add a reference to the navigator.js file into the default.html file
- Add a PageControlNavigator to the body of the default.html file like the following…
<span style="background: white; color: black;"> </span><span style="background: white; color: blue;"><</span><span style="background: white; color: maroon;">div </span><span style="background: white; color: red;">id</span><span style="background: white; color: blue;">="contenthost"
</span><span style="background: white; color: red;">data-win-control</span><span style="background: white; color: blue;">="Application2.PageControlNavigator"
</span><span style="background: white; color: red;">data-win-options</span><span style="background: white; color: blue;">="{ home: '/html/page1.html' }"></</span><span style="background: white; color: maroon;">div</span><span style="background: white; color: blue;">></span>
Note: the `data-win-control` makes this an official WinJS control. The data-win-options "home" property tells this control which page to start with and which page to return to when the user elects through the navigator to go home.
Learning a new environment or framework or object model always takes some time and exposure, so take some time, exposure yourself to tasks like this, and have fun.