
Introduction
Couple of months back I wrote an article titled TaskTracker OffLine Web Application for Mobile using HTML5,JQUERY-UI and KNOCKOUT.js In that the focus of the article
was offline programming using HTML5 and explore the features of different powerful frameworks such as JQUERY,JQUERY-UI and KNOCKOUT. This article is an extension of it and covers
some additional features such as HTML5 Canvas,Integration with back-end database using JQUERY AJAX and AJAX Enabled WCF Service. Key features
explored in this article are given below.
- Application Cache, Webstorage and Canvas features of HTML5 are used in this application
- Jquery AJAX makes your asynchronous programming easier and enables you to interact with Web Services from the Javascript.
- AJAX Enabled WCF Service and Entity Framework
Background
SPC is a very important part of quality control in any manufacturing process.Currently the data capture process for doing SPC analysis is mostly manual.This is mainly due to harsh environment in
the shop floor and it is difficult to use conventional computer or laptop there.So with the advancement in smart phone technology it is now possible to write an application for this purpose to automate
the data capture process and do the quick SPC Analysis in real time.Also with key features such as offline programming of HTML5 you can now save data locally in the absence of internet and then save it to back end
database once connected to internet for future analysis.
Hence Real Time SPC (Statistical Process Control) Application for iPad/Android Tablet will be very useful to Engineering,Manufacturing or Process Industries.This will enable quality inspectors and operators of
this industry to capture data in real time from the shop floor and do quick SPC analysis and check control charts in Real Time to ensure that the manufacturing process is in control.
You can check the working version of the application here.
Design Overview
The application is built using popular MVVM design pattern. MVVM is a design pattern very similar to old MVC design pattern and addresses the separation of concerns.
Like MVC it has model,view,but controller role is done by ViewModel. View Model is responsible for handling user interactions and also interacts with model
and updates the view. It can have additional attributes apart from Model which can be view specific. Also in a complex web application comprising of multiple views,each view
can have corresponding view model. In our application there is only one view and one view model. The key files of the application are newmain.html,SPCNewController.js,StorageController.js,controlCharts.js,
SPCAjaxHelper.js and SPCService.svc
The class diagram of the application is shown in Figure 1.

From the figure 1, RealTimeSPCUI class is a conceptual class and represents the UI for the application and is implemented as plain html. SPCViewModel is a key class
responsible for handling all the user interactions and updating the view and interacts with model. Measurement is an entity class which acts as
a model for this application.StorageController is a wrapper class and is responsible for saving and retrieving data from WebStorage.
XBarRangeChart is class responsible for control charts.
SPCAjaxHelper is a Helper class for handling JQuery AJAX interaction with WCF Service class
SPCService
Since Java script is not like conventional object oriented programming languages such as C++, C# or Java and it does not have Class construct. So all the classes are implemented differently.
I will first explain the business layer implementation,then the data layer and finally UI
Business Layer
Business layer consists of one key entity Measurement and represents Model. Another important class is a SPCViewModel
Below section shows the implementation details of Measurment class.
function Measurement() {
var self = this;
self.parameter= ko.observable("");
self.id = 1,
self.TimeStamp = ko.observable($.datepicker.formatDate('yy-mm-dd',new Date())),
self.PartNo = ko.observable(""),
self.Machine= ko.observable(""),
self.Operator=ko.observable(""),
self.Parameter= ko.observable("Inner Diameter");
self.P1=ko.observable(0),
self.P2=ko.observable(0),
self.P3=ko.observable(0),
self.P4=ko.observable(0),
self.P5=ko.observable(0),
self.PAve = ko.dependentObservable(function () {
var aveValue=(eval(self.P1())+eval(self.P2())+eval(self.P3())+eval(self.P4())+eval(self.P5()))/5;
return Math.round(aveValue*1000)/1000;
});
self.PRange = ko.dependentObservable(function () {
var m= Math.max(self.P1(),self.P2(),self.P3(),self.P4(),self.P5());
var n= Math.min(self.P1(),self.P2(),self.P3(),self.P4(),self.P5());
return Math.round((m-n)*1000)/1000;
});
}
var curMeasurement = new Measurement();
var machine= curMeasurement.machine(); curMeasurement.machine('M1');
If you see at the above code you might have noticed that the class contains only properties as it is an entity class
and do not expose any methods. But also you might have noticed that these properties are initialised with knockout constructs.These properties
are declared as observables.This will enable these properties bind to UI and will provide two way binding. So any changes
done to these properties in UI will automatically update the properties. Or if you change their values programmatically,then it will reflect those changes
in UI. One thing to remember is that the knockout observables are functions and you can't access or initialise them as normal properties. Also notice the
declaration for dependent observable properties. These properties are derived from other properties.
See the above code showing example of setting and accessing knockout observable property.
Let us now see the implementation details of SPCViewModel.This is the key class responsible for handling user interaction and
will update the UI and model.
function SPCViewModel() {
var self = this;
self.onLine = ko.observable(false);
self.filterDate = ko.observable("");
self.filterPoints = ko.dependentObservable(function () {
var partno = self.lastPart();
var parameter = self.lastParameter();
return ko.utils.arrayFilter(self.dataPoints(), function (item) {
var cp, cparam;
if ($.isFunction(item.PartNo))
cp = item.PartNo();
else
return false;
if ($.isFunction(item.Parameter))
cparam = item.Parameter();
else
return false;
if ((partno === cp) && (parameter === cparam))
return true;
else
return false;
});
});
self.removeMeasurement = function (iDP) {
self.dataPoints.remove(iDP);
var mDP = ko.toJSON(self.dataPoints);
self.normalDP = JSON.parse(mDP);
tsk_ns.storage.saveItem("measurments", mDP);
self.updateDPArray();
};
self.editMeasurement = function (iDP) {
self.selected(iDP);
self.currentDP(iDP);
self.taskMenu("Edit Data");
$("#accordion").accordion("activate", 0);
self.editFlag = true;
};
}
SPCViewModel is a core class of this application and is responsible for handling user interactions
and interacts with model and updates the view. The above code is not complete source code,but just highlight key methods.
The view model has two observable array defined for storing all measurment points. Also note the use of dependent observable
to filter the measurment points by filtering criteria.The key methods are responsible for following tasks.
- Retrieve and Save Measurment data to local webstorage.
- Retrieve and Save Measurment data to back-end database
- Analyse data and display data in tabular fashion
- Update Control Charts
Also note that the status of internet connection is updated in real time and the buttons used to save the data to the database and retrieve history are
enabled only when user is connected to internet. Above section shows only some part of the code and I request you to refer the source code for the full implementation details.
Data Layer
Data layer is implemented in two stages. Storing the data to local Webstorage and storing it to the back-end database.
Local storage is handled by StorageManager class. Details of it's implementation are given below
var tsk_ns = tsk_ns || {};
tsk_ns.storage = function () {
var local = window.localStorage,
saveItem = function (key, item) {
local.setItem(key, item);
},
getItem = function (key) {
return local.getItem(key);
},
hasLocalStorage = function () {
return ('localStorage' in window && window['localStorage'] != null);
};
return {
saveItem: saveItem,
getItem: getItem,
hasLocalStorage: hasLocalStorage
};
} ();
The above class is just a wrapper to window.localStorage and provides wrapper method to save and get the data from
the local storage. The class has hasLocalStorage method which checks whether browser supports the localStorage.
Saving and retrieval of the data to backend database is implemented using Jquery AJAX and AJAX enabled WCF
service. This is implemented using two classes. SPJAjaxHelper.js is a helper class responsible for making all ajax calls to invoke
WCF service. SPCService is a class implemented as WCF service. Implementation of these classes are given below.
function CheckIfOnLine(successMethod, failMethod) {
var sUrl = "SPCService.svc/CheckIfConnected";
$.ajax({
type: "POST",
contentType: "application/json; charset=utf-8",
url: sUrl,
dataType: "json",
processdata: false,
success: successMethod,
error: failMethod
});
}
function GetMeasurementData(msFilter,successFunction) {
var sUrl = "SPCService.svc/GetMeasurmentDataArray";
var ms = { measFilter:msFilter };
var sparam = JSON.stringify(ms);
InvokeWebService(sUrl, sparam, successFunction);
}
function UpdateMeasurment(msArray,successMethod)
{
var sUrl="SPCService.svc/UpdateMeasurmentArray";
var ps = { parray: msArray };
var sparam = JSON.stringify(ps);
InvokeWebService(sUrl,sparam,successMethod);
};
function InvokeWebService(sUrl,sparam,successMethod) {
$.ajax({
type: "POST",
contentType: "application/json; charset=utf-8",
url: sUrl,
data: sparam,
dataType: "json",
processdata: false,
success:successMethod,
error: function (result) {
alert('Service call failed: ' + result.status + ' ' + result.textStatus);
}
});
};
</reference>
SPCAJAXHelper.js file has three key methods. Checking online status,retrieving measurment data based on filter criteria and saving the data to the database.
All these method call InvokeWebService method which in turn calls ajax method of JQuery. Each methods pass appropriate
parameters,success callback methods. In case of any error the error message is displayed to the user.
Let us now see the implementation of SPCService. SPCService class exposes following methods
- CheckIfOnline
- GetMeasurmentDataArray
- UpdateMeasurmentArray
Below code shows the details of each of this methods. Please note the attribute defined for the WCF Service class.See the ServiceContract attribute
for the class. Each exposed method is declared with an attribute OperationContract and Any parameters passed to the methods such as entity classes are
having attribute of DataContract and each of the properties of entity class are decorated with the attribute DataMember.
Also the AspNetCompatibilityRequirements attribute to the class is also required. Also message exchange between WCF service and AJAX
calls made from Javascript are using JSON format. Please refer the WebInvoke attribute in below code where message format is defined.
Important point to remember is parameter names passed to invoke the methods should match exact signature of the WCF method. I have created the similar entity
classes in Javascript so that same type of parameters can be passed. In our case there are two entities MeasurmentSummary and MeasurmentFilter
I won't explain details of each method as the code is self explanatory.
[ServiceContract(Namespace = "SPCAnalysisWeb")]
[AspNetCompatibilityRequirements(RequirementsMode = AspNetCompatibilityRequirementsMode.Allowed)]
public class SPCService
{
[OperationContract]
[WebInvoke(Method = "POST", BodyStyle = WebMessageBodyStyle.WrappedRequest, ResponseFormat = WebMessageFormat.Json)]
public string CheckIfConnected()
{
return "SUCCESS";
}
[OperationContract]
[WebInvoke(Method = "POST", BodyStyle = WebMessageBodyStyle.WrappedRequest, ResponseFormat = WebMessageFormat.Json)]
public MeasurementSummary [] GetMeasurmentDataArray(MeasuremntFilter measFilter)
{
return null;
}
[OperationContract]
[WebInvoke(Method = "POST", BodyStyle = WebMessageBodyStyle.WrappedRequest, ResponseFormat = WebMessageFormat.Json)]
public string UpdateMeasurmentArray(MeasurementSummary[] parray)
{
}
}
[DataContract(Namespace = "SPCAnalysisWeb", Name = "MeasurementFilter")]
public class MeasuremntFilter
{
[DataMember(IsRequired = true, Name = "PartNo")]
public string PartNo { get; set; }
[DataMember(IsRequired = true, Name = "Parameter")]
public string Parameter { get; set; }
}
[DataContract(Namespace = "SPCAnalysisWeb", Name = "MeasurementSummary")]
public class MeasurementSummary
{
[DataMember(IsRequired = true, Name = "PartNo")]
public string PartNo { get; set; }
[DataMember(IsRequired = true, Name = "Machine")]
public string Machine { get; set; }
[DataMember(IsRequired = true, Name = "Operator")]
[DataMember(IsRequired = true, Name = "PAve")]
public double PAve { get; set; }
[DataMember(IsRequired = true, Name = "PRange")]
public double PRange { get; set; }
}
</parameter></measurementsummary></measurementsummary>
Web.config has configuration details for the WCF Service. If you are using Visual studio 2010 IDE then it has a template for AJAX Enabled
WCF Service and it creates all the boiler plate code and configuration for your. Details of Web.Config are given below.
<system.serviceModel>
<behaviors>
<serviceBehaviors>
<behavior name="ServiceBehavior">
<serviceMetadata httpGetEnabled="true" />
<serviceDebug includeExceptionDetailInFaults="true" />
</behavior>
</serviceBehaviors>
<endpointBehaviors>
<behavior name="SPCAnalysisWeb.SPCServiceAspNetAjaxBehavior">
<enableWebScript />
</behavior>
</endpointBehaviors>
</behaviors>
<serviceHostingEnvironment aspNetCompatibilityEnabled="true"
multipleSiteBindingsEnabled="true" />
<services>
<service behaviorConfiguration="ServiceBehavior" name="SPCAnalysisWeb.SPCService">
<endpoint address="" behaviorConfiguration="SPCAnalysisWeb.SPCServiceAspNetAjaxBehavior"
binding="webHttpBinding" contract="SPCAnalysisWeb.SPCService" />
</service>
</services>
</system.serviceModel>
All the configuration of WCF service is under system.servicemodel section. Key points to note are
binding attribute,whose value is set to webHttpBinding. Those who wants to know more about WCF service working
and configuration of WCF service please refer to msdn documentation.
I have used Entity framework to interact with the database. But you can also use LINQ-TO SQL.
UI Layer
UI Layer is implemented as plain html file. I have used Accordion widget of JQUERY-UI as well as Tabbed Layout.
Once all the document is loaded it excutes below initialisation code.The code defines validation rules,
JQuery-UI initialisation code and binding of view model to UI.
$(function () {
$('#tabs').tabs();
$('#measForm').validate({
rules: {
partno: "required",
machine: "required",
operator:"required",
dp1: {
required:true,
number: true
},
dp2: {
required:true,
number: true
},
dp3: {
required:true,
number: true,
},
dp4: {
required:true,
number: true
},
dp5: {
required:true,
number: true
}
}
});
$("#hisForm").validate({
rules: {
hispart: {
required:true
},
filterdatefrom: {
required:true,
date:true
},
filterdateto: {
required:true,
date:true
}
}
});
$("#accordion").accordion({active:1});
$("#taskNew,#taskSave,#taskUpdate,#btnRefresh,#btnRetrieve,#btnTest").button();
$("#taskNew").button("option", "disabled", false);
$("#taskUpdate").button("option", "disabled", true);
var viewModel = new SPCViewModel();
viewModel.init();
ko.applyBindings(viewModel);
$("#dlgSave").dialog({
autoOpen: false,
modal: true,
buttons: {
Ok: function () {
$(this).dialog("close");
viewModel.saveToDatabase();
}
}
});
var id= setInterval(viewModel.updateOnLineStatus,10000);
});
The above code does initialisation of the gui widgets and field validation for Measurement form. Also Javascript timer is setup
to update online status. Finally view model is initialised and binding is applied to the view.
One of the key part of the UI is Control Charts. I have implemented it using HTML Canvas. The key class implementing the charting functionality is
XBarRangeChart.Please refer to the source code for details of the implementation.
I have used different types of bindings such as for-each, with, form binding features of knockoutjs.
Please refer to the source code for complete details.
Configuring for Offline Working
With HTML5 we can now configure the pages,assets and resources of the application which should be served offline. This
is possible by defining the Application Manifest file, which is plain text file. Also in html tag you need
to define the manifest attribute to specify name of the manifest file. <html manifest="manfiest.appcache"> I have added manifest file with the extension of .appcache.
But you can use any extension. But we need to configure the webserver to include this new extension type as well as specify its
MIME type as text/cache-manifest.Please refer code below to refer the content of the manifest file.
Please remember that the fist line in the manifest file shoud be CACHE MANIFEST. Don't put any comments before this line.
Structure of manifest file is simple. It has three sections CACHE,NETWORK and FALLBACK.
All the pages and resources used during off-line need to be specified under CACHE: section. Pages/resources
required only during online are under NETWORK section. In FALLBACK section you can specify alternate pages
in case of fallback. That's it!
Browser supporting the application cache will initially save all the offline resources on client side and then it will always serve these resources from application cache irrespective of whether you are online or offline. So if any changes done
to these pages will reflect only when manifest file is modified. This is important point to remember. Modify the manifest
file and update the version to indicate to the browser that there is some change so that it will bring latest changes from
the server and save it again on client side.
CACHE MANIFEST
## version 2.3
CACHE:
themes/ui-darkness/jquery-ui-1.8.21.custom.css
themes/ui-darkness/images/ui-bg_flat_30_cccccc_40x100.png
themes/ui-darkness/images/ui-bg_flat_50_5c5c5c_40x100.png
themes/ui-darkness/images/ui-bg_glass_20_555555_1x400.png
themes/ui-darkness/images/ui-bg_glass_40_0078a3_1x400.png
themes/ui-darkness/images/ui-bg_glass_40_ffc73d_1x400.png
themes/ui-darkness/images/ui-bg_gloss-wave_25_333333_500x100.png
themes/ui-darkness/images/ui-bg_highlight-soft_80_eeeeee_1x100.png
themes/ui-darkness/images/ui-bg_inset-soft_25_000000_1x100.png
themes/ui-darkness/images/ui-bg_inset-soft_30_f58400_1x100.png
themes/ui-darkness/images/ui-icons_222222_256x240.png
themes/ui-darkness/images/ui-icons_4b8e0b_256x240.png
themes/ui-darkness/images/ui-icons_a83300_256x240.png
themes/ui-darkness/images/ui-icons_cccccc_256x240.png
themes/ui-darkness/images/ui-icons_ffffff_256x240.png
Styles/spcmain.css
Scripts/jquery-1.7.1.min.js
Scripts/json2.js
Scripts/jquery-ui-1.8.17.custom.min.js
Scripts/jquery-ui-timepicker-addon.js
Scripts/knockout-latest.js
Scripts/ko-protected-observable.js
Scripts/StorageManager.js
Scripts/SPCNewController.js
Scripts/jquery.validate.min.js
Scripts/additional-methods.js
Scripts/ControlCharts.js
Scripts/jquery.dateFormat-1.0.js
Scripts/SPCAjaxHelper.js
Images/app-note-icon.png
Images/Actions-document-edit-icon.png
Images/edit-trash-icon.png
newmain.htm
NETWORK:
SPCService.svc
SPCService.svc.cs
Styling for Mobile
I don't have to do major change to configure this application for mobile. Only thing you need to specify is viewport
setting in the head section of your html file. I had to define extra style for textarea tag. As its width
was overflowing outside its parent container. Please refer the code below for details.
.fixwidth
{
width:80%;
}
Points of Interest
HTML Canvas is not yet supported by all the browsers. So this code may not work on all the browsers. Luckily all the smartphone and tablets browser
support it and I have tested it on iPad,Android and Blackberry tablet.When you download the source code you need to provide the database connection string such as
server name,userID and password.
Android Phone/iPhone/iPad Users
Working version of the application is available
here.
They can bookmark this page. It will work both in off-line mode and online mode.
History
I was thinking of extending my
TaskTracker application to provide the support for saving and retrieving the data to the back-end database. But I thought it will be better to do
completely new application and also I wanted to explore the feature of HTML Canvas and hence I developed this application which is also useful to manufacturing and process Industry.
Conclusion
Due to new features in HTML5 it is now easy to develop off-line web applications.The application explores key features of the HTML5,Jquery,Jquery-UI,Jquery-Validation
and KnockoutJs. You can also see how the power of JQUERY AJAX is used to retrieve and save the data to back-end database using AJAX Enabled WCF Service. Also we can use open source framework such as PhoneGap to convert it to native application for different mobile platforms.
Please let me know your comments and suggestions. You can e-mail me for any queries or clarification about
the implementation. Thank you.
I am Solution Architect with 20+ years of IT experience in the field of real time,embedded,client/server and web based applications and Business Intelligence . I am currently working with Infor UK Ltd.