GpsGate Server JavaScript API

DateTime  1.0.0

GpsGate Server JavaScript API > DateTime > dom.js (source view)
Search:
 
Filters
/**
 * Copyright Franson Technology AB, Sweden, 2009
 * http://gpsgate.com, http://franson.com
 *
 * author Fredrik Blomqvist
 *
 * @module DOM
 *
 */

var Franson = Franson || {};
/**
 * namespace
 * @class Franson.DOM
 * @static
 */
Franson.DOM = Franson.DOM || {};


/**
 * @method isBlockVisible
 * @param {DOM|string} elem
 * @return {boolean}
 */
Franson.DOM.isBlockVisible = function(elem)
{
	elem = MochiKit.DOM.getElement(elem);
	return elem !== null && elem.style.display != 'none'; // ok?
};

/**
 * @method toggleEnabled
 * @param {DOM|string|Array[DOM|string]} elem
 */
Franson.DOM.toggleEnabled = function(elem)
{
	forEach(arguments, function(elem)
	{
		elem = MochiKit.DOM.getElement(elem);
		if (elem)
			elem.disabled = !elem.disabled;
	});
};

/**
 * @metod toggleBlockVisible
 * @param {DOM|string|Array[DOM|string]} elem
 */
Franson.DOM.toggleBlockVisible = function(elem)
{
	forEach(arguments, function(elem)
	{
		if (Franson.DOM.isBlockVisible(elem))
		{
			MochiKit.Style.hideElement(elem);
		}
		else
		{
			MochiKit.Style.showElement(elem);
		}
	});
};

/**
 * @method translateElement
 * @param {HTMLElement|string} element
 * @param {Vec2} dv. (x:dx, y:dy) vector, can also just specify only one value (default to 0)
 * @param {string} [unit='px']
 */
Franson.DOM.translateElement = function(element, dv, unit)
{
	element = MochiKit.DOM.getElement(element);
	unit = unit || 'px';
	var dx = dv.x || 0;
	var dy = dv.y || 0;

// 	var pos = MochiKit.Style.getElementPosition(element);
// 	MochiKit.Style.setElementPosition(element, {x: pos.x + dx, y: pos.y + dy}, unit);

	// todo: this works, the above doesn't!? (bug in MochiKit?)
	element.style.left = parseFloat(element.style.left) + dx + unit;
	element.style.top  = parseFloat(element.style.top) + dy + unit;
};

/**
 * sets both position and dimension for a DOM element
 * @method setElementBounds
 * @param {Element|string} element
 * @param {Bounds|Pos} boundsOrPos (x, y, w, h)
 * @param {Size} [size] if not present boundsOrPos is assumed to be bounds.
 */
Franson.DOM.setElementBounds = function(element, boundsOrPos, size)
{
	var pos = boundsOrPos;
	var dim = arguments.length == 3 ? size : boundsOrPos;

	MochiKit.Style.setElementPosition(element, pos);
	MochiKit.Style.setElementDimensions(element, dim);
};


/**
 * extracts both the element's position and size
 * @method getElementBounds
 * @param {Element|string} element
 * @return {(x: number, y: number, w: number, h: number)} bounds
 */
Franson.DOM.getElementBounds = function(element)
{
	var pos = MochiKit.Style.getElementPosition(element);
	var dim = MochiKit.Style.getElementDimensions(element);

	return {
		x: pos.x, y: pos.y,
		w: dim.w, h: dim.h
	};
};

/**
 * todo: deprecate. (only used in SOAP XML-parsing & same as MochiKit.DOM.getElementsByTagAndClassName(tagName, null, document))
 * ! <i>except</i> for one particular sub version of IE6, sigh..
 * @deprecated use <a href="http://mochikit.com/doc/html/MochiKit/DOM.html#fn-getelementsbytagandclassname">MochiKit.DOM.getElementsByTagAndClassName()</a> instead
 * @method getElementsByTagName
 * @param {DOCUMENT} document
 * @param {string} tagName
 * @return DOM[]
 */
Franson.DOM.getElementsByTagName = function(document, tagName)
{
	try
	{
		// trying to get node omitting any namespaces (latest versions of MSXML.XMLDocument)
		return document.selectNodes(".//*[local-name()=\""+ tagName +"\"]");
	}
	catch (ex) {}
	// old XML parser support
	return document.getElementsByTagName(tagName);
};

/**
 * @method appendToSelectList
 * @param {DOM.SELECT|string} select
 * @param {DOM.OPTION} option (todo: support multiple options? or array? (or just plain text also?))
 */
Franson.DOM.appendToSelectList = function(select, option)
{
	select = MochiKit.DOM.getElement(select);
	select.options[select.options.length] = option;
};

/**
 * todo: create a enableContextMenu also?
 * todo: support multiple elements?
 * @method disableContextMenu
 * @param {DOM|string} element
 */
Franson.DOM.disableContextMenu = function(element)
{
	MochiKit.DOM.getElement(element).oncontextmenu = Franson.Util.returnFalse;
};


/**
 * @method getScrollOffset
 * @param {DOM|string} node (todo: default to window?)
 * @return { x: number, y: number }
 */
Franson.DOM.getScrollOffset = function(node)
{
	node = MochiKit.DOM.getElement(node);
	return {
		x: Math.max(node.scrollWidth, node.offsetWidth),
		y: Math.max(node.scrollHeight, node.offsetHeight)
	};
};


/**
 * adjusts the mouse position to be relative the div/element that triggered the event.
 * (also adjust for window scrolling.)
 * todo: Why doesn't MochiKit handle this?
 * @method getMousePosition
 * @param {Event} mouseEvent (MochiKit Event)
 * @return {(x,y)}
 */
Franson.DOM.getMousePosition = function(mouseEvent) // absoluteMousePos?
{
	var offset = MochiKit.Style.getElementPosition(mouseEvent.src());
	var page = mouseEvent.mouse().page;

	var x = page.x - offset.x;
	var y = page.y - offset.y;

	return { x: x, y: y };
};


/**
 * moves the element to the end of it's sibling chain (<i>without disconnecting it</i>)
 * Useful to bring objects to the front for example (could be called moveToFront?)
 * (but not guaranteed to be visible, this doesn't care about z-index etc)
 * @method makeLastSibling
 * @param {DOM|string} element
 */
Franson.DOM.makeLastSibling = function(element)
{
	element = MochiKit.DOM.getElement(element);

	var parent = element.parentNode;
	if (parent)
		parent.appendChild(element);
};


/**
 * @method body
 * @return {BODY} document.body
 */
Franson.DOM.body = function()
{
	return document.body || document.getElementsByTagName('body')[0];
};


/**
 * Disables text selection for the element
 * todo: create a enableTextSelection also?
 * @method disableTextSelection
 * @param {DOM|string} element
 */
Franson.DOM.disableTextSelection = function(element)
{
	element = MochiKit.DOM.getElement(element);

	if (typeof(element.onselectstart) != 'undefined') // IE
	{
		element.onselectstart = Franson.Util.returnFalse; // doesn't work in IE7..
		element.unselectable = 'on'; //? GMap does this also but it still doesn't work in IE7 (GMap fails on IE7 also, so...)
	}
	else if (typeof(element.style.MozUserSelect) != 'undefined') // FireFox
	{
		element.style.MozUserSelect = 'none'; // (can be done in CSS also)
	}
	else if (typeof(element.style.KhtmlUserSelect) != 'undefined') // Safari
	{
		element.style.KhtmlUserSelect = 'none';
	}
	else // all other browsers (i.e: Opera)
	{
		element.onmousedown = Franson.Util.returnFalse; // ok? clash with dragging stuff? just skip?
		element.style.cursor = 'default'; // ok?
	}
/*
	if (typeof(element.ondragstart) != 'undefined')
	{
		element.ondragstart = Franson.Util.returnFalse; // change to Franson.Event.stop();
	}
	if (typeof(element.ondrag) != 'undefined')
	{
		element.ondrag = Franson.Util.returnFalse; // todo: test if this works in IE
	}
*/

/*
	// this seems to work in IE! (just need to avoid disturbing other browsers)
	Franson.Event.connectOnce(element, 'ondragstart', Franson.Event.stop);
	Franson.Event.connectOnce(element, 'onselectstart', Franson.Event.stop);
	Franson.Event.connectOnce(element, 'ondrag', Franson.Event.stop); // necessary?
	// oncontextmenu also?
*/
};


/**
 * todo: change to use Async.Deferred interface?
 * todo: see http://trac.mochikit.com/ticket/258
 * @method loadScript
 * @param {string} uri
 * @param {string|function} [bodyOrHead='head'] (hmm, necessary?)
 * @param {function} [onLoaded]
 */
Franson.DOM.loadScript = function(uri, bodyOrHead, onloaded)
{
	if (typeof(arguments[1]) == 'function')
	{
		onloaded = arguments[1];
		bodyOrHead = 'head';
	}
	else
	{
		bodyOrHead = bodyOrHead || 'head';
	}

	var scriptNode = document.createElement('script');
	scriptNode.type = 'text/javascript';

	if (typeof(onloaded) != 'undefined')
	{
		var done = false;
		// todo: this is not a 100% portable way.. (see http://remysharp.com/2007/04/12/how-to-detect-when-an-external-library-has-loaded/)
		// (though this is the way jQuery does it)
		scriptNode.onload = scriptNode.onreadystatechange = function() // handle both IE and FF etc (Safari needs a poll instead?)
		{
			if (!done && (!this.readyState || this.readyState == 'loaded' || this.readyState == 'complete'))
			{
				done = true; // necessary since the onreadystatechange may fire multiple times
				onloaded(scriptNode);
			}
		};
	}

	scriptNode.src = uri;
	document.getElementsByTagName(bodyOrHead)[0].appendChild(scriptNode);
};


if (typeof(Franson.Iter) != 'undefined') // necessary? (will not fail until used anyway..)
{
	/**
	 * @method levelOrderIter
	 * @param {DOM} node
	 * @return {Iterable[DOM]}
	 */
	Franson.DOM.levelOrderIter = function(node)
	{
		return Franson.Iter.treeLevelOrderIter(node, MochiKit.Base.itemgetter('childNodes'));
	};

	/**
	 * @method postOrderIter
	 * @param {DOM} node
	 * @return {Iterable[DOM]}
	 */
	Franson.DOM.postOrderIter = function(node)
	{
		return Franson.Iter.treePostOrderIter(node, MochiKit.Base.itemgetter('childNodes'));
	};

	/**
	 * @method preOrderIter
	 * @param {DOM} node
	 * @return {Iterable[DOM]}
	 */
	Franson.DOM.preOrderIter = function(node)
	{
		return Franson.Iter.treePreOrderIter(node, MochiKit.Base.itemgetter('childNodes'));
	};

	/**
	 * @method parentIter
	 * @param {DOM} node
	 * @return {Iterable[DOM]}
	 */
	Franson.DOM.parentIter = function(node)
	{
		return Franson.Iter.leafParentIter(node, MochiKit.Base.itemgetter('parentNode'));
	};
}

Copyright © 2009 Franson Technology AB, Sweden. All rights reserved.