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.
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.
#id, tagName,
>tagName, *, and
/. They descend into the tree, finding a new selection
of nodes to replace the current selection of nodes. The tagName
hunter is the most efficient. The * hunter is the
least efficient. The hunters shift attention from the root to
nodes within the subtree.&name, +type,
.class, [ attribute
... ], and :option. They
remove nodes from the current selection of nodes that do not match
somehow. The peckers reduce the set of nodes currently under consideration.| 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 children that have a tagName that matches. |
* |
Select all of the descendent nodes. After matching *, only peckers may be matched. |
/ |
Select all of the immediate child nodes. |
| Pecker Selector | Meaning |
. class |
Keep the nodes that have a class
component that matches the class. Same as [class~=class]. |
& name |
Keep the nodes that have a name
that matches the name. Same as [name=name]. |
_ type |
Keep the nodes that have a type
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. |
: 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. |
: text |
Keep text nodes. |
: tag |
Keep nodes that are not 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.
| Query | Action |
|---|---|
p * : text |
Select the text in all of the paragraphs |
input_radio&tikki:checked |
Select all radio buttons named "tikki"
that are currently checked. |
#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 that have a class
string 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 or deeper. |
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.
| 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. They 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 popups. |
.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(tagNametypename) |
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. |
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.
The list of methods listed here is incomplete.
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 all 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.
| Method | Description |
|---|---|
.addClass(string) |
Add a class to the nodes. |
.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. If the appendees parameter is a string, append a new text node. |
.blur() |
Remove focus from the nodes. This only makes sense for <button>,
<input>, and <textarea>
nodes. |
.check(boolean) |
Set the check for checkbox and radio nodes. |
.empty() |
Remove all of the descendants from 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. |
.enable(boolean) |
Set the enable for the nodes. |
.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 node. This throws an exception if the bunch
does not hold exactly one node, or if this method is called
at any time other than the handling of a 'click'
event. This only makes sense for <button>,
<input>, and <textarea>
nodes. It throws an exception if the bunch does not hold exactly
one node. |
.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. |
.removeClass(string) |
Remove a class from the nodes. |
.select() |
Give focus to the node and select its contents. This only makes
sense for <button>, <input>,
and <textarea> nodes. It throws an exception
if the bunch does not hold exactly one node. |
.style(name,
value) |
Set the style element 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. |
The get methods return undefined if the bunch contains
no nodes; or a single value (usually a string) if the bunch contains
exactly one node; or an array of values if the bunch contains more
than one node.
The get methods do not cascade.
| Method | Description |
|---|---|
.getCheck() |
Get the checked for the nodes. |
.getClass() |
Get the class space-separated strings for the
nodes. |
.getEnable() |
Get the boolean enable for the nodes. |
.getMark() |
Get the mark from the nodes. |
.getStyle(name) |
Get the values of the named style element of the nodes. |
.getTagName() |
Get the tag names for the nodes. |
.getValue() |
Get the value for the nodes. |
There are 6 miscellaneous methods. The miscellaneous methods do not cascade.
| 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.
|
.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. |
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 / hunter 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 and :rest 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.
Event handlers can be placed on an object with the on method. You can invent your own event types. These are events that can be fired by the browser in response to user action:
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. |
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.