F1 Rivals
Genius may have its limitations, but stupidity is not thus handicapped.
- Elbert Hubbard

The World Wide Web turns 20

Allegedly it was 20 years ago, today, 13 March, that Tim Berners Lee first dreamed up the idea of the World Wide Web. It wasn’t called the W3 back then, but the proposal that was made eventually lead to what we know today.

Here’s a news article on iTWeb and another from ReadWriteWeb about this historic occasion.

There’s more information about the history of the World Wide Web on Wikipedia.

[?]
Share This

Posted by Marc on Mar 13 2009 under Uncategorized



Building a Tab control using Activator – Part III

In the first part in this series we built a very simple tab widget which met the initial requirements, and then was extended with a number of options to increase re-usability in the second part. Amongst the options were a number for events, which I will discuss in this third part.

In the options we have specified a number of events. Most of these events are fired by the activator widget and require no interference from us (other than to listen to the changeOn event).  However, there are two events that the tabs widget will fire: changing, which is cancellable; and changed.

Prototype provides a custom event model which works just like real browser events. Elements have a fire method which is used to fire these custom events. Custom event names must be made up of two parts separated by a colon. Generally the first part is a noun describing the element that fired the event and the second part a verb describing what is happening. So the tabs widget will fire “tab:changing” when a tab has been clicked and “tab:changed” after the change has happened. By listening for these events, your code can react to changes in the state of the tabs widget.

Custom events can send additional information to event handlers in the memo of the event. For example with the tabs widget we would want to send which tab is being changed from and which tab to. It is also useful, when possible, to pass the original DOM event that triggered the custom event, because DOM events contain additional properties such as ctrlKey and altKey which your event handlers might want access to. Finally, it is often convenient to pass along the widget itself.

Now the activator widget already has observe, stopObserving and fire methods which work on the container element when a container is specified and the document otherwise. Our tabs widget always specifies a container, so there’s no need to reinvent the wheel, we’ll just steal these methods directly from the activator:

initialize: function(element, options) {
        //snip
        this.observe = this.activator.observe.bind(this.activator);
        this.stopObserving = this.activator.stopObserving.bind(this.activator);
        this.fire = this.activator.fire.bind(this.activator);
        this.observe(this.activator.options.events[this.options.changeOn], this.show.bind(this));

        //snip
},

As you can see, this also means that the this.activator.observe has become just this.observe.

In the show method we want to fire the two events. The changing event should be cancellable, meaning that an event handler can cancel the event and prevent the change of the tabs. Prototype extends event objects with a stop method. On DOM events this calls the built-in stopPropogation and preventDefault methods. As a side effect it also sets a stopped property on the event object which can then be tested for

The show method ends up looking like this:

show: function(e) {
        var tab;

        if(Object.isNumber(e) || Object.isString(e)) {
               tab = this.activator.getElement(e);
        } else {
               tab = this.activator.isElement(e.memo.element);
        }

        if(!tab) return;

        var memo = { from: this.selected, to: tab, tabs: this, event: e.memo ? e.memo.event : null };
        var ev = this.fire(this.options.events.changing, memo);
        if(ev.stopped) return;

        if(this.selected) {
               this.activator.setSelected(this.selected, false);
               $$(this.options.linkMethod(this.selected.down(this.options.linkSelector))).invoke("hide");
        }

        this.selected = tab;
        this.activator.setSelected(this.selected, true);
        $$(this.options.linkMethod(this.selected.down(this.options.linkSelector))).invoke("show");

        this.fire(this.options.events.changed, memo);
},

After getting the tab that should be shown, the method sets up the event memo which includes the tab being changed from, changed to, the tabs widget itself and the DOM event that caused the change if it exists (if it doesn’t exist that means the change is being caused programmatically by a call to show with an index or id). It then fires the changing event and checks to see if any event handler has stopped the event. Next the actual change is performed and finally the changed event is fired.

Why would you want to cancel a tab changing event? Well, in an Ajax application you might have a form on a particular tab that needs to be completed before another tab can be accessed. Or you might just want to confirm some changes before changing tabs. The changed event can be used to load data dynamically via Ajax or JSON. Or you might use it to change some other aspects of the page like headings or help text. But here is an example of using it to animate the tabs changing using the effects from Script.aculo.us.

var subnav = new Widget.Tabs("subnavigation", {
	tabSelector: "span",
	linkSelector: "a",
	linkMethod: Widget.Tabs.classLinks
});
subnav.observe(subnav.options.events.changing, function(e) {
	e.stop();
	e.memo.tabs.selected = e.memo.to;

	new Effect.SlideUp(e.memo.tabs.panels(e.memo.from)[0], {
		duration: 0.2,
		queue: {
			scope: "subnav-tabs",
			position: "end"
		},
		afterFinish: function() {
			e.memo.to.setSelected();
		}
	});
	new Effect.SlideDown(e.memo.tabs.panels(e.memo.to)[0], {
		duration: 0.3,
		delay: 0.2,
		queue: {
			scope: "subnav-tabs",
			position: "end"
		}
	});
});

The first statement creates the tabs control with a few options as we have seen a couple of times now. The second part is where it gets interesting. Here we are observing the changing event. In the observer function we stop the event which means the tabs control doesn’t proceed further in changing the tabs. Since we are going to change the tab anyway, we set the selected tab in the control to the new tab anyway. This prevents the control from getting confused about which is the selected tab. We then set up a pair or animations to hide the current tab and then show the selected on. Finally, after the first animation is finished, we change the selected tab button.

And what does all this look like? I have a demo page here.

Finally, from a functionality point of view, we need a destructor. Destructor’s are often left out of JavaScript widgets based on the idea that the widgets will be destroyed when the page unloads. With large Ajax applications however, you may be creating and destroying loads of widgets without ever leaving the page. Destroying a widget should force it to clean up after itself, remove event listeners and restore (if possible) the DOM to it’s original state.

In this case the activator widget already has a destroy method that cleans up its event handlers, so the only thing left for the tabs control to do is to show all the hidden panels. In the end the destroy method looks like this:

destroy: function() {
	this.activator.getElements("*").each(function(e) {
		this.panels(e).invoke("show");
	}, this);
	this.activator.destroy();
}

which simply shows all the panels and then destroys the activator.

And there we have it: a complete widget. But even now there’s more to do if you want to release it into the wild. We must add documentation, a page of demos, package the whole thing in a nice, easy to use zip file, and maybe submit it to a few sites. I will deal with all that in the fourth and final installment in this series.

[?]
Share This

Posted by Marc on Jan 11 2009 under Development



Building a Tab control using Activator – Part II

In the previous part I showed how to build a very basic but functional Tab control that uses Activator internally. While that code certainly works, it’s not really a reusable control. It’s missing several important features: options, events, a destructor, and downloads, documentation and demos. In this part I will deal with the first of these and also update the demo to show it off.

In order to make a widget truly reusable we need to provide a number of options. Just because the standard use-case has anchor tags inside list elements and uses the href to figure out what to show or hide, doesn’t mean that it’s always going to be like that. Similarly, although my original specification required the tabs to change on mouseover, a normal tabs control changes on click.

Read the rest of this entry »

[?]
Share This

Posted by Marc on Oct 29 2008 under Development



Building a Tab control using Activator – Part I

I have been planning a site design update for quite a while: the first quick designs were done in the middle of January. One of the things I have built into the design is a toolbar menu type control where rolling over each main item shows the sub-items similar to the one used here. Using my immense prowess as a thinker, I quickly realized that this is basically a tab control using mouseovers instead of mouseclicks. I could, of course, simply have used the one from Livepipe, but where would be the fun in that?

The Widget.Activator control is extremely adept at things involving highlighting and selecting of elements. It is intended not only to be used as a button control but also as a basis for other controls. It makes sense to use it as the basis of a tab control which is essentially a toolbar which shows and hides various content panes.

Read the rest of this entry »

[?]
Share This

Posted by Marc on Oct 21 2008 under Development



Activator.js updated – Widget.Activator

It’s been a long time since I’ve released an update to the Activator script. In the interim I have used it in several projects, as well as reused it as the basis of several controls, and made several improvements as well as fixed a number of bugs. So, here it is.

Read the rest of this entry »

[?]
Share This

Posted by Marc on Oct 13 2008 under Uncategorized



Lemmings

No, this is not a post about how the world, and the online world in particular, blindly follows the few to their doom. If it were, it wouldn’t be posted under “Fun”. No, this is a post about Lemmings. You know, that game you played on your 386, right? Right? Come on. I’m not really that old.

This is Lemmings in the browser using JavaScript. What’s incredible about it is that it was written in 2004. You know 4 years ago, before all the AJAX hype and Web 2.0. Before all the browser competition that is giving us faster scripting engines. Before everyone had a dual core on their desk.

Anyway, now I have Lemmings on my phone and Lemmings in my browser. How am I ever going to get anything done?

[?]
Share This

Posted by Marc on Oct 10 2008 under Fun



Image Transitions

One of my colleagues is developing a small website where the client wants a fairly fancy image transition on page change. He contacted me to try and figure out if this transition could be done using JavaScript. The other option, of course, was to use Flash.

First let me tell you how freakishly difficult it is to explain an image effect like this in an IM conversation. Actually a phone call won’t have helped much either. I was told that it was “like the advertising boards in the airport”. Now I haven’t been in the airport for a while, and even if I was, I don’t pay much attention to the overabundance of advertising. If I did, I’m betting I’d be struck by the sudden urge to own everything and leave the airport a much poorer man. I’m certain the whole explanation would’ve been much easier if either, and preferably both, of us had any involvement in video editing. I’m sure those guys have very exact names for these types of scene changes.

Read the rest of this entry »

[?]
Share This

Posted by Marc on Oct 03 2008 under Development



A Quick Update

I haven’t posted since March. Hell, IE8 beta 2 is out, and Google have developed and released Chrome beta in that time. There is a new version of Adobe AIR, and Flash player 10 is at Release Candidate. And what have I been doing in those six months? Well, mostly being snowed under by work.

Mostly.

Actually rather a lot has happened and in this post I will concentrate on the personal side of things that might interest some out there.

Read the rest of this entry »

[?]
Share This

Posted by Marc on Sep 26 2008 under Personal



IE8 beta 1, A first look

The IE team at Microsoft has suddenly been very busy. Last week they reversed their original decision to have IE8 render like IE7 by default. Instead IE8 will behave like, well, IE8. And now, Beta 1 is available for download.

Read the rest of this entry »

[?]
Share This

Posted by Marc on Mar 06 2008 under Software



Another Contest of Artistry

A second Pointless Waste of Time Contest of Artistry has started and looking at the entries for the first round, this one will be every bit as cool as the last one. As with the last one, there will be 4 days of drawing with 3 days of voting for every round. This time, however, I’ve added a countdown timer to the results page so that there are no GMT/UTC/DST confusions.

Read the rest of this entry »

[?]
Share This

Posted by Marc on Mar 04 2008 under Fun




ZATopSites - top sites, top web, south africa Afrigator