Widget.Activator
- Introduction
- Demos
- Default
- Customization and Methods
- Containers and Selection
- Graphical Buttons
- Custom Events and Usage
- Browser Support
- Change History
- Known Issues
- Downloads & Documentation
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.
DefaultShow/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 3Show/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]).
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.
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.
Name | Year(s) | Type |
---|---|---|
The Dark Knight | 2008 | movie |
Batman Begins | 2005 | movie |
Catwoman | 2004 | movie |
Return to the Batcave | 2003 | TV movie |
Birds of Prey | 2002-2003 | TV series |
Batman & Robin | 1997 | movie |
Batman Forever | 1995 | movie |
Batman Returns | 1992 | movie |
Batman | 1989 | movie |
Legends of the Superheroes | 1979 | TV movie |
Batgirl | 1967 | short TV movie |
Batman the Movie | 1966 | movie |
Batman | 1966-1968 | TV series |
Batman and Robin | 1949 | movie serial |
The Batman | 1943 | movie serial |
Information from here.
<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
- FireFox 1.5.0.12, 2.0.0.16, 3.0.3
- Opera 9.23, 9.52, 8.52
- Internet Explorer 6 SP2
- Internet Explorer 7.0.5703.11
- Safari 3.1
- Google Chrome beta, which has an issue with the second demo (see Issues)
Change History
Version 0.2.00: 11 Oct 2008
- Prepared for release, updated docs and demo pages
- Added MIT license
Version 0.1.15: 8 Oct 2008
- BREAKING CHANGE: the event memo is no longer the element but now contains the following properties:
- element - the element
- activator - the activator
- event - the event that triggered this event
Version 0.1.14: 5 Oct 2008
- Fixed bug where elements were still firing mouseout when disabled
Version 0.1.13: 8 Jun 2008
- Updated setEnabled so that it removes the active and hover styles if you disable an element
Version 0.1.12: 18 Apr 2008
- Updated apply so that it ensures that selected and enabled elements remain so
Version 0.1.11: 17 Mar 2008
- Fixed a bug in setSelected and setEnabled where the default was not true
Version 0.1.10: 12 Mar 2008
- Added click event
Version 0.1.9: 7 Mar 2008
- Added this.selector to save the original selector
- Added apply method which removes all and reapplies the original selector
Version 0.1.8: 3 Mar 2008
- Moved event name options into their own events options
Version 0.1.7: 25 Feb 2008
- Fixed a bug where the elements array was not correctly compacted after remove
Version 0.1.6: 23 Feb 2008
- getElements will return all elements if passed null or *
- The above affects methods like remove: remove() or remove("*") will remove all elements
- Selector in constructor is now optional
- Minor improvement in constructor - just call add instead of calling add for each element returned from $$(selector) which add does anyway
- Fixed a bug in add where it would incorrectly try to add a selector string passed in
- Moved className options into a classNames object
Version 0.1.5: 18 Feb 2008
- Fixed a bugs in selectAll and enableAll where the default was not true
Version 0.1.4: 19 Jan 2008
- Fixed a minor bug in add
- Added possibility for selector to be null - TODO: paramater mashing
Version 0.1.3: 10 Dec 2007
- Added mousedownEvent and mouseupEvent names to options
Version 0.1.2: 19 Oct 2007
- Added handlers array and updated destroy method to stopObserving all event handlers
Version 0.1.1: 18 Oct 2007
- Improved #isElement method to allow for sliding doors
- Turned event names into properties of Widget.Activator (Widget.Activator.mousedownEvent and Widget.Activator.mouseupEvent)
Version 0.1.0: 14 Oct 2007
- Initial release
Known Issues
IE6 screws up the sliding doors graphical buttons styling. This is a CSS issue and not an issue with the widget.Resolved using conditional include style sheet for IE6.- Google Chrome beta does not highlight the last two elements in the Customization and Methods demo.
If you come across any other issues please post a comment here or send me mail directly.