July 9, 2009

Tutorials and learning

Filed under: Content writing — Ben Jones @ 2:52 pm

Some time ago, a colleague of mine asked me to write a tutorial aimed at a non-typical piece of software that lead the reader from the inception of an idea to a finished product. As an educator, It was extremely difficult to ignore such an open suggestion. This following piece is what that challenge produced.

-=-=-=-=-

Our final goal

Quick modeling an early 15th Century German Barbutte

A Barbutte is a visorless war helmet of fifteenth century Italian design, often with distinctive “T” shaped or “Y” shaped opening for the eyes and mouth. The Barbutte resembles classical Greek helmets and may have been influenced by a renewed interest in ancient artifacts.
- Wikipedia

This beginner level XSI 6 tutorial provides a “how-to” for creating a simple mesh of a German variant of the Barbutte. I will focus mainly on a couple of techniques that lend themselves to rapid modeling; namely, extrusions and polygon bridging. Quick modeling lays out the basic mesh from which modifications that are more detailed can be made later. In our case, we are looking to get the most model out of the fewest operations as reasonable. However, you can always employ other methods based on your tools and experience. For now, this works quite well enough.

Since the top of the Barbutte is an oblong dome that wraps down in the back slightly, let us start with that premise. We can use the extrusion tool to create this shape rather quickly with just two arcs. The first arc, referred to as the crown_path, is a simple 200-degree; while, the second arc, referred to as the crown_shape, is a simple 180-degree arc. The crown_shape then extrudes along the crown_path to create the crown of the helm.

The arc properties dialog

Both of these arcs will be created in exactly the same manner. We will begin with creating the crown_path.

  1. Select Model->Get->Primitive->Curve->Arc
  2. Name the arc ‘crown_path
  3. Set the End Angle to 200

Now close this dialog and repeat the process for the crown_shape.

  1. Select Model->Get->Primitive->Curve->Arc
  2. Name the arc ‘crown_shape
  3. Set the End Angle to 180

Again, close the dialog when finished. Now, there is not to see since both arcs are in the same plane. Our plan is to extrude the crown_shape along the crown_path. This means that we will need to reorient the crown_shape to get the desired final shape.

The transform panel settings
The select panel

First, make sure that the crown_shape is the currently selected arc (white color usually indicates this state). The re-orientation occurs in two phases. First, we are spinning the arc about its axis. Then, we are going to reset the axis while leaving the arc in the new position. On the Transform Panel,

  1. Set the X rotation to 90
  2. Set the Y rotation to -90
  3. On the Select panel, click the CENTER button to active the arc’s center
  4. Back on the Transform Panel, set all rotations to 0
  5. Back on the Select Panel, click the OBJECT button to deactivate the arc’s center

The crown_path and crown_shape arcs

Currently, we have our two arcs as shown to the right; where the crown_shape is the white arc and the crown_path is the long black arc. The arcs are now ready for the extrusion operation.

  1. Select Model->Create->Poly.Mesh->Extrude Along Curve
  2. Drag the pick session cursor across the crown_path arc, then release it
  3. Right click the mouse to end pick session

This extrudes our crown_shape along the crown_path producing a smooth crown portion of the helm (see the image below).

After extruding the crown_shape along the crown_path

Now we have something to work with; currently, it looks more like half a doughnut than a helm.

We need to close in the doughnut hole first. To do this, we are going to collapse the inner edges of that gap on both sides.

  1. Press the E key to enter “Tagged Edges” mode
  2. Select one of the front gaps’ edges (see the below left-side image)

Selecting the first inner gap edge
All the inner gaps edges selected

As on the left:

  1. Right click that edge to activate the contextual menu
  2. Select the Select Edge Loop (no corners) option
  3. Select another of the front gaps’ edges
  4. Hold down the Control Key
  5. Select any edge from the back gap
  6. Release the Control Key
  7. Right click to end the edge selection pick session

After collasping the edges into a single component
Before translating the gaps points

You should have edges selected according to the above right-side image.

Now, collapse all of these edges into single components as follows:

  1. Right click one of the selected edges to activate the contextual menu again
  2. Select the Collapse Components option

After translating the gaps points

Once selected, these two points need to be moved down until they are at least level with the bottom edge on the right side of the crown.

  1. Press T to enter “Tagged Point” mode
  2. Drag the selection area over the two new points as shown in the above right image
  3. Press the V key to enter Translate mode
  4. Grab the Y axis handle (green) and pull it downward until it is about where the image to the left indicates

With the gaps filled on both sides, we now have the crown of the helm roughed out in its most basic form. The next step is to create the skirting that comes down from the bottom of the crown, which protects the head from eye level down to the shoulders. Again, we want to keep this simple and quick. The idea is to extrude the bottom edge of the crown downward to produce the skirting. We will do this for the entire crown and not worry about the details of the face area until later.

Selecting the first bottom edge

To accomplish this, we need to select an edge, and then expand that selection to include all the bottom edges.

  1. Press the E key to enter “Tagged Edge” editing mode
  2. Select a bottom edge of the crown (shown in red)
  3. Right click the mouse to get the contextual menu
  4. Select the Select Edge Loop (around corners) option
  5. Now select some other bottom edge section

All the bottom edges selected

This should give you something like the image to the right where the entire bottom edge is red. If only the left side is red and right side is not included; not to worry, we can add the right side.

  1. Hold down the Control key
  2. Right click on a bottom edge to get the contextual menu
  3. Select the Select Edge Loop (around corners) option
  4. Now select a bottom edge section from the right side
  5. Release the Control Key

With the entire bottom edge selected, the extrusion of the crown begins. We are not only going to extrude it down but add a little scaling and some translation to make the skirt more life like.

  1. Right click the currently selected bottom edge to get the contextual menu
  2. Select the Extrude along Axis option

Settings for the extrude tab
Settings for the transform tab

On the Extrude tab,

  1. Increase the length to 8
  2. Uncheck the Y
  3. Check the Z
  4. Set the number of Subdivisions to 5

On the Transform tab,

  1. Set the X scaling to 1.03
  2. Set the Z scaling to 1.025
  3. Set the Z translation to 0.5

After extruding the crown's skirt

The skirt should now extends down from the crown and sweeps to the left some. Here is a shaded view of where we currently stand in the process. In fact, from this step forward working in a shaded view makes life a bit easier. There are number of things left to complete before we are finished with the mesh.

From this view, the helm is beginning to take shape. We can see the rounded crown that dips down more in the back, the neck-skirting coming down and flaring out to the back. Unfortunately, our poor knight has no way to see since there is no visor area. This is our next set of steps, developing the helm’s facial opening and nasal guard.

To begin with, let us switch to the right view port since the helm’s face appears on the right side of our current view. Again, use a shaded view for working ease. Looking at the mesh, it seems a little narrow. We will have to widen the entire helm to give it proportions that are more normal. After that, we will cut away the face opening and the put the nasal guard into place.

Scaling the helm's width
Selecting the facial openings

  1. Press the Space Bar to reset the object
  2. Press the X key to enter scaling mode
  3. Grab the Z axis handle (blue) and drag it to the left

Size the helm until it is about as wide as the image to the right. Now we can cut away the face openings.

  1. Reset the object with the Space Bar
  2. Press the U key
  3. Highlight the indicated polygons
  4. Press the delete key to remove these from the mesh.

Now the nasal guard can be added the to crown by extruding a pair of edges from top center of the eye opening down between the cheek pieces. As in the skirt extrusion extruded the crown skirt down, we are going to add some adjustments to this extrusion, namely scaling to narrow the nasal as it descends.

Selecting the two nasal starting edges
The Extrude tab settings for the nasal

  1. Press the E key
  2. Select the two edges on the top of the eye opening above the gap in the cheek pieces
  3. Right click the selected edges and select the Extrude along Axis option

On the Extrude tab,

  1. Set the length to 5
  2. Set the number of Subdivisions to 4
  3. Uncheck the Y
  4. Check the Z

On the Transform tab,

  1. Set the X scaling to 0.7

After extruding the nasal, select these two edges
The Transform tab settings for the nasal

The extrusion should leave us with the nasal looking much like the one to the right. Coming down from the crown and narrowing to a more pointed form as it passes down into the gap between the two cheek pieces.

The image to the right is not exactly what you would have at this point. I have jumped ahead slightly by selecting the two adjoining nasal edges in the upper corner of the eye opening on the right side. This is in preparation for our next step.

Barbuttes typically had very rounded eye openings that angled slightly toward where the tip of the nose might be on the wearer. We need to soften these corners and an a bit of angle.

Specifically, we would like to flare the upper nasal more gracefully into the crown and round out the lower back corners of the eye openings and add some upward arching to the tops of each eye. Since I have already selected those two nasal edges, let us start with those.

The corners have been bridged

  1. Right click the selected edges (from the image above)
  2. Select the Bridge Boundary Edges option
  3. The properties on the dialog are sufficient, so no changes are needed here

This creates a polygon between those two edges, which gives the nasal a smoother broader connection to the crown. Repeat this procedure for the opposite side of the nasal as well. Additionally, use the same procedure to bridge the corner edges on the lower back corners of each eye opening. When finished, there should be four new polygons on the mesh as in the image to the left.
We will save the arching of the tops of the eye openings for little later.

After de-selecting the lower back edges
Selecting the crown's seam edge

Now let us add the crown’s seam edge. This slight raised edge runs upward along the bridge of the nasal over the top centerline of the helm and down the backside.

  1. Select a vertical edge in the center of the nasal
  2. Right that selected edge
  3. Select the Select Edge Loop (no corners) option
  4. Select another edge along that same line
  5. In the Camera View, Hold down the Control Key
  6. De-select the red edges from the base of the crown to the bottom of the skirt
  7. Release the Control Key

The Transform panel settings
The seam edge is scaled and marked hard

To make the crown’s seam edge stand out clearly, we must give it some relief above the normal curvature of the crown and make it a non-deforming hard edge.

Scaling the seam edge in both the X and Y axis pushes the edge above the crown’s curvature and adds a bit of ridge line to the nasal as well.

On the Transform Panel

  1. Hold down the Shift Key
  2. Click on both the X and Y buttons
  3. Click on the GLOBAL button
  4. Inside the viewport, gently drag the mouse until the seam rises slightly
  5. Press the E key to return to the “Tagged Edge” mode
  6. Right click on the seam to get the contextual menu
  7. Select the Mark Edge Hard option

Moving the back eye opening points

Arching the tops of the eye openings remains the last addition to the basic mesh for this tutorial.
Nothing beats some simple point edits to accomplish this feat; however, let’s do this one with a little magnetic assistance.
Using the modify tool in magnetic mode, pushing points actually slides them across the existing surface of the mesh.
This is a great time saving since the points stay relative to the mesh and don’t drift out into space.

  1. Switch to the Front Viewport
  2. Press the T key to enter “Tagged Point” mode
  3. Drag a selection rectangle over the point at the back of the eye opening
  4. Press the M key to enter modify mode
  5. Highlight only the Magnet
  6. Hold the Shift Key down
  7. Carefully slid the selected point toward the left

After moving the eye opening points

By using the Rectangular select from the “Tagged Point”, we selected the point on the opposite eye opening in addition to the one visible. The Shift key tied to the translation to both points so that the move was identical for each point. So it’s an exact two for one edit. We can now use the same technique for modifying the top of the eye opening to create a gentle arch for both eyes at once. Grab each point along the brow (top of the eye opening) and push them up until it looks something like the image to the right.

This concludes the basic mesh construction intended for the tutorial. XSI offers many methods for achieving any single task so feel free to experiment with alternative methods or approaches. Perhaps I’ll continue this later to refine the mesh with a form fitting make over, add some rolled edges, and a few additional modifications to get helm up to historical standards. So stayed tuned.

December 26, 2008

Sapphire is out

Filed under: JavaFX — Ben Jones @ 10:40 am

Seems that the Blogosphere is interested in Sapphire. Since Jim Weaver posted his first blog regarding Sapphire, it has been carried over to DZone, then into JavaLobby, then out to several other technology blogs and now has landed as an item of interest on the Sun Microsystems front page.

Thanks everyone for your interest and commentary on this JavaFX application. Below is a snapshot of the Sun page. Please head on over to Sun and express your support for JavaFX.

Sun site inclusion

December 20, 2008

A brief charting example

Filed under: JavaFX — Ben Jones @ 10:21 pm

This is the technical writeup I provided to Jim Weaver for his updated blog with some editorial changes.

One of the features of JavaFX that makes it attractive to real-time application developers is its ability to tie graphical elements to models through the binding mechanism. This mechanism makes it possible for the current state of the model to be reflected in the interface without the need to create any type of polling system.

In our Sapphire application, we collect real-time data from classroom observations. The observer records classroom events by pressing various buttons. These events are displayed in several dashboard type displays which are actively tied to supporting models. One of these displays in a time lime of events created by a series of colored rectangles. The size, placement and color of the rectangles represent different relationships in the event data. Every time an event is pressed, the data changes and the bound display automatically updates.

To achieve this, you only need three things: a data model, a display element, and an event driver of some type. Let’s take a look at one of the visual building blocks, the TimeOnTaskBlock class:

public class TimeOnTaskBlock extends CustomNode {

public var aboveColor:Color = Color.GREEN;
public var belowColor:Color = Color.RED;

public var seconds:Integer;
public var startingMark:Integer;
public var zoneWidth:Integer = 600;
public var zoneSeconds:Integer = 3600;
public var height:Integer = 100;
public var maxSegments:Number = 5;
public var segment:Number = 0;
public var x:Integer;
public var scale:Number = 0.95;

  public override function create(): Node {
    return Group {

      var maxDisplayHeight:Number = height/2;

      content: [
        Rectangle {
          x: bind zoneWidth * startingMark / zoneSeconds;
          y: bind height/2 - scale * ((maxDisplayHeight) * segment/maxSegments)
          width: bind zoneWidth * seconds / zoneSeconds;
          height: bind scale * (maxDisplayHeight * segment/maxSegments)
          fill: bind aboveColor
          strokeWidth:0
        },
        Rectangle {
          x: bind zoneWidth * startingMark / zoneSeconds;
          y: bind height / 2
          width: bind zoneWidth * seconds / zoneSeconds;
          height: bind scale * (maxDisplayHeight - (maxDisplayHeight * segment/maxSegments))
          fill: bind belowColor
          strokeWidth:0
        }
      ]
      effect: Lighting {
        light: DistantLight { azimuth: 225 elevation: 60 }
        surfaceScale: 2
      }
    };
  }
}

This custom node represents what will be displayed. It is a pair of scaled rectangles stacked on top of each other. The various attributes define shape, size, and placement. Notice the use of the the DistantLight effect to give the rectangles in the graph some depth. The next building block up from this is another custom node that handles the visual orchestration of the time blocks nodes. The DisplayTimeChart node is effectively the dashboard element being displayed. It has a data member holding a sequence of TimeOnTaskBlock nodes. Let’s take a peek at this node:

public class TimeOnTaskBlock extends CustomNode {

public var aboveColor:Color = Color.GREEN;
public var belowColor:Color = Color.RED;

public var seconds:Integer;
public var startingMark:Integer;
public var zoneWidth:Integer = 600;
public var zoneSeconds:Integer = 3600;
public var height:Integer = 100;
public var maxSegments:Number = 5;
public var segment:Number = 0;
public var x:Integer;
public var scale:Number = 0.95;

  public override function create(): Node {
    return Group {

      var maxDisplayHeight:Number = height/2;

      content: [
        Rectangle {
          x: bind zoneWidth * startingMark / zoneSeconds;
          y: bind height/2 - scale * ((maxDisplayHeight) * segment/maxSegments)
          width: bind zoneWidth * seconds / zoneSeconds;
          height: bind scale * (maxDisplayHeight * segment/maxSegments)
          fill: bind aboveColor
          strokeWidth:0
        },
        Rectangle {
          x: bind zoneWidth * startingMark / zoneSeconds;
          y: bind height / 2
          width: bind zoneWidth * seconds / zoneSeconds;
          height: bind scale * (maxDisplayHeight - (maxDisplayHeight * segment/maxSegments))
          fill: bind belowColor
          strokeWidth:0
        }
      ]
      effect: Lighting {
        light: DistantLight { azimuth: 225 elevation: 60 }
        surfaceScale: 2
      }
    };
  }
}

The TimeDisplayChart serves a couple of purposes. First it builds the overall dashboard element. This defines the usual display space, necessary labeling and element placements. Please note two aspects of this class: the group where its content is bound to the displayBlocks sequence and the second group composed of a solo TimeOnTaskBlock. By binding the content of a group to a data source, any changes in the data source will be made available to the group automatically. This effectively produces a self-updating display since we bound a displayable node. The second group which is a single instance of the TimeOnTaskBlock serves another purpose. It covers the span of time since the last data change and the current time. Since the data model stores only past events, we need a means of showing data yet to be stored. It’s real-time after all.

To place all of this into an application, an instance of TimeDisplayChart is placed into a group as follows:

Group {
  translateY:310
  translateX:10
  content:[
    TimeDisplayChart{
      width:600
      height:100
      zoneSeconds:3600
      zoneWidth:600
      background:Color.#969696
      timer: bind timer
      displayTicker: bind displayTicker
      currentSegment: bind appState.currentSegment
      timeMark: bind appState.currentTimeMark
      onColor: bind appState.onColor
      offColor:bind appState.offColor
      displayBlocks: bind displayblocks
    }
  ]
}

Here we can see the various attributes of the custom node being bound to different data sources and conditions that exit within the larger context of the application. The bindings create an active communication channel between application state data and the graphical elements. It’s convenient, responsive, and easy to manage during the development process.

You can find a wealth of information about JavaFX and what people are doing with this RIA technology over at Jim Weaver’s JavaFX blog and of course at Sun’s JavaFX.

December 18, 2008

Sapphire in the Wild!

Filed under: JavaFX — Ben Jones @ 6:59 pm

Sapphire, the classroom observation tool, has hit the web for its public debut. Written in the newly released official JavaFX 1.0 from Sun Microsystems,  Sapphire brings advanced Rich Internet Application technology to educators focused on observing classrooms. The Community Edition which is available from our website was featured by the prominent JavaFX blogger and author Jim Weaver. Check out the JavaLobby posting at JavaFX in the wild.

Thank you Jim Weaver for your interests in our JavaFX endeavors.

March 1, 2008

Behavioral Action Model - Part Three

Filed under: Programming — Ben Jones @ 2:30 pm

In part two, the conceptual underpinnings of the behavioral action model were discussed. We took a simple function from part one and coaxed it into a class then encapsulated that class into an Object. A loader function on the body tag’s “onload” method would then do real work of binding elements to their respective functionality.

In this tutorial, we are going to gloss over that actual mechanics of how the loader operates except to say that it is keyed to CSS selectors. They are effectively the glue between the element, its action and the supporting functionality.

Let’ start by resurrecting the simple page from part one:

<html>
<head>
<title>My Test</title>
<script type="text/javascript" src="link.js"></script>
<link rel="stylesheet" type="text/css" href="goLink.css"/>
</head>
<body onload="link();">

    <button class="goLink" id="mybutton">My Page</button>

</body>
</html>

First, we need to modify this page slightly. Instead of loading the Link class directly, we are going to use a loader class, namely “Behaviour“. This class has a few methods available, of which, we are most interested in the “apply” and “register” methods. The “register” method simply informs the Behaviour script of an Object that contains an action; while the “apply” method performs the necessary parsing and binding between our “bam_classes” Object and the page’s DOM.

Since these file are external files, includes are necessary which brings up a couple of important issues, nomenclature and file organization. Regardless of your preferences, be very consistent and well organized. In this tutorial, I will place scripts and css into their own directories. With that in mind, we are ready to make some modifications. First, the web page code needs to include the “Behaviour” class and our “bam_classes” class which can be found in the “bam.js” file.

<script type="text/javascript" src="scripts/js/lib/behaviour.js"></script>
<script type="text/javascript" src="scripts/js/actions/bam.js"></script>

An important browser note here, be sure to use the full tag notation for these types of includes instead of the self-closing notation. Some, not mentioned here, browsers continue to have quirky support for this notation when applied to includes.

Next we need to use the “apply” method of the Behaviour class as our loader in the body’s “onload” method:

<body onload="Behaviour.apply();">

While we’re making modification to the page, let’s move the css into its own directory as well. With all of this finished, the original page now looks like the following:

<html>
<head>
<title>My Test</title>
<script type="text/javascript" src="scripts/js/lib/behaviour.js"></script>
<script type="text/javascript" src="scripts/js/actions/bam.js"></script>
<link rel="stylesheet" type="text/css" href="css/bam.css"/>
</head>
<body onload="Behaviour.apply();

    <button class="goLink" id="mybutton">My Page</button>

</body>
</html>

Our next modification is the creation of the “bam.js” which is essentially our “bam_classes” Object from part two saved as a file. However, there is an important addition, the inclusion of a call to the “register” method from the “Behaviour” class. This call makes our object known to any calls to the “apply” method.

For brevity sake, here is the “bam.js” file as it now stands.

var bam_classes =
{
	'button.goLink #mybutton' : function(element)
	{
		element.onclick     = function() { };
		element.onmouseover = function() { };
		element.onmouseout  = function() { };
	}
};

Behaviour.register(bam_classes);

Before you cry foul and tell me that it’s not exactly like part two’s “bam_classes”, let me agree. I have good reasons for stripping out the code from the onclick method and space padding the id token used in the key. In its current state, the “Behaviour” class has a parser flaw that is unable to resolve an id delimiter (#) that has no preceding space which is part of a larger css selector; namely “tag.class#id’ needs to be ‘tag.class #id’ instead). A minor inconvenience, but one that needs some attention.

Digressing briefly, I need to discuss the “bam_class“, or more specifically - action files. Action files contain the “binding action to our functionality”. Therefore, the container Object should be as clean and simple as possible. It is very tempting to pour all the actual functionality code into the various methods within a class. However, it is not required to have the code reside here and in my experience a mistake to do so. Consider the Object as a holder for prototypes of functions defined elsewhere. This helps clear the clutter and confusion of mixing control code with execution code.

So where do I place the code? You have two choices really, in the same file as the Object (but not in the Object) or as an external file or files. For simple applications where the functionality will only be used with the action file, then in the same file is really convenient. If you plan to have a library of functions that exists and are usable independent of the behavior actions, then store the code outside the action file. Again, this is purely dependent upon you personal preferences of course.

For these considerations, I stripped out the code from within the methods in preparation of placing it into an outside
declaration, in effect “stubbing” the prototype. Using the onlick method from our Link class, we now have:

element.onclick = function()  	{ do_click(this);  };

Fundamentally, the “do_click(this)” is just a function that takes an argument. The function can be placed anywhere really, we’ll place in the action file. There is now an argument “this” which is a Javascript reserved word. It is similar to other object oriented languages and provides a self contained reference to the current Object, in our case, the Object reference that created the event to which our action is attached. My digression has ended for the moment and I should demonstrate what the action file “bam.js” contains.

var bam_classes =
{
	'button.goLink #mybutton' : function(element)
	{
		element.onclick = function()  	{ do_click(this); };
		element.onmouseover = function()  { do_mouseOver(this); };
		element.onmouseout = function()  { do_mouseOut(this);  };
	}
};

Behaviour.register(bam_classes);

/** Supporting function definition **/
function do_click(reference)
{
	alert('The button was pressed");
}

function do_mouseOver(reference)
{
	// nothing yet
}

function do_mouseOut(reference)
{
	// nothing yet
}

With the actual method code pulled out into their own definitions, we are free to code up whatever we need without entangling the control logic. You have virtually complete freedom to manipulate the DOM, do client-side validations, make Ajax calls, or whatever needs to be accomplished.

February 15, 2008

Beahvioral Action Model- Part Two

Filed under: Programming — Ben Jones @ 9:42 am

In Part One, we built a very simple page with a single button that made use of some Behavioral Action Model techniques. From part one, we had the following function that provided the muscle for our button:

function link()
{
  var btn     = document.getElementById("mybutton");
  btn.onclick = function() { self.location = 'mypage.html'; }
}

This function was made available to the document by means of the body tag’s “onload” method. This works just fine for a few functions but breaks down rather quickly when the complexity begins to rise. Fear not though, the mechanism still applies. With a little coaxing and a touch JavaScript’s flexibility, we can continue undaunted.

For starters, it would more convenient if we didn’t need to actually create a “btn” reference from within the function. Something more like the following perhaps:

function link()
{
  btn.onclick = function() { self.location = 'mypage.html'; }
}

We could then pass the “btn” reference in as an argument of the function:

function link(btn)
{
  btn.onclick = function() { self.location = 'mypage.html'; }
}

To make all of this a bit more “generic”, let’s replace the “btn” name for something less specific, like “element”.
Rewriting the above function with our substitution yields the following.

function link(element)
{
  element.onclick = function() { self.location = 'mypage.html'; }
}

At this point, we have returned to something extremely similar to our original “goto” function from part one:

function goto(url) { self.location = url; }

Although these two are similar, there are some major differences. While the latter “goto“, function is just that, a function. The former “link” function has evolved into JavaScript’s version of a class. This classifying, if you’ll pardon the expression, has created a class Link that contains an “onclick” method. We can add additional methods as well.

function Link(element)
{
  element.onclick     = function() { self.location = 'mypage.html'; };
  element.onmouseover = function() { };
  element.onmouseout  = function() { };
}

The Link class now has some extra muscle that be applied to the element under differing contexts. It can now respond to “click“, “mouseover“, and “mouseout” events. This is fine, but how do we make use of this improved link function?

In part one, we used the onload method to install the script that directly bound itself to the element. This time we will inject a little abstraction into the mixture giving us a lot more flexibility. Instead of loading “Link” class directly, we’ll install a loader function that will in turn load this class. We still have an issue with the “Link” class itself. It is not directly bound to an element as it was originally, but rather accepts a reference to one instead. So, how do we tie our class to the desired element or elements?

In JavaScript, classes are Objects and can be thus be members of other Objects. We can in fact store our “Link” class with all its methods within another Object, like an array. This would give us the ability to
store many other classes; Luckily, JavaScript offers us not only an array but also an associative array (otherwise known as maps, or hashes). Why is this so lucky you ask?

Associative arrays are special in that the array stores data as key-value pairs where the key is literally the means to access the value. This is ideal for our purposes since the key can be a text string instead of a numerical index. Let’s use the “Link” class to illustrate this point.

function Link(element)
{
  element.onclick     = function() { self.location = 'mypage.html'; };
  element.onmouseover = function() { };
  element.onmouseout  = function() { };
}

If we extract the class name to use as the key, namely “Link”. Then the contents of the class become the matching value. Since the key is text, it has been set into single quotes.

'Link' : function (element)
{
  element.onclick     = function() { self.location = 'mypage.html'; };
  element.onmouseover = function() { };
  element.onmouseout  = function() { };
}

The colon denotes an associative pair. The text string on the left is the key; while, the remaining class definition becomes the value on the right hand side. Now that our class has been converted into a key-value pair, it needs to be added to a container Object. We’ll name our Object “bam_classes” and make the assignment as follows:

var bam_classes =
{
'Link' : function (element)
{
  element.onclick     = function() { self.location = 'mypage.html'; };
  element.onmouseover = function() { };
  element.onmouseout  = function() { };
}
};

Having our class definition stored as a value tied to its function name as the key further adds a subtle layer of abstraction. Remember that the name is a text string and thus could be any string and not necessarily a traditional function or class name, like “myFunc” or “accountsPayable”. Pulling a quote from part One, …”any valid element tag, class,
attribute, or combination thereof can be used” brings us to an important juncture.

In part one, our button element was styled with the class “goLink” and had and id attribute of “mybutton“. There is no reason why we can’t use this information as the key for our class definition that is stored in the “bam_classes” Object. Fortunately, CSS provides a convenient nomenclature for just this case:

var bam_classes =
{
'button.goLink#mybutton' : function (element)
{
  element.onclick     = function() { self.location = 'mypage.html'; };
  element.onmouseover = function() { };
  element.onmouseout  = function() { };
}
};

Having the ability to use CSS selectors as the key for stored classes is a major step forward in both expressive power and the extraction of control and logic code from presentation code. We can now tie functionality to elements as broadly as all buttons, or as discretely as button of “some_class” that has an id of “some_id

Finally, we have reached the point where we jump back to the loader function that is being called in the body’s “onload” method. The purpose of the loader class is to attach all our functionality encapsulated in the bam_classes Object to their corresponding elements. The loader extracts the keys from the bam_classes Object then parses through the DOM elements within the document looking for matches. Each matched element becomes a reference that is used by the attached function.

{end part two}

February 3, 2008

Behavioral Action Model - Part One

Filed under: Programming — Ben Jones @ 12:23 pm

This is a brief tutorial on using the behavioral action model. Fundamentally, this is just a clean separation between HTML and Javascript scripting that relies on Javascript’s ability to modify the DOM. In essence, we are attaching Javascript functions to events on DOM elements using CSS as an identification system.

Let’s start with a simple button element that will link us to another page:

<button onclick="javascript:location='mypage.html'">My Page</button>

Nothing fancy, a very basic button that gets the job done with no styling. Now create a basic style for the button that gives us a font of choice and a size of 20 pixels.

.goLink { font-family:Verdana; font-size:20px; }

There, a basic style. Now let’s apply that style to our button:

<button class="goLink" onclick="javascript:location='mypage.html'">My Page</button>

Again, this is nothing fancy, just a basic button and an applied style. From this point, things begin to diverge.
What we intend to happen is that when the button is “clicked” we jump to the link provided.
Since our goal is to pull out the javascript, let’s start by cleaning up the button a bit into
something a little more concise.

<button onclick="goto('mypage.html');'">My Page</button>

This is a little cleaner, but now requires a supporting Javascript function like below:

function goto(url)
{
  self.location = url;
}

We now have a Javascript function that actually does the work when its called from within the
button by the “onclick“. But we still have Javascript in our button! Yes, but not for long.
Lets rewrite the button again and this time pull out the “onclick” event entirely.

<button class="goLink">My Page</button>

There, a really minimal button indeed. Unfortunately, our button no longer jumps to the page when clicked.
To fix this, we need to re-attach that “goto” function to the button without embedding it back into
the button. Using Javascript we can grab the element in question with a “getElementById” call
but we don’t have an “id” attribute on that button. So let’s add one:

<button class="goLink" id="mybutton">My Page</button>

Now we can do something like this:

var btn = document.getElementById("mybutton");

Doing this gives us a Javascript object that is referenced to the button element. We now have a means
by which to re-attach our “goto” function. This looks a little like the following:

btn.onclick = goto;

That statement literally adds an “onclick” method onto our object “btn” and
assigns it to a function called “goto“.
So, we’re getting closer by the moment. What we need to do now is package all this up a little neater and make
it accessible to the browser. In fact, we could even define the “goto” function within this little
package making everything even more concise.

function link()
{
  var btn     = document.getElementById("mybutton");
  btn.onclick = function() { self.location = 'mypage.html'; }
}

To activate this link function, we need to use the “onload” method of the body element.

<body onload="link();">

By using the “onload” we’re telling the browser to load up the functionality found in our “link
function and this would in turn make our button do its intended business. So what does this really look like in practice.
Let’s look at a little page that uses this technique.

<html>
<head>
<title>My Test</title>
<style>
   .goLink { font-family:Verdana; font-size:20px; }
</style>
<script>
function link()
{
  var btn     = document.getElementById("mybutton");
  btn.onclick = function() { self.location = 'mypage.html'; }
}
</script>

<body onload="link();">

<button class="goLink" id="mybutton">My Page</button>

</body>
</html>

We should now pull out the CSS definitions and all the Javascript from the HTML file and place
them into their own external files much like the following rewrite of the page:

<html>
<head>
<title>My Test</title>

<script type="text/javascript" src="link.js"></script>
<link rel="stylesheet" type="text/css" href="goLink.css"/>
</head>

<body onload="link();">

<button class="goLink" id="mybutton">My Page</button>

</body>
</html>

By doing this, we have very tight and clean HTML and likewise concise supporting files for
both the CSS and the Javascript.

Now comes the next step, ramping up the possibilities. We are not limited to using only id
attributes to attach functionality, any valid element tag, class, attribute, or combination
thereof can be used for this purpose. Using CSS notation, we could have attached our “goto
function more specifically to the button using something like ‘button.goLink#mybutton’.
Our link function would have to be rewritten to look for buttons, then for those buttons
of class “goLink” which then have an id attribute of “mybutton“.
While this might seem a bit much, it is extremely useful and very practical.

This is where a nice little Javascript library comes into play, called “Behaviour”, that
allows us to chain together our definitions into a single
Javascript object and then apply those definitions to the entire DOM with a single call.
Nice. Very nice indeed.

{end part one}

Powered by WordPress