Tag Archives: JavaScript

Part 7: Sharing Data in Knockout Components (2/2) – Events and Messages

In my previous articles I’ve shown how to build KO components that start off with a data source of their own and are pretty self contained with respect to interactions with the rest of the page. But, in the first part of this article we built a tree control that’s I am planning to use as an Index page. So an action like ‘Clicking’ a link needs to affect another part of the application/web page.

Beauty (and often the bane) of JavaScript is that there are multiple ways to do this. You could go low down to core JavaScript event handling or jQuery event handling quite easily. However, the beautiful View-ViewModel separation that you have created using KO Components would be completely ruined if you had to know the ID of the UI element to hook an event handler in another component or in the parent page for that matter.

Solution? A light weight message passing system, that subscribes to events for you and publishes the event to all who have subscribed.

Message passing whaa…

Did you just wince at the sound of ‘message passing system’, fear not, it’s not rocket science, in fact it’s pretty simple. Take the two scenarios below.

Scenario 1

The good ol’ fashioned jQuery way of handling events. You take a document element and attach an event handler function to it. When the event occurs the attached function is called. You can do this anywhere in your JavaScript code, only requirement is that the element referred to by the id is available in the HTML DOM.

Here, reference by the id of the element, breaks the model view separation where the View Model has explicit knowledge of the View’s elements. This is hard coupling and should be avoided.

Scenario 2

Instead of attaching our event handler code directly, we list our function in a centrally located – let’s call it a ‘registry’ for now, using a unique string key.

Next when the particular event happens we tell the ‘registry’ that a ‘named’ event has happened and that all subscribers should be notified.

The registry takes the name and looks up to see if any functions where registered against it, if so, those functions are called.

Thus, by using a central location for registering event names and their handlers, we have decoupled View and ViewModel. Now View can raise an event, ViewModel handles the event via KO’s event handling mechanism and then tells the central registry to dispatch a named event to all the subscribers.

The subscribers need not be a part of this ViewModel, they could be part of any ViewModel on the page. They would register to listen of the ‘named event’ by providing an event handler function. This is the key, no ‘ids’ need to be shared across ViewModels.

Once the named event occurs the event handler functions are called.

Using AmplifyJS

Now that we’ve got an idea of how we can decouple the UI from the view model and still pass data around components, let’s use AmplifyJS as our ‘events broker’ and see what it takes to implement it.

Amplify was created by the team at http://appendto.com/team and is made available under MIT and GNU OSS licenses.

Installing AmplifyJS

Installing AmplifyJS is easy. Use nuget package manager console and install package using the following command

install-package AmplifyJS

This will create a Scripts/amplify folder and put each amplify component in a separate file here. It will also place amplify.js and amplify.min.js in the Scripts folder. Since we’ll be using the entire library we’ll delete the separate component files and move the amplify.* files from Scripts to Scripts/amplify

Since we’ll need Amplify globally to watch over all messages passed to and from it, we’ll set it up in the configuration require.config.js as highlighted below

var require = {
    baseUrl: "/",
    paths: {
        "bootstrap": "Scripts/bootstrap/bootstrap",
        "historyjs": "Scripts/history/native.history",
        "crossroads": "Scripts/crossroads/crossroads",
        "jquery": "Scripts/jquery/jquery-1.9.0",
        "knockout": "Scripts/knockout/knockout-3.2.0beta.debug",
        "knockout-projections": "Scripts/knockout/knockout-projections.min",
        "signals": "Scripts/crossroads/signals",
        "text": "Scripts/require/text",
        "app": "app/app",
        "underscore": "Scripts/underscore/underscore",
        "amplify": "Scripts/amplify/amplify.min",
    },
    shim: {
        "bootstrap": {
            deps: ["jquery"]
        }
    }
}

Updating tree-node to handle click event

We update the tree-node view to wrap the text span in an anchor, and attach a click handler

<ul class="nav nav-stacked" style="padding-left:10px">
    <li class="nav list-group-item-heading selected">
        <div class="row">
            <div class="col-sm-1 hidden-xs">
                <!-- ko if: nodes().length > 0 -->
                <!-- ko if: expanded() -->
                <a data-bind="click: changeState" role="button" href="">
                    <i class="glyphicon-minus"></i>
                </a>
                <!-- /ko -->
                <!-- ko ifnot: expanded() -->
                <a data-bind="click: changeState" role="button" href="">
                    <i class="glyphicon-plus"></i>
                </a>
                <!-- /ko -->
                <!-- /ko -->
            </div>
            <div class="col-sm-5">
                <a href="" data-bind="click: nodeClicked">
                    <span data-bind="text: title"></span>
                </a>
            </div>
        </div>
    </li>
    <!-- ko if: nodes().length > 0 && expanded() === true -->
    <!-- ko foreach: nodes -->
    <li>
        <tree-node params="node: $data"></tree-node>
    </li>
    <!-- /ko -->
    <!-- /ko -->
</ul>

In the viewModel we handle the click event and raise

The following snippet handles the click event

self.nodeClicked = function (currentNode) {
	currentNode.expanded(!currentNode.expanded())
	alert("hello " + currentNode.title());
}

First up it simply raises an alert that says hello with the name of the node. We have also setup the node to flip the expanded flag.

If we run the application now and click a node, we’ll see the popup.

image

So far so good. The node has directly responded to the click event.

Raising Event using Amplify

In the tree-node.js’ nodeClicked function we can ‘raise’ an event or pass message to our queue that the click event has happened. To do this we first add reference to amplify in our module. Since we have registered it globally all we have to do is use its alias:

define(["knockout", "text!./tree-node.html", "amplify"], function (ko, treeNodeTemplate) {

Next we upload the clicked event function as follows:

self.nodeClicked = function (currentNode) {
	currentNode.expanded(!currentNode.expanded());
   var nodeName = currentNode.title();
   amplify.publish(&amp;quot;CurrentNode-NodeClicked&amp;quot;, nodeName );
}

As you can see the call to ‘raise’ or ‘publish’ the event via amplify is pretty simple. All we have done is specified a string key, and then passed on the value we want to event receiver to get, which in this case is the nodeTitle. We could have passed the entire node if we wanted.

Note: I have removed the alert from the nodeClicked Event. Now we need another component to subscribe to this event and handle it when it occurs.

The ‘Content Pane’

The node click is supposed to be handled by a ‘Content Pane’ component that pulls content from another source. For brevity, I’ll ‘re-use’ the greeter component. We update the greeter component such that it handles the click event and updates the greeting.

First we add reference to Amplify

define(["knockout", "text!./greeting.html", "amplify"], function (ko, greeterTemplate) {

Next we add a ‘subscription’ for the event and update the greeting text

    function greeterViewModel(params) {
        var self = this;
        self.greeting = ko.observable(params.name);
        self.date = ko.observable(new Date());
        amplify.subscribe("CurrentNode-NodeClicked", function (value) {
            self.greeting(value);
        });
        return self;
    }

As we can see, subscribing to the ‘event’ is as simple as

– Specifying the same key that we published it with,

– Providing a function that will be called when the event happens.

In the function we have changed the greeting property of the viewModel.

Now we add the greeter page component in the docs.html

<div class="container">
    <h1>SilkThread Documentation</h1>
    <p>
        This page serves as the root for SilkThread documentation.
        It is itself built with SilkThread and we'll see how muliple
        web-components can be put together to create a neat App.
    </p>
    <div class="row">
        <div class="col-lg-3">
            <tree params="data: data"></tree>
        </div>
        <div class="col-lg-9">
            <greeter></greeter>
        </div>
    </div>
</div>

Demo Time

We are all set, when we run the app initially we come up with this

image

When we click on Node 0 the greeting changes to

image

Also note that the node has collapsed because of the code we wrote to toggle the expanded state.

Conclusion

This light weight message Publishing-Subscribing system is an established pattern often referred to as Pub-Sub. It is a very useful pattern in terms of decoupling interactions. It is used not just in JavaScript, it can be used in highly scalable backend systems.

SignalR is another example of a Pub-Sub system that maintains subscribers on the server and publishes actions to all connected clients. But it is used across server and client systems.

So as you can see the Pub-Sub system is a versatile software development pattern that we leveraged on the client side today.

That concludes this sub-series of my overall Silkthread series. Next we will see how we can use Amplify to make http requests and send data to server and retrieve data back.

The code as always is on Github. This specific branch is saved as Part7-2.

Advertisements
Tagged , , ,

Part 4: SPA with KO Components-PushState and History JS

In the previous three parts we have seen:

At the end of the third article we saw some problems with hash based routing primarily in terms of accessibility and search engine indexing. Also the fact that hashed URLs are semantically incorrect gives us enough reason to look for alternatives.

Today we’ll explore how we can overcome some of these problems and discover some new ones Winking smile.

HTML5 and manipulating browser history

HTML5 pushState usually refers to a set of APIs that HTML5 browsers can support, to give more control to the developers on the Browser URL and the Browser’s back button behavior. These include pushState, replaceState and the event popState. Here is a nice primer on pushState on developer.mozilla.org.

Essentially, when you want to add a URL to the history you push the URL into browser history using pushState. This is done for free when you click on a link (or type in the URL) and a server returns the page. However, if you wanted to build an AJAX based navigation system where you want to intercept all link clicks and show content dynamically loaded via AJAX, the browser doesn’t know the URL’s correlation to the content. So you have to tell it explicitly what the URL is (e.g. when we are showing the ‘Settings’ page, the URL should be /settings). HTML 5 pushState and related APIs make this easier for us.

Ajax based apps also have had trouble with the browser back button. As users we are trained to hit the big honking ‘Back’ button on the browser when we want to go back to the previous page. This is correct expectation and our Web Apps should respect that. Doing AJAX based page/component loading can break this because you may have content loaded based on user interaction that is not recoverable when user hits the back button.

So ideally we should use the new found ‘pushState’ functionality to indicate on the URL the exact location of the current content that is being shown. Thus when a user hits the back button we can use the URL to load up the previous content again. Back button in HTML5 browsers fire a popState event that can be handled for these purposes.

Doing all this manually is a bit of boilerplate. In Part 3 we saw how crossroads+hasher does it (Back button is fully supported for # URLs. Today we’ll see how we can use another library called History.js. Reason for exploring History.js is that it supports the new pushState API and falls back on Hash-based routing for browsers that don’t support pushState, (one such browser, is IE9 and when I started, one of my ‘undeclared’ goals was to support IE9 and up).

Replacing Hasher.js with History.js in our sample

You can get the last version of my sample from the Part 3 branch on Github.

You can clone the History.js repo from Github here.

Your cloned folder should look like this:

image

The Scripts folder has the following the sub-folders. Mechanics behind these folder is actually pretty neat.

image

History JS Components and Dependencies

History JS depends on availability of the JSON object so for older browsers that don’t have JSON parsing built in, it refers to JSON2.js. It bootstraps itself differently based on what library you are using. So there are various adapters that bootstraps History JS correctly with the respective library.

image

The bundled* folder contains one file per-adapter. Each file contains JSON2.js, the respective Adapter and the entire HistoryJS library. So all you have to do is pick the file from either the bundled-uncompressed\ folder or if you want to use the minified version use the same file from the bundled\ folder. Note there are two subfolders under bundled\ folder – html4+html5 and html5. If you don’t want to support HTML4 the library is trimmed a little further, but we want it, so we’ll dive into the html4+html5 folder.

If you want to experiment with adapters you can pick the adapter and the History.JS file from the compressed or uncompressed folders.

In my sample I’ve picked the native.history.js file from the bundled-uncompressed\html4+html5 folder.

Adding History JS and loading via RequireJS

  1. Since it’s a base library we’ll put it in it’s own folder under Scripts

image

2. Next we update the App\boot\require.config.js to load HistoryJS after bootstrap is loaded and remove the Hasher.js dependency.

image

3. Modifying our Router: We will need multiple changes in our Router.js file to configure it to use History.js instead of Hasher.js.

a. We start by adding historyjs dependency in the module definition

image

b. Handling anchor clicks to prevent server requests directly: This is actually a big deal. Typically we navigate to a different page by specifying an Anchor tag that has a href pointing to the new page. It may be a full path or partial path. When user clicks on an anchor the request is sent to the server by the browser. When using Hasher we worked around this by using href’s that started with a #. This told the browser that the reference was in the current page itself and then we hooked into the event and did our AJAX magic to load a new page. This also had the side effect of putting a # in the URL irrespective of the browser.

To avoid # in the hrefs, we need to handle all href clicks globally and push the path to HistoryJS for managing and raising statechange events.

To do this we assign a click handler for all URLs inside the HTML body tag. We check if the href attribute starts with a #, it means it’s a deliberate reference to some place in the current page and we let the event pass through. If the href doesn’t start with a # we push the path to History using the pushState function. Note we are not using window.pushstate because we want History to manage the pushState for older browser that don’t have a native implementation.

image

c. Next we update the activateCrossroads() function to intercept HistoryJS’ statechange event and pass the new path to crossroads:

function activateCrossroads() {
History = window.History; // # 1
History.Adapter.bind(window, “statechange”, function () { // # 2
        var State = History.getState();
if (State.data.urlPath) { // # 3
return crossroads.parse(State.data.urlPath);
}
else
{
if (State.hash.length > 1) { // # 4
                var fullHash = State.hash;
var hashPath = fullHash.slice(0, fullHash.indexOf(‘?’));
return crossroads.parse(hashPath);
}
}
});
crossroads.normalizeFn = crossroads.NORM_AS_OBJECT;
crossroads.parse(‘/’); // #5
}

#1: Gets instance of the HistoryJS. Next we bind a event handler for the “statechange” event.
#2: The event handler is fired every time a new URL is pushed using pushState. In a browser this happens automatically when we click on an anchor tag. But clicking on an anchor tag that doesn’t start with a hash # results in a get from the server. We want to control this
#3: If the State.data has a valid urlPath we extract the urlPath from state provided by HistoryJS and pass it to crossroads to navigate to. However if users bookmark the path, then the urlPath comes in null. The next bit of code handles this
#4: If the urlPath is undefined, then we check if the State’s hash length is > 1. This is an indicator of a bookmarked URL and we slice out the path that crossroads needs and let crossroads navigate to it.
#5: This is invoked on activation and by default our router navigates to the home page.

Testing it out

Well, we have made all changes we need so it’s a good time to test it out. I have deployed it to Azure websites via Github deploy, so as soon as I commit to the master branch it updates the http://buildingspausingko.azurewebsites.net/ (which unfortunately is down due to unscheduled Azure maintenance at the moment, so instead of my VM accessing the site, we’ll ‘fake it’ using IE11 DOM manipulation).

On IE11 the site navigates cleanly

imageimage

I emulate IE9 DOM on IE11 and I get the rather ugly hash based URL.

image

Well, old browser users have to live with some ugly stuff unfortunately. But here is the good part, if users bookmark that URL, History JS will do it’s best to return users to the same URL.

Code for this release is at https://github.com/sumitkm/BuildingSpaUsingKO/tree/Part4

Conclusion

So we’ve now replaced the Hash based routing of Hasher.js with the pushState based one by HistoryJS. We have also seen how HistoryJS gracefully falls back when using older browsers.

With that I’ll end this article here and push the server side manipulation to the next part.

Just so you know, on modern browsers that support pushstate currently if we visit the /settings page directly it will show us an invalid URL.

image

Ideally it will show a 404, but my 404 redirection is broken so it’s showing this weird error. Eitherways, we’ll end up with an error. In the next part we’ll see how we can fix this.

Tagged , , , , , ,

Part 3: KO Components – Routes and Hashes

Part 1: Dipping your feet into Knockout JS Components
Part 2: Knockout Components – Separating Templates from View Model

As we continue our journey to learn more about KO Components, today we look at how we can  navigate around different ‘views’ and manage hyperlinks.

There are multiple libraries out there that allow you to do this. Today we’ll see how to use Crossroads for routing and Hasher for managing URLs. They internally use the Signals JS library. All three are written by Miller Medeiros. Now you could do all things these three libraries to with Sammy.js too. I will probably look at Sammy.js at some point in future, but Sammy is more opinionated on how it does routing and event handling, while I wanted to go one level lower and fiddle around myself. BTW I am in no way promoting one over the other, just that today’s sample uses Crossroads, Hasher and Signals.

Adding dependencies

All three libraries are not available as Nuget packages so we’ve to get them from their Github Repos directly. I have linked to the repos above.

Apart from the above three we will also use knockout-projections extension library by Steve Sanderson. This provides helper methods to deal with KO arrays.

I have downloaded them and added to the solution resulting in the following folder layout:

image
Figure 1

Updating require.config.js

We update the require.config.js to add the additional references so Require knows where to get them from as and when required.

var require = {
baseUrl: “/”,
paths: {
“bootstrap”: “Scripts/bootstrap/bootstrap”,
“crossroads”: “Scripts/crossroads/crossroads”,
“jquery”: “Scripts/jquery/jquery-1.9.0”,
“knockout”: “Scripts/knockout/knockout-3.2.0beta.debug”,
“knockout-projections”: “Scripts/knockout/knockout-projections.min”,
“signals”: “Scripts/crossroads/signals”,
“hasher”: “Scripts/crossroads/hasher”,
“text”: “Scripts/require/text”
},
shim: {
“bootstrap”: {
deps: [“jquery”]
}
}
}

Restructuring the App layout and adding a page

Since we are going to demo navigation, it’s good to have at least one more page to navigate to. So we’ll introduce a loosely coupled concept of ‘page-components’. These are basically registered as ko.components but they are containers and in turn use other ko components.

As I said in my previous article the folder structure I was using is pretty arbitrary and open to updates.

Under App we will add a pages folder which will have all our ‘page’ components. I have added two, home and settings.

image
Figure 2

The home page-component

The Home page component has the standard HTML + JS structure. I have in-fact taken out the greeter instances from Index.html. We’ll see how we can pass data between two components. We’ll add a collection of ‘guests’ in home view model which will be passed to the greeter component. So our home.js will be as follows:

define([“knockout”, “text!./home.html”], function (ko, homeTemplate) {
function homeViewModel(params) {
var self = this;
self.title = ko.observable(‘Dipping your feet into KnockoutJS’);
self.guests = ko.observableArray([]);
self.guests.push({ guestName: “Sumit” });
self.guests.push({ guestName: “Optimus” });
self.guests.push({ guestName: “Bumblebee” });
return self;
}
return { viewModel: homeViewModel, template: homeTemplate };
});

We have put the header text in a property called title. We also have an observable array of guests who the greeter component needs to greet. Instead of hard-coding the names this could have come from a server API call.

The home.html is as follows

<h2 data-bind=”text: title”></h2>
<hr />
<!– ko foreach: guests –>
<greeter params=’name: guestName’></greeter>
<!– /ko –>
<pre data-bind=”text: ko.toJSON($data, null, 5)”></pre>

We have bound the title to the header element.

Next we have a standard ko foreach that loops through each element in guests collection. The params attribute takes a JSON snippet so we pass it appropriately as name: guestName. KO can evaluate the observable and pass the appropriate value to the greeter component.

Setting up Routing using Crossroads and Hasher

In Figure 2 above you’ll note we have a new file called router.js.

The Router is defined as an AMD module. It takes in an object with the property routes that has an array of routes that are ‘registered’. So the routes property is going to hold all our routes.

As of now we have defined two routes, one is the home page that is at the root of the site and the second is the settings page that should be at the /settings URL.

When the module is initialized the Router function is invoked (acts as the ‘constructor’) with the routes defined. These are added to crossroads. I have added a method to log every routing event to the console.

The activateCrossroads function sets up Hasher to listen for hash changes and on change invoke crossroads to do the routing.

/// <reference path=”/Scripts/crossroads/crossroads.js” />
define([“jquery”,”knockout”, “crossroads”, “hasher”], function ($, ko, crossroads, hasher) {

    return new Router({
routes: [
{ url: ”, params: { page: ‘home’ } },
{ url: ‘settings’, params: { page: ‘settings’ } }
]
});

    function Router(config) {
var currentRoute = this.currentRoute = ko.observable({});

        ko.utils.arrayForEach(config.routes, function (route)
{
crossroads.addRoute(route.url, function (requestParams)
{
currentRoute(ko.utils.extend(requestParams, route.params));
});
});
crossroads.routed.add(console.log, console);
activateCrossroads();
}

    function activateCrossroads() {
function parseHash(newHash, oldHash){
crossroads.parse(newHash);
}
        crossroads.normalizeFn = crossroads.NORM_AS_OBJECT;

        hasher.initialized.add(parseHash);
hasher.changed.add(parseHash);
hasher.init();
}
});

With routing all set, let’s setup the Index page and register the new components before we can test out our changes.

Updating the Index.html page

The Index page has now become a nearly empty shell. We will add two links in the header, one for Home and the other for Settings page.

<div class=”navbar navbar-inverse navbar-fixed-top”>
<div class=”container”>
<div class=”navbar-header”>
<button type=”button” class=”navbar-toggle” data-toggle=”collapse” data-target=”.navbar-collapse”>
<span class=”icon-bar”></span>
<span class=”icon-bar”></span>
<span class=”icon-bar”></span>
</button>
<a class=”navbar-brand” href=”/”>KO Components</a>
<ul class=”nav navbar-nav”>
<li>
<a href=”#”>Home</a>
                </li>
<li>
<a href=”#settings”>Settings</a>
                </li>
</ul>
</div>
</div>
</div>
<div id=”page” class=”container” style=”padding-top:50px” data-bind=”component: { name: route().page, params: route }”></div>


By default the page will land at the Home page and when user clicks on Settings the routing library will take it to the Settings page (or back to home page depending on the link clicked).

The div with id=page is our equivalent of RenderBody in MVC. The current page as defined by the route with be displayed here. As you can see it is using a div to bind any component that is presented to it by the router. If you remember we have setup two routes with page names home and settings. So these are the names of our home and page components. Let’s register them in startup.js.

Registering new components

We’ll add the two new components to startup.js and also initialize our router and pass it to ko as root view model.

To initialize router we use Require’s module loading to request for it in the required collection. Note the syntax ./router. This is because router.js is not a part of the Scripts folder rather it is in the same folder as the startup.js and also the fact that it’s not defined in require.config.js.

Another difference to note is how we are setting up settings component. This is the way to setup HTML only components that have no Javascript associated with them.

The home component is registered like greeter as we had done before.

define([‘jquery’, ‘knockout’, ‘./router’, ‘bootstrap’, ‘knockout-projections’], function ($, ko, router) {
ko.components.register(‘greeter’, { require: ‘App/components/greeter/greeting’ });
ko.components.register(‘home’, { require: ‘App/pages/home/home’ });
    ko.components.register(‘settings’, {
        template: { require: ‘text!App/pages/settings/settings.html’ }
});
ko.applyBindings({ route: router.currentRoute });
});

With our components registered, we are all set to try it out.

Demo time

When we run the app, and see the Debug window, you will notice we have downloads the styles and templates that pertain to the Index page, the Home page and the greeter component. The Settings component has not been downloaded yet.

image

Now if you clear the Network activity window and click on Settings, you will note that only one file is downloaded and that is settings.html. This may seem insignificant for this demo, but has a huge impact when your applications grow big and have hundreds of components (yes, they can have 100s of components, just take my word for it Winking smile).

image

It is all the more fun to note that now if you switch back to Home page no components are called from the server because the browser has everything it needs, so unless you want to force refresh the page with data from server, navigating between pages is as fluid as a client app!

image

So we have navigation between pages and just in time loads. What about the dreaded browser Back button? Well, if you play around with it, you’ll notice back button works perfectly fine and crossroads is able to switch between views thanks to Hasher monitoring hash changes. Excellent, we could have stopped here and gone home happy but…!

Hashes in URLs, bot accessibility and best practices

If you were a observing keenly, you would have noticed that when we navigated to settings page the URL is /settings instead it is #settings. This is because we are using the age old # prefix to prevent the browser from hitting the server when someone clicks on a link. Now you realize what Hasher is doing. It’s listening to the hashchanged event and invoking crossroads (albeit in a cross browser compliant way).

This gives us a problem where our URLs are not semantic. This is a headache from bot accessibility because search robots don’t really ‘invoke’ AJAX calls to get new views when they encounter a # url. There is a nice series by Derick Bailey on drawbacks of hash URLs on Los Techies site.

As you will see from his articles, HTML5 pushState comes to the rescue to a large extent. I say large extent because once we get pushState into picture we have to start looking at the server side as well because if you don’t have # in your URL, bookmarked URLs will directly request the server to serve the URL e.g. the /settings page. In our case there is no /settings page only index.html that uses client side manipulation to get you to /settings URL. But fear not, we’ll work everything out.

Pushstate is important enough to warrant a separate article in itself. You can refer to Derick’s article for the basics, his sample is in Backbone.js and Rails. You should be able to grasp the idea, but either ways I will do it in KO and ASP.NET MVC.

Side note – Google search and Hashbangs ( #! )

Once AJAX apps became popular Google came up with a suggestion for appending a bang ( ! ) after the hash to make it apparent to search engines that the URL warranted an AJAX call, but after the initial rush to hashbang everything, the industry settled back into semantic URLs primarily because of problems associated with handling #! at the server and it’s non-standard nature.

Source Code

I have branched the master out part Part3 and it is available on Github at https://github.com/sumitkm/BuildingSpaUsingKO/tree/Part3

Tagged , , , ,

QuickBytes: Visual Studio 2013 and JavaScript Debugging

Yesterday I found out something new about Visual Studio. Documentation indicates that it has been with us since VS 2012 (maybe earlier) but I encountered it yesterday.

I have a MVC4 project created in VS2010 and some CSHTML files have accrued some JavaScript crud in form of inline <script>…</script>. I usually refactor them out whenever I can but yesterday I was doing something else and wasn’t in a position to refactor the code at that point. So I tried to put in a breakpoint inside one of these script chunks and I couldn’t. So far, I’ve put breakpoints in the runtime page that comes up in Visual Studio’s Solution Explorer and they were are hit when executing in the browser, but yesterday I couldn’t even set a breakpoint.

After a little bit of ducking around I found that you could add the following line in the JavaScript to force the debugger where you want to start debugging and then continue with F10/F11 as usual

debugger;

I was initially indignant at Visual Studio that it ‘made’ me do this by default instead of allowing me to set the breakpoint. Looks a step backward, but then I realized that it was likely some setting in my Dev Setup is not right. I haven’t had a chance to investigate what’s not right, and I used the above hack to resolve my current issues. If you know of a way that kicks VS2013 into enabling breakpoints in inline JS code, do let me know.

Inline JS code is BAD and shouldn’t be used, period. But at times when you are prototyping you tend to take liberties, also not everyone in the team has 15 years of experience writing code, so cruft sometimes comes in. If VS is forcing my hand by making me write clean JavaScript code by default, that’s good, but I also want to know the ‘evil’ way to workaround Winking smile, Cheers!

Tagged , ,

Welcome #TypeScript – a.k.a. the Future is JavaScript

Disclaimer: It’s 4 am in the morning, and I have to get this out of my system. Apologies if I sound like I am rambling.

[Update October 2, 2012: If you want a ‘no-rumor’ Introduction to TypeScript head over to my post on www.devcurry.com]

What is TypeScript?

A few hours ago Anders Hejlsberg the father of C# and Microsoft Fellow launched to the world, via a Channel9 Video his latest baby – TypeScript, a type conformant superset of JavaScript that compiles down to JavaScript as of now. Nearly simultaneously Microsoft Developer Division’s head honcho Somasegar announced it on his blog as well. The site www.typescriptlang.org went live too.

Initial Reaction

My first initial reaction was knee-jerk and ‘why another Dart’ and ‘this is Java all over again’. Lots of .NET devs had the same reaction (refer to the first comment on the thread in the Channel 9 video) Smile.

After I watched the entire video, I would be lying if I said I don’t like TypeScript. As much as I hate to learn new syntax again, the pervasiveness of JavaScript has hit me over the last few years and grudgingly (at first, and out of a a necessity now) I have adopted JavaScript (rather JS Frameworks) as essential additions to my web development toolkit.

Good parts about TypeScript are

1. Follows the developing ECMAScript6 standard proposal and is going to keep updating itself till the proposal is adopted.

2. Will emit JavaScript making it truly write-once run anywhere.

3. Superb tooling support.

[Update]

4. How can I forget, it’s open source and code is on the next hippest thing to GitHub (Git on Codeplex).

[/Update]

Something like TypeScript is heaven sent for C# junkies like me. So in short am I interested in TypeScript? Hell yeah!

Conspiracy Theories

What’s Microsoft without a few conspiracy theories? My favorite MS gossip source is @MossyBlog from www.riagenic.com. Sometime ago he tweeted that MS is planning to kill .NET. No one took him seriously. But now let me conspire and cook up a few theories of my own, with tongue firmly planted in cheek here I go:

1. TypeScript is DevDiv’s revenge for killing of Silverlight. Silverlight was killed in Win8 in favor of JavaScript and HTML5 and WinJS was cooked up hastily. TypeScript is the comeback kid. It’s JavaScript, it works with the HTML5 story and as per Soma you can build Win8 apps using it. Woo hoo! Strike 1 DevDiv.

2. TypeScript is open source! BAM! Take that WinDiv! Strike 2 DevDiv.

2. Embrace evolution of .NET: Developers all over the world will have to embrace the evolution of .NET. In other words, soon there will be only C, C++, Assembly at low level and JavaScript at high level. Everything else will be JavaScript emitter. So by next release of Windows you will probably having a C# compiler that emits JavaScript (ECMAScript 6).

3. I will go out on a limb and say, the Windows Desktop as we know today is in it’s last iteration. Next version of Windows will boot to a ‘desktop replacement’ that runs on the IE engine. WinJS Apps already do this today. Tomorrow everything will be JS. Boot to the web! In your face ChromeBooks!

4. Don’t hate on the phrase ‘Application Scale’ it only means applications as rich as Silverlight/XAML and WinForms. Now for the biggest JavaScript fan will also admit that JavaScript wasn’t the best for these things.

5. TypeScript might just be the convergence point of DevDiv and WinDiv where they call a truce and live happily hereafter Winking smile.

Signing off

As someone who skipped the XAML/Silverlight bus, I never really got worked up with the so called death of Silverlight or WPF. Only now I have started using XAML and I say good riddance. WinRT may not be perfect, but a fresh start is fine.

But the nagging question for millions of Silverlight folks around the globe, why did MS have to kill SL, well they didn’t, they were busy building TypeScript, an eventual successor for it!

Tagged , , , ,
%d bloggers like this: