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-panel.js 12KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587
  1. AUI.add('aui-panel', function(A) {
  2. /**
  3. * The Panel Utility - Panel is a container that has specific functionality
  4. * and structural components that make it the good for building block for
  5. * application-oriented user interfaces. Panel also provides built-in
  6. * expandable and collapsible behavior, along with a variety of prebuilt tool
  7. * buttons that can be wired up to provide other customized behavior. Panels
  8. * can be easily dropped into any Container or layout.
  9. *
  10. * @module aui-panel
  11. */
  12. var Lang = A.Lang,
  13. isArray = Lang.isArray,
  14. isBoolean = Lang.isBoolean,
  15. WidgetStdMod = A.WidgetStdMod,
  16. DOC = A.config.doc,
  17. BOUNDING_BOX = 'boundingBox',
  18. COLLAPSE = 'collapse',
  19. COLLAPSED = 'collapsed',
  20. COLLAPSIBLE = 'collapsible',
  21. ICON = 'icon',
  22. ID = 'id',
  23. MINUS = 'minus',
  24. PANEL = 'panel',
  25. PLUS = 'plus',
  26. TITLE = 'title',
  27. ICONS = 'icons',
  28. USE_ARIA = 'useARIA',
  29. VISIBLE = 'visible',
  30. EMPTY_STR = '',
  31. getClassName = A.getClassName,
  32. CSS_CLEARFIX = getClassName('helper', 'clearfix'),
  33. CSS_COLLAPSED = getClassName(PANEL, COLLAPSED),
  34. CSS_PANEL = getClassName(PANEL),
  35. CSS_PANEL_HD_TEXT = getClassName(PANEL, 'hd', 'text'),
  36. CSS_PANEL_ICONS = getClassName(PANEL, 'icons'),
  37. CSS_PANELS = {
  38. body: 'bd',
  39. footer: 'ft',
  40. header: 'hd'
  41. },
  42. NODE_BLANK_TEXT = DOC.createTextNode(''),
  43. TPL_HEADER_TEXT = '<span class="' + CSS_PANEL_HD_TEXT + '"></span>';
  44. /**
  45. * <p><img src="assets/images/aui-panel/main.png"/></p>
  46. *
  47. * A base class for Panel, providing:
  48. * <ul>
  49. * <li>Widget Lifecycle (initializer, renderUI, bindUI, syncUI, destructor)</li>
  50. * <li>Built-in expandable and collapsible behavior</li>
  51. * <li>Prebuilt tool buttons that can be wired up to provide other customized behavior</li>
  52. * <li>Good for building block for application-oriented user interfaces</li>
  53. * <li>Can be easily dropped into any Container or layout</li>
  54. * </ul>
  55. *
  56. * Quick Example:<br/>
  57. *
  58. * <pre><code>var instance = new A.Panel({
  59. * collapsible: true,
  60. * collapsed: true,
  61. * headerContent: 'Panel 1',
  62. * bodyContent: 'Content'
  63. * }).render();
  64. * </code></pre>
  65. *
  66. * Check the list of <a href="Panel.html#configattributes">Configuration Attributes</a> available for
  67. * Panel.
  68. *
  69. * @class Panel
  70. * @constructor
  71. * @extends Component
  72. * @uses WidgetStdMod
  73. * @param config {Object} Object literal specifying widget configuration properties.
  74. */
  75. var Panel = function() {};
  76. /**
  77. * Static property used to define the default attribute
  78. * configuration for the Panel.
  79. *
  80. * @property Panel.ATTRS
  81. * @type Object
  82. * @static
  83. */
  84. Panel.ATTRS = {
  85. bodyContent: {
  86. value: EMPTY_STR
  87. },
  88. /**
  89. * Whether the panel is displayed collapsed.
  90. *
  91. * @attribute collapsed
  92. * @default false
  93. * @type boolean
  94. */
  95. collapsed: {
  96. value: false,
  97. validator: isBoolean
  98. },
  99. /**
  100. * Whether the panel is able to be collapsed.
  101. *
  102. * @attribute collapsible
  103. * @default false
  104. * @type boolean
  105. */
  106. collapsible: {
  107. value: false,
  108. validator: isBoolean
  109. },
  110. headerContent: {
  111. value: EMPTY_STR
  112. },
  113. /**
  114. * The title to be displayed on the Panel.
  115. *
  116. * @attribute title
  117. * @default ''
  118. * @type Boolean | String
  119. */
  120. title: {
  121. value: '',
  122. validator: function(v) {
  123. return Lang.isString(v) || isBoolean(v);
  124. }
  125. },
  126. /**
  127. * <p>Array of <a href="ButtonItem.html">ButtonItem</a> configuration objects to be displayed as icons
  128. * on the Panel title.</p>
  129. *
  130. * Example:
  131. *
  132. * <pre><code>icons: [ { icon: 'close', id: 'close' } ]</code></pre>
  133. *
  134. * For more information how to use this option see
  135. * <a href="ButtonItem.html">ButtonItem</a>.
  136. *
  137. * @attribute icons
  138. * @default []
  139. * @type Array
  140. */
  141. icons: {
  142. value: [],
  143. validator: isArray
  144. },
  145. /**
  146. * @attribute strings
  147. * @description Collection of strings used to label elements of the Panel's UI.
  148. * @default null
  149. * @type Object
  150. */
  151. strings: {
  152. value: {
  153. toggle: 'Toggle collapse'
  154. }
  155. },
  156. /**
  157. * True if Panel should use ARIA plugin
  158. *
  159. * @attribute useARIA
  160. * @default true
  161. * @type Boolean
  162. */
  163. useARIA: {
  164. value: true
  165. }
  166. };
  167. Panel.prototype = {
  168. /**
  169. * Construction logic executed during Panel instantiation. Lifecycle.
  170. *
  171. * @method initializer
  172. * @protected
  173. */
  174. initializer: function(config) {
  175. var instance = this;
  176. instance.after('collapsedChange', instance._afterCollapsedChange);
  177. instance.after('render', instance._afterPanelRender);
  178. instance.after('titleChange', instance._afterTitleChange);
  179. },
  180. /**
  181. * Refreshes the rendered UI, based on Widget State
  182. *
  183. * @method syncUI
  184. * @protected
  185. *
  186. */
  187. syncUI: function() {
  188. var instance = this;
  189. if (instance.get(USE_ARIA)) {
  190. instance.plug(A.Plugin.Aria, {
  191. after: {
  192. processAttribute: function(event) {
  193. var instance = this;
  194. var host = instance.get('host');
  195. if (event.aria.attrName == COLLAPSED) {
  196. var collapsed = host.get(COLLAPSED);
  197. if (host.icons) {
  198. var icons = host.icons;
  199. var collapseItem = icons.item(COLLAPSE);
  200. if (collapseItem) {
  201. instance.setAttribute(
  202. 'pressed',
  203. collapsed,
  204. collapseItem.get(BOUNDING_BOX)
  205. );
  206. }
  207. }
  208. instance.setAttribute(
  209. 'hidden',
  210. collapsed,
  211. host.bodyNode
  212. );
  213. event.halt();
  214. }
  215. }
  216. },
  217. attributes: {
  218. collapsed: 'hidden'
  219. }
  220. });
  221. }
  222. },
  223. /**
  224. * Collapse the panel setting the
  225. * <a href="Panel.html#config_collapsed">collapsed</a> attribute to
  226. * <code>true</code>.
  227. *
  228. * @method collapse
  229. */
  230. collapse: function() {
  231. var instance = this;
  232. instance.set(COLLAPSED, true);
  233. },
  234. /**
  235. * Expand the panel setting the
  236. * <a href="Panel.html#config_collapsed">collapsed</a> attribute to
  237. * <code>false</code>.
  238. *
  239. * @method expand
  240. */
  241. expand: function() {
  242. var instance = this;
  243. instance.set(COLLAPSED, false);
  244. },
  245. /**
  246. * Toggle the visibility of the Panel toggling the value of the
  247. * <a href="Widget.html#config_visible">visible</a> attribute.
  248. *
  249. * @method toggle
  250. */
  251. toggle: function() {
  252. var instance = this;
  253. instance.set(
  254. VISIBLE,
  255. !instance.get(VISIBLE)
  256. );
  257. },
  258. /**
  259. * Toggle the <a href="Panel.html#config_collapsed">collapsed</a> value.
  260. * Expanding and collapsing the Panel.
  261. *
  262. * @method toggleCollapse
  263. */
  264. toggleCollapse: function() {
  265. var instance = this;
  266. if (instance.get(COLLAPSED)) {
  267. instance.expand();
  268. }
  269. else {
  270. instance.collapse();
  271. }
  272. },
  273. /**
  274. * Add css classes neede for the Panel in the passed <code>section</code>.
  275. *
  276. * @method _addPanelClass
  277. * @param {String} section <a href="WidgetStdMod.html">WidgetStdMod</a> section (i.e., body, header, footer).
  278. * @protected
  279. */
  280. _addPanelClass: function(section) {
  281. var instance = this;
  282. var sectionNode = instance[section + 'Node'];
  283. if (sectionNode) {
  284. var rootCssClass = CSS_PANELS[section];
  285. var cssClassMod = getClassName(PANEL, rootCssClass);
  286. // using instance.name to add the correct component name
  287. // when Panel is used to build another component using A.build
  288. var instanceName = instance.name;
  289. var cssClass = getClassName(instanceName, rootCssClass);
  290. sectionNode.addClass(cssClassMod);
  291. sectionNode.addClass(cssClass);
  292. }
  293. },
  294. /**
  295. * Render the <a href="Panel.html#config_icons">icons</a>.
  296. *
  297. * @method _renderIconButtons
  298. * @protected
  299. */
  300. _renderIconButtons: function() {
  301. var instance = this;
  302. var icons = instance.get(ICONS);
  303. if (instance.get(COLLAPSIBLE)) {
  304. var icon = instance.get(COLLAPSED) ? PLUS : MINUS;
  305. icons.unshift(
  306. {
  307. icon: icon,
  308. id: COLLAPSE,
  309. handler: {
  310. fn: instance.toggleCollapse,
  311. context: instance
  312. },
  313. title: instance.get('strings').toggle
  314. }
  315. );
  316. }
  317. instance.icons = new A.Toolbar(
  318. {
  319. children: icons
  320. }
  321. )
  322. .render(instance.headerNode);
  323. var toolbarBoundingBox = instance.icons.get(BOUNDING_BOX);
  324. toolbarBoundingBox.addClass(CSS_PANEL_ICONS);
  325. instance.setStdModContent(WidgetStdMod.HEADER, toolbarBoundingBox, WidgetStdMod.BEFORE);
  326. },
  327. /**
  328. * Render the Panel header text with the value of
  329. * <a href="Panel.html#config_title">title</a>.
  330. *
  331. * @method _renderHeaderText
  332. * @protected
  333. */
  334. _renderHeaderText: function() {
  335. var instance = this;
  336. /**
  337. * Stores the created node for the header of the Panel.
  338. *
  339. * @property headerTextNode
  340. * @type Node
  341. * @protected
  342. */
  343. instance.headerTextNode = A.Node.create(TPL_HEADER_TEXT).addClass(CSS_PANEL_HD_TEXT);
  344. if (!instance.get(TITLE)) {
  345. instance.set(TITLE, instance.headerNode.html());
  346. }
  347. instance.setStdModContent(WidgetStdMod.HEADER, EMPTY_STR);
  348. instance._syncTitleUI();
  349. },
  350. /**
  351. * Sync the UI for the collapsed status (i.e., icons, height etc).
  352. *
  353. * @method _syncCollapsedUI
  354. * @protected
  355. */
  356. _syncCollapsedUI: function() {
  357. var instance = this;
  358. if (instance.get(COLLAPSIBLE)) {
  359. var bodyNode = instance.bodyNode;
  360. var boundingBox = instance.get(BOUNDING_BOX);
  361. var collapsed = instance.get(COLLAPSED);
  362. if (instance.icons) {
  363. var icons = instance.icons;
  364. var collapseItem = icons.item(COLLAPSE);
  365. if (collapseItem) {
  366. collapseItem.set(
  367. ICON,
  368. collapsed ? PLUS : MINUS
  369. );
  370. }
  371. }
  372. if (collapsed) {
  373. bodyNode.hide();
  374. boundingBox.addClass(CSS_COLLAPSED);
  375. }
  376. else {
  377. bodyNode.show();
  378. boundingBox.removeClass(CSS_COLLAPSED);
  379. }
  380. }
  381. },
  382. /**
  383. * Sync the
  384. * <a href="Panel.html#property_headerTextNode">headerTextNode</a> with the
  385. * value of the <a href="Panel.html#config_title">title</a>.
  386. *
  387. * @method _syncTitleUI
  388. * @protected
  389. */
  390. _syncTitleUI: function() {
  391. var instance = this;
  392. var headerTextNode = instance.headerTextNode;
  393. var title = instance.get(TITLE);
  394. headerTextNode.html(title);
  395. instance.setStdModContent(WidgetStdMod.HEADER, headerTextNode, WidgetStdMod.BEFORE);
  396. },
  397. /**
  398. * Fires after the value of
  399. * <a href="Panel.html#config_collapsed">collapsed</a> change.
  400. *
  401. * @method _afterCollapsedChange
  402. * @param {EventFacade} event
  403. * @protected
  404. */
  405. _afterCollapsedChange: function(event) {
  406. var instance = this;
  407. instance._syncCollapsedUI();
  408. },
  409. /**
  410. * Fires after render phase.
  411. *
  412. * @method _afterPanelRender
  413. * @param {EventFacade} event
  414. * @protected
  415. */
  416. _afterPanelRender: function(event) {
  417. var instance = this;
  418. instance.headerNode.addClass(CSS_CLEARFIX);
  419. instance._addPanelClass('body');
  420. instance._addPanelClass('footer');
  421. instance._addPanelClass('header');
  422. instance._renderHeaderText();
  423. instance._renderIconButtons();
  424. instance.get('contentBox').setAttribute('role', 'tablist');
  425. instance._syncCollapsedUI();
  426. instance._setDefaultARIAValues();
  427. },
  428. /**
  429. * Fires after the value of
  430. * <a href="Panel.html#config_title">title</a> change.
  431. *
  432. * @method _afterTitleChange
  433. * @param {EventFacade} event
  434. * @protected
  435. */
  436. _afterTitleChange: function(event) {
  437. var instance = this;
  438. instance._syncTitleUI();
  439. },
  440. /**
  441. * Set default ARIA roles and attributes.
  442. * @method _setDefaultARIAValues
  443. * @protected
  444. */
  445. _setDefaultARIAValues: function() {
  446. var instance = this;
  447. if (!instance.get(USE_ARIA)) {
  448. return;
  449. }
  450. var headerNode = instance.headerNode;
  451. var headerNodeId = headerNode.generateID();
  452. var bodyNode = instance.bodyNode;
  453. var bodyNodeId = bodyNode.generateID();
  454. var ariaRoles = [
  455. {
  456. name: 'tab',
  457. node: headerNode
  458. },
  459. {
  460. name: 'tabpanel',
  461. node: bodyNode
  462. }
  463. ];
  464. instance.aria.setRoles(ariaRoles);
  465. var ariaAttributes = [
  466. {
  467. name: 'controls',
  468. value: bodyNodeId,
  469. node: headerNode
  470. },
  471. {
  472. name: 'labelledby',
  473. value: headerNodeId,
  474. node: bodyNode
  475. },
  476. {
  477. name: 'describedby',
  478. value: headerNodeId,
  479. node: bodyNode
  480. }
  481. ];
  482. if (instance.icons) {
  483. var collapseItem = instance.icons.item(COLLAPSE);
  484. if (collapseItem) {
  485. ariaAttributes.push(
  486. {
  487. name: 'controls',
  488. value: bodyNodeId,
  489. node: collapseItem.get(BOUNDING_BOX)
  490. }
  491. );
  492. }
  493. }
  494. instance.aria.setAttributes(ariaAttributes);
  495. }
  496. }
  497. A.Panel = A.Component.build(PANEL, A.Component, [A.WidgetStdMod, Panel]);
  498. }, '@VERSION@' ,{requires:['aui-component','widget-stdmod','aui-toolbar','aui-aria'], skinnable:true});