/*______________
|       ______  |   U I Z E     J A V A S C R I P T     A P I
|     /      /  |   -----------------------------------------
|    /    O /   |    MODULE : Uize.Node Package (version 1.2.1)
|   /    / /    |    AUTHOR : Chris van Rensburg (http://www.tomkidding.com)
|  /    / /  /| |    ONLINE : http://www.tomkidding.com/uize/uize-js-api
| /____/ /__/_| | COPYRIGHT : (c)2004-2006 Chris van Rensburg
|          /___ |   LICENSE : Distributed under the terms of the GNU General Public License
|_______________|             http://www.gnu.org/licenses/gpl.txt
*/

/*
	TO DO
		- NEW WIRE EVENTS MECHANISM
			- Uize.Node static methods to implement
				- unwireEvent
				- unwireEvents

			- Uize.Widget instance methods to add
				- unwireNodeEvent
				- unwireNodeEvents

			- what's involved in unwiring events
				- lookup in the hash table by the handler to find the wiring
					- node
					- eventName
					- handler
				- with the wiring...
					- remove the handler from the node
					- delete the entry from the hash table

			- consider providing a way of unwiring wirings by specifying the wiring IDs, and returning wiring IDs from wireEvent(s)

			**** make sure that wireEvent handles rewiring the same event for the same node
				1) when is this likely to happen? what code might do this?
				2) how would I accomplish this without wireEvent becoming too slow?

			- make changes so that wired nodes are only remembered by ID (make IDs on the fly for nodes without)
			- for all widget classes...
				- make sure no events are being wired in a way that they wouldn't get unwired
				- look at moving more child widget creation into constructor rather than wireUi

		- getByMatch to observe an optional scope property that has the effect of limiting the search within a certain node

		- consider eliminating old style of event handler registering code in favor of using new style event listeners
		- facility for specifying a set of nodes using a match object (eg {class:/^heading\d+$/}
*/

/*ScruncherSettings Mappings=",Uize_Node" LineCompacting="TRUE"*/

/*?
	Introduction
		Summary
			Implements a suite of methods to facilitate manipulation of DOM nodes (HTML Element nodes, to be exact)

		Requires
			Has no requirements.

		Features
			Node Blob
				Many of the methods in this package can operate on multiple nodes at a time by specifying the nodes using the =nodeBLOB= parameter.

				This parameter may be...

				- a string, being the =id= of one node
				- an object reference to one node
				- a =null= or =undefined= value, which will be ignored
				- an array, whose elements are node blobs
				- an object, whose properties have values that are node blobs

				Effectively, this means that one can specify an arbitrary number of nodes in an arbitrarily complex data structure, combining nested arrays and objects as appropriate to the application.

				EXAMPLE
				....................................................................
				Uize.Node.show (['saveButton','cancelButton','skipButton'],true);
				....................................................................

				In the above example, the =nodeBLOB= parameter is an array, where each element is a string representing the =id= of a button to show.

				EXAMPLE
				....................................................................
				var
					topButtons = ['loginLogoutButton','checkoutButton','helpButton'],
					bottomButtons = ['saveButton','cancelButton','skipButton']
				;
				Uize.Node.show ([topButtons,bottomButtons],true);
				....................................................................

				In a slightly more complex example, the =nodeBLOB= parameter is an array, where each element is itself an array of button node ids.

				If a particular method can accept an =nodeBLOB= parameter, it will be noted in the reference section for that method.
*/

(function () {
	if (typeof Uize == 'undefined') Uize = {};

	/*** Variables for Scruncher Optimization ***/
		var
			_package = Uize.Node = {},
			_undefined,
			_string = 'string',
			_true = true,
			_false = false,
			_null = null,
			_navigator = navigator,
			_userAgent = _navigator.userAgent.toLowerCase (),
			_isIe = _navigator.appName == 'Microsoft Internet Explorer',
			_isMozilla = _userAgent.indexOf ('gecko') > -1,
			_hidden = 'hidden'
		;

	/*** Initialization ***/
		var
			_wirings = {},
			_wiringIdsByOwnerId = {},
			_totalWirings = 0
		;

	/*** Public Static Methods ***/
		_package.display = function (_nodeBlob,_mustDisplay) {
			_setStyle (_nodeBlob,{display:_mustDisplay || _mustDisplay === _undefined ? 'block' : 'none'});
			/*?
				Static Methods
					Uize.Node.display
						Displays or hides the specified =Node Blob=, using the "display" CSS property.

						SYNTAX
						................................................
						Uize.Node.display (nodeBLOB,mustDisplayANYTYPE);
						................................................

						While typically a Boolean, the =mustDisplayANYTYPE= parameter can be of any type and the node(s) will be displayed if it resolves to =true=, and hidden if it resolves to =false= - with the exception of =undefined=, when the node(s) will be displayed (see explanation below).

						VARIATIONS
						..................................
						Uize.Node.displayNode (nodeBLOB);
						..................................

						When no =mustDisplayANYTYPE= parameter is specified (or when its value is =undefined=), the node(s) will be displayed.

						NOTES
						- compare to the =Uize.Node.show= static method
						- This method can operate on multiple nodes at a time. For more details, see the section on =Node Blob=.
			*/
		};

		var _doForAll = _package.doForAll = function (_nodeBlob,_function,_idPrefix,_idDelimiter) {
			function _doForAllClosure (_nodeBlob) {
				if (_nodeBlob) {
					if (_isNode (_nodeBlob)) {
						_function (_nodeBlob);
					} else {
						var _typeofNodeBlob = typeof _nodeBlob;
						if (_typeofNodeBlob == _string) {
							_doForAllClosure (_getByNameOrId (_joinIdPrefixAndNodeId (_idPrefix,_nodeBlob,_idDelimiter)));
						} else if (
							(_typeofNodeBlob == 'object' || _typeofNodeBlob == 'function') &&
							typeof _nodeBlob.length == 'number'
						) {
							var _nodeBlobLength = _nodeBlob.length;
							for (var _subNodeBlobNo = 0; _subNodeBlobNo < _nodeBlobLength; _subNodeBlobNo++)
								_doForAllClosure (_nodeBlob [_subNodeBlobNo])
							;
						} else if (_typeofNodeBlob == 'object') {
							for (var _subNodeBlobName in _nodeBlob)
								_doForAllClosure (_nodeBlob [_subNodeBlobName])
							;
						}
					}
				}
			}
			_doForAllClosure (_nodeBlob);
			/*?
				Static Methods
					Uize.Node.doForAll
						Iterates through the specified =Node Blob=, calling the specified function for each node and passing the node reference as a parameter.

						SYNTAX
						.........................................
						Uize.Node.doForAll (nodeBLOB,actionFUNC);
						.........................................

						EXAMPLE
						.........................................................................................
						Uize.Node.doForAll (
							['topLeftAddButton','topRightAddButton','bottomLeftAddButton','bottomRightAddButton'],
							function (node) {
								node.src = 'images/add-button.gif';
								node.style.border = '1px solid #fff';
								Uize.Node.wireEvent (node,'onclick',handleAddButtonClick);
							}
						);
						.........................................................................................

						VARIATIONS
						....................................................................
						Uize.Node.doForAll (nodeBLOB,actionFUNC,idPrefixSTR,idDelimiterSTR);
						....................................................................

						When the optional =idPrefixSTR= and =idDelimiterSTR= parameters are specified, then any nodes specified in the =nodeBLOB= using a string ID are resolved by first applying the ID prefix and delimiter.
			*/
		};

		var _doRectanglesOverlap = _package.doRectanglesOverlap =
		function (_aLeft,_aTop,_aWidth,_aHeight,_bLeft,_bTop,_bWidth,_bHeight) {
			var
				_aRight = _aLeft + _aWidth - 1,
				_aBottom = _aTop + _aHeight - 1,
				_bRight = _bLeft + _bWidth - 1,
				_bBottom = _bTop + _bHeight - 1
			;
			return (
				(
					(_aTop >= _bTop && _aTop <= _bBottom) ||
					(_aBottom >= _bTop && _aBottom <= _bBottom) ||
					(_aTop < _bTop && _aBottom > _bBottom)
				) && (
					(_aLeft >= _bLeft && _aLeft <= _bRight) ||
					(_aRight >= _bLeft && _aRight <= _bRight) ||
					(_aLeft < _bLeft && _aRight > _bRight)
				)
			);
			/*?
				Static Methods
					Uize.Node.doRectanglesOverlap
						Returns a boolean, indicating whether or not the rectangles specified by the two coordinate sets overlap one another. Two rectangles are considered to overlap if any part of either rectangle is contained by the other.

						SYNTAX
						.................................................................
						Uize.Node.doRectanglesOverlap (
							aLeftPixelsINT,aTopPixelsINT,aRightPixelsINT,aBottomPixelsINT,
							bLeftPixelsINT,bTopPixelsINT,bRightPixelsINT,bBottomPixelsINT
						);
						.................................................................
			*/
		};

		var _getById = _package.getById = function (_node,_idPrefix,_idDelimiter,_nodeCache) {
			var _result;
			if (typeof _node == _string) {
				var _nodeId = _joinIdPrefixAndNodeId (_idPrefix,_node,_idDelimiter);
				if (_nodeCache) _result = _nodeCache [_nodeId];
				if (_result === _undefined) {
					_result = document.getElementById (_nodeId);
					if (_nodeCache) _nodeCache [_nodeId] = _result;
				}
			} else {
				_result = _node;
			}
			return _result;
			/*?
				Static Methods
					Uize.Node.getById
						Returns a reference to the specified node, where the node is specified by its ID.

						SYNTAX
						.................................
						Uize.Node.getById (nodeSTRorOBJ);
						.................................

						NOTES
						- in the event that the value of the =nodeSTRorOBJ= parameter is actually a reference to a node, then that value will simply be returned
						- in the event that a node specified by ID does not exist in the DOM, then the value =null= will be returned
						- compare to the =Uize.Node.getByNameOrId= static method
						- see also the =Uize.Node.getByMatch= static method
			*/
		};

		var _getByNameOrId = _package.getByNameOrId = function (_nameOrId) {
			var _node = document.getElementsByName (_nameOrId);
			if (_node.length == 1) {
				_node = _node [0];
			} else if (_node.length == 0) {
				_node = _getById (_nameOrId);
			}
			return _node;
			/*?
				Static Methods
					Uize.Node.getByNameOrId
						Returns a reference to the specified node, where the node may be specified by its ID or by the value of its =name= attribute.

						SYNTAX
						..........................................
						Uize.Node.getByNameOrId (nodeNameOrIdSTR);
						..........................................

						If there are multiple nodes with the same value for their =name= attribute, then a reference to the first one will be returned.

						NOTES
						- in the event that the specified node does not exist in the DOM, then the value =null= will be returned
						- compare to the =Uize.Node.getById= static method
						- see also the =Uize.Node.getByMatch= static method
			*/
		};

		_package.getByMatch = function (_properties) {
			var
				_matchingNodes = [],
				_unusedProperties = {},
				_nodePool
			;
			for (var _propertyName in _properties)
				_unusedProperties [_propertyName] = _properties [_propertyName]
			;
			if (_unusedProperties.name) {
				_nodePool = document.getElementsByName (_unusedProperties.name);
				delete _unusedProperties.name;
			} else if (_unusedProperties.tagName) {
				_nodePool = document.getElementsByTagName (_unusedProperties.tagName);
				delete _unusedProperties.tagName;
			} else {
				_nodePool = document.getElementsByTagName ('*');
			}
			var _nodePoolLength = _nodePool.length;
			for (var _nodeNo = 0; _nodeNo < _nodePoolLength; _nodeNo++) {
				var
					_node = _nodePool [_nodeNo],
					_isMatch = _true
				;
				for (var _propertyName in _unusedProperties) {
					if (_node [_propertyName] != _unusedProperties [_propertyName]) {
						_isMatch = _false;
						break;
					}
				}
				if (_isMatch) _matchingNodes.push (_node)
			}
			return _matchingNodes;
			/*?
				Static Methods
					Uize.Node.getByMatch
						Returns an array, representing those nodes within the document whose properties match the specified property set.

						SYNTAX
						.....................................
						Uize.Node.getByMatch (propertiesOBJ);
						.....................................

						EXAMPLE
						.............................................................................
						var buttonImages = Uize.Node.getByMatch ({tagName:'img',className:'button'});
						.............................................................................

						The above example will return an array of all the nodes in the document that are =IMG= tags and that have their =class= attribute set to the value =button=.

						NOTES
						- in the event that no matches are found, an empty array will be returned
						- see also the =Uize.Node.getById= and =Uize.Node.getByNameOrId= static methods
			*/
		};

		var _getCoords = _package.getCoords = function (_node,_parentVisible,_calledDuringChildNodeCalculation) {
			var
				_x = 0,
				_y = 0,
				_width = 0,
				_height = 0,
				_seen = null,
				_window = window
			;
			if (_node == _window) {
				var
					_windowDimensions = _getDimensions (_window),
					_documentElement = document.documentElement
				;
				_x = _documentElement.scrollLeft;
				_y = _documentElement.scrollTop;
				_width = _windowDimensions.width;
				_height = _windowDimensions.height;
			} else {
				_node = _package.getById (_node);
				if (_isNode (_node)) {
					if (_parentVisible === _undefined) _parentVisible = true;
					if (_node.tagName == 'A' && _node.childNodes.length == 1 && _node.childNodes [0].tagName == 'IMG')
						/* NOTE:
							this is a workaround for Mozilla, which doesn't seem to be able to give reliable values for determining coordinates of links that fully enclose IMG tags. In such cases, using the child IMG tag for determining coordinates is reliable. This workaround has no negative effect in IE, so it is not conditionalized
						*/
						_node = _node.childNodes [0]
					;
					var
						_offsetParent = null,
						_nodeHasStyle = _node.style !== _undefined,
						_nodeVisibility = _nodeHasStyle ? _node.style.visibility : '',
						_nodeVisible =
							_nodeVisibility == 'visible' ||
							_parentVisible == 'treat as visible' ||
							((_nodeVisibility == '' || _nodeVisibility == 'inherit') && _parentVisible)
						,
						_parentNode = _offsetParent
					;
					if (!_parentNode) _parentNode = _node;
					_offsetParent = _parentNode;
					/* IMPORTANT:
						not sure how this code may interact with the image map stuff above (assumptions, assumptions...)
					*/
					while (_parentNode.parentNode && typeof _parentNode.parentNode != 'unknown') {
						if (_seen == null) {
							if (_parentNode.style.visibility === 'visible') {
								_seen = true;
							} else if (_parentNode.style.visibility === 'hidden') {
								_seen = false;
							}
						}
						if (_parentNode == _offsetParent) {
							if (_parentNode.offsetLeft !== _undefined) _x += _parentNode.offsetLeft;
							if (_parentNode.offsetTop !== _undefined) _y += _parentNode.offsetTop;
							_offsetParent = _parentNode.offsetParent;
						}
						if (_parentNode != document.body && _parentNode != document.documentElement) {
							/* NOTE:
								it's not just for container nodes that are scrolled, but also container nodes that are scrollable (that's where the scrollWidth is greater than the offsetWidth)
							*/
							if (
								_parentNode != _node &&
								(_parentNode.scrollWidth > _parentNode.offsetWidth || _parentNode.scrollHeight > _parentNode.offsetHeight)
							) {
								_x -= _parentNode.scrollLeft;
								_y -= _parentNode.scrollTop;
								if (_isIe) {
									_x += _parentNode.clientLeft;
									_y += _parentNode.clientTop;
								}
								if (_seen !== false) {
									var _parentNodeCoords = _getCoords (_parentNode,_undefined,_true);
									if (
										!_doRectanglesOverlap (
											_x,_y,_node.offsetWidth,_node.offsetHeight,
											_parentNodeCoords.x,_parentNodeCoords.y,_parentNodeCoords.width,_parentNodeCoords.height
										)
									) {
										_seen = false;
									}
								}
							}
						}
						_parentNode = _parentNode.parentNode;
					}
					if (_seen == null) _seen = true;
					_seen = _seen && _doRectanglesOverlap (
						_x,_y,_node.offsetWidth,_node.offsetHeight,
						document.body.scrollLeft,document.body.scrollTop,document.body.offsetWidth,document.body.offsetHeight
					);

					// alert (_seen);

					/*** calculate dimensions ***/
					if (_width == 0 || _height == 0) {
						if (_nodeVisible) {
							if (_node.offsetWidth !== _undefined) _width = _node.offsetWidth;
							if (_node.offsetHeight !== _undefined) _height = _node.offsetHeight;
						}
						/* WORKAROUND:
							this is a workaround to handle the fact that a container DIV may report offset dimensions of 0, even though it contain many child nodes
						*/
						if (!_calledDuringChildNodeCalculation && (_width == 0 || _height == 0) && _node.tagName == 'DIV') {
							/* NOTE:
								_calledDuringChildNodeCalculation is used as a workaround to avoid infinite recursion that would lead to a stack overflow
							*/
							var
								_childNodes = _node.childNodes,
								_childNodesLength = _childNodes.length
							;
							for (var _childNodeNo = 0; _childNodeNo < _childNodesLength; _childNodeNo++) {
								if (_childNodes [_childNodeNo].nodeName.charAt (0) != '#') {
									var _childCoords = _getCoords (_childNodes [_childNodeNo],_nodeVisible);
									if (_childCoords.width != 0 || _childCoords.height != 0) {
										_width = Math.max (_width,_childCoords.right - _x + 1);
										_height = Math.max (_height,_childCoords.bottom - _y + 1);
									}
								}
							}
						}
						/* end of workaround */
					}
				}
			}
			return {
				x:_x,
				y:_y,
				width:_width,
				height:_height,
				area:_width * _height,
				left:_x,
				top:_y,
				right:_x + _width - 1,
				bottom:_y + _height - 1,
				seen:_seen
			};
			/*?
				Static Methods
					Uize.Node.getCoords
						Returns an object, representing the coordinates of the specified node, relative to the top left of the document.

						SYNTAX
						...................................
						Uize.Node.getCoords (nodeSTRorOBJ);
						...................................

						RETURN
						......................
						{
							x : pixelsINT,
							y : pixelsINT,
							width : pixelsINT,
							height : pixelsINT,
							area : pixelsINT,
							left : pixelsINT,
							top : pixelsINT,
							right : pixelsINT,
							bottom : pixelsINT,
							seen : BOOL
						}
						......................

						The "x" and "left" properties of the return object are equivalent, as are the "y" and "top" properties.

						NOTES
						- compare to the =Uize.Node.getDimensions= static method
			*/
		};

		var _getDimensions = _package.getDimensions = function (_node) {
			/*?
				Static Methods
					Uize.Node.getDimensions
						Returns an object, containing =width= and =height= properties that reflect the displayed dimensions for the specified node.

						SYNTAX
						..................................................
						nodeDims = Uize.Node.getDimensions (nodeSTRorOBJ);
						..................................................

						RETURN VALUE
						................
						{
							width : INT,
							height : INT
						}
						................
			*/
			var
				_width = 0,
				_height = 0,
				_window = window
			;
			if (_node == _window) {
				var _documentElement = document.documentElement;
				_width = _documentElement.clientWidth || _window.innerWidth || _documentElement.offsetWidth;
				_height = _documentElement.clientHeight || _window.innerHeight || _documentElement.offsetHeight;
			} else {
				_node = _package.getById (_node);
				if (_node) {
					_width = Math.max (
						(_getStyleAttribute (_node,'width').replace (/px/i,'') - 0) || 0,
						_node.offsetWidth || 0
					);
					_height = Math.max (
						(_getStyleAttribute (_node,'height').replace (/px/i,'') - 0) || 0,
						_node.offsetHeight || 0
					);
				}
			}
			return {width:_width,height:_height};
		};

		_package.getEffectiveBgColor = function (_node) {
			var _background = '';
			while ((!_background || _background == 'transparent' || _background == 'none') && _node) {
				_background = _getStyleAttribute (_node,'backgroundColor');
				_node = _node.parentNode;
			}
			return _background;
			/*?
				Static Methods
					Uize.Node.getEffectiveBgColor
						Returns a string, representing the effective background color for the specified node.

						SYNTAX
						.............................................
						Uize.Node.getEffectiveBgColor (nodeSTRorOBJ);
						.............................................

						This method will ascend the parent hierarchy until a node is found whose background is not set to ='transparent'= or ='none'=. So, for example, if the specified node has its background set to ='none'= but its parent node has its background set to ='#fff'=, then this method will return the value ='#fff'=.
			*/
		};

		var _getOpacityProperties = _package.getOpacityProperties = function (_opacity) {
			return (
				_isIe
					? {filter:'alpha(opacity=' + Math.round (_opacity * 100) + ')'}
					: {opacity:(_isMozilla && _userAgent.indexOf ('firefox/1.0') > -1 ? .999 : 1) * _opacity}
			);
			/*?
				Static Methods
					Uize.Node.getOpacityProperties
						Returns an object, being the CSS style properties necessary in order to achieve the specified degree of opacity.

						SYNTAX
						..............................................
						Uize.Node.getOpacityProperties (opacityFLOAT);
						..............................................

						For standards compliant browsers, the returned object contains an "opacity" property, while for Internet Explorer it contains a "filter" property.

						The returned object can be "stitched" into a style properties parameter, using the =Uize.copyInto= static method, in order to prepare a subsequent call to the =Uize.Node.setStyle= static method, as follows...

						EXAMPLE
						.........................................
						Uize.Node.setStyle (
							'someNodeId',
							Uize.copyInto (
								{
									display : 'block',
									position  :'absolute',
									visibility : 'inherit',
									top : '100px'
								},
								Uize.Node.getOpacityProperties (.5)
							)
						);
						.........................................
			*/
		};

		_package.getOpacityStr = function (_opacity) {
			return _stylePropertiesAsStr (_getOpacityProperties (_opacity));
		};

		var _getStyleAttribute = _package.getStyleAttribute = function (_node,_attribute) {
			/*?
				Static Methods
					Uize.Node.getStyleAttribute
						Returns the value of the specified style attribute for the specified node.

						SYNTAX
						............................................................
						Uize.Node.getStyleAttribute (nodeSTRorOBJ,bttributeNameSTR);
						............................................................

						Style attributes for a node that are defined inside style sheets (whether inline or external) rather than in the node's =style= attribute are not reflected in the =style= property of the node in the DOM. This can be frustrating when trying to run code that may conditionalize based upon the values of certain style attributes. This method acts as an abstraction to use the appropriate technique for the given browser to determine the value of a specified style attribute. In some browsers this may be done using the =getComputedStyle= method, while in other browsers it may be done using the =currentStyle= property.
			*/
			var _value = '';
			_node = _package.getById (_node);
			if (_node) {
				if (
					document.defaultView &&
					document.defaultView.getComputedStyle &&
					document.defaultView.getComputedStyle (_node,'')
				) {
					_value = document.defaultView.getComputedStyle (_node,'') [_attribute];
				} else if (_node.currentStyle) {
					_value = _node.currentStyle.getAttribute (_attribute);
				} else {
					_value = _node.style [_attribute];
				}
			}
			return _value;
		};

		var _getText = _package.getText = function (_node) {
			var _text = '';
			_node = _package.getById (_node);
			if (_node) {
				function _gatherText (_node) {
					if (typeof _node.innerText == _string) {
						_text = _node.innerText.replace (/\r|\n|\r\n/g,'');
					} else if (typeof _node.textContent == _string) {
						_text = _node.textContent;
					} else {
						if (_node.nodeType == 3) _text = _node.data;
						if (_node.childNodes) {
							var
								_childNodes = _node.childNodes,
								_childNodesLength = _childNodes.length
							;
							for (var _childNodeNo = 0; _childNodeNo < _childNodesLength; _childNodeNo++)
								_text += _getText (_childNodes [_childNodeNo])
							;
						}
					}
				}
				_gatherText (_node);
			}
			return _text;
			/*?
				Static Methods
					Uize.Node.getText
						Returns a string, representing the text content of the specified node.

						SYNTAX
						.................................
						Uize.Node.getText (nodeSTRorOBJ);
						.................................

						In Internet Explorer, this method employs the =innerText= property, removing all linebreaks. In other browsers that support the =textContent= property, this is used. For browsers that support neither, this method iterates recursively through the child nodes and cumulatively harvests the text content using the data property of all the text nodes.

						EXAMPLE
						............................
						<div id="testNode">
							<p>This is a test</p>
							<table>
								<tr>
									<td> of</td>
									<td> the</td>
								</tr>
							</table>
							<blockquote>
								<ul>
									<li> emergency
									<li> broadcasting
								</ul>
								<p> network</p>
							</blockquote>
						</div>
						............................

						In the above example, the statement =Uize.Node.getText ('testNode')= would return roughly ='this is a test of the emergency broadcasting network'= (between browsers there might be variability with the whitespace content).

						NOTES
						- this method is not quaranteed to return exactly the same value for the exact same markup in all browsers
			*/
		};

		_package.injectHtml = function (_nodeBlob,_html,_mode) {
			var _isInnerReplace, _isOuterReplace, _isInnerTop, _isOuterTop, _isOuterBottom, _isInnerBottom;
			(
				(_isInnerReplace = _mode == 'inner replace') ||
				(_isOuterReplace = _mode == 'outer replace') ||
				(_isInnerTop = _mode == 'inner top') ||
				(_isOuterTop = _mode == 'outer top') ||
				(_isOuterBottom = _mode == 'outer bottom') ||
				(_isInnerBottom = _true)
			);
			_doForAll (
				_nodeBlob,
				function (_node) {
					var _nodeChildNodes = _node.childNodes;
					if (
						_isInnerReplace ||
						(!_nodeChildNodes.length && (_isInnerTop || _isInnerBottom))
					) {
						_node.innerHTML = _html;
					} else if (_isOuterReplace && _isIe) {
						_node.outerHTML = _html;
					} else {
						var _dummyNode = document.createElement ('DIV');
						_dummyNode.innerHTML = _html;
						var
							_nodesToInject = _dummyNode.childNodes,
							_takeNodesToInjectFromBottom = _isInnerTop || _isOuterBottom,
							_nodeParentNode = _node.parentNode
						;
						while (_nodesToInject.length) {
							var _childNodeToInject =
								_nodesToInject [_takeNodesToInjectFromBottom ? _nodesToInject.length - 1 : 0]
							;
							if (_isInnerBottom) {
								_node.appendChild (_childNodeToInject);
							} else if (_isInnerTop) {
								_node.insertBefore (_childNodeToInject,_nodeChildNodes [0]);
							} else if (_isOuterTop || _isOuterReplace) {
								_nodeParentNode.insertBefore (_childNodeToInject,_node);
							} else if (_isOuterBottom) {
								var _nodeNextSibling = _node.nextSibling;
								_nodeNextSibling
									? _nodeParentNode.insertBefore (_childNodeToInject,_nodeNextSibling)
									: _nodeParentNode.appendChild (_childNodeToInject)
								;
							}
						}
						if (_isOuterReplace)
							_nodeParentNode.removeChild (_node)
						;
					}
				}
			);
			/*?
				Static Methods
					Uize.Node.injectHtml
						Injects the specified HTML markup into the specified =Node Blob=. The action of this method is different to simply setting the =innerHTML= property in that it does not replace the existing contents, but instead adds to it.

						SYNTAX
						........................................
						Uize.Node.injectHtml (nodeBLOB,htmlSTR);
						........................................

						VARIATIONS
						..........................................................
						Uize.Node.injectHtml (nodeBLOB,htmlSTR,injectionModeSTR);
						..........................................................

						When the optional =injectionModeSTR= parameter is specified, the manner in which the HTML is injected can be controlled. The default value for this parameter, ='inner bottom'=, results in the HTML being appended to the existing contents. However, if the value ='inner top'= is specified, then the HTML will be injected before the existing contents.

						Injection Modes
							- inner bottom: HTML will be injected inside the node, after all of its contents
							- inner top: HTML will be injected inside the node, before all of its contents
							- outer bottom: HTML will be injected outside the node, right after the node
							- outer top: HTML will be injected outside the node, right before the node
							- inner replace: HTML will replace the contents in the node (equivalent to innerHTML replacement)
							- outer replace: HTML will replace the node itself (equivalent to IE's outerHTML replacement)

						NOTES
						- This method can operate on multiple nodes at a time. For more details, see the section on =Node Blob=.
						- compare to the =Uize.Node.setInnerHtml= static method
			*/
		};

		var _isNode = _package.isNode = function (_node) {
			return _node && typeof _node == 'object' && (_node.getAttribute || (_node.self && _node.self == _node));
			/*?
				Static Methods
					Uize.Node.isNode
						Returns a boolean, indicating whether or not the specified value is a node reference.

						SYNTAX
						.......................................
						Uize.Node.isNode (possibleNodeANYTYPE);
						.......................................

						In order for this method to return =true=, the value of the =possibleNodeANYTYPE= parameter *must* be an object reference to an element node, and not merely a string whose value is the ID of a node.
			*/
		};

		_package.isOnNodeTree = function (_node,_rootNode) {
			_node = _getById (_node);
			_rootNode = _getById (_rootNode);
			var
				_result = false,
				_currentNode = _node
			;
			while (_currentNode && !_result) {
				_result = _currentNode == _rootNode;
				try {
					_currentNode = _currentNode.parentNode;
				} catch (_error) {
					/* NOTE:
						In some cases in Firefox, trying to get the parentNode property of form nodes results in a weird permission denied exception. In this case we can't determine if the node is in the tree, so we return false.

						As it turns out, as this function is used in the mouseover/mouseout redundancy eliminator mechanism, returning false when this exception occurs results in the desired behavior -- but there may be lurking issues with this behavior.
					*/
					_currentNode = null;
				}
			}
			return _result;
			/*?
				Static Methods
					Uize.Node.isOnNodeTree
						Returns a boolean, indicating whether or not the specified node is contained somewhere within the node tree of the specified root node.

						SYNTAX
						.......................................................
						Uize.Node.isOnNodeTree (nodeSTRorOBJ,rootNodeSTRorOBJ);
						.......................................................

						NOTES
						- returns =true= if the =nodeSTRorOBJ= and =rootNodeSTRorOBJ= parameters both specify the same node
			*/
		};

		var _joinIdPrefixAndNodeId = _package.joinIdPrefixAndNodeId = function (_idPrefix,_nodeId,_idDelimiter) {
			return (_idPrefix || '') + (_idPrefix && _nodeId && _idDelimiter ? _idDelimiter : '') + _nodeId;
		};

		_package.remove = function (_nodeBlob) {
			_doForAll (_nodeBlob,function (_node) {_node.parentNode.removeChild (_node)});
			/*?
				Static Methods
					remove
						Removes the specified =Node Blob= from the DOM.

						SYNTAX
						............................
						Uize.Node.remove (nodeBLOB);
						............................

						NOTES
						- if other references to nodes being removed are still being maintained, those nodes will not be freed from memory until all those other references are nulled
						- This method can operate on multiple nodes at a time. For more details, see the section on =Node Blob=.
			*/
		};

		_package.setClipRect = function (_nodeBlob,_top,_right,_bottom,_left) {
			_setStyle (
				_nodeBlob,
				{clip:'rect(' + _top + 'px ' + _right + 'px ' + _bottom + 'px ' + _left + 'px)'}
			);
			/*?
				Static Methods
					Uize.Node.setClipRect
						Serializes the specified clip parameters into a string and sets the value of the "clip" CSS property for the specified =Node Blob=.

						SYNTAX
						...................................................................
						Uize.Node.setClipRect (nodeBLOB,topINT,rightINT,bottomINT,leftINT);
						...................................................................

						NOTES
						- This method can operate on multiple nodes at a time. For more details, see the section on =Node Blob=.
			*/
		};

		_package.setCoords = function (_nodeBlob,_coords) {
			var
				_coordsIsArray = typeof _coords.length == 'number',
				_propertyNames = {left:0,top:1,width:2,height:3},
				_styleProperties = {}
			;
			for (var _propertyName in _propertyNames) {
				var _value = _coordsIsArray ? _coords [_propertyNames [_propertyName]] : _coords [_propertyName];
				if (typeof _value == 'string' || typeof _value == 'number')
					_styleProperties [_propertyName] = Math.round (_value) + 'px'
				;
			}
			_setStyle (_nodeBlob,_styleProperties);
			/*?
				Static Methods
					Uize.Node.setCoords
						Sets the left, top, width, and height coordinates for the specified =Node Blob=.

						SYNTAX
						................................................
						Uize.Node.setCoords (nodeBLOB,coordsARRAYorOBJ);
						................................................

						The =coordsARRAYorOBJ= parameter can be an object of the form...

						...............
						{
							left : INT,
							top : INT,
							width : INT,
							height : INT
						}
						...............
						
						...or an array of the form...

						........................................
						[ leftINT, topINT, widthINT, heightINT ]
						........................................

						NOTES
						- This method can operate on multiple nodes at a time. For more details, see the section on =Node Blob=.
						- see also the =Uize.Node.getCoords= static method
			*/
		};

		_package.setInnerHtml = function (_nodeBlob,_html) {
			_doForAll (_nodeBlob,function (_node) {_node.innerHTML = _html});
			/*?
				Static Methods
					Uize.Node.setInnerHtml
						Sets the value of the =innerHTML= property of the specified =Node Blob=.

						SYNTAX
						..........................................
						Uize.Node.setInnerHtml (nodeBLOB,htmlSTR);
						..........................................

						NOTES
						- This method can operate on multiple nodes at a time. For more details, see the section on =Node Blob=.
						- compare to the =Uize.Node.injectHtml= static method
			*/
		};

		_package.setOpacity = function (_nodeBlob,_opacity) {
			/*?
				Static Methods
					Uize.Node.setOpacity
						Sets the opacity (and, therefore, the transparency) of the specified =Node Blob=.

						SYNTAX
						.............................................
						Uize.Node.setOpacity (nodeBLOB,opacityFLOAT);
						.............................................

						Varying degrees of opacity are achieved in different browsers using slightly different techniques. This method acts as an abstraction so you can set opacity for a node in a standard way. =opacityFLOAT= should be a number in the range of =0= to =1=, where =0= represents completely invisible, =1= represents completely opaque, and any fractional values inbetween represent varying degrees of transparency / opacity.

						NOTES
						- This method can operate on multiple nodes at a time. For more details, see the section on =Node Blob=.
			*/
			_setStyle (_nodeBlob,_getOpacityProperties (_opacity));
		};

		_package.setProperties = function (_nodeBlob,_properties) {
			_doForAll (
				_nodeBlob,
				function (_node) {
					for (var _property in _properties)
						_node [_property] = _properties [_property]
					;
				}
			);
			/*?
				Static Methods
					Uize.Node.setProperties
						Sets values for an arbitrary set of properties for the specified =Node Blob=.

						SYNTAX
						.................................................
						Uize.Node.setProperties (nodeBLOB,propertiesOBJ);
						.................................................

						EXAMPLE
						...........................................................
						Uize.Node.setProperties (
							['thumbnailImage0','thumbnailImage1','thumbnailImage2'],
							{
								src : 'images/blank.gif',
								width : 200,
								height : 150,
								alt : 'loading...',
								title : 'loading...'
							}
						);
						...........................................................

						NOTES
						- This method can operate on multiple nodes at a time. For more details, see the section on =Node Blob=.
			*/
		};

		var _setStyle = _package.setStyle = function (_nodeBlob,_properties) {
			/*?
				Static Methods
					Uize.Node.setStyle
						Sets values for an arbitrary set of style attributes for the specified =Node Blob=.

						SYNTAX
						............................................
						Uize.Node.setStyle (nodeBLOB,propertiesOBJ);
						............................................

						EXAMPLE
						..................................................
						Uize.Node.setStyle (
							['navButton1Id','navButton2Id','navButton3Id'],
							{
								display : 'block',
								position  :'absolute',
								visibility : 'inherit',
								top : '100px'
							}
						);
						..................................................

						NOTES
						- This method can operate on multiple nodes at a time. For more details, see the section on =Node Blob=.
			*/
			_doForAll (
				_nodeBlob,
				function (_node) {
					var _styleObject = _node.style;
					for (var _property in _properties)
						_styleObject [_property] = _properties [_property]
					;
				}
			);
		};

		_package.show = function (_nodeBlob,_mustShow) {
			/*?
				Static Methods
					Uize.Node.show
						Lets you show or hide the specified =Node Blob=.

						SYNTAX
						.......................................
						Uize.Node.show (nodeBLOB,mustShowBOOL);
						.......................................

						This method operates on the =visibility= style attribute of nodes. When =true= is specified for the =mustShowBOOL= parameter, then the =visibility= attribute is set to ="inherit"=. When =false= is specified, the =visibility= attribute is set to ="hidden"=.

						NOTES
						- This method can operate on multiple nodes at a time. For more details, see the section on =Node Blob=.
			*/
			_setStyle (_nodeBlob,{visibility:_mustShow || _mustShow === _undefined ? 'inherit' : _hidden});
		};

		_package.showClickable = function (_nodeBlob,_clickable) {
			_setStyle (
				_nodeBlob,
				{cursor:_clickable || _clickable === _undefined ? (_isIe ? 'hand' : 'pointer') : 'default'}
			);
			/*?
				Static Methods
					Uize.Node.showClickable
						Sets the value of the "cursor" style property of the specified =Node Blob= so that the node(s) appear either clickable or not, depending on the specified boolean value. This is useful for DOM nodes that need to be wired up with click actions by JavaScript code, but that don't have CSS selectors from the document applying the appropriate cursor style to them.

						SYNTAX
						....................................................
						Uize.Node.showClickable (nodeBLOB,clickableANYTYPE);
						....................................................

						While typically a Boolean, the =clickableANYTYPE= parameter can be of any type and the node(s) will be set to appear clickable if it resolves to =true=, and not clickable if it resolves to =false= - with the exception of =undefined=, when the node(s) will be set to appear clickable (see explanation below).

						VARIATIONS
						...................................
						Uize.Node.showClickable (nodeBLOB);
						...................................

						When no =clickableANYTYPE= parameter is specified (or when its value is =undefined=), the node(s) will be set to appear clickable.

						NOTES
						- This method can operate on multiple nodes at a time. For more details, see the section on =Node Blob=.
			*/
		};

		_package.showInLayoutFlow = function (_nodeBlob,_mustShow) {
			/*?
				Static Methods
					Uize.Node.showInLayoutFlow
						Lets you show a node in the layout flow of its surrounding HTML or remove it from the layout flow.

						SYNTAX
						...................................................
						Uize.Node.showInLayoutFlow (nodeBLOB,mustShowBOOL);
						...................................................

						The effect of this method is similar to setting a value for the =display= CSS property, except without the negative side effects of using =display:none= to take a node out of the layout flow. In some browsers, nodes that have their =display= CSS property set to =none= (or that are contained inside a DOM tree where the parent node has its =display= set to =none=) will report offset dimensions of zero and may report other less than useful values for runtime related rendering properties, thereby tripping up JavaScript UI setup code that may act on such nodes.

						Instead of using the =display= property, this method sets values for both the =position= and =visibility= properties. When a value of =true= is specified for the =mustShowBOOL= parameter, then the =position= property is set to =relative= and the =visibility= property is set to =inherit=. And when =false= is specified for =mustShowBOOL=, then =position= is set to =absolute= and =visibility= is set to =hidden=.

						NOTES
						- This method can operate on multiple nodes at a time. For more details, see the section on =Node Blob=.
			*/
			_mustShow = _mustShow !== _false;
			_setStyle (
				_nodeBlob,
				{
					position:_mustShow ? 'static' : 'absolute',
					visibility:_mustShow ? 'inherit' : _hidden
				}
			);
		};

		var _stylePropertiesAsStr = _package.stylePropertiesAsStr = function (_properties) {
			var _result = '';
			for (var _property in _properties)
				_result += _property + ':' + _properties [_property] + '; '
			;
			return _result;
			/*?
				Static Methods
					Uize.Node.stylePropertiesAsStr
						Returns a string, representing the serialization of the specified set of CSS style properties.

						SYNTAX
						...............................................
						Uize.Node.stylePropertiesAsStr (propertiesOBJ);
						...............................................

						EXAMPLE
						.................................
						Uize.Node.stylePropertiesAsStr ({
							display : 'block',
							position  :'absolute',
							visibility : 'inherit',
							top : '100px'
						});
						.................................

						In the above example, the =Uize.Node.stylePropertiesAsStr= method call would return the string output ='display:block; position:absolute; visibility:inherit; top:100px;'=.
			*/
		};

		_package.unwireEventsByOwnerId = function (_wiringOwnerId,_eventMatch) {
			/* BUG!!!
				There's a bug here in the assumption that when you unwire events of a certain owner, the entire set will be unwired. This is not the case if a match limits this set. Consequently, unwireNodeEventsByMatch of Uize.Widget will not work correctly.
			*/
			var _wiringIds = _wiringIdsByOwnerId [_wiringOwnerId];
			if (_wiringIds) {
				var
					_eventMatchNode, _eventMatchEventName, _eventMatchHandler,
					_effectivelyHasEventMatch =
						_eventMatch &&
						(
							(_eventMatchNode = _package.getById (_eventMatch.node)) ||
							(_eventMatchEventName = _eventMatch.eventName) ||
							(_eventMatchHandler = _eventMatch.handler)
						)
				;
				for (var _wiringIdNo = 0; _wiringIdNo < _wiringIds.length; _wiringIdNo++) {
					var
						_wiringId = _wiringIds [_wiringIdNo],
						_wiring = _wirings [_wiringId],
						_node = _wiring._node,
						_eventName = _wiring._eventName
					;
					if (
						!_effectivelyHasEventMatch ||
						(
							(!_eventMatchNode || _eventMatchNode == _node) &&
							(!_eventMatchEventName || _eventMatchEventName == _eventName) &&
							(!_eventMatchHandler || _eventMatchHandler == _wiring._handler)
						)
					) {
						try {
							_isIe
								? _node.detachEvent (_eventName,_wiring._handlerCaller)
								: _node.removeEventListener (_eventName.substr (2),_wiring._handlerCaller,_false)
							;
						} catch (_error) {
							// the node must be gone already, so don't do anything
						}
						if (_effectivelyHasEventMatch) {
							_wiringIds.splice (_wiringIdNo,1);
							_wiringIdNo--;
						}
						delete _wirings [_wiringId];
					}
				}
				if (!_effectivelyHasEventMatch || !_wiringIds.length)
					delete _wiringIdsByOwnerId [_wiringOwnerId]
				;
			}
			/*?
				Static Methods
					Uize.Node.unwireEventsByOwnerId
						Unwires node event handlers that have been wired for the specified owner. This method is primarily intended for the implementation of the =Uize.Widget= class, but may also be useful when coding less formal mappings of interaction logic to sets of DOM nodes.

						SYNTAX
						.............................................
						Uize.Node.unwireEventsByOwnerId (ownerIdSTR);
						.............................................

						VARIATIONS
						...........................................................
						Uize.Node.unwireEventsByOwnerId (ownerIdSTR,eventMatchOBJ);
						...........................................................

						When the optional =eventMatchOBJ= parameter is specified, then node event handlers of the specified owner will only be unwired if they fit the specified match criteria. The =eventMatchOBJ= parameter is an object that may contain any of the properties =node=, =eventName=, and =handler=, where =node= should be a reference to a DOM node, =eventName= should be the name of a node event, and =handler= should be a string of JavaScript code or a function reference.

						EXAMPLE 1
						......................................................................
						Uize.Node.unwireEventsByOwnerId ('imageViewer',{eventName:'onclick'});
						......................................................................

						In this example, all "onclick" handlers of the owner "imageViewer" would be unwired.

						EXAMPLE 2
						....................................................................
						Uize.Node.unwireEventsByOwnerId ('imageViewer',{node:'zoomButton'});
						....................................................................

						In this example, all handlers wired for the "zoomButton" node of the owner ='imageViewer'= would be unwired.

						NOTES
						- see also the =Uize.Node.wireEvent= and =Uize.Node.wireEvents= static methods
			*/
		};

		var _wireEvent = _package.wireEvent = _package.addEventHandler/* DEPRECATED */ =
		function (_nodeBlob,_eventName,_handler,_wiringOwnerId) {
			/*?
				Static Methods
					Uize.Node.wireEvent
						Lets you add an event handler for the specified =Node Blob=.

						SYNTAX
						................................................................
						Uize.Node.wireEvent (nodeBLOB,eventNameSTR,eventHandlerSTRorFN);
						................................................................

						DEPRECATED NAMES
						- addEventHandler

						Different browsers provide different ways of registering event handlers for nodes. This method acts as an abstraction so you can manage event handlers in a standard way in your code.

						VARIATIONS
						...........................................................................
						Uize.Node.wireEvent (nodeBLOB,eventNameSTR,eventHandlerSTRorFN,ownerIdSTR);
						...........................................................................

						When the optional =ownerIdSTR= parameter is specified, then the wired node event will be associated to the specified owner, thus allowing easy unwiring of all wired node events of a specific owner using the =Uize.Node.unwireEventsByOwnerId= static method. This ownership mechanism is primarily intended for the implementation of the =Uize.Widget= class, but may also be useful when coding less formal mappings of interaction logic to sets of DOM nodes.

						NOTES
						- This method can operate on multiple nodes at a time. For more details, see the section on =Node Blob=.
						- compare to the =Uize.Node.wireEvent= static method
			*/
			_wiringOwnerId = _wiringOwnerId || '';
			_doForAll (
				_nodeBlob,
				function (_node) {
					/*** update handler mapping info ***/
						var _wiringId = _totalWirings++;
						if (!_wiringIdsByOwnerId [_wiringOwnerId])
							_wiringIdsByOwnerId [_wiringOwnerId] = []
						;
						_wiringIdsByOwnerId [_wiringOwnerId].push (_wiringId);

					/*** make handler caller function ***/
						var _handlerCaller;
						if (_eventName == 'onmouseover') {
							_handlerCaller = _package._makeOnmouseoverHandlerCaller (_wiringId);
						} else if (_eventName == 'onmouseout') {
							_handlerCaller = _package._makeOnmouseoutHandlerCaller (_wiringId);
						} else {
							_handlerCaller = _package._makeGenericHandlerCaller (_wiringId);
						}

					/*** add entry in handler map ***/
						_wirings [_wiringId] = {
							_node:_node,
							_eventName:_eventName,
							_handler:_handler,
							_handlerCaller:_handlerCaller
						};

					/*** wire the event ***/
						_isIe
							? _node.attachEvent (_eventName,_handlerCaller)
							: _node.addEventListener (_eventName.substr (2),_handlerCaller,_false)
						;
						if (
							_node.tagName == 'A' && !_node [_eventName] &&
							(_eventName == 'onmousedown' || _eventName == 'onclick')
						)
							_node [_eventName] = _package._returnFalse
						;

					_totalWirings++;
				}
			);
		};

		_package.wireEvents = _package.addEventHandlers/* DEPRECATED */ =
		function (_nodeBlob,_eventsToHandlers,_wiringOwnerId) {
			for (var _event in _eventsToHandlers)
				_wireEvent (_nodeBlob,_event,_eventsToHandlers [_event],_wiringOwnerId)
			;
			/*?
				Static Methods
					Uize.Node.wireEvents
						Lets you conveniently register handlers for multiple events of the specified =Node Blob=, in a single method call.

						SYNTAX
						...........................................................
						Uize.Node.wireEvents (nodeBLOB,eventNamesToHandlersMapOBJ);
						...........................................................

						This method has the effect of iteratively calling the =Uize.Node.wireEvent= static method for each event-name-to-handler mapping in the =eventNamesToHandlersMapOBJ= object, where the contents of this object are of the form...

						...................................
						{
							event1Name:event1HandlerSTRorFN,
							event2Name:event2HandlerSTRorFN,
							...
							eventNName:eventNHandlerSTRorFN
						}
						...................................

						EXAMPLE
						...................................................................
						Uize.Node.wireEvents (
							'infoLink',
							{
								onmouseover:
									function () {Uize.Node.display ('infoLinkPreview')},
								onmouseout:
									function () {Uize.Node.display ('infoLinkPreview',false)},
								onclick:
									function () {Uize.Node.display ('info')}
							}
						);
						...................................................................

						VARIATIONS
						......................................................................
						Uize.Node.wireEvents (nodeBLOB,eventNamesToHandlersMapOBJ,ownerIdSTR);
						......................................................................

						When the optional =ownerIdSTR= parameter is specified, then the wired node events will be associated to the specified owner, thus allowing easy unwiring of all wired node events of a specific owner using the =Uize.Node.unwireEventsByOwnerId= static method. This ownership mechanism is primarily intended for the implementation of the =Uize.Widget= class, but may also be useful when coding less formal mappings of interaction logic to sets of DOM nodes.

						NOTES
						- This method can operate on multiple nodes at a time. For more details, see the section on =Node Blob=.
						- compare to the =Uize.Node.wireEvent= static method
			*/
		};

	/*** Private Static Properties ***/
		_package._wirings = _wirings;
}) ();

Uize.Node._makeGenericHandlerCaller = function (_wiringId) {
	var _function =
		function (_event) {
			_event = _event || window.event;
			var _wiring = Uize.Node._wirings [_wiringId];
			return _wiring._handler.call (_wiring._node,_event);
		}
	;
	return _function;
};

Uize.Node._makeOnmouseoverHandlerCaller = function (_wiringId) {
	var _function =
		function (_event) {
			_event = _event || window.event;
			var
				_wiring = Uize.Node._wirings [_wiringId],
				_exitNode = _event.fromElement || _event.relatedTarget,
				_returnValue
			;
			if (
				!_exitNode ||
				!(_exitNode.Uize_Widget_Drag_shield || Uize.Node.isOnNodeTree (_exitNode,_wiring._node))
			)
				_returnValue = _wiring._handler.call (_wiring._node,_event)
			;
			return _returnValue;
		}
	;
	return _function;
};

Uize.Node._makeOnmouseoutHandlerCaller = function (_wiringId) {
	var _function =
		function (_event) {
			_event = _event || window.event;
			var
				_wiring = Uize.Node._wirings [_wiringId],
				_entryNode = _event.toElement || _event.relatedTarget,
				_returnValue
			;
			if (
				!_entryNode ||
				!(_entryNode.Uize_Widget_Drag_shield || Uize.Node.isOnNodeTree (_entryNode,_wiring._node))
			)
				_returnValue = _wiring._handler.call (_wiring._node,_event)
			;
			return _returnValue;
		}
	;
	return _function;
};

Uize.Node._returnFalse = Uize.Node.returnFalse = function () {
	return false
	/*?
		Static Methods
			Uize.Node.returnFalse
				Returns the boolean value =false=. This method can be assigned to event handlers to cancel their default action, as in the following example...

				EXAMPLE
				.......................................
				myNode.onclick = Uize.Node.returnFalse;
				.......................................

				If you are cancelling the default action for many nodes in a page, then using this static method allows you to share a single function - by reference - across all these nodes.

				NOTES
				- see also the =Uize.Node.returnTrue= static method
	*/
};

Uize.Node.returnTrue = function () {
	return true
	/*?
		Static Methods
			Uize.Node.returnTrue
				Returns the boolean value =true=. This method can be assigned to event handlers to enable their default action, as in the following example...

				EXAMPLE
				......................................
				myNode.onclick = Uize.Node.returnTrue;
				......................................

				If you are enabling the default action for many nodes in a page, then using this static method allows you to share a single function - by reference - across all these nodes.

				NOTES
				- see also the =Uize.Node.returnFalse= static method
	*/
};

