# inputEx-library

### inputEx 0.5.1

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

    (function() {

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

    /**
     * Create a menu field
     * @class inputEx.MenuField
     * @extends inputEx.Field
     * @constructor
     * @param {Object} options Added options:
     * <ul>
     *    <li>typeInvite : text to display when no selection made</li>
     *	   <li>menuItems : contains descriptions of menu items</li>
     *	   <li>menuTrigger : event to trigger menu show</li>
     *    <li>menuPosition : array of corners positions (syntax : ['menu popup corner','invite div corner'])</li>
     *    <li>menuConfig (optional) : object used as a config for the YUI Menu generated by MenuField
     * </ul>
     */
    inputEx.MenuField = function(options) {
    	inputEx.MenuField.superclass.constructor.call(this,options);
    };

    lang.extend(inputEx.MenuField, inputEx.Field, {
       /**
        * Set the default values of the options
        * @param {Object} options Options object as passed to the constructor
        */
    	setOptions: function(options) {
    	   inputEx.MenuField.superclass.setOptions.call(this,options);

    	   // Overwrite options:
    	   this.options.className = options.className ? options.className : 'inputEx-Field inputEx-MenuField';

    	   // New options
    	   this.options.typeInvite = options.typeInvite || inputEx.messages.menuTypeInvite;
    	   this.options.menuTrigger = options.menuTrigger || "click";
    	   this.options.menuPosition = options.menuPosition || ["tl","tr"];
    	   this.options.menuItems = options.menuItems;

    	   // Configuration options for the generated YUI Menu instance
    	   this.options.menuConfig = options.menuConfig || {};
    	},

    	/**
        * Build a menu
        */
       renderComponent: function() {

          // Div to display the invite, then the selected text
          this.el = inputEx.cn('div', {className:'inputEx-Result'}, null, this.options.typeInvite);
          YAHOO.util.Dom.addClass(this.el, (this.options.menuPosition[1] == "tr") ? "inputEx-RightArrow" : "inputEx-DownArrow");
          this.fieldContainer.appendChild(this.el);

          // Keep selected value in a hidden field
    	   this.hiddenEl = inputEx.cn('input', {type: 'hidden', name: this.options.name || '', value: this.options.value || ''});
    	   this.fieldContainer.appendChild(this.hiddenEl);

    	   // Init Menu
    	   this.initMenu();
       },

       // Parse menuItems option to add ids, listeners, etc.
    	initMenuItems: function() {

    	   // Keep corresponding text for each value selectable in the menu
    	   //   -> will be used to display selection after click
    	   this._textFromValue = {};

    	   var that = this;

    	   /*
    	   * Recursive function to edit a level of menuItems
    	   *
    	   * args :
    	   *   -> conf : an array of menuItems
    	   *   -> level : how deeply nested are these menuItems (4 is max)
    	   */
    	   var levelInit = function (conf,level) {
    	      if (level>4) throw new Error("MenuField : too much recursion, menuItems property should be 5 level deep at most.");

    	      var item;
    	      for (var i=0, length = conf.length; i < length; i++) {
    	         item = conf[i];
                 if (YAHOO.lang.isUndefined(item.text) && !YAHOO.lang.isUndefined(item.value)) {
    	            item.text = item.value;
    	         }
    	         if (YAHOO.lang.isUndefined(item.value) && !YAHOO.lang.isUndefined(item.text)) {
    	            item.value = item.text;
    	         }

                // item with submenu
                //   -> explore deeper
    	         if (!YAHOO.lang.isUndefined(item.submenu)) {

    	            // ensure there is an id on submenu (else submenu is not created)
    	            if (YAHOO.lang.isUndefined(item.submenu.id)) {
    	               item.submenu.id = YAHOO.util.Dom.generateId();
    	            }

    	            // continue one level deeper
    	            levelInit(item.submenu.itemdata,level+1);

    	         // item without submenu
    	         //   -> add click listener to this item
    	         //   -> pass selected value to the listener (as the 3rd argument)
    	         } else {
    	            that._textFromValue[item.value] = item.text;
    	            item.onclick = {fn:function() {that.onItemClick.apply(that,arguments);},obj:item.value};
    	         }
    	      }
    	   };

    	   levelInit(this.options.menuItems,0);

    	},

       initMenu: function() {
    	   this.initMenuItems(); // edit this.options.menuItems

          this.menuContainer = inputEx.cn('div');
    	   this.fieldContainer.appendChild(this.menuContainer);

    	   var context = [this.el].concat(this.options.menuPosition);

    	   // Add generated context to the menuConfig
    	   this.options.menuConfig.context = context;

          this.menu = new YAHOO.widget.Menu(YAHOO.util.Dom.generateId(),this.options.menuConfig);
          this.menu.addItems(this.options.menuItems);
          this.menu.render(this.menuContainer);
       },

       initEvents: function() {
          this.menu.subscribe("show", this.menu.focus);

          // Listener to show menu
          YAHOO.util.Event.addListener(this.el, this.options.menuTrigger, function() {
             if (!this.menu.cfg.getProperty("visible")) {
                this.menu.align();
                this.menu.show();
             }
          }, null, this);
       },

       onItemClick: function(p_sType, p_aArgs, p_Value) {
          this.setValue(p_Value,true);
       },

       getValue: function() {
          return this.hiddenEl.value;
       },

       setValue: function(value, sendUpdatedEvt) {
          // update text
          this.el.innerHTML = this._textFromValue[value] || this.options.typeInvite;

          // set value
          this.hiddenEl.value = (!!this._textFromValue[value]) ? value : '';
    	   inputEx.MenuField.superclass.setValue.call(this,value, sendUpdatedEvt);
       }

    });

    inputEx.messages.menuTypeInvite = "Click here to select";

    // Register this class as "menu" type
    inputEx.registerType("menu", inputEx.MenuField);

    })();

Copyright © 2010 Eric Abouaf All rights reserved.