ALPHA
Widget Structure
DOM API
Sample widgets: Roman Bats Sudoku JSLint

ADsafe DOM API

ADsafe provides an application programming interface to the Document Object Model. It improves the security, portability, and reliability of the DOM.

This allows the widget program to affect the structure, content, appearance, and behavior of the widget in a convenient way, while also constraining the program so that it cannot do bad things.

The ADSAFE.go method provides access to the dom object. The dom object is the root of the widget's document tree. The widget's document tree is a subtree of the page's complete document tree. ADsafe limits all interactions to the subtree. It is not possible to get back to the document root.

Query

The dom object has a q (for query) method. It takes a query string that returns a bunch object that provides access to zero or more nodes selected from the subtree.

The query language somewhat resembles CSS selectors. A query is a sequence of one or more selectors. There are two kinds of selectors: hunters and peckers.

Query Selectors
Hunter Selector Meaning
# id Select the descendent node that has an id that matches the id. ADsafe requires that every id be unique. This selector only makes sense in the first position.
tagName Select all of the descendent nodes that have a tagName that matches. dom.q('p') matches all <p> elements.
+ tagName Select all of the immediate siblings that have a tagName that matches.
> tagName Select all of the immediate children that have a tagName that matches.
/ Select all of the immediate child nodes.
* Select all of the descendent nodes. After matching *, only peckers may be matched.
Pecker Selector Meaning
. class Keep the nodes that have a class attribute that matches the class. Same as [class~=class].
& name Keep the nodes that have a name attribute that matches the name. Same as [name=name].
_ type Keep the nodes that have a type attribute that matches the type. Same as [type=type]. This is usually used with <input> and <button> tags. It can also be used with <link>, <object>, <param>, <ol>, <ul>, <li>, and <style>.
[ attribute ] Keep the nodes that have the named attribute.
[ attribute = value ] Keep the nodes with the named attribute that matches the value.
[ attribute != value ] Keep the nodes with the named attribute that do not match the value.
[ attribute *= value ] Keep the nodes with the named attribute that contain the value.
[ attribute ^= value ] Keep the nodes with the named attribute that start with the value.
[ attribute $= value ] Keep the nodes with the named attribute that end with the value.
[ attribute ~= value ] Keep the nodes with the named attribute that contain the value as an element in a space-separated list.
[ attribute |= value ] Keep the nodes with the named attribute that contain the value as an element in a minus-separated list.
: first Keep the first node in the bunch.
: rest Keep all of the nodes in the bunch except the first.
: even Keep half of the nodes in the bunch, starting with the second.
: odd Keep half of the nodes in the bunch, starting with the first.
: hidden Keep nodes that are currently hidden.
: visible Keep nodes that are currently visible.
: disabled Keep nodes that are currently disabled.
: enabled Keep nodes that are currently enabled.
: checked Keep nodes that are currently checked.
: unchecked Keep nodes that are not currently checked.
: focus Keep the node that has focus.
: blur Keep nodes that do not have focus.
: text Keep text nodes.
: tag Keep nodes that are not text nodes.
: trim Keep nodes that are not useless text nodes.

The dom.q method returns a bunch object that represents zero or more nodes (depending on the success of the query). A bunch has methods that can act upon all of the nodes it represents. A bunch also has a q method, so a bunch can be the root (or roots) of subtrees for additional searches.

Sample Queries
Query Action
h1 + p * : text Select the text in all of the paragraphs that immediately follow H1 tags.
input_radio&tikki:unchecked Select all radio buttons named "tikki" that are currently unchecked.
#KODA_FORM button_submit Select the submit button that is a descendent of the element with an id of KODA_FORM.
p.topic.special Select all paragraph tags that have a class attribute containing both topic and special.
img [alt*=free] Select all image tags that have an alt attribute containing free.
ol//:enabled:visible Select all of the visible, enabled tags in an ordered list that are grandchildren.
form input_hidden Select all hidden fields within forms.
form input:hidden Select all input nodes that are hidden within forms.
*_text Select all nodes with type="text" attributes.
*:text Select all text nodes.

In addition to the q method, the dom object has methods for making new HTML nodes and for altering the structure of the document tree.

dom Methods
Method Description
.append(bunch) Append the nodes in the bunch after the last element of the dom subtree. It returns the dom object.
.combine(array) Combine an array of bunches into a single bunch. This is the opposite of the bunch.explode method.
.count() It returns the number 1.
.ephemeral(bunch) Designate a bunch as ephemeral. The nodes will be removed when ephemeral is called again, or when the mouse button comes up, or when the escape key is pressed. This is a convenient way of getting rid of short-lived things like tips and popups. If bunch is null, then the current ephemeral nodes are removed.
.fragment() Make a new HTML document fragment. A fragment can be a container of nodes. It disappears when appended to the live document tree.
.prepend(bunch) Prepend the nodes in the bunch before the first element of the dom subtree. It returns the dom object.
.q(query) Search the dom subtree. It returns a new bunch object containing the nodes that matched the query. It always returns a bunch object, even if the query selected no nodes. It will throw an exception if the query is not well formed or if the first selector is not a hunter.
.remove() The widget's nodes are all removed from the document. At this point, the widget is useless.
.row(array) Make a new <tr> node. Append to it a new <td> node wrapping a text node for each element of the array. It returns a bunch containing the <tr> node. The row will not be attached to the document tree.
.tag(tagName, type, name) Make a new HTML node. If tagName is 'button' or 'input', supply an extra parameter that determines the type of the element, such as 'submit' or 'radio'. A third parameter optionally names the node. This is used to group radio buttons together, so that at most one radio button in a group can be checked. It returns a bunch containing the one new node. It will not be attached to the document tree.
.text(string) Make a new text node. It returns a bunch containing the text node. It will not be attached to the document tree. If the argument is an array of strings, it will return an array of text nodes.

Bunch Objects

A bunch object is the result of calling the q method.

A bunch object has a large set of useful methods. These can be broken into three groups: Those that set, those that get, and the miscellaneous.

Bunch Set Methods

Every set method returns the bunch it was called with. This allows a cascade style of programming, eliminating the need to make redundant queries or to cache bunches.

Every set method acts on each of the nodes in the bunch. If the bunch has no nodes, nothing happens. If the value parameter is an array, then each node will get one value from the array. An exception will be thrown if the length of the value array is not the same as the number of nodes in the bunch.

Bunch Set Methods
Method Description
.append(appendees) Append the nodes in the bunch of appendees after the last element of each node. If the bunch contains more than one node, the appendees will be deeply cloned before each insertion.
.blur() Remove focus from the nodes. This only makes sense for <button>, <input>, and <textarea> nodes.
.check(value) Set the check state for checkbox and radio nodes.
.class(string)
.klass(string)
Set the CSS class of the nodes. (The alternate spelling is to circumvent a reserved word problem in the ECMAScript Standard, Third Edition.)
.each(func) Pass each node to a function. The func argument is a function that takes a bunch argument.
.empty() Remove all of the descendants from the nodes.
.enable(boolean) Set the enable for the nodes.
.ephemeral() Remove all the nodes when the escape key is pressed, or when the mouse buttom goes up, or when another bunch is declared ephemeral.
.fire(event) Fire an event on every node in the bunch. The event value is either a string ("click") or an object with an event property ({event: "click"}). Events fired by this method will notify only handlers registered with the on method, and will not trigger any browser actions.
.focus() Give focus to the first node. This throws an exception if the bunch is empty, or if this method is called at any time other than the handling of a 'click' event unless ADsafe is able to determine that the widget already has focus. This only makes sense for <button>, <input>, and <textarea> nodes.
.mark(value) Set a mark on every tag node in the bunch.
.off(eventName, func) Remove event handlers from nodes. bunch.off() removes all event handlers. bunch.off('click') removes all onclick handlers. bunch.off('click', myclickhandler) removes a particular onclick handler.
.on(eventName, func) Add an event handler to the nodes in the bunch.
.prepend(prependees) Prepend the nodes in the bunch of prependees before the first element of each node. If the bunch contains more than one node, the prependees will be deeply cloned before each insertion.
.protect() Protect the nodes. Once protected, a node's getParent method will throw instead of providing access to the node's parent. Events will not bubble up past a protected node.
.select() Give focus to the first node and select its contents. This only makes sense for <input> and <textarea> nodes. It throws an exception if the bunch is empty.
.selection(string) Replace the user-selected text in an input_text or textarea with the string.
.style(name, value) Set the style element of the nodes to the value. Use the name 'float', not 'cssFloat' or 'styleFloat', to set the float style property.
.title(value) Set the title attribute of the nodes to the value.
.value(value) Set the value for the nodes. For nodes that do not have value attributes, it removes all of the child nodes and appends a new text node. It does nothing to nodes that have a type of "password".

Bunch Get Methods

The get- methods return undefined if the bunch contains no nodes; or a single value (usually a string) if the bunch contains one or more nodes. The get-s methods return a possibly empty array.

The get- and get-s methods do not cascade.

Bunch Get Methods
Method Description
.getCheck()
.getChecks()
Get the checked boolean for the nodes.
.getClass()
.getClasses()
Get the class attributes for the nodes.
.getEnable()
.getEnables()
Get the enable boolean for the nodes.
.getMark()
.getMarks()
Get the mark from the nodes.
.getName()
.getNames()
Get the name attribute of the nodes.
.getOffsetHeight()
.getOffsetHeights()
Get the offsetHeight of the nodes. The offsetHeight is the actual height, including the border and excluding the margin.
.getOffsetWidth()
.getOffsetWidths()
Get the offsetWidth of the nodes. The offsetWidth is the actual width, including the border and excluding the margin.
.getParent() Get a bunch containing the parents of the nodes. This can produce duplicates if the query is over two or more siblings. An attempt to get the root node of the widget will throw an exception.
.getSelection() Get the user-selected text in an input_text or textarea.
.getStyle(name)
.getStyles(name)
Get the values of the named style element of the nodes. Use the name 'float', not 'cssFloat' or 'styleFloat', to get the float style property.
.getTagName()
.getTagNames()
Get the tag names for the nodes.
.getTitle()
.getTitles()
Get the title attribute of the nodes.
.getValue()
.getValues()
Get the value for the nodes. If a node does not have a value, but has a first child that is a text node, then the value of that text node will be obtained. It produces undefined from nodes that have a type of "password".

Bunch Miscellaneous Methods

There are 9 miscellaneous methods. The miscellaneous methods do not cascade.

Bunch Miscellaneous Methods
Method Description
.clone(deep, number) Clone the nodes. It returns a new bunch of nodes that are not attached to the document tree. If the optional deep parameter is true, then all of the child nodes are also cloned. If the optional number parameter is a number, then an array will be returned containing number copies of the bunch.
.count() Get the number of nodes in the bunch. (This count does not include the children.)
.explode() Get an array of bunches that each contain a single node for each node in the bunch. The length of the array will be the same as the .count() of the bunch.
.fragment() Make a new HTML document fragment.
.q(query) Search the subtrees of the nodes. It returns a new bunch object containing the nodes that matched the query. It always returns a bunch object, even if the query selected no nodes. It will throw an exception if the query is not well formed. A query never modifies the bunch; it produces a new bunch.
.remove()

Remove the nodes. It removes nodes that have parents from their parents.

When a node is removed, its event handlers are removed, as well as the event handlers of all of its children.

.replace(replacement)

Replace the nodes. The optional replacement parameter is either a bunch object or an array of bunch objects. It does not replace nodes that do not have parents. It returns nothing. Replacement has no effect on nodes that do not have parents. If the replacement is empty, this bunch is removed. Otherwise, the bunch is replaced with all of the nodes in the replacement.

When a node is removed, its event handlers are removed, as well as the event handlers of all of its children.

.tag(tagName, type, name) Make a new HTML node. If tagName is 'button' or 'input', supply an extra parameter that determines the type of the element, such as 'submit' or 'radio'. A third parameter optionally names the node. This is used to group radio buttons together, so that at most one radio button in a group can be checked. It returns a bunch containing the one new node. It will not be attached to the document tree.
.text(string) Make a new text node. It returns a bunch containing the text node. It will not be attached to the document tree. If the argument is an array of strings, it will return a bunch of text nodes.

Text Nodes

The q method provides access to two kinds of nodes: tag nodes (the stuff in HTML that is inside the angle brackets), and text nodes (the stuff outside the angle brackets).

The * and / selectors will select both tag and text nodes. The other hunter selectors select only tag nodes.

The :text selector keeps only text nodes. The :first, :rest , and :trim selectors can keep both text and tag nodes. All of the other peckers keep only tag nodes.

The only methods that work on text nodes are .value(string) that sets the text of the text node, .getValue() that gets the text of the text node, .replace(replacers), .remove(), and .clone().

The other set methods ignore text nodes. The other get methods return undefined from text nodes.

Events

Event handlers can be placed on an object with the on method. You can invent your own event types. These are the events that can be fired by the browser in response to user action:

Browser events
mouseover The mouse has moved over a tag.
mousedown The mouse button goes down while over a tag.
mouseup The mouse button goes up while over a tag.
mouseout The mouse has left a tag.
click The mouse button came up before the mouse left the tag.
doubleclick The mouse button came up twice quickly before the mouse left the tag.
specialclick The alternate mouse button came up before the mouse left the tag.
blur The select, input, or textarea that had focus lost focus.
focus A select, input, or textarea was given focus by the user.
keypress The tag with focus receives a character from the keyboard.
enterkey The tag with focus receives the enter key character from the keyboard.
escapekey The tag with focus receives the escape key character from the keyboard.
change On select, input and textarea tags: The value was changed by the user. This event does not bubble.

You can fire any of these events yourself, but doing so will not trigger the browser's default action. Only the user can trigger the default action.

An event object could have any of these properties:

Event Property Name Meaning
altKey A boolean that indicates the state of an alt key.
ctrlKey A boolean that indicates the state of the control key.
key The code of the pressed key.
shiftKey A boolean that indicates the state of the shift key.
target A bunch that gives access to the node that was the target of the event.
that A bunch that gives access to the node that is handling the event. that could be the same as target, or it could be a parent or ancestor of the target if bubbling occurs.
type A string containing the type of the event.
x The horizontal position of the cursor relative to the target's container.
y The vertical position of the cursor relative to the target's container.

An event object may have a bubble method. Calling that method will cause the event to bubble up to the parent of that object.

An event object may have a preventDefault method. Calling that method will cause the cancellation of the browser's default action.