Widget-Buttons.js revision 80d53e62b2ae5fa5ab6ae4fbcfcbfd8ef5764dd7
e8721886dbfd32e88cc7077cbee4b6bb1b44b443Peter Major/**
e8721886dbfd32e88cc7077cbee4b6bb1b44b443Peter Major * Provides header/footer button support for Widgets that implement the WidgetStdMod extension
e8721886dbfd32e88cc7077cbee4b6bb1b44b443Peter Major *
e8721886dbfd32e88cc7077cbee4b6bb1b44b443Peter Major * @module widget-buttons
8b6198b1170e3128c5df83267597f0058d07c70dJames Phillpotts * @author tilomitra
e8721886dbfd32e88cc7077cbee4b6bb1b44b443Peter Major */
e8721886dbfd32e88cc7077cbee4b6bb1b44b443Peter Major
e8721886dbfd32e88cc7077cbee4b6bb1b44b443Peter Majorvar BOUNDING_BOX = "boundingBox",
e8721886dbfd32e88cc7077cbee4b6bb1b44b443Peter Major VISIBLE = "visible",
e8721886dbfd32e88cc7077cbee4b6bb1b44b443Peter Major CLICK = "click",
e8721886dbfd32e88cc7077cbee4b6bb1b44b443Peter Major RENDER_UI = "renderUI",
e8721886dbfd32e88cc7077cbee4b6bb1b44b443Peter Major BIND_UI = "bindUI",
e8721886dbfd32e88cc7077cbee4b6bb1b44b443Peter Major SYNC_UI = "syncUI",
e8721886dbfd32e88cc7077cbee4b6bb1b44b443Peter Major BTN = "button",
e8721886dbfd32e88cc7077cbee4b6bb1b44b443Peter Major BTN_CONTENT = "button-content",
e8721886dbfd32e88cc7077cbee4b6bb1b44b443Peter Major BTN_WRAPPER = "button-wrapper",
e8721886dbfd32e88cc7077cbee4b6bb1b44b443Peter Major BUTTON_CHANGE = "buttonsChange",
e8721886dbfd32e88cc7077cbee4b6bb1b44b443Peter Major getCN = Y.ClassNameManager.getClassName,
e8721886dbfd32e88cc7077cbee4b6bb1b44b443Peter Major CREATE = Y.Node.create;
e8721886dbfd32e88cc7077cbee4b6bb1b44b443Peter Major
e8721886dbfd32e88cc7077cbee4b6bb1b44b443Peter Major
e8721886dbfd32e88cc7077cbee4b6bb1b44b443Peter Major/**
e8721886dbfd32e88cc7077cbee4b6bb1b44b443Peter Major * Widget extension, which can be used to add header/footer buttons support to a widget that implements the WidgetStdMod extension,
e8721886dbfd32e88cc7077cbee4b6bb1b44b443Peter Major *
e8721886dbfd32e88cc7077cbee4b6bb1b44b443Peter Major * @class WidgetButtons
1f48f8236de7de97be1c6b9d06bef50b379c8801jenkins * @param {Object} config User configuration object
e8721886dbfd32e88cc7077cbee4b6bb1b44b443Peter Major */
e8721886dbfd32e88cc7077cbee4b6bb1b44b443Peter Majorfunction WidgetButtons(config) {
e8721886dbfd32e88cc7077cbee4b6bb1b44b443Peter Major
e8721886dbfd32e88cc7077cbee4b6bb1b44b443Peter Major Y.after(this._renderUIButtons, this, RENDER_UI);
e8721886dbfd32e88cc7077cbee4b6bb1b44b443Peter Major Y.after(this._bindUIButtons, this, BIND_UI);
e8721886dbfd32e88cc7077cbee4b6bb1b44b443Peter Major Y.after(this._syncUIButtons, this, SYNC_UI);
5ec701c9f8ccc403ee6fd3e41239df7dcd9faddeBruno Lavit
e8721886dbfd32e88cc7077cbee4b6bb1b44b443Peter Major
e8721886dbfd32e88cc7077cbee4b6bb1b44b443Peter Major}
e8721886dbfd32e88cc7077cbee4b6bb1b44b443Peter Major
e8721886dbfd32e88cc7077cbee4b6bb1b44b443Peter Major/**
e8721886dbfd32e88cc7077cbee4b6bb1b44b443Peter Major * Static property used to define the default attribute
e8721886dbfd32e88cc7077cbee4b6bb1b44b443Peter Major * configuration introduced by WidgetButtons.
e8721886dbfd32e88cc7077cbee4b6bb1b44b443Peter Major *
e8721886dbfd32e88cc7077cbee4b6bb1b44b443Peter Major * @property WidgetButtons.ATTRS
e8721886dbfd32e88cc7077cbee4b6bb1b44b443Peter Major * @type Object
e8721886dbfd32e88cc7077cbee4b6bb1b44b443Peter Major * @static
e8721886dbfd32e88cc7077cbee4b6bb1b44b443Peter Major */
e8721886dbfd32e88cc7077cbee4b6bb1b44b443Peter MajorWidgetButtons.ATTRS = {
e8721886dbfd32e88cc7077cbee4b6bb1b44b443Peter Major
e8721886dbfd32e88cc7077cbee4b6bb1b44b443Peter Major
e8721886dbfd32e88cc7077cbee4b6bb1b44b443Peter Major /**
e8721886dbfd32e88cc7077cbee4b6bb1b44b443Peter Major * @attribute buttons
e8721886dbfd32e88cc7077cbee4b6bb1b44b443Peter Major * @type {Array}
e8721886dbfd32e88cc7077cbee4b6bb1b44b443Peter Major * @default [
e8721886dbfd32e88cc7077cbee4b6bb1b44b443Peter Major {
e8721886dbfd32e88cc7077cbee4b6bb1b44b443Peter Major type: "close"
e8721886dbfd32e88cc7077cbee4b6bb1b44b443Peter Major }
e8721886dbfd32e88cc7077cbee4b6bb1b44b443Peter Major ],
e8721886dbfd32e88cc7077cbee4b6bb1b44b443Peter Major * @description <p>An array of objects, with each object corresponding to a button that you want to be added to the widget. Each button can have upto 4 properties:</p>
e8721886dbfd32e88cc7077cbee4b6bb1b44b443Peter Major *
e8721886dbfd32e88cc7077cbee4b6bb1b44b443Peter Major * <p>type: {string} Use one of the default buttons provided by the WidgetButtons class. Set this to "close" if you want the
e8721886dbfd32e88cc7077cbee4b6bb1b44b443Peter Major * [x] at the top-right corner of the window. If this key has a value, then values for the remaining properties below don't need to be provided.</p>
e8721886dbfd32e88cc7077cbee4b6bb1b44b443Peter Major *
e8721886dbfd32e88cc7077cbee4b6bb1b44b443Peter Major * <p>value: {string} HTML string or text that should be shown on the button</p>
e8721886dbfd32e88cc7077cbee4b6bb1b44b443Peter Major * <p>action: {function} The callback function that should be executed when the button is clicked.</p>
e8721886dbfd32e88cc7077cbee4b6bb1b44b443Peter Major * <p>href: {string} (optional) The link to redirect to if the button is clicked> If not supplied, defaults to "#"</p>
e8721886dbfd32e88cc7077cbee4b6bb1b44b443Peter Major * <p>section: {string || object} Whether the button should be placed in the header or footer. Represented as "header" or "footer"</p>
e8721886dbfd32e88cc7077cbee4b6bb1b44b443Peter Major */
e8721886dbfd32e88cc7077cbee4b6bb1b44b443Peter Major buttons: {
e8721886dbfd32e88cc7077cbee4b6bb1b44b443Peter Major
e8721886dbfd32e88cc7077cbee4b6bb1b44b443Peter Major value: [
e8721886dbfd32e88cc7077cbee4b6bb1b44b443Peter Major {
e8721886dbfd32e88cc7077cbee4b6bb1b44b443Peter Major type: "close"
e8721886dbfd32e88cc7077cbee4b6bb1b44b443Peter Major }
e8721886dbfd32e88cc7077cbee4b6bb1b44b443Peter Major ],
e8721886dbfd32e88cc7077cbee4b6bb1b44b443Peter Major validator: Y.Lang.isArray
e8721886dbfd32e88cc7077cbee4b6bb1b44b443Peter Major }
e8721886dbfd32e88cc7077cbee4b6bb1b44b443Peter Major
e8721886dbfd32e88cc7077cbee4b6bb1b44b443Peter Major};
e8721886dbfd32e88cc7077cbee4b6bb1b44b443Peter Major
e8721886dbfd32e88cc7077cbee4b6bb1b44b443Peter Major
e8721886dbfd32e88cc7077cbee4b6bb1b44b443Peter Major/**
e8721886dbfd32e88cc7077cbee4b6bb1b44b443Peter Major * Static hash of buttons that have all their properties defined, so that they can be used by supplying a value to the "type" property in the button attribute.
e8721886dbfd32e88cc7077cbee4b6bb1b44b443Peter Major * The "close" button is currently defined in this object (sets the [x] in the top-right of the header).
e8721886dbfd32e88cc7077cbee4b6bb1b44b443Peter Major *
a62d691262d0b1a55b3fc79eba377ac7bd1c0629jeff.schenk * @property WidgetButtons.DEFAULT_BUTTONS
e8721886dbfd32e88cc7077cbee4b6bb1b44b443Peter Major * @static
e8721886dbfd32e88cc7077cbee4b6bb1b44b443Peter Major * @type object
e8721886dbfd32e88cc7077cbee4b6bb1b44b443Peter Major */
e8721886dbfd32e88cc7077cbee4b6bb1b44b443Peter MajorWidgetButtons.DEFAULT_BUTTONS = {
e8721886dbfd32e88cc7077cbee4b6bb1b44b443Peter Major "close": {
e8721886dbfd32e88cc7077cbee4b6bb1b44b443Peter Major value:'<div style="background:url(http://yui.yahooapis.com/3.4.0pr3/build/panel/assets/skins/sam/sprite_icons.gif) no-repeat; width:13px; height:13px; background-position: 0 2px;"></div>',
e8721886dbfd32e88cc7077cbee4b6bb1b44b443Peter Major action: function(e) {
e8721886dbfd32e88cc7077cbee4b6bb1b44b443Peter Major e.preventDefault();
e8721886dbfd32e88cc7077cbee4b6bb1b44b443Peter Major this.hide();
e8721886dbfd32e88cc7077cbee4b6bb1b44b443Peter Major },
e8721886dbfd32e88cc7077cbee4b6bb1b44b443Peter Major section: Y.WidgetStdMod.HEADER
e8721886dbfd32e88cc7077cbee4b6bb1b44b443Peter Major }
e8721886dbfd32e88cc7077cbee4b6bb1b44b443Peter Major};
e8721886dbfd32e88cc7077cbee4b6bb1b44b443Peter Major
e8721886dbfd32e88cc7077cbee4b6bb1b44b443Peter Major/**
e8721886dbfd32e88cc7077cbee4b6bb1b44b443Peter Major * Static hash of default class names used for the inner <span> ("content"), the <a> ("button"), and the outer span ("wrapper")
e8721886dbfd32e88cc7077cbee4b6bb1b44b443Peter Major *
e8721886dbfd32e88cc7077cbee4b6bb1b44b443Peter Major * @property WidgetButtons.BUTTON_CLASS_NAMES
e8721886dbfd32e88cc7077cbee4b6bb1b44b443Peter Major * @static
e8721886dbfd32e88cc7077cbee4b6bb1b44b443Peter Major * @type object
e8721886dbfd32e88cc7077cbee4b6bb1b44b443Peter Major */
e8721886dbfd32e88cc7077cbee4b6bb1b44b443Peter MajorWidgetButtons.BUTTON_CLASS_NAMES = {
e8721886dbfd32e88cc7077cbee4b6bb1b44b443Peter Major button: getCN(BTN),
e8721886dbfd32e88cc7077cbee4b6bb1b44b443Peter Major content: getCN(BTN_CONTENT),
e8721886dbfd32e88cc7077cbee4b6bb1b44b443Peter Major wrapper: Y.Widget.getClassName(BTN_WRAPPER)
e8721886dbfd32e88cc7077cbee4b6bb1b44b443Peter Major};
e8721886dbfd32e88cc7077cbee4b6bb1b44b443Peter Major
e8721886dbfd32e88cc7077cbee4b6bb1b44b443Peter Major
e8721886dbfd32e88cc7077cbee4b6bb1b44b443Peter Major/**
e8721886dbfd32e88cc7077cbee4b6bb1b44b443Peter Major * <p>Object used to specify the HTML template for the buttons. Consists of the following properties</p>
e8721886dbfd32e88cc7077cbee4b6bb1b44b443Peter Major * <p>defaultTemplate: Specifies the HTML markup for each button</p>
e8721886dbfd32e88cc7077cbee4b6bb1b44b443Peter Major * <p>wrapper: Specifies the HTML markup for the wrapper, which is a DOM Element that wraps around all the buttons</p>
e8721886dbfd32e88cc7077cbee4b6bb1b44b443Peter Major *
e8721886dbfd32e88cc7077cbee4b6bb1b44b443Peter Major * @property WidgetButtons.TEMPLATES
e8721886dbfd32e88cc7077cbee4b6bb1b44b443Peter Major * @static
e8721886dbfd32e88cc7077cbee4b6bb1b44b443Peter Major * @type object
e8721886dbfd32e88cc7077cbee4b6bb1b44b443Peter Major */
e8721886dbfd32e88cc7077cbee4b6bb1b44b443Peter MajorWidgetButtons.TEMPLATES = {
e8721886dbfd32e88cc7077cbee4b6bb1b44b443Peter Major defaultTemplate: "<a href={href} class='"+WidgetButtons.BUTTON_CLASS_NAMES.button+"'><span class='"+WidgetButtons.BUTTON_CLASS_NAMES.content+"'>{value}</a>",
e8721886dbfd32e88cc7077cbee4b6bb1b44b443Peter Major wrapper: "<span class='"+WidgetButtons.BUTTON_CLASS_NAMES.wrapper+"'></span>",
e8721886dbfd32e88cc7077cbee4b6bb1b44b443Peter Major clearfix: "<div style='clear:both;'></div>"
e8721886dbfd32e88cc7077cbee4b6bb1b44b443Peter Major};
e8721886dbfd32e88cc7077cbee4b6bb1b44b443Peter Major
e8721886dbfd32e88cc7077cbee4b6bb1b44b443Peter MajorWidgetButtons.prototype = {
e8721886dbfd32e88cc7077cbee4b6bb1b44b443Peter Major // *** Instance Members *** //
e8721886dbfd32e88cc7077cbee4b6bb1b44b443Peter Major
e8721886dbfd32e88cc7077cbee4b6bb1b44b443Peter Major _hdBtnNode : null,
e8721886dbfd32e88cc7077cbee4b6bb1b44b443Peter Major _ftBtnNode : null,
e8721886dbfd32e88cc7077cbee4b6bb1b44b443Peter Major _buttonsArray : [],
e8721886dbfd32e88cc7077cbee4b6bb1b44b443Peter Major _uiHandlesButtons : [],
e8721886dbfd32e88cc7077cbee4b6bb1b44b443Peter Major
e8721886dbfd32e88cc7077cbee4b6bb1b44b443Peter Major /**
e8721886dbfd32e88cc7077cbee4b6bb1b44b443Peter Major * Creates the button nodes based on whether they are defined as being in the header or footer
e8721886dbfd32e88cc7077cbee4b6bb1b44b443Peter Major * <p>
e8721886dbfd32e88cc7077cbee4b6bb1b44b443Peter Major * This method is invoked after renderUI is invoked for the Widget class
e8721886dbfd32e88cc7077cbee4b6bb1b44b443Peter Major * using YUI's aop infrastructure.
e8721886dbfd32e88cc7077cbee4b6bb1b44b443Peter Major * </p>
e8721886dbfd32e88cc7077cbee4b6bb1b44b443Peter Major * @method _renderUIButtons
e8721886dbfd32e88cc7077cbee4b6bb1b44b443Peter Major * @protected
e8721886dbfd32e88cc7077cbee4b6bb1b44b443Peter Major */
e8721886dbfd32e88cc7077cbee4b6bb1b44b443Peter Major _renderUIButtons : function () {
e8721886dbfd32e88cc7077cbee4b6bb1b44b443Peter Major
e8721886dbfd32e88cc7077cbee4b6bb1b44b443Peter Major this._removeButtonNode(true,true);
e8721886dbfd32e88cc7077cbee4b6bb1b44b443Peter Major this._hdBtnNode = CREATE(WidgetButtons.TEMPLATES.wrapper);
e8721886dbfd32e88cc7077cbee4b6bb1b44b443Peter Major this._ftBtnNode = CREATE(WidgetButtons.TEMPLATES.wrapper);
e8721886dbfd32e88cc7077cbee4b6bb1b44b443Peter Major this._createButtons();
e8721886dbfd32e88cc7077cbee4b6bb1b44b443Peter Major
e8721886dbfd32e88cc7077cbee4b6bb1b44b443Peter Major
e8721886dbfd32e88cc7077cbee4b6bb1b44b443Peter Major
e8721886dbfd32e88cc7077cbee4b6bb1b44b443Peter Major },
e8721886dbfd32e88cc7077cbee4b6bb1b44b443Peter Major
e8721886dbfd32e88cc7077cbee4b6bb1b44b443Peter Major /**
e8721886dbfd32e88cc7077cbee4b6bb1b44b443Peter Major * Binds event listeners to listen for events on the buttons.
e8721886dbfd32e88cc7077cbee4b6bb1b44b443Peter Major * <p>
e8721886dbfd32e88cc7077cbee4b6bb1b44b443Peter Major * This method is invoked after bindUI is invoked for the Widget class
e8721886dbfd32e88cc7077cbee4b6bb1b44b443Peter Major * using YUI's aop infrastructure.
e8721886dbfd32e88cc7077cbee4b6bb1b44b443Peter Major * </p>
e8721886dbfd32e88cc7077cbee4b6bb1b44b443Peter Major * @method _bindUIButtons
e8721886dbfd32e88cc7077cbee4b6bb1b44b443Peter Major * @protected
e8721886dbfd32e88cc7077cbee4b6bb1b44b443Peter Major */
e8721886dbfd32e88cc7077cbee4b6bb1b44b443Peter Major _bindUIButtons : function () {
e8721886dbfd32e88cc7077cbee4b6bb1b44b443Peter Major
e8721886dbfd32e88cc7077cbee4b6bb1b44b443Peter Major var self = this;
e8721886dbfd32e88cc7077cbee4b6bb1b44b443Peter Major
e8721886dbfd32e88cc7077cbee4b6bb1b44b443Peter Major Y.each(this._buttonsArray, function(o) {
e8721886dbfd32e88cc7077cbee4b6bb1b44b443Peter Major self._attachEventsToButton(o);
e8721886dbfd32e88cc7077cbee4b6bb1b44b443Peter Major });
e8721886dbfd32e88cc7077cbee4b6bb1b44b443Peter Major this.after(BUTTON_CHANGE, this._afterButtonsChange);
e8721886dbfd32e88cc7077cbee4b6bb1b44b443Peter Major
e8721886dbfd32e88cc7077cbee4b6bb1b44b443Peter Major },
e8721886dbfd32e88cc7077cbee4b6bb1b44b443Peter Major
e8721886dbfd32e88cc7077cbee4b6bb1b44b443Peter Major /**
e8721886dbfd32e88cc7077cbee4b6bb1b44b443Peter Major * Binds event listeners to listen for events on the buttons
e8721886dbfd32e88cc7077cbee4b6bb1b44b443Peter Major * <p>
e8721886dbfd32e88cc7077cbee4b6bb1b44b443Peter Major * This method is invoked after bindUI is invoked for the Widget class
e8721886dbfd32e88cc7077cbee4b6bb1b44b443Peter Major * using YUI's aop infrastructure.
e8721886dbfd32e88cc7077cbee4b6bb1b44b443Peter Major * </p>
e8721886dbfd32e88cc7077cbee4b6bb1b44b443Peter Major * @method _bindUIButtons
e8721886dbfd32e88cc7077cbee4b6bb1b44b443Peter Major * @protected
8b6198b1170e3128c5df83267597f0058d07c70dJames Phillpotts */
8b6198b1170e3128c5df83267597f0058d07c70dJames Phillpotts _syncUIButtons : function () {
8b6198b1170e3128c5df83267597f0058d07c70dJames Phillpotts
8b6198b1170e3128c5df83267597f0058d07c70dJames Phillpotts if (this._hdBtnNode.hasChildNodes()) {
8b6198b1170e3128c5df83267597f0058d07c70dJames Phillpotts this.setStdModContent(Y.WidgetStdMod.HEADER, this._hdBtnNode, Y.WidgetStdMod.AFTER);
8b6198b1170e3128c5df83267597f0058d07c70dJames Phillpotts this._appendClearFix();
8b6198b1170e3128c5df83267597f0058d07c70dJames Phillpotts }
8b6198b1170e3128c5df83267597f0058d07c70dJames Phillpotts if (this._ftBtnNode.hasChildNodes()) {
921c9e8e47accb592cc0dcda4f6973aabc1935ceNeil Madden this.setStdModContent(Y.WidgetStdMod.FOOTER, this._ftBtnNode, Y.WidgetStdMod.AFTER);
921c9e8e47accb592cc0dcda4f6973aabc1935ceNeil Madden }
921c9e8e47accb592cc0dcda4f6973aabc1935ceNeil Madden
921c9e8e47accb592cc0dcda4f6973aabc1935ceNeil Madden
e8721886dbfd32e88cc7077cbee4b6bb1b44b443Peter Major
e8721886dbfd32e88cc7077cbee4b6bb1b44b443Peter Major
},
/**
* Add a button to the existing set of buttons
*
* @method _bindUIButtons
* @param button {object} The object literal consisting of the button's properties and callback function
* @public
*/
addButton: function (button) {
var btns = this.get('buttons');
btns.push(button);
this.set('buttons', btns);
},
/**
* Iterate through the buttons attribute, create Y.Node instances of each button and append them to either the _hdBtnNode or _ftBtnNode nodes.
*
* @method _createButtons
* @protected
*/
_createButtons : function () {
var btns = this.get('buttons'),
template = '',
html = '',
node,
self = this,
defBtns;
Y.each(btns, function(o) {
//Check to see if the type property is defined, and if a button corresponds to that type.
if (o.type && WidgetButtons.DEFAULT_BUTTONS[o.type]) {
o = WidgetButtons.DEFAULT_BUTTONS[o.type];
}
template = Y.Lang.sub(WidgetButtons.TEMPLATES.defaultTemplate, {
href: o.href || '#',
value: o.value
});
//create Y.Node instance of button
node = CREATE(template);
//push the node onto an array of all the buttons
self._buttonsArray.push({node: node, cb: o.action});
//append it to the wrapper node
if (o.section === Y.WidgetStdMod.HEADER) {
self._hdBtnNode.appendChild(node);
}
else if (o.section === Y.WidgetStdMod.FOOTER) {
self._ftBtnNode.appendChild(node);
}
else {
Y.log("Warning: One of the buttons did not have the specified sections property, and was not attached to the appropriate section.");
}
});
return true;
},
_appendClearFix: function () {
//if (!this.get("headerContent")) {
this.setStdModContent(Y.WidgetStdMod.HEADER, CREATE(WidgetButtons.TEMPLATES.clearfix), Y.WidgetStdMod.AFTER);
//}
},
/**
* Attaches the event listeners to execute the callback function after button click.
*
* @method _attachEventsToButton
* @protected
*/
_attachEventsToButton : function (o) {
this._uiHandlesButtons.push(o.node.after(CLICK, o.cb, this));
},
/**
* Attaches the event listeners to execute the callback function after button click.
*
* @method _attachEventsToButton
* @protected
*/
_afterButtonsChange : function (e) {
this._detachEventsFromButtons();
this._renderUIButtons();
this._bindUIButtons();
this._syncUIButtons();
},
/**
* Removes the header and footer button wrappers from the DOM if they exist
*
* @method _removeButtonNode
* @param fromHd {bool} Whether to remove the header button wrapper
* @param fromFt {bool} Whether to remove the footer button wrapper
* @protected
*/
_removeButtonNode : function(fromHd, fromFt) {
if (fromHd && this._hdBtnNode && this._hdBtnNode.hasChildNodes()) {
this._hdBtnNode.remove();
this._hdBtnNode = null;
}
if (fromFt && this._ftBtnNode && this._ftBtnNode.hasChildNodes()) {
this._ftBtnNode.remove();
this._ftBtnNode = null;
}
},
/**
* Detaches all event listeners from the buttons
*
* @method _detachEventsFromButtons
* @protected
*/
_detachEventsFromButtons : function () {
Y.each(this._uiHandlesButtons, function(h){
h.detach();
});
this._uiHandlesButtons = [];
}
}
Y.WidgetButtons = WidgetButtons;