May 29, 2012

A simple drawing grid with HTML 5

This week, we will build a simple drawing grid using HTML5 and javascript. In the coming weeks we will transform this simple example into a fully functional drawing application. For this demo, the entire browser window will be a canvas and resizing or reloading the window will clear it.
The first step is to define our canvas and add some css that will set the size of the canvas to the size of the browser window.

<!DOCTYPE HTML>
<html>
	<style type="text/css">
	html, body { width: 100%; height: 100%; margin: 0px; }
	</style>
	<body>
		<canvas id="grid">
			<p>Your browser does not support HTML5 canvas</p>
		</canvas>
	</body>
</html>

This is all that is required to create a canvas that consumes the entire browser window. The next step is to add javascript to the page so we can have an interactive drawing surface. We will be using jquery and loading a script named grid.js; which will perform the canvas updates.

<!DOCTYPE HTML>
<html>
	<head>
		<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.7.1/jquery.min.js" type="text/javascript"></script>
	</head>
	<style type="text/css">
	html, body { width: 100%; height: 100%; margin: 0px;  }
	</style>
	<body>
		<canvas id="grid">
			<p>Your browser does not support HTML5 canvas</p>
		</canvas>
		<script type="text/javascript" src="scripts/grid.js"></script>
	</body>
</html>

The next step is to create a folder named “scripts” and within it create a text file called grid.js using your favorite editor. The grid.js script will be responsible for all of the canvas updating. For starters, we will need to define the callbacks for window events in order to initialize the canvas data. “window.onresize” will be used so that the canvas can be cleared when the window is resized.

window.onload = window.onresize = function() {
	var grid_canvas = document.getElementById("grid");
	var ctx = grid_canvas.getContext("2d");
	var viewWidth = window.innerWidth;
	var viewHeight = window.innerHeight;
	var backgroundColor = "rgb(0,0,255)";

	grid_canvas.style.position = "fixed";
	grid_canvas.setAttribute("width", viewWidth);
	grid_canvas.setAttribute("height", viewHeight);
	grid_canvas.style.top = 0;
	grid_canvas.style.left = 0;

	ctx.clearRect(0,0,viewWidth,viewHeight);
	ctx.fillStyle = backgroundColor;
	ctx.fillRect(0,0,viewWidth,viewHeight);	
}

At this point, the canvas is created, but isn’t very interesting. To draw on the canvas, we will rely on mouse events. In this demo, holding down the left mouse button and dragging will fill in cells of the grid that the mouse is hovering over. Holding any other mouse button down and dragging will be used for an “erase” function. It’s not actually erasing, but coloring the cells in with the defined background color. The following should be added to the window event callback defined above.

var xOffset = $("#grid").offset().left;
var yOffset = $("#grid").offset().top;
var mouseDown = false;
var mouseButton = 0;
var penColor = "rgb(255,255,255)";
var penWeight = 5;

$("#grid").mousedown(function(e) {
	mouseDown = true;
	mouseButton = e.which;
}).bind('mouseup', function() {
	mouseDown = false;
});

$("#grid").mousemove(function(e) {
	if (mouseDown) {
		var x = Math.floor((e.pageX-xOffset) / penWeight);
		var y = Math.floor((e.pageY-yOffset) / penWeight);

		ctx.fillStyle = mouseButton == 1 ? penColor : backgroundColor;
		ctx.fillRect(x*penWeight, y*penWeight, penWeight, penWeight);
	}
});

Loading the page now should result in a functional drawing application. Changing the “penWeight” variable will alter the cell sizes on the hidden grid. As a small optimization, you may consider storing the last cell that was drawn to and skipping a redraw (included in the source example) if the user is still moving with the cell. At smaller cell sizes, this becomes less important.

The demo for the grid can be found here.

Advertisement
May 22, 2012

Using Task for responsive UI in WPF

Blocking of the UI thread in a WPF application causes the application to become unresponsive. It is a common problem with several solutions, but usage of Task is in my opinion the most elegant solution because of readability and code brevity.
For this example we have a simple WPF application with a button that starts a long running loop. A busy indicator is displayed while the loop is running.

_busyIndicator.IsBusy = true;

for (var i = 0; i &lt; 100; i++)
{
  System.Threading.Thread.Sleep(50);
}

_busyIndicator.IsBusy = false;

As written, this code will freeze the app for the duration of the loop since it blocks execution of the UI thread. The solution is to run the loop Asynchronously and using Task is the easiest way to accomplish it in this case.

_busyIndicator.IsBusy = true;

var T = new Task(() =>
{
  for (var i = 0; i &lt; 100; i++)
  {
    System.Threading.Thread.Sleep(50);
  }
});

T.Start();

_busyIndicator.IsBusy = false;

However, this bit of code will crash the application because we have not passed control back to the context of the UI thread. The ‘Task.ContinueWith’ method can be used to serve that purpose.

var T = new Task(() =>
{
  for (var i = 0; i < 100; i++)
  {
    System.Threading.Thread.Sleep(50);
  }
});

T.ContinueWith(antecedent => _busyIndicator.IsBusy = false, TaskScheduler.FromCurrentSynchronizationContext());

Running the application will now result in complete responsiveness. You can move, resize, or perform other operations while the loop is running. However, there are cases where CPU intensive loops may cause the busy indicator to not be displayed. In WPF, the UI render events are queued to prevent issues related to multiple execution of the same event. To prevent this, we want to make sure that the busy indicator is displayed. And for that we can use a timer event.

private System.Windows.Threading.DispatcherTimer _timer = null;
public MainWindow()
{
  InitializeComponent();
  _timer = new DispatcherTimer();
  _timer.IsEnabled = false;
  _timer.Tick += new System.EventHandler(RunTask);
}

private void StartProcess(object sender, RoutedEventArgs e)
{
  _busyIndicator.IsBusy = true;
  _timer.Interval = new TimeSpan(0,0,0,0,100);
  _timer.Start();
  // go back to the user thread, giving the busy indicator a chance to come up before the next timer tick event
}

void RunTask(object sender, System.EventArgs e)
{
  _timer.IsEnabled = false;

  var T = new Task(() =>
  {
    for (var i = 0; i < 100; i++)
    {
      System.Threading.Thread.Sleep(50);
    }
  });

  T.ContinueWith(antecedent => _busyIndicator.IsBusy = false, TaskScheduler.FromCurrentSynchronizationContext());
  T.Start();
}

So, when the user clicks the button, the busy indicator is set to true first, the timer is started, and once it has ticked the Task is called. Using the timer event in this manner ensures that the loop will not be executed until the busy indicator is rendered.

The complete source code for this example can be found in our github repository.

Tags: ,
May 3, 2012

Linear Regression with Excel 2010

Linear regression is a way to determine how close two number series of data: x (independent) and y (potentially dependent), fit a linear function of the form: y = a*x + b.

This is the first of a series of planned posts that will cover how to set up linear regression a variety of different languages. This week, we will discuss the easiest method of performing Linear regression analysis; and that is with Excel 2010.

First, we will need to enable the Analysis ToolPak for Excel:

1)      Click File and select options

2)      Select Add-ins on the left hand menu

3)      Select Excel Add-ins in the drop down list named Manage at the bottom of the pop up

4)      Click the ‘Go’ button

5)      Tick the checkbox for Analysis ToolPak if it is empty

6)      Click the ‘Ok’ button

Once the Add-in is installed, create a table of data similar to the following:

x

y

7

216

12

302

14

431

6

151

22

677

38

958

14

431

9

227

10

308

11

277

To perform the Regression analysis, select a cell and then click the ‘Data’ ribbon tab. Then double-click the Data Analysis section of the ribbon. This will present a popup similar to the following:

 

 
Data Analysis
 

 

Select the Regression option and click the ‘Ok’ button. This will prompt another popup to enter the cell ranges for the data which will be analyzed:

 

 

Select Range

 

 

For the Input Y Range, select all cells in the Y column; including the header. Do the same for the Input X Range using the X column. Be sure to select the Labels checkbox and then click the ‘Ok’ button. Doing so will create the regression analysis within your spreadsheet:

 

 
Summary
 

 

Next week, we will talk a bit about what all of this means, but for right now, we will focus on the R Square value, and the Coefficients of the rows labeled ‘Intercept’ and ‘x’. The best way to demonstrate the significance of these values is to present them in a scatter chart with the linear trend line being rendered. This can be done in the following steps:

1)      Click an empty cell

2)      Select the ‘Insert’ ribbon tab

3)      Select the Scatter Plot and choose ‘Scatter with only Markers’

4)      Right Click in the center of the Chart and choose ‘Select Data’

5)      Highlight your data table  including the column header lines

6)      Click the ‘Ok’ button

Your chart should be displayed similar to the following:

 

 
Scatter Plot

 

 

The following steps can be used to display the linear trend line in the chart:

1)      Left Click any of the plot markers

2)      Right Click and select ‘Add Trendline’

3)      Select Linear in the Trendline Options pop up

4)      Enable the checkbox for ‘Display Equation on chart’

5)      Enable the checkbox for ‘Display R-Squared value on chart’

6)      Click the close button

 

 
Linear Trend

 

 

And there you have it; Linear Regression done simply in Excel 2010. You should notice that the formula given uses the values obtained in the Summary Output of the Data Analysis step. Next week, we will discuss how to perform Regression analysis programmatically in C#.

April 4, 2012

WCF and Entity Framework Pitfall

Recently I was tasked with creating a client application that interacted with an existing MVC Web Application. Specifically it was an Excel Add-In that would manipulate data from the same database that the Web Application used. Since we were using Entity Framework 4.1 and code first, the simplest solution for me was to just create the Data Contracts for the service on the existing models. Or so I thought.

Setting everything up went very smoothly, but testing the service resulted in obscure error messages and eventually a timeout.  After some painful debugging, it turned out that the Lazy Loading of Entity Framework and Serialization (WCF) do not play nicely when you have foreign keys represented as virtual child classes and many-to-many relationships.

The problem is that with Lazy loading, if for example Entity A serialization accesses Entity B, Entity B is Lazy Loaded and serialized. Serialization of Entity B accesses Entity A and Entity A Lazy Loads again. This keeps repeating infinitely and is called circular lazy loading.

The solution is to disable Lazy Loading at the time of each call.

dbContext.ContextOptions.LazyLoadingEnabled = false;

With Lazy Loading disabled, the classes are serialized correctly for standard Entity Framework classes.

Another option (that I ultimately chose) is to create separate classes as Data Transfer Objects and map them to the Entity Framework classes. If you choose the Data Transfer Object method, I highly recommend using AutoMapper. Mapping the objects with AutoMapper is extremely simple and can be accomplished in a few lines of code.

var lineItems = dbContext.LineItems.Where(li => li.QuoteId == quoteId).ToList();

Mapper.CreateMap<LineItem, LineItemDto>();

return  Mapper.Map<List<LineItem>, List<LineItemDto>>(lineItems);

AutoMapper is great for cases like mine in which the client doesn’t really need the entire entity. However, if your application does need all of the fields in each of your entity classes, then certainly disabling Lazy Loading would be worth trying first.

March 20, 2012

Securing static content with ASP.NET forms authentication

A colleague of mine recently asked me how to secure static content on an IIS server and I thought I would quickly list the steps here for others that are looking for a quick guide on how to do it.

First, the URL Authorization role service should be enabled on the IIS server. To do this, open the Server Manager and go to Roles -> Web Server (IIS) -> Add Role Services and then click the checkbox for URL Authorization.

Next, the Manage pipeline mode should be set to Integrated for the Application Pool that the application is running under. You can verify this by opening the IIS Manager and going to the Connections pane. Expand ‘Sites’ and navigate to your web site (or application). In the Actions pane, click Advanced Settings. Then click on the General Section followed by clicking the Application Pool entry.

Lastly, the web.config will need to instruct IIS to use ASP.NET’s UrlAuthorization Module and / or FormsAuthentication module. Here’s an example for both:

  <system.webServer>
    <modules>
. . . removed other modules …
      <remove name="FormsAuthenticationModule" />
      <add name="FormsAuthenticationModule" type="System.Web.Security.FormsAuthenticationModule" />

      <remove name="UrlAuthorization" />
      <add name="UrlAuthorization" type="System.Web.Security.UrlAuthorizationModule" />

    </modules>

Forms authentication requires that you specify <authorization> tags. Here’s an example that allows ‘anonymous’ to download images:

<configuration>
  <system.web>
    <authorization>

<deny users=”?” />

</authorization>

. . . removed other config . .

  </system.web>

  <location path="ErrorPages">
    <system.web>
      <authorization>
        <allow users="*" />
      </authorization>
    </system.web>
  </location>

  <location path="Images">
    <system.web>
      <authorization>
        <allow users="*" />
      </authorization>
    </system.web>
  </location>

This should be all that is required for securing your static content with ASP.NET forms authentication. For further reading, I would suggest this page.

March 13, 2012

Forcing a single instance of a process in .Net with Mutex

In a recent application, a requirement was to allow for only a single instance to be running at a time. Typically I would do this with Systems.Diagnostics.Process and search for an instance of my running application, but I wanted to try the Mutex method because it appeared to be simpler and a bit lighter.

A Mutex is a synchronization primitive that can be used for interprocess synchronization while most other locking mechanisms are process specific. You can read more about Mutex here</>.

It turned out to be much simpler than I had expected, so I thought I would share how to set it up in a Windows Form project. The first step is to add a class with some native methods that are required to bring the application to the top if it is already running.

class NativeMethods
{
    public const int HWND_BROADCAST = 0xffff;
    public static readonly int WM_SHOWME = RegisterWindowMessage("WM_SHOWME");
    [DllImport("user32")]
    public static extern bool PostMessage(IntPtr hwnd, int msg, IntPtr wparam, IntPtr lparam);
    [DllImport("user32")]
    public static extern int RegisterWindowMessage(string message);
}

The next step is to define the Mutex that will be used to identify the process.

static class Program
{
    private static readonly Mutex mutex = new Mutex(true, "{5D562B9B-8B2B-4A30-979A-083BDE97B99E}");
    ...

The Mutex.WaitOnce method provides the magic for checking if our process is already running. It has an overload that takes two parameters; Time to wait and a Boolean for exiting the context. WaitOnce returns true if it is able to enter and false if it is not. So, with the following, we can launch the application if it is not already open.

if (mutex.WaitOne(TimeSpan.Zero, true))
{
    Application.EnableVisualStyles();
    Application.SetCompatibleTextRenderingDefault(false);
    Application.Run(new Form1());</p>
}

And in the else block the existing process can be brought to the top of the display.

if (mutex.WaitOne(TimeSpan.Zero, true))
{
    Application.EnableVisualStyles();
    Application.SetCompatibleTextRenderingDefault(false);
    Application.Run(new Form1());
    mutex.ReleaseMutex();</p>
}
else
{
    NativeMethods.PostMessage(
    (IntPtr)NativeMethods.HWND_BROADCAST,
    NativeMethods.WM_SHOWME,
    IntPtr.Zero,
    IntPtr.Zero);</p>
}

So there you have it. The application will only allow for one instance and will be brought to the front of the display if a user attempts to launch it while it is running.

February 28, 2012

Creating an HTML5 Timer, part 2

Last week, we created a generic timer using canvas and the setInterval function. This week, we will add some audio elements and stylize the application using CSS3.  This timer is going to have an optional ticking sound for each second that elapses and an alarm sound when it has expired.

Adding sounds in HTML5 is done by defining elements with the <audio> tag. We’ll need to define a couple of them for our sounds without the controls attribute.

 

<audio id=”clockTick” preload=”auto”>

<source src=”audio/tick.mp3″ type=”audio/mpeg” />

<source src=”audio/tick.wav” type=”audio/wav” />

audio tag not supported.

</audio>

<audio id=”alarm” preload=”auto”>

<source src=”audio/alarm.mp3″ type=”audio/mpeg” />

<source src=”audio/alarm.wav” type=”audio/wav” />

</audio>

 

Next we’ll add a helper function to play the sounds.

 

function playSoundById(elementId) {

document.getElementById(elementId).play();

}

 

Since the ticking sound is optional, users will be able to turn it off with a button that toggles.

 

<div><input id=”muteButton” type=button value=”Mute” style=”width:97px; font-weight:bold” onClick=”muteClock()” ></div>

 

function muteClock() {

clockMuted = !clockMuted;

if (clockMuted == true) {

muteButton.value = “Un-Mute”;

return;

}

muteButton.value = “Mute”;

}

 

The last step for the sounds is to make calls to the helper function that we created. The ticking sound should be called from inside the setInterval function and the alarm sound will be called from inside the finish() function.

 

if (!clockMuted) {

playSoundById(‘clockTick’);

}

playSoundById(‘alarm’);

 

Last week, we built the interface using a simple html table.  This week, we have removed the table and now rely on CSS to position the elements. This gives us a bit more flexibility for the positioning of elements as well as the styling.

 

<div id=”container”>

<section id=”displaySection”>

<div class=”time”>

<input id=”elapsedTime” value=”0:00:00″ readonly=”readonly”>

</div>

<div id=”clock”>

<canvas id=”canvas” width=”100″ height=”100″>

Your browser does not support the canvas tag

</canvas>

<div class=”controls”>

<div><input name=”starter” type=button value=”Start” style=”width:97px; font-weight:bold” onClick=”startClock()” ></div>

<div><input name=”pauser” type=button value=”Pause” style=”width:97px; font-weight:bold” onClick=”pauseClock()” ></div>

<div><input name=”resetter” type=button value=”Reset” style=”width:97px; font-weight:bold” onClick=”resetClock()” ></div>

<div><input id=”muteButton” type=button value=”Mute” style=”width:97px; font-weight:bold” onClick=”muteClock()” ></div>

</div>

</div>

</section>

<section id=”settingSection”>

<div class=”settings”>

<input id=”hours” placeholder=”hh” type=”number” value=”” onkeypress=”validate(event)” />

<input id=”minutes” placeholder=”mm” type=”number” value=”” onkeypress=”validate(event)” />

<input id=”seconds” placeholder=”ss” type=”number” value=”” onkeypress=”validate(event)” />

</div>

</section>

</div>

 

And with a bit of CSS, our timer looks like the following.

You can see the CSS for our timer by viewing the source of the demo, although I would encourage you to experiment with some different styles of your own.

Tags:
February 21, 2012

Creating an HTML 5 Timer, part 1

This week, we will be creating a functional timer using HTML 5 timer elements. For visualization, we will use the canvas element to visualize time elapsed as well as an overlay that displays a message when the time has expired.

As a first step, we will craft the HTML for the interface. At the top of the page, we will display elapsed time followed by a canvas element the represents the elapsed time.

<input id=”elapsedTime” value=”0:00:00″ readonly=”readonly” style=”border:none; vertical-align:middle text-align:center; width:120px; font-size:32px; font-weight:bold” >

<td>

<div id=”container”>

<canvas id=”canvas” width=”100″ height=”100″>

Your browser does not support the canvas tag

</canvas>

<div id=”timesUp” style=”position:absolute; top:95px; left:12px; color:red”></div>

</div>

</td>

You will notice that the canvas and has been wrapped in a container that includes the another div. This extra div will be used for an overlay message to be displayed when the time has expired.

Next, we’ll add some input boxes so users can specify hours, minutes, and seconds as well as some buttons for starting, stopping, and resetting the timer.

<td>

<input id=”hours” type=”text” value=”” style=”width:26px” onkeypress=”validate(event)” />

<input id=”minutes” type=”text” value=”” style=”width:26px” onkeypress=”validate(event)” />

<input id=”seconds” type=”text” value=”” style=”width:26px” onkeypress=”validate(event)” />

</td>

<td>

<input name=”starter” type=button value=”Start” style=”width:97px; font-weight:bold” onClick=”startClock()” >

</td>

<td>

<input name=”pauser” type=button value=”Pause” style=”width:97px; font-weight:bold” onClick=”pauseClock()” >

</td>

<td>

<input name=”resetter” type=button value=”Reset” style=”width:97px; font-weight:bold” onClick=”resetClock()” >

</td>

In our input boxes for hours, minutes, and seconds, we want to limit the input to integers. To do this, we’ll use the validate event and regular expressions.

function validate(evt) {

var theEvent = evt || window.event;

var key = theEvent.keyCode || theEvent.which;

key = String.fromCharCode( key );

var regex = /[0-9]|\./;

if( !regex.test(key) ) {

theEvent.returnValue = false;

if(theEvent.preventDefault) theEvent.preventDefault();

}

}

Now we will need to create the script that drives the timer. When the page is loaded, we will need to initialize some variables and render our canvas element.

var interval = 1000;

var limit = 0;

var canvas, ctx, size, startAngle, wedgeSize, fillClr, elapsed, intervalId, timerElement;

var hh=0, mm=0, ss=0;

var hInput, mInput, sInput, overlay;

$(document).ready(function() {

canvas = $(“#canvas”)[0];

ctx = canvas.getContext(‘2d’);

size = Math.min(canvas.width, canvas.height);

startAngle = -Math.PI/2;

timerElement = document.getElementById(‘elapsedTime’);

hInput = document.getElementById(‘hours’);

mInput = document.getElementById(‘minutes’);

sInput = document.getElementById(‘seconds’);

overlay = document.getElementById(‘timesUp’);

initClock();

});

Notice the initClock function that is called. We don’t have that yet, so let’s create it. This function will be responsible for resetting variables as well as drawing the initial canvas element.

function initClock() {

timerElement.value = “0:00:00”;

overlay.innerHTML = “”;

elapsed = 0;

wedgeSize = (interval / limit) * Math.PI * 2;

fillClr = “#fff8dc”;

var bgClr = ctx.createLinearGradient( 0, 0, canvas.width, canvas.height );

bgClr.addColorStop( 0, “#000000” );

bgClr.addColorStop( 1, “#999999” );

fillClr = ctx.createLinearGradient( 0, 0, canvas.width, canvas.height );

fillClr.addColorStop( 0, “#AAAAAA” );

fillClr.addColorStop( 1, “#EEEEEE” );

var drawX = drawY = radius = size / 2;

var circle = canvas.getContext(“2d”);

circle.globalAlpha = 1;

circle.beginPath();

circle.arc(drawX, drawY, radius, 0, Math.PI * 2, true);

circle.fillStyle = bgClr;

circle.fill();

circle.lineWidth = 0.25;

circle.strokeStyle = “#000000”;

circle.stroke();

}

At this point, all that is left to do is to plug in the buttons that we defined earlier. So let’s start with getting the timer running. This function will parse the user input for hours, minutes, and seconds and kick off the timer using HTML5’s setInterval function. The setInterval function will repeatedly be called until it is cleared, so we can take advantage of this to advance our visual representations.

function startClock() {

limit = (parseInt(hInput.value == “” ? “0” : hInput.value) * 3600)

+ (parseInt(mInput.value == “” ? “0” : mInput.value) * 60)

+ parseInt(sInput.value == “” ? “0” : sInput.value);

limit *= 1000;

intervalId = setInterval(function () {

elapsed = elapsed + interval;

wedgeSize = (elapsed / limit) * Math.PI * 2;

updateTime();

var drawX = drawY = radius = size / 2;

var endAngle = startAngle + wedgeSize;

var wedge = canvas.getContext(“2d”);

wedge.beginPath();

wedge.moveTo(drawX, drawY);

wedge.arc(drawX, drawY, radius, startAngle, endAngle, false);

wedge.closePath();

wedge.fillStyle = fillClr;

wedge.fill();

wedge.lineWidth = 0.25;

wedge.strokeStyle = “#eeeeee”;

wedge.stroke();

if (elapsed >= limit) {

clearInterval(intervalId);

finish();

}

}, interval);

}

You should notice a call to an updateTime() function. We’ll need to create this function as it is responsible for the text display of elapsed time.

function updateTime() {

var s,m;

ss += 1;

s = ss < 10 ? ‘0’ + ss : ss;

if (ss > 59) {

ss = 0;

s = ’00’;

mm += 1;

}

m = mm < 10 ? ‘0’ + mm : mm;

if (mm > 59) {

mm = 0;

m = ’00’;

hh += 1;

}

timerElement.value = hh + ‘:’ + m + ‘:’ + s;

}

Once the elapsed time has reached the limit, clearInterval () is called as well as a finish().  The finish() function is something we will need to create. Its purpose for now is to display some text in the overlay.

function finish(){

overlay.innerHTML = “Time is up!”;

}

Since we want our users to be able to pause the timer, we can attach the clearInterval() function to the Pause button.

function pauseClock() {

clearInterval(intervalId);

}

Finally, we will need to create a function for the Reset button. This function will stop the clock, zero out the elapsed time, and re-initialize the canvas.

function resetClock() {

pauseClock();

elapsed = hh = mm = ss = 0;

initClock();

}

You can see the demo in action here. Next week we will add a bit a polish to the interface as well as add some audio indicators for interval updates and an alarm when the time limit is hit.

February 14, 2012

Multiple View Models with Knockout

In a recent project, I was required to create a form for user input in a web page. Each section of the form is distinct and serves a unique purpose, so I chose to use a tabbed layout . The order in which the forms are completed was not a strict requirement, so some visual indication of which sections were completed was also a requirement.

I decided to use Knockout js for the data binding to take advantage its easy data bindings as well as the ko.computed method to determine which sections are complete.  While creating a design for this, it became apparent that each section (tab) should be its own view model. The problem was that there really isn’t any documentation on how to create multiple view models on a single page. There is an obscure reference deep in the Knockout js documentation that does not clearly explain how to do it.

After a bit of googling, I could not find any clear instructions on how to solve the problem; only some single line answers. After getting small hints from several google search results and some trial and error, I was able to come up with a clean solution.

The solution is actually quite simple, but I thought I would share it with since having a clear example would have saved me a lot of time.

The first thing to do is to create your sections on the page with a unique id.

<section class="tab" id="firstSection">
	<h1>First Section</h1>
	<p>First Name: <strong data-bind="text: name"></strong></p>
	<p>First name: <input data-bind="value: name" /></p>

</section>

<section class="tab" id="secondSection">
	<h1>Second Section</h1>
	<p>Second Name: <strong data-bind="text: name"></strong></p>
	<p>Second name: <input data-bind="value: name" /></p>	
</section>

One thing you may notice about this example is that it is using the same variable name called “name” in each section. This is one of the benefits of using multiple view models since those variables are only accessible in the scope of the view model.

Second, you will need to define your view models. There is nothing special about how these are defined for this particular solution.

function firstViewModel() {
	var self = this;
	self.name = ko.observable("Enter Name");			
};

function secondViewModel() {
	var self = this;
	self.name = ko.observable("Enter Name");	
};

Lastly, you will need to apply the bindings for the view models and assign them to the previously defined sections.

ko.applyBindings(new firstViewModel, $("#firstSection")[0]);
ko.applyBindings(new secondViewModel, $("#secondSection")[0]);

Take note of the second parameter passed to the applyBindings method as it does the magic of isolating the view model to a specific element on the page.  I am not sure why this isn’t clearly documented anywhere, but hopefully this post proves useful to anyone that is looking to add support for multiple view models on a single page.

A working demo can be found here

January 31, 2012

Creating a simple pie chart with HTML5 Canvas Part 3

Over the last two weeks, we have created a simple pie chart and then added some functionality. This week we will focus on some design aspects to improve the presentation of the chart.

While contrasting colors for each slice of the pie can be used for a clear distinction between slices, using a border for each one generally looks nicer. This is easily accomplished using the .stroke method.

 

ctx.lineWidth = 1;

ctx.strokeStyle = “#fff”;

ctx.stroke();

 

Another simple way to improve the appearance of the chart is to add some color gradient for each slice. Using color gradients will give the chart a more modern look and are extremely simple to add. The first step is to define the gradient as follows.

 

var gradient = ctx.createLinearGradient( 0, 0, canvas.width, canvas.height );

gradient.addColorStop( 0, “#ddd” );

gradient.addColorStop( 1, colors[i] );

 

Once the gradient is defined, we can set it as the fillStyle for the context and call the fill method.

 

ctx.fillStyle = gradient;

ctx.fill();

 

Last week we added rendering of the pie slice values at the bottom of the screen. While that does the job of giving the user information about the slice, it forces them to look away from the chart. To improve on that, we will have the value of the slice be rendered at the position of the mouse. The effect will be that the value follows the user as they hover over the slices.

 

ctx.fillStyle = ‘#fff’;

ctx.font = ‘bold 10px verdana’;

ctx.fillText(pieData[slice][‘value’], x, y, 20);

 

While adding these improvements may seem trivial, they are worth mentioning due to the fact that they transform what was a simple and dull chart into one that is more functional, intuitive, and professional.

For the full source and a working demo, please follow the link below.

 http://yojimbocorp.com/demos/pieChart3.html