WinRT JavaScript - Custom Controls
Written by Ian Elliot   
Article Index
WinRT JavaScript - Custom Controls
Standard configuration
Events

Events

Handling events and more to the point passing them on to the user of your custom control is one of the more important aspects of creating it. Basically the idea is that you have to handle the events from the DOM components that make up your control and pass them on using despatchEvent.

This is a topic that can become complicated very quickly as you try to do real things. Let's keep it simply by setting up a new even called totalclick which is fired when the user clicks anywhere on our custom control - in practice you would want to implement events that respond to different parts of your control rather than the entire surface.

The first thing we have to do is add an event handler for the canvas click event. This we do as part of the constructor. The event handler receives the event from the canvas, processes it and then triggers an event of its own based on it. In a real custom control you might process it to return specific details such as the x,y position of the click within your control or something similar. In this example all we will do is pass the event parameter on:

c.addEventListener("click",
 function (e) {
  this.dispatchEvent("totalclick", e);
});

Recall that c is the DOM canvas object you have created. The this is supposed to refer to your custom control and it does at the point where you define this event handler. The problem is that this doens't reference your control when the event handler is invoked and so it doesn't work. To make sure that te dispatch is done in the context of your control you have to save the "this" reference in a new variable that will be used when the event handler is invoked:

var that = this;
c.addEventListener("click",
 function (e) {
  that.dispatchEvent("totalclick", e);
});

How can the event handler access the "that" variable when your control's constructor is long finished? The answer is closure. The event handling function retains access ot all of the variables that were in scope when it was defined - this is the reason closure is so useful.

Now that we have dispatched the even we can start using it - only we can't. The custom control doesn't have a dispatchEvent method. Adding one is made easy by a utility function:

WinJS.Class.mix(MyControls.MyCanvasControl,
                     WinJS.UI.DOMEventMixin);

This adds as the methods like  addEventListener,
removeEventListener, and dispatchEvent to your control. Mix-in methods take one object and add the methods/properties of another to it. In this case the mix function adds the methods/properties of the DOMEventMixin object to your control.

There is another useful mix-in class that will add Onevent properties to your class:

WinJS.Class.mix(MyControls.MyCanvasControl,
      WinJS.Utilities.
        createEventProperties("totalclick"));

In this case we support just one event totalclick but you can include an array of event names - minus the "on" prefix.

Now we are ready to use the new totalclick event. You can set the event handler in code or HTML just as if it was a standard event and really there is nothing new to add. For example to add and event handler to respond to "totalclick" you might use:

MyCanvas1.addEventListener('totalclick',
 function (e) {
  instructions
 }
);

Assuming that you assigned the Id "MyCanvas1" in the HTML to the instance of the custom control you wanted to add the event handler to.

Event handlers can be much more complicated than this but the basic steps are always the same:

  • Mix-in the DOM event methods into your control and optionally Mix-in onEvent properties.
  • Intercept the events from the DOM objects that make up your control.
  • Process the event data and dispatch a new event.

The full code for our custom control is:

WinJS.Namespace.define("MyControls",
{
 MyCanvasControl: function (element, options){
   this.element = element ||
          document.createElement("div");
   element.winControl = this;
   this.element = element;
   WinJS.UI.setOptions(this, options);
   this.color = this.color || "rgb(200,0,0)";
   var c = document.createElement("canvas");
   c.width = "500";
   c.height = "500";
   var that = this;
   c.addEventListener("click", function (e) {
    that.dispatchEvent("totalclick", e);
   });
   var ctx = c.getContext("2d");
   ctx.fillStyle =this.color ;
   ctx.fillRect(10, 10, 100, 50);
   this.element.appendChild(c);
  }
});


WinJS.Class.mix(MyControls.MyCanvasControl,
  WinJS.Utilities.
      createEventProperties("totalclick"));
WinJS.Class.mix(MyControls.MyCanvasControl,
      WinJS.UI.DOMEventMixin);

 

The HTML using the control is:

<div id="MyCanvas1"
 data-win-control="MyControls.MyCanvasControl"
 data-win-options="{color:'rgb(0,0,255)'}">
</div>

 

And an example of and event handler for the totalclick event is:

MyCanvas1.addEventListener('totalclick',
 function (e) {
  instructions;
});

 

Custom controls are surprisingly easy to build in WinJS but don't over use them. In many cases a Template object can do the same job or even a complete HTML page.

 

 cover

 Creating JavaScript/HTML5 Metro Applications

 

 

 

 

Still to come, chapters on Promises, Life Cycle and Data Binding.

espbook

 

Comments




or email your comment to: comments@i-programmer.info

To be informed about new articles on I Programmer, install the I Programmer Toolbar, subscribe to the RSS feed, follow us on, Twitter, Facebook, Google+ or Linkedin,  or sign up for our weekly newsletter.