jsbeans

jsbeans  1.0.0

jsbeans > jsbeans > dom.js (source view)
Search:
 
Filters
/*!
 * Copyright (c) 2009 Francesco Mele jsbeans@francescomele.com
 *
 * This Software is licenced under the LGPL Licence (GNU Lesser General 
 * Public License).
 * In addition to the LGPL Licence the Software is subject to the 
 * following conditions:
 * 
 * 	i	every modification must be public and comunicated to the Author
 * 	ii	every "jsbean" added to this library must be self consistent 
 * 		except for the dependence from jsbeans-x.x.x.js
 * 	iii	copyright notice and this permission notice shall be included 
 * 		in all copies or substantial portions of the Software
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
 * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
 * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
 * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
 * OTHER DEALINGS IN THE SOFTWARE.
 */

/**
 * A set of utilities to manage DOM Objects
 * @namespace jsbeans
 * @class dom
 * @static
 */

/**
 * @config Defining base object <code class="class">jsbeans.dom</code>.
 * @private
 */
jsbeans.define("jsbeans.dom");

/**
 * Appends {@param} <code class="param">object_to_append</code> at the same level of {@param} <code class="param">base_object</code>, just after it.<br/>
 * Note that no check will be performed on given arguments. Passing DOM Object is up to developer.
 * @method insertAfter
 * @param base_object {DOM} if <code>null</code> or <code>undefined</code> <code>document.firstChild</code> will be used.
 * @param object_to_append {DOM}
 * @static
 */
jsbeans.dom.insertAfter = function(obj, newObj) {
	if (obj == null || typeof(obj) == "undefined") {
		obj = document.firstChild;
	}
	obj.parentNode.insertBefore(newObj, obj.nextSibling);
};

/**
 * Removes {@param} <code class="param">object_to_remove</code>. Useful to direct removing DOM Objects.<br/>
 * Note that no check will be performed on given arguments. Passing DOM Object is up to developer.
 * @method removeSelf
 * @param object_to_remove {DOM}
 * @static
 */
jsbeans.dom.removeSelf = function(obj) {
	if (obj == null || typeof(obj) == "undefined") {
		obj = document.firstChild;
	}
	obj.parentNode.removeChild(obj);
};

/**
 * Switches {@param} <code class="param">object_to_move</code> with next sibling. Effect seems to move down given Object<br/>
 * Note that no check will be performed on given arguments. Passing DOM Object is up to developer.<br/>
 * <span class="fixme">FIXME</span>: it seems that cloning nodes makes some conflict with event handlers attached via javascript (i.e. jquery.mouseout(...))
 * @method moveDown
 * @param object_to_move {DOM} if <code>null</code> or <code>undefined</code> the method will exit silently.
 * @static
 */
jsbeans.dom.moveDown = function(obj) {
	if (obj == null || typeof(obj) == "undefined") {
		return;
	}
	var next, cur = obj;
	var num = 0;
	for (; cur; cur = cur["nextSibling"]) {
		if (cur.nodeType == 1 && ++num == 2) {
			next = cur;
			break;
		}
	}
	if (typeof(next) != "undefined") {
		var clone = obj.cloneNode(true);
		jsbeans.dom.insertAfter(next, clone);
		jsbeans.dom.removeSelf(obj);
	}
};

/**
 * Switches {@param} <code class="param">object_to_move</code> with previous sibling. Effect seems to move up given Object<br/>
 * Note that no check will be performed on given arguments. Passing DOM Object is up to developer.<br/>
 * <span class="fixme">FIXME</span>: it seems that cloning nodes makes some conflict with event handlers attached via javascript (i.e. jquery.mouseout(...))
 * @method moveUp
 * @param object_to_move {DOM} if <code>null</code> or <code>undefined</code> the method will exit silently.
 * @static
 */
jsbeans.dom.moveUp = function(/*DOM*/obj) {
	if (obj == null || typeof(obj) == "undefined") {
		return;
	}
	var prev, cur = obj;
	var num = 0;
	for (; cur; cur = cur["previousSibling"]) {
		if (cur.nodeType == 1 && ++num == 2) {
			prev = cur;
			break;
		}
	}
	if (typeof(prev) != "undefined") {
		var clone = obj.cloneNode(true);
		obj.parentNode.insertBefore(clone, prev);
		jsbeans.dom.removeSelf(obj);
	}
};

/**
 * Starting from {@param} <code class="param">node</code> this method will call {@param} <code class="param">func</code> on every next sibling recursively.<br/>
 * Note that no check will be performed on given arguments. Passing DOM Object is up to developer.
 * @method visit
 * @param node {DOM}
 * @param func {Function}
 * @static
 */
jsbeans.dom.visit = function(node, func) {
	func(node);
	node = node.firstChild;
	while(node) {
		jsbeans.dom.visit(node, func);
		node = node.nextSibling;
	}
};

/**
 * Returns an Array of DOM objects that match <strong>exactly</strong> the same value for the given attribute name.<br/>
 * For "class" attribute it chekcs for a class among the defined ones. Example: &lt;input type="text" class="className1 className2" /> is found even using jsbeans.dom.getElementsByAttribute("class", "className1").<br/>
 * Note: this kind of functionality is now widely supported by almost all javascript libraries. It probably won't be deleted, but checking its presence after an update is encouraged.
 * @method getElementsByAttribute
 * @param attribute {String} the attribute name of a DOM Object
 * @param value {String} the attribute value to match
 * @return {Array&lt;DOM>}
 * @static
 */
jsbeans.dom.getElementsByAttribute = function(attr, value) {
	var res = new Array();
	jsbeans.dom.visit(document.body, function(node) {
		if (attr == "class") {
			if (node.className && node.className.match(new RegExp("(^|\\s)" + value + "(\\s|$)"))) {
				res.push(node);
			}
		} 
		else {
			var current = node.nodeType === 1 && node.getAttribute(attr);
			if (typeof(current) === "string" && (current === value || typeof(value) !== "string")) {
				res.push(node);
			}
		}
	});
	return res;
};
/**
 * A shortcut to create DOM Elements.<br/>
 * Note 1: for "class" attribute use <code>className</code>.<br/>
 * Note 2: for "style" use nested rules (e.g. <code>{style: {border: "1px solid red", color: "#de45ff"}}</code>)
 * @method create
 * @param tagName {String} the name of a DOM Object (e.g 'div')
 * @param [options] {JSON} set of attributes
 * @return {DOM}
 * @static
 */
jsbeans.dom.create = function(tagName, attrs) {
	var res = document.createElement(tagName);
	var attrs = attrs || {};
	for (p in attrs) {
		if (("" + p).toLowerCase() != "style") {
			res[p] = attrs[p];
		}
		else {
			for (style in attrs["style"]) {
				res.style[style] = attrs["style"][style];
			}
		}
	}
	return res;
};

Copyright © 2016 Francesco Mele. All rights reserved.