Adept Software Development

Adept: (A)pplication (D)evelopment (E)nterprise to (P)ersonal (T)ransition. It is a system I am developing to leverage Enterprise developer skills to produce stand-alone software for other market segments. This is a general software development blog discussing issues about project, architecture, design and development. The emphasis will be in Java, but many of the issues will be more general. Almost all will be technical.

http://marringtons.com

Tuesday, September 13, 2005

JavaScript Events - Part 3 - An Event Library

My first attempt at an event library allowed a single event to be attached to multiple elements, as well as multiple event methods to a single event on a single element. This is very useful when you want to track the mouse since you need to register the same even for multiple windows or frames. However, it did require the creation of a special event object and then to have that object attached. Consequently - except for the special mouse tracking case - most of my events were set in the time honoured way:
element.onclick = function( evt)
  {
    evt = evt || event;
    if (! evt.target)
      evt.target = evt.srcElement;
    alert( "clicking " + evt.target
  }

 

The problems grew:
  1. Every event function had to have the first two lines to ensure basic data conformity between browsers.
  2. If more than one piece of independent code wanted to set the same event, they had to know about each other or the event call was lost.
  3. The target field pointed to the element that triggered the event, not necessarily the element that owned the event. The latter isn't available from the event object for IE.
I wanted to create a library that:
  1. Could be called to set for an element event that already had others functions attached - either by HTML or due to earlier calls. Events needed to be called from most recent to oldest set.
  2. Would provide an event object already normalised for browser differences.
  3. Would provide an owner field that worked across all browsers.
  4. Could ease coding by setting multiple events for a single element, and multiple elements with the same event.

Usage

The core method is called, surprisingly enough, Events.add(). It requires a reference to the element, the event name and a function to run when the event is triggered.
  • The event name, as with the DOM equivalent, does not start with "on". In other words, use "click", not "onclick".
  • It will call multiple action methods for a single event.
  • If the HTML had an event set, this event will be added as well.
  • The action function has a normalised event object as its one parameter.
  • It includes valid target and owner fields.
Events.add( menu, "click",
  function( event)
    {
      Panel.menuHover = false;
      menu.style.display = "none";
      Panel.hideShield( menu.panel);
      return true;
    });

 

This can still cause a tedious amount of coding when a lot of events need to be set for a single element. I use an addEvents() method for these cases. It still sets events on a single element, but now it picks up these events from the methods of an object called events. This makes for some clear self-documenting code.
Events.addEvents( tabBarTextNode, Panel.tabActions);
...
Panel.tabActions = {events : {}};

Panel.tabActions.events.click =
  function( evt)
    {
      var panel
        = Elements.getPanel( evt.target).panel;
      Panel.setFocus( panel);
    }

Panel.tabActions.events.contextmenu = 
  function( evt)
  {
    var panel = Elements.getPanel(
                evt.target).panel;

    var menu = Panel._contextMenu(
                panel, Mouse.location( evt));

    menu.style.top =
      Panel.frame.height - menu.offsetHeight;
      
    return false;
  }

 

Less common - but just as important - are the situations where the same event and action need to be set on many elements. This following method has to use the parameters in a different order with the elements at the end, so that we can add as much as is needed.
Events.addSameEvent( "contextmenu",
  function() {alert('not allowed');},
  panel.titleBar, panel.resizeBox,
  panel.shadowRight, panel.shadowBottom);

 

This last method is going to take some describing - as is always the case when objects are used. It's used if you need to add an event to multiple elements that can be used to call multiple actions. None of the methods above will do the job. We can add multiple events to a single element, but we can't add a new event and have it be available to more than one element. The object newList resolves this deficiency: it creates a method that's also an object, so it can have state as well as function. The state is used to point to a list of events, rather than attach them to the element as we do above.
// Called once to create event function objects.
Mouse.events = {};
Mouse.events.mousemove
  = Events.newList( "mousemove");
  
Mouse.events.mouseup
  = Events.newList( "mouseup");

Mouse.events.blur
  = Events.newList( "blur");
...
// Called for each object we want
// to trigger the event list for.
// Note that the events added are
// function object, not just functions.
Mouse.initialise = function( w)
  { Events.addEvents( w, Mouse); }
...
// Elsewhere we add new events that will be
// called for each registered element
Mouse.events.mousemove.add( Panel.onmousemove);
Mouse.events.mouseup.add( Panel.onmouseup);

 

The mouse object here is the only occasion so far when I've used this more complex structure. Every window registers itself for Mouse events by calling Mouse.initialise(). Other modules that need to do something special on these actions register themselves with the action function objects using add(). To put it simply, Panel.onmousemove() will be called for each registered window.

Now, I suppose you want the library code. Well you can't have it yet. This article is already too long. I'll release it next week, so nyah.

2 Comments:

Anonymous Anonymous said...

again it's cool , cool and cool. Keep it this way !

Thursday, September 29, 2005 9:21:00 pm  
Anonymous Anonymous said...

I enjoy reading your blog! :)

Friday, March 28, 2008 6:31:00 pm  

Post a Comment

<< Home