I must confess, it has been a long time since I wrote something here at the blog, I have been busy doing HTML5, jQueryMobile teaching. Of course I also got the time to work on the next release of XSockets.NET – A new release is coming during xmas!
So, in this post I will give I you an idea of how we cam build real-time web application using two of my favorite frameworks jQueryMobile and KnockoutJS. The real-time parts is built on the XSockets.NET WebSocketServer (framework)
The example is an very simple “Auction” containing a few different views , it’s a single-page-web-app . There is no backend at all except the WebSocket Server, that enables the real-time parts of the auction.
In a few days there will be an enhancement of this simple demo, a complete backend will be implemented, until that I hope you will enjoy this sample.
We must keep in mind that I just want to show an concept, not a complete system, but for those of you that wants more – its coming :-)
Ok lets have a look at the markup
JavaScript and other “dependencies "
<link rel="stylesheet" href="http://code.jquery.com/mobile/1.0/jquery.mobile-1.0.min.css" />
<script src="http://code.jquery.com/jquery-1.6.4.min.js" type="text/javascript"></script>
<script src="http://code.jquery.com/mobile/1.0/jquery.mobile-1.0.min.js" type="text/javascript"></script>
<script src="http://xsockets.net/js/knockout-1.3.0beta.js" type="text/javascript"></script>
<script src="http://xsockets.net/js/JXSockets-0.9.4.js" type="text/javascript"></script>
The auction contains the following views ( JQueryMobile )
Home (page)
The pages contains a couple of menu elements, I will just cover latest, create and details (where you place bids)
<div data-role="header" data-position="fixed">
<h1>
KnockoutAuction</h1>
</div>
<div data-role="content">
<p style="text-align: center">
Welcome to this XSockets.NET show case using jQueryMobile and KnockoutJS - two utterly
good frameworks
</p>
<ul data-role="listview" data-inset="true">
<li data-role="list-divider">Menu</li>
<li><a href="#latest">
<h2>
Latest auctions</h2>
<p>
Show the 15 latest crazy auctions</p>
</a></li>
<li><a href="#search">
<h2>
Find</h2>
<p>
Find things you never thought existed...</p>
</a></li>
<li><a href="#create">
<h2>
Create a new auction</h2>
<p>
Sell ??your surplus stuff...</p>
</a></li>
</ul>
</div>
<div data-role="footer" data-position="fixed">
<h2>
Team XSockets.NET 2011
</h2>
</div>
</div>
Latest
This view contains a list of auctions , by using the data-bind=”” attribute (KnockoutJS) we bind the “listview/template” to the" model using foreach: auctions" , then by adding other data-bind attributes the the child element we gain control of the markup and rendering. I also add a custom attribute auctionid, had some problems adding a “proper” html5 data attribute using the knockout templates. The auctionid attribute will be used to “track” the element later.
<div data-role="header" data-position="fixed">
<a href="//" data-icon="back">Home</a>
<h1>
Latest auctions</h1>
</div>
<div data-role="content">
<ul data-bind="foreach: auctions" id="listofauctions" data-role="listview" data-inset="true">
<li>
<a data-bind="click:function() { auctionModel.show($data) }">
<h2 data-bind="text: Caption"></h2>
<p data-bind="attr: { auctionid: Id }"><strong>Latest bid:<span data-bind="text: Price" class="bid"></span></strong></p>
<p data-bind="text: Description">
</p>
</a>
</li>
</ul>
</div>
<div data-role="footer" data-position="fixed">
<h2>
Team XSockets.NET 2011
</h2>
</div>
</div>
Create a new auction
<div data-role="header" data-position="fixed">
<a href="/" data-icon="back">Home</a>
<h1>
Create</h1>
<a href="#" data-icon="check" data-bind="click: newAuction">Save</a>
</div>
<div data-role="content">
<div data-role="fieldcontain">
<label for="caption">
Caption:</label>
<input type="text" id="caption" name="caption" data-bind="value: auction.Caption, valueUpdate: 'afterkeydown'" />
</div>
<div data-role="fieldcontain">
<label for="description">
Description:</label>
<input type="text" id="description" name="description" data-bind="value: auction.Description, valueUpdate: 'afterkeydown'" />
</div>
<div data-role="fieldcontain">
<label for="price">
Price:</label>
<input type="number" id="price" name="price" data-bind="value: auction.Price, alueUpdate: 'afterkeydown'" />
</div>
</div>
<div data-role="footer" data-position="fixed">
<h2>
Team XSockets.NET 2011
</h2>
</div>
</div>
Placebid ( Details)
Lets the user place a bid. The view contains of three elements bound to the “model”, the <p> tag , (<span )> that is the actual price and the input element.
<div data-role="header" data-position="fixed">
<a href="#latest" data-icon="back">Back</a>
<h1 data-bind="text: bid.Caption">
</h1>
<a href="#" data-icon="check" data-bind="click: placeBid">Place bid</a>
</div>
<div data-role="content">
<h2 data-bind="text: bid.Caption"></h2>
<p data-bind="text: bid.Description">
</p>
<p data-bind="attr: { auctionid: bid.Id }"><strong>Current bid:<span data-bind="text: bid.Price" class="bid"></span></strong></p>
<div data-role="fielcontain">
<label for="bid">
Your bid:</label>
<input type="number" data-bind="value: bid.Price" />
</div>
</div>
<div data-role="footer" data-position="fixed">
<h2>
Team XSockets.NET 2011
</h2>
</div>
</div>
JavaScript
Below is the applications JavaScript code, you will find a quick explanation just below the code snippets
bid: {
Id: ko.observable(),
Caption: ko.observable(),
Description: ko.observable(),
Price: ko.observable()
},
auction: {
Id: ko.observable(),
Caption: ko.observable(),
Description: ko.observable(),
Price: ko.observable()
},
auctions: ko.observableArray([]),
newAuction: function () {
this.auction.Id = guidGenerator();
// Broadcast the new auction to listners and server for storage..
ws.trigger("AuctionCreated", ko.toJS(this.auction), function () {
$.mobile.changePage("#confirmcreate");
});
},
add: function (auction) {
this.auctions.push(auction);
},
find: function (query), { // not yet implemented },
placeBid: function () {
ws.trigger("UpdatePrice", ko.toJS(this.bid), function () {
$.mobile.changePage("#latest");
});
},
show: function (auction) {
this.bid.Id(auction.Id)
this.bid.Caption(auction.Caption)
this.bid.Description(auction.Description);
this.bid.Price(auction.Price)
$.mobile.changePage("#details");
}
};
The JavaScript Code above represents the model of the applications, it contains object, arrays and methods. The model consists of an KnockoutJS observable array that detects and responds to changes on collection of objects, in this case auctions. The model also contains some observable objects (bid, auction) , the model is activated by passing it to applyBindings method of KnockoutJS; applyBindings(auctionModel);
There are some methods that needs to be explained a bit, newAuciton triggers using jXSockets API (sends) a message (JSON) event named “AuctionCreated” to the WebSocket ws . worth mentioning is that we need to serialize the auction object to be sent as JSON using the ko.toJS metod. In the callback of the WebSocket trigger we redirects the user to the “ConfirmCreate” view of out application.
When we are dealing with our bids, w pretty much does the same thing, have a look at he placeBid method below.
The show(auction) method “maps” the event argument of the actual auction to be shown , and changes the jQueryMobile page to details. Not that the auction parameter of method is mapped to the bid object of out viewModel, giving us the possibility to keep track of changes and send those to the view and elements linked to each property of the bid object as shown in this codesnippet (markup)
<p data-bind="text: bid.Description"></p>
The text element of the <h2> and <p> tag is bound to the auctionModels bid object , when we from our array of object generates the markup using KnockoutJS astute template engine giving us the opportunity to bind our observable observable array to a listview widget (control) of jQueryMobile as shown here;
<li><a data-bind="click:function() { auctionModel.show($data) }">
<h2 data-bind="text: Caption">
</h2>
<p data-bind="attr: { auctionid: Id }">
<strong>Latest bid:<span data-bind="text: Price" class="bid"></span></strong></p>
<p data-bind="text: Description">
</p>
</a></li>
</ul>
If we just have a short look at the attributes of the <ul> I suppose that you get point, we got an data-bind attribute saying “foreach:auctions” , this tells Knockout that this is the actual object/array to use for rendering , as you can see in the child elements of the <ul> we got some other data-bind attributes, setting text and attributes of the elements. The <a> tag has an click event defind, telling that when a user click’s we pass the complete auction object to out auctionModel.show(auction)
Inside the detail (placebid) markup above you will find a <a> tag with a data-bind that looks like this;
When the user hits the “Placebid” button the placeBid method of our viewModel is invoked and the following code is executed
$.mobile.changePage("#latest");
});
We just triggers an and WebSockets event named UpdatePrice and passes the bid object, and within the callback there is a simple redirect.
So what's my point then, this may not be so interesting ? As you may noticed we doesn’t deal with any “incoming” messages yet, nothing is changed in the model at all.
Lets have a look at how we wire up the application to listen to those messages we trigger .
Establish connection to the WebSocket and WebSocket handler
The code above creates an new connection to our WebSocket Server and Handler, in this case we just use a generic handler ( Receives and broadcasts all incoming messages to all connected clients)
Is the KnockoutAuction open or close?
By subscribing to the “native” events of the WebSocket (open/close) , inside the callback of open you can se that we triggers an message called “LoadAuctions” , and just passes an empty JSON object, what we do here I simulating a call to a server that will respond with the auctions stored in any kind of database
ws.trigger("LoadAuctions", {});
});
ws.bind("close", function () { });
as there is no backend in this example , I just create some when receiving the “LoadAuctions” message. By binding an eventhandler/subscription for the “LoadAuctions” message as follows
ws.one("LoadAuctions", function (auctions) {
// Add some sample auctions
auctionModel.add(new auction(1, "XBox", "This is a test", 1200));
auctionModel.add(new auction(2, "Playstation 2", "This is a test", 500));
auctionModel.add(new auction(3, "Volvo v40", "This is a test", 4000));
auctionModel.add(new auction(4, "Summer house", "This is a test", 10000));
});
When we receives a messages named “LoadAuctions” I add a few static auctions to the auctionModel by calling the add method of the model. Also note that we are using the .one() method od jXSockets, Why? we just need to listen to “LoadAuctions” once, as we will receive the rest in real-time, as they are created, we don’t need to poll for new auctions all the time…
Listen to new auction
auctionModel.add(auction);
$("#listofauctions").listview("refresh");
});
By just creating a event handler/subscription to the AuctionCreated messages ( triggered from the models newAuctions) we are able to just add it the the models (auctions) , as we use jQueryMobile we also need to refresh the listview widget.
Listen to bids
When a user hits the “Placebid” button ( as shown above) as UpdatePrice message is triggered , the following event handler/subscription will the be invoked.
$("[auctionid='" + auction.Id + "'] span").text(auction.Price);
});
As you see there is an jQuery selecor tracing all the elements containing an attribute called auctionid , the inboud messages id (auction.Id) is appended to the selector then the text node of its child span I set the the “new Price”, this could of can be handled by KnockoutJS and observables as well.
This pretty much explain how the "KnockutAuction” works, and how we can take advantages of WebSockets using the XSockets.NET WebSocketServer.
The code can be studied, executed , edited and tested at jsbin - http://jsbin.com/ukulum/
Links
- KnockoutJS – http://knockoutjs.com
- jQuery Mobile – http://jQuerymobile.com
- XSockets.NET – http://xsockets.net
- This code (Markup, JS etc) - http://jsbin.com/ukulum/ ( Requires a WebSocket compatible browser such as Chrome or Safari)
- XSockets Free CodeCamp in Stockholm January 2012 – Register now! http://xsocketscodecamp2.eventbrite.com/
Magnus Thor


hi magnus, do you happen to have the entire code of this sample available (including the server part)?
SvaraRaderaHi, Yes, the things you see in the demo, they are available above, as well as on the JSBIN url (http://jsbin.com/ukulum/) , The server is very easy to set upp and develop on, just create a new MVC3 Project add the code mention above, and the use Package Manager Console to add the XSockets.NET WebSocket Server ( type Install-Package ) , it is very easy to add more functionallity to it.
SvaraRaderaPlease don hesitate to ask questions, shoot em to my email magnus.thor74@gmail.com or to contact@xsockets.net and we will make sure that you get attention.
Kind regards
Magnus Thor
Cool - but posting an F5'able VS SLN is way easier for you potential users ;)
SvaraRaderaBTW: when will XSockets 1.0 RTM? It has been RC1 for some time, right? Thanks.
SvaraRaderaThe sample @ http://jsbin.com/ukulum does not work - there are a couple of 404s showing up... :(
SvaraRaderaI also tried the client code to move to latest knockout.js and XServer without any success.
Hi, XSocket's has been on RC1 for about 1 month, i will be in RTM in a near by future. We just released a update, and are now gathering feedback such as yours.
RaderaFeel free to email me now, and we can hook up att out G+ Hangout, and give you some instructions / pointers .
The examples in JSBIN in based on the old 0.9.x version, and is no longer something that we maintain, bu there are a bunch of other samples in the samt area. Joing our hangout now?
Here is the URL to the hangout..
SvaraRaderahttps://plus.google.com/hangouts/extras/talk.google.com/xsockets
I was hanging out there all day (CET) ... :) Nobody else showed up.
SvaraRadera