Widget.Activator

Why a hovering/activation script? Can't we just do this with CSS pseudo-classes? Well yes and no. For one, not all browsers support pseudo-classes on all elements. Secondly, this script goes much further in providing en/disabling and selection control, which pseudo-classes are not going to provide.

This script can (and will) be used in a number of other widgets. It's one of those core Widgets that is used over and over again to provide interactivity and control. It could, for example, be used as the basis for a toolbar, a tab view, a menu or a accordian widget. In fact, it can be used with any widget that has buttons as it's basis and requires hovering, selection and the ability to enable or disable elements. Or even controls which you wouldn't traditionally think of as using "buttons", but also require hovering and selection, as can be seen by this example.

Activator.js makes use of the excellent Prototype library and is currently using version 1.6.0.3.

To use the script, include the following scripts in the head section:

		<script src='js/prototype.js'></script>
		<script src='js/activator.js'></script>
	

Also included in the head section is a style sheet containing the style rules for the activator:

		<link href='css/activator.css' rel='stylesheet' />
	

See the demos for examples of how to instantiate and use Activators.

Demos

Default

This demo shows the usage of the activator in the very simplest case.

Default

Show/Hide Code
				new Activator("#defaultDemo");
			
				<span id='defaultDemo'>Default</span>
			
				.selected {
					background-color: #eee;
				}
				.hover {
					background-color: #f90;
				}
				.active {
					background-color: #f00;
				}
				.disabled {
					background-color: #333;
					color: #999;
				}
			

Customizing Using Class Names

The following demo shows how to customize the CSS classes. The spans used in the example have no default styling at all, and are styled by setting the className in the options. Additionally, the hover, active, selected and disabled classes are overridden. Finally the demo also shows how to select or disable buttons by their index.

Button 0 Button 1 Button 2 Button 3

Show/Hide Code
				var classNamesActivator = new Widget.Activator(".classNamesDemo", {
					classNames: {
						normal: "customButton",
						hover: "customButtonHover",
						active: "customButtonActive",
						selected: "customButtonSelected",
						disabled: "customButtonDisabled"
					}
				});
				classNamesActivator.setSelected(1);
				classNamesActivator.setEnabled(2, false);
			
				<span class='classNamesDemo'>Button 0</span>
				<span class='classNamesDemo'>Button 1</span>
				<span class='classNamesDemo'>Button 2</span>
				<span class='classNamesDemo'>Button 3</span>
			

Using a Container and Selection

The demo below show how to use a container for activator controls and style the activator to look like an old style hideously ugly checked toolbar without overriding the default class names. The extendElements option adds methods that can be used in event handlers or anywhere else to each element member of the activator. The methods added are (by default): getActivator(), isSelected(), setSelected([bool]), isEnabled(), setEnabled([bool]).

Button 0 Button 1 Button 2 Button 3

Show/Hide Code
				var containerActivator = new Widget.Activator("#containerActivator span", {
					container: "containerActivator",
					extendElements: true
				});
				containerActivator.observe(Widget.Activator.mouseupEvent, function(event) {
					event.memo.setSelected(!event.memo.isSelected())
				});
			
				<span>Button 0</span>
				<span>Button 1</span>
				<span>Button 2</span>
				<span>Button 3</span>
			
				#containerActivator {
					background-color: #aaa;
					padding: 6px;
				}
				#containerActivator span {
					background-color: #aaa;
					border: 2px solid #aaa;
					cursor: default;
					padding: 3px;
				}
				#containerActivator .hover {
					background-color: #ccc;
					border-style: outset;
				}
				#containerActivator .selected {
					border-style: inset;
				}
				#containerActivator .active {
					background-color: #ccc;
					border-style: inset;
					color: #f00;
				}
				#containerActivator .disabled {
					color: #999;
					font-style: italic;
				}
			

Sliding doors and Buttons

This demo using the sliding doors technique to style buttons with a nice graphical background that will stretch to the content width. In addition the script shows how you can use the mouseup event to enable and disable another activator button. Finally, there is a bug in Firefox that begins selecting the button text when it is changed. Setting the proprietary MozUserSelect style on the button prevents text selection.

Log messages will appear here.
Show/Hide Code
				var buttonActivator = new Widget.Activator(".button", {
					container: "buttonContainer"
				});
				buttonActivator.observe(Widget.Activator.mouseupEvent, function(event) {
					new Insertion.Top("buttonLog", event.memo.innerHTML.stripTags() + " clicked.<br />");
					if(event.memo.identify() == "disableButton") {
						if(buttonActivator.isEnabled("button1")) {
							buttonActivator.setEnabled("#button1", false);
							$("disableButton").down().update("Enable Button 1");
						} else {
							buttonActivator.setEnabled("#button1", true);
							$("disableButton").down().update("Disable Button 1");
						}
					}
				});

				//Work around for FF text selection on change bug
				$("disableButton").setStyle({ MozUserSelect: "none" });
			
				<div id='buttonContainer'>
					<span class='button' id='button1'><span>Button 1</span></span>
					<span class='button'><span>Button 2 With Long Text</span></span>
					<span class='button' id='disableButton'><span>Disable Button 1</span></span>
				</div>
			
				#buttonContainer .button {
					background-image: url(../images/button_r1_c1.gif);
					background-position: left center;
					background-repeat: no-repeat;
					background-color: white;
					height: 32px;
					padding: 6px;
					margin-left: 7px;
					cursor: default;
				}

				#buttonContainer .button span {
					background-image: url(../images/button_r1_c2.gif);
					background-position: right center;
					background-repeat: no-repeat;
					background-color: white;
					padding: 6px;
					padding-right: 13px;
					color: white;
				}

				#buttonContainer .hover {
					background-image: url(../images/button_hover_r1_c1.gif);
					background-color: white;
				}

				#buttonContainer .hover span {
					background-image: url(../images/button_hover_r1_c2.gif);
					background-color: white;
				}

				#buttonContainer .active {
					background-image: url(../images/button_active_r1_c1.gif);
					background-color: white;
				}

				#buttonContainer .active span {
					background-image: url(../images/button_active_r1_c2.gif);
					background-color: white;
				}

				#buttonContainer .disabled {
					background-image: url(../images/button_disabled_r1_c1.gif);
					background-color: white;
				}

				#buttonContainer .disabled span {
					background-image: url(../images/button_disabled_r1_c2.gif);
					background-color: white;
					color: #ccc;
				}
			

Custom Events and Usage

In this demo we have a table with two activators: one for the headers and one for the rows. For this reason, we need to use custom event names, or the event listeners would receive events from both. Changing event names is as easy as passing in a new event name in the options of the constructor. This demo is shows a usage for the activator that is not simply another toolbar control. Finally, this demo also provides the reason for the breaking change in version 0.1.15. Having access to the original event that triggered the event fired by the activator, one is able to check properties of that event. In this case, the ctrlKey property is checked, thus enabling selection of multiple rows when CTRL is held down. Now in under 50 lines of code, we have a sortable table with multiple selection. Not bad.

NameYear(s)Type
The Dark Knight2008movie
Batman Begins2005movie
Catwoman2004movie
Return to the Batcave2003TV movie
Birds of Prey2002-2003TV series
Batman & Robin1997movie
Batman Forever1995movie
Batman Returns1992movie
Batman1989movie
Legends of the Superheroes1979TV movie
Batgirl1967short TV movie
Batman the Movie1966movie
Batman1966-1968TV series
Batman and Robin1949movie serial
The Batman1943movie serial

Information from here.

Log messages will appear here.
Show/Hide Code
				<table id='customEventsTable'>
					<thead>
						<tr><th>Name</th><th>Year(s)</th><th>Type</th></tr>
					</thead>
					<tbody>
						<tr><td>The Dark Knight</td><td>2008</td><td>movie</td></tr>
						<tr><td>Batman Begins</td><td>2005</td><td>movie</td></tr>
						<tr><td>Catwoman</td><td>2004</td><td>movie</td></tr>
						<tr><td>Return to the Batcave</td><td>2003</td><td>TV movie</td></tr>
						<tr><td>Birds of Prey</td><td>2002-2003</td><td>TV series</td></tr>
						<tr><td>Batman & Robin</td><td>1997</td><td>movie</td></tr>
						<tr><td>Batman Forever</td><td>1995</td><td>movie</td></tr>
						<tr><td>Batman Returns</td><td>1992</td><td>movie</td></tr>
						<tr><td>Batman</td><td>1989</td><td>movie</td></tr>
						<tr><td>Legends of the Superheroes</td><td>1979</td><td>TV movie</td></tr>
						<tr><td>Batgirl</td><td>1967</td><td>short TV movie</td></tr>
						<tr><td>Batman the Movie</td><td>1966</td><td>movie</td></tr>
						<tr><td>Batman</td><td>1966-1968</td><td>TV series</td></tr>
						<tr><td>Batman and Robin</td><td>1949</td><td>movie serial</td></tr>
						<tr><td>The Batman</td><td>1943</td><td>movie serial</td></tr>
					</tbody>
				</table>
				<button type='button' id='tableGetSelected'>Get Selected</button>
				<p>Information from <a href='http://www.superheroeslives.com/indexbatman.htm'>here</a>.</p>
				<div class='log' id='eventsLog'>
					Log messages will appear here.
				</div>
			
				var customActivatorHeaders =  new Widget.Activator("thead th", {
					container: "customEventsTable",
					events: {
						click: "table:headerClicked"
					},
					extendElements: true,
					singleSelect: true
				});
				customActivatorHeaders.observe("table:headerClicked", function(e) {
					$("eventsLog").insert({
						top: "Sorting by " + e.memo.element.innerHTML + ".<br />"
					});
					e.memo.element.setSelected();
					var index = e.memo.element.previousSiblings().length;
					var body = $("customEventsTable").down("tbody");
					var rows = body.childElements();
					rows = rows.sortBy(function(row) {
						return row.childElements()[index].innerHTML;
					}.bind(this));
					rows.each(function(row) {
						body.insert(row);
					});
				});
				var customActivatorBody = new Widget.Activator("tbody tr", {
					container: "customEventsTable",
					events: {
						click: "table:rowSelected"
					},
					extendElements: true
				});
				customActivatorBody.observe("table:rowSelected", function(e) {
					if(!e.memo.event.ctrlKey) {
						e.memo.activator.selectAll(false);
					}
					e.memo.element.setSelected(!e.memo.element.isSelected());
					$("eventsLog").insert({
						top: e.memo.element.down("td").innerHTML + " " + (e.memo.element.isSelected() ? "" : "de") + "selected.<br />"
					});
				});
				$("tableGetSelected").observe("click", function(e) {
					var msg = customActivatorBody.getSelected().collect(function(element) {
						return element.down("td").innerHTML;
					}).join(", ");
					$("eventsLog").insert({
						top: msg + ".<br />"
					});
				});
			
				#customEventsTable {
					border: 1px solid #999;
					border-collapse: collapse;
				}

				#customEventsTable td {
					border: 1px solid #999;
					padding-left: 2px;
					padding-right: 2px;
				}

				#customEventsTable .hover {
					background-color: #0af;
				}

				#customEventsTable .active, #customEventsTable .selected {
					background-color: #09f;
				}
			

Browser Support

The script has been tested in

all on Windows XP SP2 and all basic functionality works. Please see the known issues for any browser specific problems. If you use or test this script on another system and it works (or doesn't), please let me know. You can post comments here or send me mail directly.

Change History

Version 0.2.00: 11 Oct 2008

Version 0.1.15: 8 Oct 2008

Version 0.1.14: 5 Oct 2008

Version 0.1.13: 8 Jun 2008

Version 0.1.12: 18 Apr 2008

Version 0.1.11: 17 Mar 2008

Version 0.1.10: 12 Mar 2008

Version 0.1.9: 7 Mar 2008

Version 0.1.8: 3 Mar 2008

Version 0.1.7: 25 Feb 2008

Version 0.1.6: 23 Feb 2008

Version 0.1.5: 18 Feb 2008

Version 0.1.4: 19 Jan 2008

Version 0.1.3: 10 Dec 2007

Version 0.1.2: 19 Oct 2007

Version 0.1.1: 18 Oct 2007

Version 0.1.0: 14 Oct 2007

Known Issues

If you come across any other issues please post a comment here or send me mail directly.

Downloads & Documentation

Download (129KB)
Documentation