jsbeans

jsbeans  1.0.0

jsbeans > jsbeans > Select.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 javascript Object with both static and instance methods 
 * @namespace jsbeans
 * @class Select
 * @constructor
 * @param [id] {String} if provided it stores the Select Object for future use.
 * */
jsbeans.Select = function() {
	this._id = arguments[0] || null;
};

/**
 * Orders Select's Options by their text, not by value.<br/>
 * It calls the static method
 * @method order
 * @param [caseSensitive] {boolean} optional, <code>false</code>
 * */
jsbeans.Select.prototype.order = function() {
	jsbeans.Select.order(this._id, arguments[0]);
};

/**
 * Filters Options of a second Select based on value of the selected option pf the first.<br/>
 * Second options are mapped using style class. See <a href="../jsbeans.Select.html">jsbeans.Select page</a> for details and running sample.
 * @method setDependant
 * @param childId {String}
 * @param [parentId] {String}
 * */
jsbeans.Select.prototype.setDependant = function(childId /*, parentId*/) {
	var parentId = arguments[1] || this._id;
	var parent = document.getElementById(parentId);
	var child =	document.getElementById(childId);
	if (parent == null || child == null) {
		return;
	}
	
	var div = document.createElement("div");
	div.style.display = "none";
	div.innerHTML = "<select style='display:none' id='" + parentId + childId + "'></select>";
	document.body.appendChild(div);

	var pc = document.getElementById(parentId + childId);
	for (var i = 0; i < child.childNodes.length; i++) {
		pc.appendChild(child.childNodes[i].cloneNode(true));
	}
	child.innerHTML = "";
	
	var _dependant = function(all, dependant, val) {
		for (var i = 0; i < all.options.length; i++) {
			var className = all.options[i].className;
			var classes = typeof(className) != "undefined" ? className.split(" ") : new Array();
			for (var j = 0; j < classes.length; j++) {
				if (classes[j] != "" && classes[j] == "sub_" + val) {
					dependant.appendChild(all.options[i].cloneNode(true));
				}
			}
		}
	};
	
	var parentVal = parent.value;
	_dependant(pc, child, parentVal);

	parent.onchange = function() {
		child.innerHTML = "";
		var parentVal = this.value;
		_dependant(pc, child, parentVal);
	};
	parent = null;
};


/**
 * @method _get
 * @param object {String | DOM}
 * @return {DOM}
 * @private
 * @static
 * */
jsbeans.Select._get = function(v) {
	var res = null;
	if (typeof(v) == "string") {
		res = document.getElementById(v);
	} 
	else if (typeof(v) == "object") {
		res = v;
	}
	if (res != null && res.nodeName && res.nodeName.toString().toLowerCase() == "select") {
		return res;
	}
	return null;
};

/**
 * Useful primarly in multiple selects, a way to delete Options.
 * @method removeSelected
 * @param object {String | DOM} the Select Object or its <code>id</code>
 * @static
 * */
jsbeans.Select.removeSelected = function(sel) {
	sel = jsbeans.Select._get(sel);
	if (sel == null) {
		return;
	}
	var toBeRemoved = new Array();
	for (var i = 0, opt; opt = sel.options[i]; i++) {
		if (opt.selected) {
			toBeRemoved.push(opt);
		}
	}
	for (var i = 0, opt; opt = toBeRemoved[i]; i++) {
		sel.removeChild(opt);
	}
};

/**
 * @method _remove
 * @param node {DOM}
 * @param arr {Array}
 * @private
 * @static
 * */
jsbeans.Select._remove = function(o, a) {
	for (var i = 0, opt; opt = a[i]; i++) {
		o.removeChild(opt);
	}
};

/**
 * Copy selected Options from {@param} <code class="param">source</code> to {@param} <code class="param">destination</code> removing them from {@param} <code class="param">source</code>.
 * @method move
 * @param source {String | DOM} the Select Object (or its <code>id</code>)
 * @param destination {String | DOM} the Select Object (or its <code>id</code>)
 * @param [options] {JSON}
 * <pre>
 * order: boolean, // order both source and destination by text. Optional, default false.
 * orderSource: boolean, // order only source by text.
 * orderDestination: boolean, // order only destination by text.
 * </pre>
 * @static
 * */
jsbeans.Select.move = function(from, to /*, options*/) {
	from = jsbeans.Select._get(from);
	to = jsbeans.Select._get(to);
	if (from == null || to == null) {
		return;
	}
	var options = arguments[2] || {order: true};
	var toBeRemoved = new Array();
	for (var i = 0, opt; opt = from.options[i]; i++) {
		if (opt.selected) {
			var found = false;
			for (var j = 0, opt2; opt2 = to.options[j]; j++) {
				if (opt2.text == opt.text) {
					found = true;
					break;
				}
			}
			if (!found) {
				to.appendChild(opt.cloneNode(true));
				toBeRemoved.push(opt);
			}
		}
	}
	for (var i = 0, opt; opt = toBeRemoved[i]; i++) {
		from.removeChild(opt);
	}
	if (options.order && options.order == true) {
		jsbeans.Select.order(from);
		jsbeans.Select.order(to);
	} 
	else {
		if (options.orderSource && options.orderSource == true) {
			jsbeans.Select.order(from);
		}
		if (options.orderDestination && options.orderDestination == true) {
			jsbeans.Select.order(to);
		}
	}
};

/**
 * Copy all Options from {@param} <code class="param">source</code> to {@param} <code class="param">destination</code> removing them from {@param} <code class="param">source</code>.
 * @method moveAll
 * @param source {String | DOM} the Select Object (or its <code>id</code>)
 * @param destination {String | DOM} the Select Object (or its <code>id</code>)
 * @param [options] {JSON}
 * <pre>
 * order: boolean, // order destination by text. Optional, default false.
 * orderDestination: boolean, // order only destination by text.
 * </pre>
 * @static
 * */
jsbeans.Select.moveAll = function(from, to /*, options*/) {
	from = jsbeans.Select._get(from);
	to = jsbeans.Select._get(to);
	if (from == null || to == null) {
		return;
	}
	var options = arguments[2] || {order: true};
	var toBeRemoved = new Array();
	for (var i = 0, opt; opt = from.options[i]; i++) {
		var found = false;
		for (var j = 0, opt2; opt2 = to.options[j]; j++) {
			if (opt2.text == opt.text) {
				found = true;
				break;
			}
		}
		if (!found) {
			to.appendChild(opt.cloneNode(true));
			toBeRemoved.push(opt);
		}
	}
	for (var i = 0, opt; opt = toBeRemoved[i]; i++) {
		from.removeChild(opt);
	}
	if (options.order && options.order == true) {
		jsbeans.Select.order(to);
	} 
	else {
		if (options.orderDestination && options.orderDestination == true) {
			jsbeans.Select.order(to);
		}
	}
};
/**
 * Copy selected Options from {@param} <code class="param">source</code> to {@param} <code class="param">destination</code>.
 * @method copy
 * @param source {String | DOM} the Select Object (or its <code>id</code>)
 * @param destination {String | DOM} the Select Object (or its <code>id</code>)
 * @param [options] {JSON}
 * <pre>
 * order: boolean, // order both destination by text. Optional, default false.
 * orderDestination: boolean, // order only destination by text.
 * </pre>
 * @static
 * */
jsbeans.Select.copy = function(from, to /*, options*/) {
	from = jsbeans.Select._get(from);
	to = jsbeans.Select._get(to);
	if (from == null || to == null) {
		return;
	}
	var options = arguments[2] || {order: true};
	for (var i = 0, opt; opt = from.options[i]; i++) {
		if (opt.selected) {
			var found = false;
			for (var j = 0, opt2; opt2 = to.options[j]; j++) {
				if (opt2.text == opt.text) {
					found = true;
					break;
				}
			}
			if (!found) {
				to.appendChild(opt.cloneNode(true));
			}
		}
	}
	if (options.order && options.order == true) {
		jsbeans.Select.order(to);
	} 
	else {
		if (options.orderDestination && options.orderDestination == true) {
			jsbeans.Select.order(to);
		}
	}
};
/**
 * Copy selected Options from {@param} <code class="param">source</code> to {@param} <code class="param">destination</code>.
 * @method copyAll
 * @param source {String | DOM} the Select Object (or its <code>id</code>)
 * @param destination {String | DOM} the Select Object (or its <code>id</code>)
 * @param [options] {JSON}
 * <pre>
 * order: boolean, // order destination by text. Optional, default false.
 * orderDestination: boolean, // order only destination by text.
 * </pre>
 * @static
 * */
jsbeans.Select.copyAll = function(from, to /*, options*/) {
	from = jsbeans.Select._get(from);
	to = jsbeans.Select._get(to);
	if (from == null || to == null) {
		return;
	}
	var options = arguments[2] || {order: true};
	for (var i = 0, opt; opt = from.options[i]; i++) {
		var found = false;
		for (var j = 0, opt2; opt2 = to.options[j]; j++) {
			if (opt2.text == opt.text) {
				found = true;
				break;
			}
		}
		if (!found) {
			to.appendChild(opt.cloneNode(true));
		}
	}
	if (options.order && options.order == true) {
		jsbeans.Select.order(to);
	} 
	else {
		if (options.orderDestination && options.orderDestination == true) {
			jsbeans.Select.order(to);
		}
	}
};
/**
 * Returns the lowest Options among {@param} <code class="param">select</code>'s Options by text using <code>&lt;</code> operator.
 * @method min
 * @param select {String | DOM} the Select Object (or its <code>id</code>)
 * @return object {Option}
 * @static
 * */
jsbeans.Select.min = function(select) {
	select = jsbeans.Select._get(select);
	if (select == null || !select.options || select.options.length == 0) {
		return null;
	}
	var res = select.options[0];
	for (var i = 0, opt; opt = select.options[i]; i++) {
		if (opt.text < res.text) {
			res = opt;
		}
	}
	return res;
};
/**
 * Returns the highest Options among {@param} <code class="param">select</code>'s Options by text using <code>&gt;</code> operator.
 * @method min
 * @param select {String | DOM} the Select Object (or its <code>id</code>)
 * @return object {Option}
 * @static
 * */
jsbeans.Select.max = function(select) {
	select = jsbeans.Select._get(select);
	if (select == null || !select.options || select.options.length == 0) {
		return null;
	}
	var res = select.options[0];
	for (var i = 0, opt; opt = select.options[i]; i++) {
		if (opt.text > res.text) {
			res = opt;
		}
	}
	return res;
};
/**
 * Shows only Options of {@param} <code class="param">select</code> whose text contains string {@param} <code class="param">value</code>.
 * @method filter
 * @param value {String}
 * @param select {String | DOM} the Select Object (or its <code>id</code>)
 * @static
 * */
jsbeans.Select.filter = function(value, select) {
	select = jsbeans.Select._get(select);
	if (select == null || value == null) {
		// TODO check if may return void
		return null;
	}
	var sel = document.getElementById("jsbeans_Select_filter_" + select);
	if (sel == null || typeof(sel) == "undefined") {
		// clone the select and hide it
		sel = document.createElement("select");
		sel.setAttribute("id", "jsbeans_Select_filter_" + select);
		sel.style.display = "none";
		sel.style.position = "absolute";
		sel.style.top = "-1000px";
		sel.style.left = "-1000px";
		for (var i = 0; i < select.options.length; i++) {
			sel.appendChild(select.options[i].cloneNode(true));
		}
		document.body.appendChild(sel);
	}
	// empty the select
	select.innerHTML = "";
	var value = value.toLowerCase();
	// now fill the select with matching options
	for (var i = 0, opt; opt = sel.options[i]; i++) {
		if (opt.text.toLowerCase().indexOf(value) != -1) {
			select.appendChild(opt.cloneNode(true));
		}
	}
};
/**
 * As {@method} <code class="methd">filter</code> creates hidden selects, developer can purge all created ones calling this.<br/>
 * Please note that selects currently filtered may <strong>NOT</strong> be restored! Developer may need to clean filter's input before calling this;<br/>
 * jQuery sample: <code>$("#filterInput").val("").keyup();<br/>jsbeans.Select.filterObjectCleaner();</code>
 * @method filterObjectCleaner
 * @static
 * */
jsbeans.Select.filterObjectCleaner = function() {
	var selects = document.getElementsByTagName("select");
	for (var i = 0, sel; sel = selects[i]; i++) {
		if (sel.id && sel.id.indexOf("jsbeans_Select_filter_") != -1) {
			sel.parentNode.removeChild(sel);
		}
	}
};
/**
 * Orders Options by text.
 * @method order
 * @param select {String | DOM}
 * @param [caseSensitive] {boolean} default <code>false</code>
 * @static
 * */
jsbeans.Select.order = function(id /*, caseSensitive*/) {
	var sel = jsbeans.Select._get(id);
	if (sel == null) {
		return;
	}
	var caseSensitive = arguments[1] || false;
	var _o = new Array();
	for (var i = 0, opt; opt = sel.options[i]; i++) {
		if (caseSensitive) {
			_o.push(opt.text);
		} 
		else {
			_o.push(opt.text.toLowerCase());
		}
	}
	_o = _o.sort();
	var res = new Array();
	for (var i = 0; i < _o.length; i++) {
		for (var j = 0, opt; opt = sel.options[j]; j++) {
			if (caseSensitive) {
				if (opt.text == _o[i]) {
					res.push(opt);
					break;
				}
			} 
			else {
				if (opt.text.toLowerCase() == _o[i].toLowerCase()) {
					res.push(opt);
					break;
				}
			}
		}
	}
	for (var i = 0, opt; opt = sel.options[i]; i++) {
		opt = null;
	}
	for (var i = 0; i < res.length; i++) {
		sel.appendChild(res[i]);
	}
};

Copyright © 2016 Francesco Mele. All rights reserved.