text: /**
   * NativeListBox.js
   *
   * Copyright, Moxiecode Systems AB
   * Released under LGPL License.
   *
   * License: http://www.tinymce.com/license
   * Contributing: http://www.tinymce.com/contributing
   */
  
  (function(tinymce) {
  	var DOM = tinymce.DOM, Event = tinymce.dom.Event, each = tinymce.each, Dispatcher = tinymce.util.Dispatcher, undef;
  
  	/**
  	 * This class is used to create list boxes/select list. This one will generate
  	 * a native control the way that the browser produces them by default.
  	 *
  	 * @class tinymce.ui.NativeListBox
  	 * @extends tinymce.ui.ListBox
  	 */
  	tinymce.create('tinymce.ui.NativeListBox:tinymce.ui.ListBox', {
  		/**
  		 * Constructs a new button control instance.
  		 *
  		 * @constructor
  		 * @method NativeListBox
  		 * @param {String} id Button control id for the button.
  		 * @param {Object} s Optional name/value settings object.
  		 */
  		NativeListBox : function(id, s) {
  			this.parent(id, s);
  			this.classPrefix = 'mceNativeListBox';
  		},
  
  		/**
  		 * Sets the disabled state for the control. This will add CSS classes to the
  		 * element that contains the control. So that it can be disabled visually.
  		 *
  		 * @method setDisabled
  		 * @param {Boolean} s Boolean state if the control should be disabled or not.
  		 */
  		setDisabled : function(s) {
  			DOM.get(this.id).disabled = s;
  			this.setAriaProperty('disabled', s);
  		},
  
  		/**
  		 * Returns true/false if the control is disabled or not. This is a method since you can then
  		 * choose to check some class or some internal bool state in subclasses.
  		 *
  		 * @method isDisabled
  		 * @return {Boolean} true/false if the control is disabled or not.
  		 */
  		isDisabled : function() {
  			return DOM.get(this.id).disabled;
  		},
  
  		/**
  		 * Selects a item/option by value. This will both add a visual selection to the
  		 * item and change the title of the control to the title of the option.
  		 *
  		 * @method select
  		 * @param {String/function} va Value to look for inside the list box or a function selector.
  		 */
  		select : function(va) {
  			var t = this, fv, f;
  
  			if (va == undef)
  				return t.selectByIndex(-1);
  
  			// Is string or number make function selector
  			if (va && typeof(va)=="function")
  				f = va;
  			else {
  				f = function(v) {
  					return v == va;
  				};
  			}
  
  			// Do we need to do something?
  			if (va != t.selectedValue) {
  				// Find item
  				each(t.items, function(o, i) {
  					if (f(o.value)) {
  						fv = 1;
  						t.selectByIndex(i);
  						return false;
  					}
  				});
  
  				if (!fv)
  					t.selectByIndex(-1);
  			}
  		},
  
  		/**
  		 * Selects a item/option by index. This will both add a visual selection to the
  		 * item and change the title of the control to the title of the option.
  		 *
  		 * @method selectByIndex
  		 * @param {String} idx Index to select, pass -1 to select menu/title of select box.
  		 */
  		selectByIndex : function(idx) {
  			DOM.get(this.id).selectedIndex = idx + 1;
  			this.selectedValue = this.items[idx] ? this.items[idx].value : null;
  		},
  
  		/**
  		 * Adds a option item to the list box.
  		 *
  		 * @method add
  		 * @param {String} n Title for the new option.
  		 * @param {String} v Value for the new option.
  		 * @param {Object} o Optional object with settings like for example class.
  		 */
  		add : function(n, v, a) {
  			var o, t = this;
  
  			a = a || {};
  			a.value = v;
  
  			if (t.isRendered())
  				DOM.add(DOM.get(this.id), 'option', a, n);
  
  			o = {
  				title : n,
  				value : v,
  				attribs : a
  			};
  
  			t.items.push(o);
  			t.onAdd.dispatch(t, o);
  		},
  
  		/**
  		 * Executes the specified callback function for the menu item. In this case when the user clicks the menu item.
  		 *
  		 * @method getLength
  		 */
  		getLength : function() {
  			return this.items.length;
  		},
  
  		/**
  		 * Renders the list box as a HTML string. This method is much faster than using the DOM and when
  		 * creating a whole toolbar with buttons it does make a lot of difference.
  		 *
  		 * @method renderHTML
  		 * @return {String} HTML for the list box control element.
  		 */
  		renderHTML : function() {
  			var h, t = this;
  
  			h = DOM.createHTML('option', {value : ''}, '-- ' + t.settings.title + ' --');
  
  			each(t.items, function(it) {
  				h += DOM.createHTML('option', {value : it.value}, it.title);
  			});
  
  			h = DOM.createHTML('select', {id : t.id, 'class' : 'mceNativeListBox', 'aria-labelledby': t.id + '_aria'}, h);
  			h += DOM.createHTML('span', {id : t.id + '_aria', 'style': 'display: none'}, t.settings.title);
  			return h;
  		},
  
  		/**
  		 * Post render handler. This function will be called after the UI has been
  		 * rendered so that events can be added.
  		 *
  		 * @method postRender
  		 */
  		postRender : function() {
  			var t = this, ch, changeListenerAdded = true;
  
  			t.rendered = true;
  
  			function onChange(e) {
  				var v = t.items[e.target.selectedIndex - 1];
  
  				if (v && (v = v.value)) {
  					t.onChange.dispatch(t, v);
  
  					if (t.settings.onselect)
  						t.settings.onselect(v);
  				}
  			};
  
  			Event.add(t.id, 'change', onChange);
  
  			// Accessibility keyhandler
  			Event.add(t.id, 'keydown', function(e) {
  				var bf, DOM_VK_LEFT = 37, DOM_VK_RIGHT = 39, DOM_VK_UP = 38, DOM_VK_DOWN = 40, DOM_VK_RETURN = 13, DOM_VK_SPACE = 32;
  
  				Event.remove(t.id, 'change', ch);
  				changeListenerAdded = false;
  
  				bf = Event.add(t.id, 'blur', function() {
  					if (changeListenerAdded) return;
  					changeListenerAdded = true;
  					Event.add(t.id, 'change', onChange);
  					Event.remove(t.id, 'blur', bf);
  				});
  
  				if (e.keyCode == DOM_VK_RETURN || e.keyCode == DOM_VK_SPACE) {
  					onChange(e);
  					return Event.cancel(e);
  				} else if (e.keyCode == DOM_VK_DOWN || e.keyCode == DOM_VK_UP) {
  					// allow native implementation (navigate select element options)
  					e.stopImmediatePropagation();
  				}
  			});
  
  			t.onPostRender.dispatch(t, DOM.get(t.id));
  		}
  	});
  })(tinymce);
  