(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);
})();