Dashboard sipadu mbip
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

aui-button-item-debug.js 14KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636
  1. AUI.add('aui-button-item', function(A) {
  2. /**
  3. * The ButtonItem Utility
  4. *
  5. * @module aui-button-item
  6. */
  7. var Lang = A.Lang,
  8. isString = Lang.isString,
  9. getClassName = A.getClassName,
  10. NAME = 'buttonitem',
  11. BOUNDING_BOX = 'boundingBox',
  12. BUTTON = 'button',
  13. CONTENT_BOX = 'contentBox',
  14. DOT = '.',
  15. HANDLER = 'handler',
  16. ICON = 'icon',
  17. ICON_NODE = 'iconNode',
  18. LABEL = 'label',
  19. LABEL_NODE = 'labelNode',
  20. ONLY = 'only',
  21. RESET = 'reset',
  22. STATE = 'state',
  23. SUBMIT = 'submit',
  24. TITLE = 'title',
  25. TYPE = 'type',
  26. CSS_BUTTON = getClassName(NAME),
  27. CSS_BUTTON_ICON = getClassName(NAME, ICON),
  28. CSS_BUTTON_LABEL = getClassName(NAME, LABEL),
  29. CSS_BUTTON_ICON_LABEL = getClassName(NAME, ICON, LABEL),
  30. CSS_BUTTON_ICON_ONLY = getClassName(NAME, ICON, ONLY),
  31. CSS_BUTTON_LABEL_ONLY = getClassName(NAME, LABEL, ONLY),
  32. CSS_ICON = getClassName(ICON),
  33. REGEX_ICON = new RegExp(CSS_ICON + '-([a-zA-Z0-9-]+)'),
  34. TPL_BUTTON = '<button type="{0}"></button>',
  35. TPL_ICON = '<span class="' + [CSS_BUTTON_ICON, CSS_ICON].join(' ') + '"></span>',
  36. TPL_LABEL = '<span class="' + CSS_BUTTON_LABEL + '"></span>';
  37. /**
  38. * A base class for ButtonItem, providing:
  39. * <ul>
  40. * <li>Widget Lifecycle (initializer, renderUI, bindUI, syncUI, destructor)</li>
  41. * <li>An optional icon or label</li>
  42. * <li>Managed user interaction states (default, active, hover)</li>
  43. * <li>Keyboard accessible</li>
  44. * </ul>
  45. *
  46. * Quick Example:<br/>
  47. *
  48. * <pre><code>var instance = new A.ButtonItem({
  49. * icon: 'gear',
  50. * label: 'Configuration'
  51. * }).render();
  52. * </code></pre>
  53. *
  54. * Check the list of <a href="ButtonItem.html#configattributes">Configuration Attributes</a> available for
  55. * ButtonItem.
  56. *
  57. * @param config {Object} Object literal specifying widget configuration properties.
  58. *
  59. * @class ButtonItem
  60. * @constructor
  61. * @extends Component
  62. * @uses WidgetChild
  63. */
  64. var ButtonItem = A.Component.create(
  65. {
  66. /**
  67. * Static property provides a string to identify the class.
  68. *
  69. * @property ButtonItem.NAME
  70. * @type String
  71. * @static
  72. */
  73. NAME: NAME,
  74. /**
  75. * Static property provides an array to specify which classes augment this one.
  76. *
  77. * @property ButtonItem.AUGMENTS
  78. * @type array
  79. * @static
  80. */
  81. AUGMENTS: [A.WidgetChild],
  82. /**
  83. * Static property used to define the default attribute
  84. * configuration for the ButtonItem.
  85. *
  86. * @property ButtonItem.ATTRS
  87. * @type Object
  88. * @static
  89. */
  90. ATTRS: {
  91. /**
  92. * Whether to track the active state of the button.
  93. *
  94. * @attribute activeState
  95. * @default false
  96. * @type Boolean
  97. */
  98. activeState: {
  99. value: false
  100. },
  101. /**
  102. * An object map of the CSS class names to use for the different interaction states.
  103. *
  104. * @attribute classNames
  105. * @type Object
  106. */
  107. classNames: {},
  108. /**
  109. * Whether to apply the default interaction state to the button
  110. *
  111. * @attribute defaultState
  112. * @default true
  113. * @type Boolean
  114. */
  115. defaultState: {},
  116. /**
  117. * An event callback to handle when a user interacts with the button.
  118. * This can either be a function that will be attached on click, or
  119. * an object map that accepts the following keys:
  120. * <code>{fn: // The function to execute
  121. * context: // The context to execute the function in
  122. * type: // The type of event to listen for (defaults to "click")
  123. * }</code>
  124. *
  125. * @attribute handler
  126. * @default false
  127. * @type Function | Object
  128. */
  129. handler: {
  130. lazyAdd: false,
  131. value: null
  132. },
  133. /**
  134. * Whether to track the hover interaction state of the button.
  135. *
  136. * @attribute hoverState
  137. * @default true
  138. * @type Boolean
  139. */
  140. hoverState: {},
  141. /**
  142. * The icon to use inside of the button. Possible values are:
  143. *
  144. * @attribute icon
  145. * @type String
  146. */
  147. icon: {
  148. value: ''
  149. },
  150. /**
  151. * DOM Node to display the icon of the ButtonItem. If not
  152. * specified try to query using HTML_PARSER an element inside
  153. * boundingBox which matches <code>aui-button-icon</code>.
  154. *
  155. * @attribute iconNode
  156. * @default Generated div element.
  157. * @type String
  158. */
  159. iconNode: {
  160. valueFn: function() {
  161. return A.Node.create(TPL_ICON);
  162. }
  163. },
  164. /**
  165. * An id that can be used to identify a button.
  166. *
  167. * @attribute hoverState
  168. * @type Boolean
  169. */
  170. id: {
  171. valueFn: function() {
  172. return A.guid();
  173. }
  174. },
  175. /**
  176. * Text to use inside of the button.
  177. *
  178. * @attribute label
  179. * @type String
  180. */
  181. label: {
  182. value: ''
  183. },
  184. /**
  185. * DOM Node to display the text of the ButtonItem. If not
  186. * specified try to query using HTML_PARSER an element inside
  187. * boundingBox which matches <code>aui-button-label</code>.
  188. *
  189. * @attribute labelNode
  190. * @default Generated div element.
  191. * @type String
  192. */
  193. labelNode: {
  194. valueFn: function() {
  195. return A.Node.create(TPL_LABEL);
  196. }
  197. },
  198. /**
  199. * Text to use as the title attribute of the button.
  200. *
  201. * @attribute title
  202. * @type String
  203. */
  204. title: {
  205. setter: '_setTitle',
  206. value: false
  207. },
  208. /**
  209. * Button type.
  210. *
  211. * @attribute type
  212. * @default button
  213. * @type String
  214. */
  215. type: {
  216. validator: function(val) {
  217. return (val === BUTTON || val === SUBMIT || val === RESET);
  218. },
  219. value: BUTTON
  220. }
  221. },
  222. /**
  223. * Object hash, defining how attribute values are to be parsed from
  224. * markup contained in the widget's content box.
  225. *
  226. * @property ButtonItem.HTML_PARSER
  227. * @type Object
  228. * @static
  229. */
  230. HTML_PARSER: {
  231. iconNode: function(srcNode) {
  232. return srcNode.one(DOT+CSS_BUTTON_ICON);
  233. },
  234. labelNode: function(srcNode) {
  235. return srcNode.one(DOT+CSS_BUTTON_LABEL);
  236. },
  237. icon: function(srcNode) {
  238. var iconNode = srcNode.one(DOT+CSS_BUTTON_ICON);
  239. if (iconNode) {
  240. this.set(ICON_NODE, iconNode);
  241. var cssClass = iconNode.attr('class');
  242. var match = cssClass.match(REGEX_ICON);
  243. return match && match[1];
  244. }
  245. },
  246. label: function(srcNode) {
  247. var labelNode = srcNode.one(DOT+CSS_BUTTON_LABEL);
  248. if (labelNode) {
  249. this.set(LABEL_NODE, labelNode);
  250. return labelNode.text();
  251. }
  252. }
  253. },
  254. constructor: function(config) {
  255. var instance = this;
  256. var buttonType = 'button';
  257. if (config) {
  258. if (isString(config)) {
  259. config = {
  260. icon: config
  261. };
  262. }
  263. else if (config.type) {
  264. buttonType = config.type;
  265. }
  266. }
  267. instance.BOUNDING_TEMPLATE = Lang.sub(TPL_BUTTON, [buttonType]);
  268. ButtonItem.superclass.constructor.call(instance, config);
  269. },
  270. UI_ATTRS: [HANDLER, ICON, LABEL, TITLE, TYPE],
  271. prototype: {
  272. BOUNDING_TEMPLATE: TPL_BUTTON,
  273. CONTENT_TEMPLATE: null,
  274. /**
  275. * Create the DOM structure for the ButtonItem. Lifecycle.
  276. *
  277. * @method renderUI
  278. * @protected
  279. */
  280. renderUI: function() {
  281. var instance = this;
  282. instance._renderStates();
  283. instance._renderIconNode();
  284. instance._renderLabelNode();
  285. },
  286. /**
  287. * Sync the ButtonItem UI. Lifecycle.
  288. *
  289. * @method syncUI
  290. * @protected
  291. */
  292. syncUI: function() {
  293. var instance = this;
  294. var icon = instance.get('icon');
  295. var label = instance.get('label');
  296. var title = instance.get('title');
  297. if (icon) {
  298. instance._uiSetIcon(icon);
  299. }
  300. if (label) {
  301. instance._uiSetLabel(label);
  302. }
  303. if (title) {
  304. instance._uiSetTitle(title);
  305. }
  306. },
  307. /**
  308. * Renders the underlying markup for the <a href="ButtonItem.html#config_icon">icon</a>.
  309. *
  310. * @method _renderIconNode
  311. * @protected
  312. * @return {Node}
  313. */
  314. _renderIconNode: function() {
  315. var instance = this;
  316. instance.get(CONTENT_BOX).append(
  317. instance.get(ICON_NODE)
  318. );
  319. },
  320. /**
  321. * Renders the underlying markup for the <a href="ButtonItem.html#config_label">label</a>.
  322. *
  323. * @method _renderLabelNode
  324. * @protected
  325. * @return {Node}
  326. */
  327. _renderLabelNode: function() {
  328. var instance = this;
  329. instance.get(CONTENT_BOX).append(
  330. instance.get(LABEL_NODE)
  331. );
  332. },
  333. /**
  334. * Retrieves the state value from either the current instance, or if defined, the
  335. * parent widget.
  336. *
  337. * @method _getState
  338. * @param {String} key The state name to retrieve
  339. * @param {Object} parent The parent widget to attempt to retrieve the state from
  340. * @protected
  341. * @return {Object}
  342. */
  343. _getState: function(key, parent) {
  344. var instance = this;
  345. var value = instance.get(key);
  346. var state = value;
  347. if (parent) {
  348. value = parent.get(key);
  349. if (!Lang.isUndefined(value)) {
  350. state = value;
  351. }
  352. }
  353. return state;
  354. },
  355. /**
  356. * Attaches state interaction management to the widget.
  357. *
  358. * @method _renderStates
  359. * @param {EventFacade} event
  360. * @protected
  361. */
  362. _renderStates: function(event) {
  363. var instance = this;
  364. var parent = instance.get('parent');
  365. var activeState = instance._getState('activeState', parent);
  366. var classNames = instance._getState('classNames', parent);
  367. var defaultState = instance._getState('defaultState', parent);
  368. var hoverState = instance._getState('hoverState', parent);
  369. instance.plug(
  370. A.Plugin.StateInteraction,
  371. {
  372. activeState: activeState,
  373. classNames: classNames,
  374. defaultState: defaultState,
  375. hoverState: hoverState
  376. }
  377. );
  378. },
  379. /**
  380. * Setter for the title attribute
  381. *
  382. * @method _setTitle
  383. * @protected
  384. */
  385. _setTitle: function(value) {
  386. var instance = this;
  387. if (value === null) {
  388. value = instance.get('label');
  389. }
  390. else if (value === false) {
  391. value = '';
  392. }
  393. return String(value);
  394. },
  395. /**
  396. * Syncs the boundingBox class names to reflect whether the children only have icons or labels or both.
  397. *
  398. * @method _syncChildrenStates
  399. * @protected
  400. */
  401. _syncChildrenStates: function() {
  402. var instance = this;
  403. var icon = instance.get('icon');
  404. var label = instance.get('label');
  405. var hasIconAndLabel = (icon && label);
  406. var hasLabelOnly = (!icon && label);
  407. var hasIconOnly = (icon && !label);
  408. var boundingBox = instance.get(BOUNDING_BOX);
  409. boundingBox.toggleClass(CSS_BUTTON_ICON_LABEL, hasIconAndLabel);
  410. boundingBox.toggleClass(CSS_BUTTON_ICON_ONLY, hasIconOnly);
  411. boundingBox.toggleClass(CSS_BUTTON_LABEL_ONLY, hasLabelOnly);
  412. },
  413. _uiSetDisabled: function(val) {
  414. var instance = this;
  415. var boundingBox = instance.get(BOUNDING_BOX);
  416. if (val) {
  417. boundingBox.attr('disabled', 'disabled');
  418. }
  419. else {
  420. boundingBox.removeAttribute('disabled');
  421. }
  422. A.ButtonItem.superclass._uiSetDisabled.apply(instance, arguments);
  423. },
  424. /**
  425. * Updates the UI for the icon in response to the <a href="ButtonItem.html#event_HandlerChange">Handler</a> event.
  426. *
  427. * @method _uiSetHandler
  428. * @param {String} val Handler name
  429. * @protected
  430. */
  431. _uiSetHandler: function(value) {
  432. var instance = this;
  433. var fn = value;
  434. var parent = instance.get('parent');
  435. var context = (parent && parent._DEFAULT_CONTEXT) || instance._DEFAULT_CONTEXT || instance;
  436. var type = 'click';
  437. var args = instance;
  438. var customArgs;
  439. if (Lang.isObject(fn)) {
  440. var handlerConfig = fn;
  441. fn = handlerConfig.fn || fn;
  442. context = handlerConfig.context || context;
  443. type = handlerConfig.type || type;
  444. customArgs = handlerConfig.args;
  445. }
  446. if (Lang.isFunction(fn)) {
  447. var interactionHandle = instance._interactionHandle;
  448. if (interactionHandle) {
  449. interactionHandle.detach();
  450. }
  451. var boundFn = A.rbind.apply(A, [fn, context, args].concat(customArgs || []));
  452. instance._interactionHandle = instance.on(
  453. type,
  454. function() {
  455. if (!instance.get('disabled')) {
  456. boundFn.apply(this, arguments);
  457. }
  458. }
  459. );
  460. }
  461. },
  462. /**
  463. * Updates the UI for the icon in response to the <a href="ButtonItem.html#event_iconChange">iconChange</a> event.
  464. *
  465. * @method _uiSetIcon
  466. * @param {String} val Icon name
  467. * @protected
  468. */
  469. _uiSetIcon: function(val) {
  470. var instance = this;
  471. var iconNode = instance.get(ICON_NODE);
  472. var action = 'show';
  473. if (!val) {
  474. action = 'hide';
  475. }
  476. val = getClassName(ICON, val);
  477. iconNode.replaceClass(instance._iconPrevVal, val);
  478. iconNode[action]();
  479. instance._syncChildrenStates();
  480. instance._iconPrevVal = val;
  481. },
  482. /**
  483. * Updates the UI for the label in response to the <a href="ButtonItem.html#event_labelChange">labelChange</a> event.
  484. *
  485. * @method _uiSetLabel
  486. * @param {String} val The new value
  487. * @protected
  488. */
  489. _uiSetLabel: function(val) {
  490. var instance = this;
  491. var labelNode = instance.get(LABEL_NODE);
  492. var action = 'show';
  493. if (!val) {
  494. action = 'hide';
  495. }
  496. labelNode.text(val);
  497. labelNode[action]();
  498. instance._syncChildrenStates();
  499. },
  500. /**
  501. * Updates the UI for the title in response to the <a href="ButtonItem.html#event_titleChange">titleChange</a> event.
  502. *
  503. * @method _uiSetTitle
  504. * @param {String} val The new value
  505. * @protected
  506. */
  507. _uiSetTitle: function(val) {
  508. var instance = this;
  509. var boundingBox = instance.get(BOUNDING_BOX);
  510. boundingBox.setAttribute(TITLE, val);
  511. },
  512. /**
  513. * Updates the UI for the type in response to the <a href="ButtonItem.html#event_typeChange">typeChange</a> event.
  514. *
  515. * @method _uiSetType
  516. * @param {String} val The new value
  517. * @protected
  518. */
  519. _uiSetType: function(val) {
  520. var instance = this;
  521. var boundingBox = instance.get(BOUNDING_BOX);
  522. boundingBox.setAttribute(TYPE, val);
  523. }
  524. }
  525. }
  526. );
  527. A.ButtonItem = ButtonItem;
  528. }, '@VERSION@' ,{requires:['aui-base','aui-state-interaction','widget-child'], skinnable:true});