|
|||||||||
PREV CLASS NEXT CLASS | FRAMES NO FRAMES | ||||||||
SUMMARY: FIELD | CONSTR | METHOD | DETAIL: FIELD | CONSTR | METHOD |
Defined in flavors.js
Working with Javascript on the web is famous for browser inconsistencies, to the point where a lot of people think they "hate Javascript" when what they really hate is the inconsistencies across browsers.
XBLinJS has it even worse; not only does it want to work across browsers in the conventional sense, it also wants to work in Mozilla with XUL, and even in non-browser things that use ECMAScript, like Flash, anything that uses the same general DOM event model. This makes merely programming cross-browser look like a piece of cake.
XBLinJS addresses this issue by creating several "flavors" of XBLinJS, as defined in this file. These flavors provide methods that the Widget class uses to perform its work, and does other things like managing constants. (For instance, the Browser flavor of XBLinJS has constants for determining what browser it is running in, whereas the XUL flavor has no need of that, but it may have other constants it wants to use.)
The documentation for this class lays out the complete set of things a Flavor can change, which you should change in sub-classes to create new flavors. If you find that you need things that aren't already in Flavor specifications, please mail the development list on Sourceforge and I will be happy to work with you to pull the additional things out.
This is a reverse template pattern, based on the way Javascript can dynamically choose a super-class to inherit from; this allows you to inherit from Widget, which is cleaner and simpler thing to do than constantly inheriting from "BrowserFlavor", and also means you can switch out flavors without affecting the rest of your code. (Odds are you'll never want to switch from Browser to Flash, but you may want to swap to a browser-specific flavor based on some criteria computed at run time.)
One of the design requirements is that you can leave in extra flavors without causing any errors, so many computations must be wrapped up in functions that will only be executed if that flavor is used. For example, the Browser flavor has constants based on the navigator.userAgent string, but other ECMAScript environments may not have this available at all, requiring either convoluted "if" statements or deferred execution. We have to protect that from execution until we know what environment the user desires. Your own flavors, of course, may do as they please.
This is a "virtual class"; the methods named here are more for the documentation opportunity than the implementation value. When you override these, you do not need to call the superclass, EXCEPT if you happen to override .init, which should generally be called before your own .init, in case you want to override it.
(Note if you're going to create another Flavor that uses real XML like XUL does, it may be good to drop me a line and ask me to extract the XML support into a superclass that you can use without getting the XUL support in the way, such as the event handling.)
Field Summary | |
Object |
flavorConstants
Constants defined by this flavor. |
Object |
flavorFixups
code to run when a flavor is resolved for use |
Constructor Summary | |
Flavor
()
Define a "flavor" of XBLinJS. |
Method Summary | |
void
|
attachHandlerToNode(node, event, handler)
attaches an event handler to a DOM node |
void
|
createElement(nodeType)
creates a DOM node |
void
|
getAttributeFrom(node, key)
Get an attribute from a node, be it Widget or DOM node. |
void
|
getElementsByTagName(tagName, node)
Wraps the getElementsByTagName, because it can be either document.getElementsByTagName or document.getElementsByTagNameNS. |
void
|
initData(atts)
copies all constants onto the object |
void
|
setAttributeOn(node, key, value)
set an attribute on something, either DOM node or Widget |
Field Detail |
Object flavorConstants
Each flavor can define constants to use; they may either be actual values, or functions that will take no arguments and return a value, which will be resolved by resolveFlavor().
Upon construction of a Flavor object, all constants are copied into the object, so bear that in mind while naming them. (They need to be copied to allow sub-objects to selectively override them, which is highly useful.) Try to keep the number reasonable, although in general the time needed to copy the constants will most likely be swamped by other initialization.
Object flavorFixups
Certain flavors require certain code to be run in order to be used correctly; for instance the Browser flavor has to run code to restore the DOM constants such as ELEMENT_NODE that IE doesn't see fit to include. This object contains named functions that take no arguments and do whatever extra initialization the flavor needs to run properly.
Constructor Detail |
Flavor()
Method Detail |
void attachHandlerToNode(node, event, handler)
This attaches an event handler to the given DOM node, which regrettably varies widely from implementation to implementation.
New flavors should try using the BrowserFlavor implementation of this method or the DOM2Flavor.
node
- The DOM node to attach the event to.
event
- The name of the event, without the "on". e.g., click, not onclick.
handler
- The function handler for the event.
void createElement(nodeType)
This creates a DOM node with the given name. This is generally used to distinguish between a creation with a namespace, and a creation without. (If you need a new flavor, you can generally take either BrowserFlavor's implementation of this, or DOM2Flavor's implementation.)
void getAttributeFrom(node, key)
Generally a complement to .setAttributeOn.
Note that, strictly speaking, this isn't a "method", as it never uses this. This is an organizational tool, and resolveFlavor will move these functions into the global space.When you see .getAttributeFrom, it's one of the Flavor functions.
void getElementsByTagName(tagName, node)
tagName
- The tag name to retrieve, with the namespace as appropriate.
document
- The document (or element) to call it on.
void initData(atts)
This copies all the constants onto the object, and should always end up called, usually by Widget.
void setAttributeOn(node, key, value)
Regrettably, there are some subtleties involved with setting attributes on nodes. I would have thought node.setAttribute(key, value) would always be the same as node[key] = value, but that is not true. What's worse is that to my knowledge, there is never a reason to allow one, but not the other.
setAttributeOn should be used in preference to .setAttribute, unless you know that for all possible flavors, for all possible "key" values, the call will work correctly. The code shipped with XBLinJS tries to be very agnostic about it to maximize the value of the shipped widgets; your code, which will likely be more targetted, may not need to worry so much about .setAttribute. Still, some of the flavors do do some nice cross-platform flattening that you may wish to take advantage of.
Flavors implementing this method should check to see if the node is a Widget, and if so, call .setAttribute on it. Otherwise, do what your Flavor needs to do with the key and value.
Note that, strictly speaking, this isn't a "method", as it never uses this. This is an organizational tool, and resolveFlavor will move these functions into the global space.When you see .setAttributeOn, it's one of the Flavor functions.
|
|||||||||
PREV CLASS NEXT CLASS | FRAMES NO FRAMES | ||||||||
SUMMARY: FIELD | CONSTR | METHOD | DETAIL: FIELD | CONSTR | METHOD |