# inputEx-library

### inputEx 0.5.1

inputEx-library > inputEx > SelectField.js (source view)
Search:
Filters Show Private Show Protected Show Deprecated

    (function () {

    	var Event = YAHOO.util.Event, lang = YAHOO.lang;

    	/**
    	 * Create a select field
    	 * @class inputEx.SelectField
    	 * @extends inputEx.Field
    	 * @constructor
    	 * @param {Object} options Added options:
    	 * <ul>
    	 *    <li>choices: contains the list of choices configs ([{value:'usa'}, {value:'fr', label:'France'}])</li>
    	 * </ul>
    	 */
    	inputEx.SelectField = function (options) {
    		inputEx.SelectField.superclass.constructor.call(this, options);
    	};

    	lang.extend(inputEx.SelectField, inputEx.Field, {

    		/**
    		 * Set the default values of the options
    		 * @param {Object} options Options object as passed to the constructor
    		 */
    		setOptions: function (options) {

    			var i, length;

    			inputEx.SelectField.superclass.setOptions.call(this, options);

    			this.options.choices = lang.isArray(options.choices) ? options.choices : [];

    			// Retro-compatibility with old pattern (changed since 2010-06-30)
    			if (lang.isArray(options.selectValues)) {

    				for (i = 0, length = options.selectValues.length; i < length; i += 1) {

    					this.options.choices.push({
    						value: options.selectValues[i],
    						label: "" + ((options.selectOptions && !lang.isUndefined(options.selectOptions[i])) ? options.selectOptions[i] : options.selectValues[i])
    					});

    				}
    			}

    		},

    		/**
    		 * Build a select tag with options
    		 */
    		renderComponent: function () {

    			var i, length;

    			// create DOM <select> node
    			this.el = inputEx.cn('select', {

    				id: this.divEl.id ? this.divEl.id + '-field' : YAHOO.util.Dom.generateId(),
    				name: this.options.name || ''

    			});

    			// list of choices (e.g. [{ label: "France", value:"fr", node:<DOM-node>, visible:true }, {...}, ...])
    			this.choicesList = [];

    			// add choices
    			for (i = 0, length = this.options.choices.length; i < length; i += 1) {
    				this.addChoice(this.options.choices[i]);
    			}

    			// append <select> to DOM tree
    			this.fieldContainer.appendChild(this.el);
    		},

    		/**
    		 * Register the "change" event
    		 */
    		initEvents: function () {
    			Event.addListener(this.el, "change", this.onChange, this, true);
    			Event.addFocusListener(this.el, this.onFocus, this, true);
    			Event.addBlurListener(this.el, this.onBlur, this, true);
    		},

    		/**
    		 * Set the value
    		 * @param {String} value The value to set
    		 * @param {boolean} [sendUpdatedEvt] (optional) Wether this setValue should fire the updatedEvt or not (default is true, pass false to NOT send the event)
    		 */
    		setValue: function (value, sendUpdatedEvt) {

    			var i, length, choice, firstIndexAvailable, choiceFound = false;

    			for (i = 0, length = this.choicesList.length; i < length ; i += 1) {

    				if (this.choicesList[i].visible) {

    					choice = this.choicesList[i];

    					if (value === choice.value) {

    						choice.node.selected = "selected";
    						choiceFound = true;
    						break; // choice node already found

    					} else if (lang.isUndefined(firstIndexAvailable)) {

    						firstIndexAvailable = i;
    					}

    				}

    			}

    			// select value from first choice available when
    			// value not matching any visible choice
    			//
    			// if no choice available (-> firstIndexAvailable is undefined), skip value setting
    			if (!choiceFound && !lang.isUndefined(firstIndexAvailable)) {

    				choice = this.choicesList[firstIndexAvailable];
    				choice.node.selected = "selected";
    				value = choice.value;

    			}

    			// Call Field.setValue to set class and fire updated event
    			inputEx.SelectField.superclass.setValue.call(this, value, sendUpdatedEvt);
    		},

    		/**
    		 * Return the value
    		 * @return {Any} the selected value
    		 */
    		getValue: function () {

    			var choiceIndex;

    			if (this.el.selectedIndex >= 0) {

    				choiceIndex = inputEx.indexOf(this.el.childNodes[this.el.selectedIndex], this.choicesList, function (node, choice) {
    					return node === choice.node;
    				});

    				return this.choicesList[choiceIndex].value;

    			} else {

    				return "";

    			}
    		},

    		/**
    		 * Disable the field
    		 */
    		disable: function () {
    			this.el.disabled = true;
    		},

    		/**
    		 * Enable the field
    		 */
    		enable: function () {
    			this.el.disabled = false;
    		},

    		createChoiceNode: function (choice) {

    			return inputEx.cn('option', {value: choice.value}, null, choice.label);

    		},

    		removeChoiceNode: function (node) {

    			// remove from selector
    			//
    			//   -> style.display = 'none' would work only on FF (when node is an <option>)
    			//   -> other browsers (IE, Chrome...) require to remove <option> node from DOM
    			//
    			this.el.removeChild(node);

    		},

    		disableChoiceNode: function (node) {

    			node.disabled = "disabled";

    		},

    		enableChoiceNode: function (node) {

    			node.removeAttribute("disabled");

    		},

    		/**
    		 * Attach an <option> node to the <select> at the specified position
    		 * @param {HTMLElement} node The <option> node to attach to the <select>
    		 * @param {Int} position The position of the choice in choicesList (may not be the "real" position in DOM)
    		 */
    		appendChoiceNode: function (node, position) {

    			var domPosition, i;

    			// Compute real DOM position (since previous choices in choicesList may be hidden)
    			domPosition = 0;

    			for (i = 0; i < position; i += 1) {

    				if (this.choicesList[i].visible) {

    					domPosition += 1;

    				}

    			}

    			// Insert in DOM
    			if (domPosition < this.el.childNodes.length) {

    				YAHOO.util.Dom.insertBefore(node, this.el.childNodes[domPosition]);

    			} else {

    				this.el.appendChild(node);

    			}
    		}

    	});

    	// Augment prototype with choice mixin (functions : addChoice, removeChoice, etc.)
    	lang.augmentObject(inputEx.SelectField.prototype, inputEx.mixin.choice);

    	// Register this class as "select" type
    	inputEx.registerType("select", inputEx.SelectField, [
    		{
    			type: 'list',
    			name: 'choices',
    			label: 'Choices',
    			elementType: {
    				type: 'group',
    				fields: [
    					{ label: 'Value', name: 'value', value: '' }, // not required to allow '' value (which is default)
    					{ label: 'Label', name: 'label' } // optional : if left empty, label is same as value
    				]
    			},
    			value: [],
    			required: true
    		}
    	]);

    }());

Copyright © 2010 Eric Abouaf All rights reserved.