/hippo/src/main/webapp/ext/pkgs/pkg-toolbars-debug.js

http://hdbc.googlecode.com/ · JavaScript · 1374 lines · 705 code · 94 blank · 575 comment · 131 complexity · d44e9adbaa65786f594ca1e021ac1f46 MD5 · raw file

  1. /*!
  2. * Ext JS Library 3.0.0
  3. * Copyright(c) 2006-2009 Ext JS, LLC
  4. * licensing@extjs.com
  5. * http://www.extjs.com/license
  6. */
  7. /**
  8. * @class Ext.layout.ToolbarLayout
  9. * @extends Ext.layout.ContainerLayout
  10. * Layout manager implicitly used by Ext.Toolbar.
  11. */
  12. Ext.layout.ToolbarLayout = Ext.extend(Ext.layout.ContainerLayout, {
  13. monitorResize : true,
  14. triggerWidth : 18,
  15. lastOverflow : false,
  16. noItemsMenuText : '<div class="x-toolbar-no-items">(None)</div>',
  17. // private
  18. onLayout : function(ct, target){
  19. if(!this.leftTr){
  20. target.addClass('x-toolbar-layout-ct');
  21. target.insertHtml('beforeEnd',
  22. '<table cellspacing="0" class="x-toolbar-ct"><tbody><tr><td class="x-toolbar-left" align="left"><table cellspacing="0"><tbody><tr class="x-toolbar-left-row"></tr></tbody></table></td><td class="x-toolbar-right" align="right"><table cellspacing="0" class="x-toolbar-right-ct"><tbody><tr><td><table cellspacing="0"><tbody><tr class="x-toolbar-right-row"></tr></tbody></table></td><td><table cellspacing="0"><tbody><tr class="x-toolbar-extras-row"></tr></tbody></table></td></tr></tbody></table></td></tr></tbody></table>');
  23. this.leftTr = target.child('tr.x-toolbar-left-row', true);
  24. this.rightTr = target.child('tr.x-toolbar-right-row', true);
  25. this.extrasTr = target.child('tr.x-toolbar-extras-row', true);
  26. }
  27. var side = this.leftTr;
  28. var pos = 0;
  29. var items = ct.items.items;
  30. for(var i = 0, len = items.length, c; i < len; i++, pos++) {
  31. c = items[i];
  32. if(c.isFill){
  33. side = this.rightTr;
  34. pos = -1;
  35. }else if(!c.rendered){
  36. c.render(this.insertCell(c, side, pos));
  37. }else{
  38. if(!c.xtbHidden && !this.isValidParent(c, side.childNodes[pos])){
  39. var td = this.insertCell(c, side, pos);
  40. td.appendChild(c.getDomPositionEl().dom);
  41. c.container = Ext.get(td);
  42. }
  43. }
  44. }
  45. //strip extra empty cells
  46. this.cleanup(this.leftTr);
  47. this.cleanup(this.rightTr);
  48. this.cleanup(this.extrasTr);
  49. this.fitToSize(target);
  50. },
  51. cleanup : function(row){
  52. var cn = row.childNodes;
  53. for(var i = cn.length-1, c; i >= 0 && (c = cn[i]); i--){
  54. if(!c.firstChild){
  55. row.removeChild(c);
  56. }
  57. }
  58. },
  59. insertCell : function(c, side, pos){
  60. var td = document.createElement('td');
  61. td.className='x-toolbar-cell';
  62. side.insertBefore(td, side.childNodes[pos]||null);
  63. return td;
  64. },
  65. hideItem : function(item){
  66. var h = (this.hiddens = this.hiddens || []);
  67. h.push(item);
  68. item.xtbHidden = true;
  69. item.xtbWidth = item.getDomPositionEl().dom.parentNode.offsetWidth;
  70. item.hide();
  71. },
  72. unhideItem : function(item){
  73. item.show();
  74. item.xtbHidden = false;
  75. this.hiddens.remove(item);
  76. if(this.hiddens.length < 1){
  77. delete this.hiddens;
  78. }
  79. },
  80. getItemWidth : function(c){
  81. return c.hidden ? (c.xtbWidth || 0) : c.getDomPositionEl().dom.parentNode.offsetWidth;
  82. },
  83. fitToSize : function(t){
  84. if(this.container.enableOverflow === false){
  85. return;
  86. }
  87. var w = t.dom.clientWidth;
  88. var lw = this.lastWidth || 0;
  89. this.lastWidth = w;
  90. var iw = t.dom.firstChild.offsetWidth;
  91. var clipWidth = w - this.triggerWidth;
  92. var hideIndex = -1;
  93. if(iw > w || (this.hiddens && w >= lw)){
  94. var i, items = this.container.items.items, len = items.length, c;
  95. var loopWidth = 0;
  96. for(i = 0; i < len; i++) {
  97. c = items[i];
  98. if(!c.isFill){
  99. loopWidth += this.getItemWidth(c);
  100. if(loopWidth > clipWidth){
  101. if(!c.xtbHidden){
  102. this.hideItem(c);
  103. }
  104. }else{
  105. if(c.xtbHidden){
  106. this.unhideItem(c);
  107. }
  108. }
  109. }
  110. }
  111. }
  112. if(this.hiddens){
  113. this.initMore();
  114. if(!this.lastOverflow){
  115. this.container.fireEvent('overflowchange', this.container, true);
  116. this.lastOverflow = true;
  117. }
  118. }else if(this.more){
  119. this.clearMenu();
  120. this.more.destroy();
  121. delete this.more;
  122. if(this.lastOverflow){
  123. this.container.fireEvent('overflowchange', this.container, false);
  124. this.lastOverflow = false;
  125. }
  126. }
  127. },
  128. createMenuConfig : function(c, hideOnClick){
  129. var cfg = Ext.apply({}, c.initialConfig),
  130. group = c.toggleGroup;
  131. Ext.apply(cfg, {
  132. text: c.overflowText || c.text,
  133. iconCls: c.iconCls,
  134. icon: c.icon,
  135. itemId: c.itemId,
  136. disabled: c.disabled,
  137. handler: c.handler,
  138. scope: c.scope,
  139. menu: c.menu,
  140. hideOnClick: hideOnClick
  141. });
  142. if(group || c.enableToggle){
  143. Ext.apply(cfg, {
  144. group: group,
  145. checked: c.pressed,
  146. listeners: {
  147. checkchange: function(item, checked){
  148. c.toggle(checked);
  149. }
  150. }
  151. });
  152. }
  153. delete cfg.xtype;
  154. delete cfg.id;
  155. return cfg;
  156. },
  157. // private
  158. addComponentToMenu : function(m, c){
  159. if(c instanceof Ext.Toolbar.Separator){
  160. m.add('-');
  161. }else if(Ext.isFunction(c.isXType)){
  162. if(c.isXType('splitbutton')){
  163. m.add(this.createMenuConfig(c, true));
  164. }else if(c.isXType('button')){
  165. m.add(this.createMenuConfig(c, !c.menu));
  166. }else if(c.isXType('buttongroup')){
  167. c.items.each(function(item){
  168. this.addComponentToMenu(m, item);
  169. }, this);
  170. }
  171. }
  172. },
  173. clearMenu : function(){
  174. var m = this.moreMenu;
  175. if(m && m.items){
  176. this.moreMenu.items.each(function(item){
  177. delete item.menu;
  178. });
  179. }
  180. },
  181. // private
  182. beforeMoreShow : function(m){
  183. var h = this.container.items.items,
  184. len = h.length,
  185. c,
  186. prev,
  187. needsSep = function(group, item){
  188. return group.isXType('buttongroup') && !(item instanceof Ext.Toolbar.Separator);
  189. };
  190. this.clearMenu();
  191. m.removeAll();
  192. for(var i = 0; i < len; i++){
  193. c = h[i];
  194. if(c.xtbHidden){
  195. if(prev && (needsSep(c, prev) || needsSep(prev, c))){
  196. m.add('-');
  197. }
  198. this.addComponentToMenu(m, c);
  199. prev = c;
  200. }
  201. }
  202. // put something so the menu isn't empty
  203. // if no compatible items found
  204. if(m.items.length < 1){
  205. m.add(this.noItemsMenuText);
  206. }
  207. },
  208. initMore : function(){
  209. if(!this.more){
  210. this.moreMenu = new Ext.menu.Menu({
  211. listeners: {
  212. beforeshow: this.beforeMoreShow,
  213. scope: this
  214. }
  215. });
  216. this.more = new Ext.Button({
  217. iconCls: 'x-toolbar-more-icon',
  218. cls: 'x-toolbar-more',
  219. menu: this.moreMenu
  220. });
  221. var td = this.insertCell(this.more, this.extrasTr, 100);
  222. this.more.render(td);
  223. }
  224. },
  225. destroy : function(){
  226. Ext.destroy(this.more, this.moreMenu);
  227. Ext.layout.ToolbarLayout.superclass.destroy.call(this);
  228. }
  229. /**
  230. * @property activeItem
  231. * @hide
  232. */
  233. });
  234. Ext.Container.LAYOUTS.toolbar = Ext.layout.ToolbarLayout;
  235. /**
  236. * @class Ext.Toolbar
  237. * @extends Ext.Container
  238. * <p>Basic Toolbar class. Although the <tt>{@link Ext.Container#defaultType defaultType}</tt> for Toolbar
  239. * is <tt>{@link Ext.Button button}</tt>, Toolbar elements (child items for the Toolbar container) may
  240. * be virtually any type of Component. Toolbar elements can be created explicitly via their constructors,
  241. * or implicitly via their xtypes, and can be <tt>{@link #add}</tt>ed dynamically.</p>
  242. * <p>Some items have shortcut strings for creation:</p>
  243. * <pre>
  244. <u>Shortcut</u> <u>xtype</u> <u>Class</u> <u>Description</u>
  245. '->' 'tbfill' {@link Ext.Toolbar.Fill} begin using the right-justified button container
  246. '-' 'tbseparator' {@link Ext.Toolbar.Separator} add a vertical separator bar between toolbar items
  247. ' ' 'tbspacer' {@link Ext.Toolbar.Spacer} add horiztonal space between elements
  248. * </pre>
  249. *
  250. * Example usage of various elements:
  251. * <pre><code>
  252. var tb = new Ext.Toolbar({
  253. renderTo: document.body,
  254. width: 600,
  255. height: 100,
  256. items: [
  257. {
  258. // xtype: 'button', // default for Toolbars, same as 'tbbutton'
  259. text: 'Button'
  260. },
  261. {
  262. xtype: 'splitbutton', // same as 'tbsplitbutton'
  263. text: 'Split Button'
  264. },
  265. // begin using the right-justified button container
  266. '->', // same as {xtype: 'tbfill'}, // Ext.Toolbar.Fill
  267. {
  268. xtype: 'textfield',
  269. name: 'field1',
  270. emptyText: 'enter search term'
  271. },
  272. // add a vertical separator bar between toolbar items
  273. '-', // same as {xtype: 'tbseparator'} to create Ext.Toolbar.Separator
  274. 'text 1', // same as {xtype: 'tbtext', text: 'text1'} to create Ext.Toolbar.TextItem
  275. {xtype: 'tbspacer'},// same as ' ' to create Ext.Toolbar.Spacer
  276. 'text 2',
  277. {xtype: 'tbspacer', width: 50}, // add a 50px space
  278. 'text 3'
  279. ]
  280. });
  281. * </code></pre>
  282. * Example adding a ComboBox within a menu of a button:
  283. * <pre><code>
  284. // ComboBox creation
  285. var combo = new Ext.form.ComboBox({
  286. store: new Ext.data.ArrayStore({
  287. autoDestroy: true,
  288. fields: ['initials', 'fullname'],
  289. data : [
  290. ['FF', 'Fred Flintstone'],
  291. ['BR', 'Barney Rubble']
  292. ]
  293. }),
  294. displayField: 'fullname',
  295. typeAhead: true,
  296. mode: 'local',
  297. forceSelection: true,
  298. triggerAction: 'all',
  299. emptyText: 'Select a name...',
  300. selectOnFocus: true,
  301. width: 135,
  302. getListParent: function() {
  303. return this.el.up('.x-menu');
  304. },
  305. iconCls: 'no-icon' //use iconCls if placing within menu to shift to right side of menu
  306. });
  307. // put ComboBox in a Menu
  308. var menu = new Ext.menu.Menu({
  309. id: 'mainMenu',
  310. items: [
  311. combo // A Field in a Menu
  312. ]
  313. });
  314. // add a Button with the menu
  315. tb.add({
  316. text:'Button w/ Menu',
  317. menu: menu // assign menu by instance
  318. });
  319. tb.doLayout();
  320. * </code></pre>
  321. * @constructor
  322. * Creates a new Toolbar
  323. * @param {Object/Array} config A config object or an array of buttons to <tt>{@link #add}</tt>
  324. * @xtype toolbar
  325. */
  326. Ext.Toolbar = function(config){
  327. if(Ext.isArray(config)){
  328. config = {items: config, layout: 'toolbar'};
  329. } else {
  330. config = Ext.apply({
  331. layout: 'toolbar'
  332. }, config);
  333. if(config.buttons) {
  334. config.items = config.buttons;
  335. }
  336. }
  337. Ext.Toolbar.superclass.constructor.call(this, config);
  338. };
  339. (function(){
  340. var T = Ext.Toolbar;
  341. Ext.extend(T, Ext.Container, {
  342. defaultType: 'button',
  343. trackMenus : true,
  344. internalDefaults: {removeMode: 'container', hideParent: true},
  345. toolbarCls: 'x-toolbar',
  346. initComponent : function(){
  347. T.superclass.initComponent.call(this);
  348. /**
  349. * @event overflowchange
  350. * Fires after the overflow state has changed.
  351. * @param {Object} c The Container
  352. * @param {Boolean} lastOverflow overflow state
  353. */
  354. this.addEvents('overflowchange');
  355. },
  356. // private
  357. onRender : function(ct, position){
  358. if(!this.el){
  359. if(!this.autoCreate){
  360. this.autoCreate = {
  361. cls: this.toolbarCls + ' x-small-editor'
  362. };
  363. }
  364. this.el = ct.createChild(Ext.apply({ id: this.id },this.autoCreate), position);
  365. }
  366. },
  367. /**
  368. * Adds element(s) to the toolbar -- this function takes a variable number of
  369. * arguments of mixed type and adds them to the toolbar.
  370. * @param {Mixed} arg1 The following types of arguments are all valid:<br />
  371. * <ul>
  372. * <li>{@link Ext.Button} config: A valid button config object (equivalent to {@link #addButton})</li>
  373. * <li>HtmlElement: Any standard HTML element (equivalent to {@link #addElement})</li>
  374. * <li>Field: Any form field (equivalent to {@link #addField})</li>
  375. * <li>Item: Any subclass of {@link Ext.Toolbar.Item} (equivalent to {@link #addItem})</li>
  376. * <li>String: Any generic string (gets wrapped in a {@link Ext.Toolbar.TextItem}, equivalent to {@link #addText}).
  377. * Note that there are a few special strings that are treated differently as explained next.</li>
  378. * <li>'-': Creates a separator element (equivalent to {@link #addSeparator})</li>
  379. * <li>' ': Creates a spacer element (equivalent to {@link #addSpacer})</li>
  380. * <li>'->': Creates a fill element (equivalent to {@link #addFill})</li>
  381. * </ul>
  382. * @param {Mixed} arg2
  383. * @param {Mixed} etc.
  384. * @method add
  385. */
  386. // private
  387. lookupComponent : function(c){
  388. if(Ext.isString(c)){
  389. if(c == '-'){
  390. c = new T.Separator();
  391. }else if(c == ' '){
  392. c = new T.Spacer();
  393. }else if(c == '->'){
  394. c = new T.Fill();
  395. }else{
  396. c = new T.TextItem(c);
  397. }
  398. this.applyDefaults(c);
  399. }else{
  400. if(c.isFormField || c.render){ // some kind of form field, some kind of Toolbar.Item
  401. c = this.constructItem(c);
  402. }else if(c.tag){ // DomHelper spec
  403. c = new T.Item({autoEl: c});
  404. }else if(c.tagName){ // element
  405. c = new T.Item({el:c});
  406. }else if(Ext.isObject(c)){ // must be button config?
  407. c = c.xtype ? this.constructItem(c) : this.constructButton(c);
  408. }
  409. }
  410. return c;
  411. },
  412. // private
  413. applyDefaults : function(c){
  414. if(!Ext.isString(c)){
  415. c = Ext.Toolbar.superclass.applyDefaults.call(this, c);
  416. var d = this.internalDefaults;
  417. if(c.events){
  418. Ext.applyIf(c.initialConfig, d);
  419. Ext.apply(c, d);
  420. }else{
  421. Ext.applyIf(c, d);
  422. }
  423. }
  424. return c;
  425. },
  426. // private
  427. constructItem : function(item, type){
  428. return Ext.create(item, type || this.defaultType);
  429. },
  430. /**
  431. * Adds a separator
  432. * @return {Ext.Toolbar.Item} The separator {@link Ext.Toolbar.Item item}
  433. */
  434. addSeparator : function(){
  435. return this.add(new T.Separator());
  436. },
  437. /**
  438. * Adds a spacer element
  439. * @return {Ext.Toolbar.Spacer} The spacer item
  440. */
  441. addSpacer : function(){
  442. return this.add(new T.Spacer());
  443. },
  444. /**
  445. * Forces subsequent additions into the float:right toolbar
  446. */
  447. addFill : function(){
  448. this.add(new T.Fill());
  449. },
  450. /**
  451. * Adds any standard HTML element to the toolbar
  452. * @param {Mixed} el The element or id of the element to add
  453. * @return {Ext.Toolbar.Item} The element's item
  454. */
  455. addElement : function(el){
  456. return this.addItem(new T.Item({el:el}));
  457. },
  458. /**
  459. * Adds any Toolbar.Item or subclass
  460. * @param {Ext.Toolbar.Item} item
  461. * @return {Ext.Toolbar.Item} The item
  462. */
  463. addItem : function(item){
  464. return Ext.Toolbar.superclass.add.apply(this, arguments);
  465. },
  466. /**
  467. * Adds a button (or buttons). See {@link Ext.Button} for more info on the config.
  468. * @param {Object/Array} config A button config or array of configs
  469. * @return {Ext.Button/Array}
  470. */
  471. addButton : function(config){
  472. if(Ext.isArray(config)){
  473. var buttons = [];
  474. for(var i = 0, len = config.length; i < len; i++) {
  475. buttons.push(this.addButton(config[i]));
  476. }
  477. return buttons;
  478. }
  479. return this.add(this.constructButton(config));
  480. },
  481. /**
  482. * Adds text to the toolbar
  483. * @param {String} text The text to add
  484. * @return {Ext.Toolbar.Item} The element's item
  485. */
  486. addText : function(text){
  487. return this.addItem(new T.TextItem(text));
  488. },
  489. /**
  490. * Adds a new element to the toolbar from the passed {@link Ext.DomHelper} config
  491. * @param {Object} config
  492. * @return {Ext.Toolbar.Item} The element's item
  493. */
  494. addDom : function(config){
  495. return this.add(new T.Item({autoEl: config}));
  496. },
  497. /**
  498. * Adds a dynamically rendered Ext.form field (TextField, ComboBox, etc). Note: the field should not have
  499. * been rendered yet. For a field that has already been rendered, use {@link #addElement}.
  500. * @param {Ext.form.Field} field
  501. * @return {Ext.Toolbar.Item}
  502. */
  503. addField : function(field){
  504. return this.add(field);
  505. },
  506. /**
  507. * Inserts any {@link Ext.Toolbar.Item}/{@link Ext.Button} at the specified index.
  508. * @param {Number} index The index where the item is to be inserted
  509. * @param {Object/Ext.Toolbar.Item/Ext.Button/Array} item The button, or button config object to be
  510. * inserted, or an array of buttons/configs.
  511. * @return {Ext.Button/Item}
  512. */
  513. insertButton : function(index, item){
  514. if(Ext.isArray(item)){
  515. var buttons = [];
  516. for(var i = 0, len = item.length; i < len; i++) {
  517. buttons.push(this.insertButton(index + i, item[i]));
  518. }
  519. return buttons;
  520. }
  521. return Ext.Toolbar.superclass.insert.call(this, index, item);
  522. },
  523. // private
  524. initMenuTracking : function(item){
  525. if(this.trackMenus && item.menu){
  526. this.mon(item, {
  527. 'menutriggerover' : this.onButtonTriggerOver,
  528. 'menushow' : this.onButtonMenuShow,
  529. 'menuhide' : this.onButtonMenuHide,
  530. scope: this
  531. });
  532. }
  533. },
  534. // private
  535. constructButton : function(item){
  536. var b = item.events ? item : this.constructItem(item, item.split ? 'splitbutton' : this.defaultType);
  537. this.initMenuTracking(b);
  538. return b;
  539. },
  540. // private
  541. onDisable : function(){
  542. this.items.each(function(item){
  543. if(item.disable){
  544. item.disable();
  545. }
  546. });
  547. },
  548. // private
  549. onEnable : function(){
  550. this.items.each(function(item){
  551. if(item.enable){
  552. item.enable();
  553. }
  554. });
  555. },
  556. // private
  557. onButtonTriggerOver : function(btn){
  558. if(this.activeMenuBtn && this.activeMenuBtn != btn){
  559. this.activeMenuBtn.hideMenu();
  560. btn.showMenu();
  561. this.activeMenuBtn = btn;
  562. }
  563. },
  564. // private
  565. onButtonMenuShow : function(btn){
  566. this.activeMenuBtn = btn;
  567. },
  568. // private
  569. onButtonMenuHide : function(btn){
  570. delete this.activeMenuBtn;
  571. }
  572. });
  573. Ext.reg('toolbar', Ext.Toolbar);
  574. /**
  575. * @class Ext.Toolbar.Item
  576. * @extends Ext.BoxComponent
  577. * The base class that other non-interacting Toolbar Item classes should extend in order to
  578. * get some basic common toolbar item functionality.
  579. * @constructor
  580. * Creates a new Item
  581. * @param {HTMLElement} el
  582. * @xtype tbitem
  583. */
  584. T.Item = Ext.extend(Ext.BoxComponent, {
  585. hideParent: true, // Hiding a Toolbar.Item hides its containing TD
  586. enable:Ext.emptyFn,
  587. disable:Ext.emptyFn,
  588. focus:Ext.emptyFn
  589. /**
  590. * @cfg {String} overflowText Text to be used for the menu if the item is overflowed.
  591. */
  592. });
  593. Ext.reg('tbitem', T.Item);
  594. /**
  595. * @class Ext.Toolbar.Separator
  596. * @extends Ext.Toolbar.Item
  597. * A simple class that adds a vertical separator bar between toolbar items
  598. * (css class:<tt>'xtb-sep'</tt>). Example usage:
  599. * <pre><code>
  600. new Ext.Panel({
  601. tbar : [
  602. 'Item 1',
  603. {xtype: 'tbseparator'}, // or '-'
  604. 'Item 2'
  605. ]
  606. });
  607. </code></pre>
  608. * @constructor
  609. * Creates a new Separator
  610. * @xtype tbseparator
  611. */
  612. T.Separator = Ext.extend(T.Item, {
  613. onRender : function(ct, position){
  614. this.el = ct.createChild({tag:'span', cls:'xtb-sep'}, position);
  615. }
  616. });
  617. Ext.reg('tbseparator', T.Separator);
  618. /**
  619. * @class Ext.Toolbar.Spacer
  620. * @extends Ext.Toolbar.Item
  621. * A simple element that adds extra horizontal space between items in a toolbar.
  622. * By default a 2px wide space is added via css specification:<pre><code>
  623. .x-toolbar .xtb-spacer {
  624. width:2px;
  625. }
  626. * </code></pre>
  627. * <p>Example usage:</p>
  628. * <pre><code>
  629. new Ext.Panel({
  630. tbar : [
  631. 'Item 1',
  632. {xtype: 'tbspacer'}, // or ' '
  633. 'Item 2',
  634. // space width is also configurable via javascript
  635. {xtype: 'tbspacer', width: 50}, // add a 50px space
  636. 'Item 3'
  637. ]
  638. });
  639. </code></pre>
  640. * @constructor
  641. * Creates a new Spacer
  642. * @xtype tbspacer
  643. */
  644. T.Spacer = Ext.extend(T.Item, {
  645. /**
  646. * @cfg {Number} width
  647. * The width of the spacer in pixels (defaults to 2px via css style <tt>.x-toolbar .xtb-spacer</tt>).
  648. */
  649. onRender : function(ct, position){
  650. this.el = ct.createChild({tag:'div', cls:'xtb-spacer', style: this.width?'width:'+this.width+'px':''}, position);
  651. }
  652. });
  653. Ext.reg('tbspacer', T.Spacer);
  654. /**
  655. * @class Ext.Toolbar.Fill
  656. * @extends Ext.Toolbar.Spacer
  657. * A non-rendering placeholder item which instructs the Toolbar's Layout to begin using
  658. * the right-justified button container.
  659. * <pre><code>
  660. new Ext.Panel({
  661. tbar : [
  662. 'Item 1',
  663. {xtype: 'tbfill'}, // or '->'
  664. 'Item 2'
  665. ]
  666. });
  667. </code></pre>
  668. * @constructor
  669. * Creates a new Fill
  670. * @xtype tbfill
  671. */
  672. T.Fill = Ext.extend(T.Item, {
  673. // private
  674. render : Ext.emptyFn,
  675. isFill : true
  676. });
  677. Ext.reg('tbfill', T.Fill);
  678. /**
  679. * @class Ext.Toolbar.TextItem
  680. * @extends Ext.Toolbar.Item
  681. * A simple class that renders text directly into a toolbar
  682. * (with css class:<tt>'xtb-text'</tt>). Example usage:
  683. * <pre><code>
  684. new Ext.Panel({
  685. tbar : [
  686. {xtype: 'tbtext', text: 'Item 1'} // or simply 'Item 1'
  687. ]
  688. });
  689. </code></pre>
  690. * @constructor
  691. * Creates a new TextItem
  692. * @param {String/Object} text A text string, or a config object containing a <tt>text</tt> property
  693. * @xtype tbtext
  694. */
  695. T.TextItem = Ext.extend(T.Item, {
  696. constructor: function(config){
  697. if (Ext.isString(config)) {
  698. config = { autoEl: {cls: 'xtb-text', html: config }};
  699. } else {
  700. config.autoEl = {cls: 'xtb-text', html: config.text || ''};
  701. }
  702. T.TextItem.superclass.constructor.call(this, config);
  703. },
  704. /**
  705. * Updates this item's text, setting the text to be used as innerHTML.
  706. * @param {String} t The text to display (html accepted).
  707. */
  708. setText : function(t) {
  709. if (this.rendered) {
  710. this.el.dom.innerHTML = t;
  711. } else {
  712. this.autoEl.html = t;
  713. }
  714. }
  715. });
  716. Ext.reg('tbtext', T.TextItem);
  717. // backwards compat
  718. T.Button = Ext.extend(Ext.Button, {});
  719. T.SplitButton = Ext.extend(Ext.SplitButton, {});
  720. Ext.reg('tbbutton', T.Button);
  721. Ext.reg('tbsplit', T.SplitButton);
  722. })();
  723. /**
  724. * @class Ext.ButtonGroup
  725. * @extends Ext.Panel
  726. * Container for a group of buttons. Example usage:
  727. * <pre><code>
  728. var p = new Ext.Panel({
  729. title: 'Panel with Button Group',
  730. width: 300,
  731. height:200,
  732. renderTo: document.body,
  733. html: 'whatever',
  734. tbar: [{
  735. xtype: 'buttongroup',
  736. {@link #columns}: 3,
  737. title: 'Clipboard',
  738. items: [{
  739. text: 'Paste',
  740. scale: 'large',
  741. rowspan: 3, iconCls: 'add',
  742. iconAlign: 'top',
  743. cls: 'x-btn-as-arrow'
  744. },{
  745. xtype:'splitbutton',
  746. text: 'Menu Button',
  747. scale: 'large',
  748. rowspan: 3,
  749. iconCls: 'add',
  750. iconAlign: 'top',
  751. arrowAlign:'bottom',
  752. menu: [{text: 'Menu Item 1'}]
  753. },{
  754. xtype:'splitbutton', text: 'Cut', iconCls: 'add16', menu: [{text: 'Cut Menu Item'}]
  755. },{
  756. text: 'Copy', iconCls: 'add16'
  757. },{
  758. text: 'Format', iconCls: 'add16'
  759. }]
  760. }]
  761. });
  762. * </code></pre>
  763. * @xtype buttongroup
  764. */
  765. Ext.ButtonGroup = Ext.extend(Ext.Panel, {
  766. /**
  767. * @cfg {Number} columns The <tt>columns</tt> configuration property passed to the
  768. * {@link #layout configured layout manager}. See {@link Ext.layout.TableLayout#columns}.
  769. */
  770. /**
  771. * @cfg {String} baseCls Defaults to <tt>'x-btn-group'</tt>. See {@link Ext.Panel#baseCls}.
  772. */
  773. baseCls: 'x-btn-group',
  774. /**
  775. * @cfg {String} layout Defaults to <tt>'table'</tt>. See {@link Ext.Container#layout}.
  776. */
  777. layout:'table',
  778. defaultType: 'button',
  779. /**
  780. * @cfg {Boolean} frame Defaults to <tt>true</tt>. See {@link Ext.Panel#frame}.
  781. */
  782. frame: true,
  783. internalDefaults: {removeMode: 'container', hideParent: true},
  784. initComponent : function(){
  785. this.layoutConfig = this.layoutConfig || {};
  786. Ext.applyIf(this.layoutConfig, {
  787. columns : this.columns
  788. });
  789. if(!this.title){
  790. this.addClass('x-btn-group-notitle');
  791. }
  792. this.on('afterlayout', this.onAfterLayout, this);
  793. Ext.ButtonGroup.superclass.initComponent.call(this);
  794. },
  795. applyDefaults : function(c){
  796. c = Ext.ButtonGroup.superclass.applyDefaults.call(this, c);
  797. var d = this.internalDefaults;
  798. if(c.events){
  799. Ext.applyIf(c.initialConfig, d);
  800. Ext.apply(c, d);
  801. }else{
  802. Ext.applyIf(c, d);
  803. }
  804. return c;
  805. },
  806. onAfterLayout : function(){
  807. var bodyWidth = this.body.getFrameWidth('lr') + this.body.dom.firstChild.offsetWidth;
  808. this.body.setWidth(bodyWidth);
  809. this.el.setWidth(bodyWidth + this.getFrameWidth());
  810. }
  811. /**
  812. * @cfg {Array} tools @hide
  813. */
  814. });
  815. Ext.reg('buttongroup', Ext.ButtonGroup);
  816. /**
  817. * @class Ext.PagingToolbar
  818. * @extends Ext.Toolbar
  819. * <p>As the amount of records increases, the time required for the browser to render
  820. * them increases. Paging is used to reduce the amount of data exchanged with the client.
  821. * Note: if there are more records/rows than can be viewed in the available screen area, vertical
  822. * scrollbars will be added.</p>
  823. * <p>Paging is typically handled on the server side (see exception below). The client sends
  824. * parameters to the server side, which the server needs to interpret and then respond with the
  825. * approprate data.</p>
  826. * <p><b>Ext.PagingToolbar</b> is a specialized toolbar that is bound to a {@link Ext.data.Store}
  827. * and provides automatic paging control. This Component {@link Ext.data.Store#load load}s blocks
  828. * of data into the <tt>{@link #store}</tt> by passing {@link Ext.data.Store#paramNames paramNames} used for
  829. * paging criteria.</p>
  830. * <p>PagingToolbar is typically used as one of the Grid's toolbars:</p>
  831. * <pre><code>
  832. Ext.QuickTips.init(); // to display button quicktips
  833. var myStore = new Ext.data.Store({
  834. ...
  835. });
  836. var myPageSize = 25; // server script should only send back 25 items
  837. var grid = new Ext.grid.GridPanel({
  838. ...
  839. store: myStore,
  840. bbar: new Ext.PagingToolbar({
  841. {@link #store}: myStore, // grid and PagingToolbar using same store
  842. {@link #displayInfo}: true,
  843. {@link #pageSize}: myPageSize,
  844. {@link #prependButtons}: true,
  845. items: [
  846. 'text 1'
  847. ]
  848. })
  849. });
  850. * </code></pre>
  851. *
  852. * <p>To use paging, pass the paging requirements to the server when the store is first loaded.</p>
  853. * <pre><code>
  854. store.load({
  855. params: {
  856. start: 0, // specify params for the first page load if using paging
  857. limit: myPageSize,
  858. foo: 'bar'
  859. }
  860. });
  861. * </code></pre>
  862. * <p><u>Paging with Local Data</u></p>
  863. * <p>Paging can also be accomplished with local data using extensions:</p>
  864. * <div class="mdetail-params"><ul>
  865. * <li><a href="http://extjs.com/forum/showthread.php?t=57386">Ext.ux.data.PagingStore</a></li>
  866. * <li>Paging Memory Proxy (examples/ux/PagingMemoryProxy.js)</li>
  867. * </ul></div>
  868. * @constructor
  869. * Create a new PagingToolbar
  870. * @param {Object} config The config object
  871. * @xtype paging
  872. */
  873. (function() {
  874. var T = Ext.Toolbar;
  875. Ext.PagingToolbar = Ext.extend(Ext.Toolbar, {
  876. /**
  877. * @cfg {Ext.data.Store} store
  878. * The {@link Ext.data.Store} the paging toolbar should use as its data source (required).
  879. */
  880. /**
  881. * @cfg {Boolean} displayInfo
  882. * <tt>true</tt> to display the displayMsg (defaults to <tt>false</tt>)
  883. */
  884. /**
  885. * @cfg {Number} pageSize
  886. * The number of records to display per page (defaults to <tt>20</tt>)
  887. */
  888. pageSize : 20,
  889. /**
  890. * @cfg {Boolean} prependButtons
  891. * <tt>true</tt> to insert any configured <tt>items</tt> <i>before</i> the paging buttons.
  892. * Defaults to <tt>false</tt>.
  893. */
  894. /**
  895. * @cfg {String} displayMsg
  896. * The paging status message to display (defaults to <tt>'Displaying {0} - {1} of {2}'</tt>).
  897. * Note that this string is formatted using the braced numbers <tt>{0}-{2}</tt> as tokens
  898. * that are replaced by the values for start, end and total respectively. These tokens should
  899. * be preserved when overriding this string if showing those values is desired.
  900. */
  901. displayMsg : 'Displaying {0} - {1} of {2}',
  902. /**
  903. * @cfg {String} emptyMsg
  904. * The message to display when no records are found (defaults to 'No data to display')
  905. */
  906. emptyMsg : 'No data to display',
  907. /**
  908. * @cfg {String} beforePageText
  909. * The text displayed before the input item (defaults to <tt>'Page'</tt>).
  910. */
  911. beforePageText : 'Page',
  912. /**
  913. * @cfg {String} afterPageText
  914. * Customizable piece of the default paging text (defaults to <tt>'of {0}'</tt>). Note that
  915. * this string is formatted using <tt>{0}</tt> as a token that is replaced by the number of
  916. * total pages. This token should be preserved when overriding this string if showing the
  917. * total page count is desired.
  918. */
  919. afterPageText : 'of {0}',
  920. /**
  921. * @cfg {String} firstText
  922. * The quicktip text displayed for the first page button (defaults to <tt>'First Page'</tt>).
  923. * <b>Note</b>: quick tips must be initialized for the quicktip to show.
  924. */
  925. firstText : 'First Page',
  926. /**
  927. * @cfg {String} prevText
  928. * The quicktip text displayed for the previous page button (defaults to <tt>'Previous Page'</tt>).
  929. * <b>Note</b>: quick tips must be initialized for the quicktip to show.
  930. */
  931. prevText : 'Previous Page',
  932. /**
  933. * @cfg {String} nextText
  934. * The quicktip text displayed for the next page button (defaults to <tt>'Next Page'</tt>).
  935. * <b>Note</b>: quick tips must be initialized for the quicktip to show.
  936. */
  937. nextText : 'Next Page',
  938. /**
  939. * @cfg {String} lastText
  940. * The quicktip text displayed for the last page button (defaults to <tt>'Last Page'</tt>).
  941. * <b>Note</b>: quick tips must be initialized for the quicktip to show.
  942. */
  943. lastText : 'Last Page',
  944. /**
  945. * @cfg {String} refreshText
  946. * The quicktip text displayed for the Refresh button (defaults to <tt>'Refresh'</tt>).
  947. * <b>Note</b>: quick tips must be initialized for the quicktip to show.
  948. */
  949. refreshText : 'Refresh',
  950. /**
  951. * @deprecated
  952. * <b>The defaults for these should be set in the data store.</b>
  953. * Object mapping of parameter names used for load calls, initially set to:
  954. * <pre>{start: 'start', limit: 'limit'}</pre>
  955. */
  956. /**
  957. * The number of records to display per page. See also <tt>{@link #cursor}</tt>.
  958. * @type Number
  959. * @property pageSize
  960. */
  961. /**
  962. * Indicator for the record position. This property might be used to get the active page
  963. * number for example:<pre><code>
  964. * // t is reference to the paging toolbar instance
  965. * var activePage = Math.ceil((t.cursor + t.pageSize) / t.pageSize);
  966. * </code></pre>
  967. * @type Number
  968. * @property cursor
  969. */
  970. initComponent : function(){
  971. var pagingItems = [this.first = new T.Button({
  972. tooltip: this.firstText,
  973. overflowText: this.firstText,
  974. iconCls: 'x-tbar-page-first',
  975. disabled: true,
  976. handler: this.moveFirst,
  977. scope: this
  978. }), this.prev = new T.Button({
  979. tooltip: this.prevText,
  980. overflowText: this.prevText,
  981. iconCls: 'x-tbar-page-prev',
  982. disabled: true,
  983. handler: this.movePrevious,
  984. scope: this
  985. }), '-', this.beforePageText,
  986. this.inputItem = new Ext.form.NumberField({
  987. cls: 'x-tbar-page-number',
  988. allowDecimals: false,
  989. allowNegative: false,
  990. enableKeyEvents: true,
  991. selectOnFocus: true,
  992. listeners: {
  993. scope: this,
  994. keydown: this.onPagingKeyDown,
  995. blur: this.onPagingBlur
  996. }
  997. }), this.afterTextItem = new T.TextItem({
  998. text: String.format(this.afterPageText, 1)
  999. }), '-', this.next = new T.Button({
  1000. tooltip: this.nextText,
  1001. overflowText: this.nextText,
  1002. iconCls: 'x-tbar-page-next',
  1003. disabled: true,
  1004. handler: this.moveNext,
  1005. scope: this
  1006. }), this.last = new T.Button({
  1007. tooltip: this.lastText,
  1008. overflowText: this.lastText,
  1009. iconCls: 'x-tbar-page-last',
  1010. disabled: true,
  1011. handler: this.moveLast,
  1012. scope: this
  1013. }), '-', this.refresh = new T.Button({
  1014. tooltip: this.refreshText,
  1015. overflowText: this.refreshText,
  1016. iconCls: 'x-tbar-loading',
  1017. handler: this.refresh,
  1018. scope: this
  1019. })];
  1020. var userItems = this.items || this.buttons || [];
  1021. if (this.prependButtons) {
  1022. this.items = userItems.concat(pagingItems);
  1023. }else{
  1024. this.items = pagingItems.concat(userItems);
  1025. }
  1026. delete this.buttons;
  1027. if(this.displayInfo){
  1028. this.items.push('->');
  1029. this.items.push(this.displayItem = new T.TextItem({}));
  1030. }
  1031. Ext.PagingToolbar.superclass.initComponent.call(this);
  1032. this.addEvents(
  1033. /**
  1034. * @event change
  1035. * Fires after the active page has been changed.
  1036. * @param {Ext.PagingToolbar} this
  1037. * @param {Object} pageData An object that has these properties:<ul>
  1038. * <li><code>total</code> : Number <div class="sub-desc">The total number of records in the dataset as
  1039. * returned by the server</div></li>
  1040. * <li><code>activePage</code> : Number <div class="sub-desc">The current page number</div></li>
  1041. * <li><code>pages</code> : Number <div class="sub-desc">The total number of pages (calculated from
  1042. * the total number of records in the dataset as returned by the server and the current {@link #pageSize})</div></li>
  1043. * </ul>
  1044. */
  1045. 'change',
  1046. /**
  1047. * @event beforechange
  1048. * Fires just before the active page is changed.
  1049. * Return false to prevent the active page from being changed.
  1050. * @param {Ext.PagingToolbar} this
  1051. * @param {Object} params An object hash of the parameters which the PagingToolbar will send when
  1052. * loading the required page. This will contain:<ul>
  1053. * <li><code>start</code> : Number <div class="sub-desc">The starting row number for the next page of records to
  1054. * be retrieved from the server</div></li>
  1055. * <li><code>limit</code> : Number <div class="sub-desc">The number of records to be retrieved from the server</div></li>
  1056. * </ul>
  1057. * <p>(note: the names of the <b>start</b> and <b>limit</b> properties are determined
  1058. * by the store's {@link Ext.data.Store#paramNames paramNames} property.)</p>
  1059. * <p>Parameters may be added as required in the event handler.</p>
  1060. */
  1061. 'beforechange'
  1062. );
  1063. this.on('afterlayout', this.onFirstLayout, this, {single: true});
  1064. this.cursor = 0;
  1065. this.bindStore(this.store);
  1066. },
  1067. // private
  1068. onFirstLayout : function(){
  1069. if(this.dsLoaded){
  1070. this.onLoad.apply(this, this.dsLoaded);
  1071. }
  1072. },
  1073. // private
  1074. updateInfo : function(){
  1075. if(this.displayItem){
  1076. var count = this.store.getCount();
  1077. var msg = count == 0 ?
  1078. this.emptyMsg :
  1079. String.format(
  1080. this.displayMsg,
  1081. this.cursor+1, this.cursor+count, this.store.getTotalCount()
  1082. );
  1083. this.displayItem.setText(msg);
  1084. }
  1085. },
  1086. // private
  1087. onLoad : function(store, r, o){
  1088. if(!this.rendered){
  1089. this.dsLoaded = [store, r, o];
  1090. return;
  1091. }
  1092. var p = this.getParams();
  1093. this.cursor = (o.params && o.params[p.start]) ? o.params[p.start] : 0;
  1094. var d = this.getPageData(), ap = d.activePage, ps = d.pages;
  1095. this.afterTextItem.setText(String.format(this.afterPageText, d.pages));
  1096. this.inputItem.setValue(ap);
  1097. this.first.setDisabled(ap == 1);
  1098. this.prev.setDisabled(ap == 1);
  1099. this.next.setDisabled(ap == ps);
  1100. this.last.setDisabled(ap == ps);
  1101. this.refresh.enable();
  1102. this.updateInfo();
  1103. this.fireEvent('change', this, d);
  1104. },
  1105. // private
  1106. getPageData : function(){
  1107. var total = this.store.getTotalCount();
  1108. return {
  1109. total : total,
  1110. activePage : Math.ceil((this.cursor+this.pageSize)/this.pageSize),
  1111. pages : total < this.pageSize ? 1 : Math.ceil(total/this.pageSize)
  1112. };
  1113. },
  1114. /**
  1115. * Change the active page
  1116. * @param {Integer} page The page to display
  1117. */
  1118. changePage : function(page){
  1119. this.doLoad(((page-1) * this.pageSize).constrain(0, this.store.getTotalCount()));
  1120. },
  1121. // private
  1122. onLoadError : function(){
  1123. if(!this.rendered){
  1124. return;
  1125. }
  1126. this.refresh.enable();
  1127. },
  1128. // private
  1129. readPage : function(d){
  1130. var v = this.inputItem.getValue(), pageNum;
  1131. if (!v || isNaN(pageNum = parseInt(v, 10))) {
  1132. this.inputItem.setValue(d.activePage);
  1133. return false;
  1134. }
  1135. return pageNum;
  1136. },
  1137. onPagingFocus : function(){
  1138. this.inputItem.select();
  1139. },
  1140. //private
  1141. onPagingBlur : function(e){
  1142. this.inputItem.setValue(this.getPageData().activePage);
  1143. },
  1144. // private
  1145. onPagingKeyDown : function(field, e){
  1146. var k = e.getKey(), d = this.getPageData(), pageNum;
  1147. if (k == e.RETURN) {
  1148. e.stopEvent();
  1149. pageNum = this.readPage(d);
  1150. if(pageNum !== false){
  1151. pageNum = Math.min(Math.max(1, pageNum), d.pages) - 1;
  1152. this.doLoad(pageNum * this.pageSize);
  1153. }
  1154. }else if (k == e.HOME || k == e.END){
  1155. e.stopEvent();
  1156. pageNum = k == e.HOME ? 1 : d.pages;
  1157. field.setValue(pageNum);
  1158. }else if (k == e.UP || k == e.PAGEUP || k == e.DOWN || k == e.PAGEDOWN){
  1159. e.stopEvent();
  1160. if((pageNum = this.readPage(d))){
  1161. var increment = e.shiftKey ? 10 : 1;
  1162. if(k == e.DOWN || k == e.PAGEDOWN){
  1163. increment *= -1;
  1164. }
  1165. pageNum += increment;
  1166. if(pageNum >= 1 & pageNum <= d.pages){
  1167. field.setValue(pageNum);
  1168. }
  1169. }
  1170. }
  1171. },
  1172. // private
  1173. getParams : function(){
  1174. //retain backwards compat, allow params on the toolbar itself, if they exist.
  1175. return this.paramNames || this.store.paramNames;
  1176. },
  1177. // private
  1178. beforeLoad : function(){
  1179. if(this.rendered && this.refresh){
  1180. this.refresh.disable();
  1181. }
  1182. },
  1183. // private
  1184. doLoad : function(start){
  1185. var o = {}, pn = this.getParams();
  1186. o[pn.start] = start;
  1187. o[pn.limit] = this.pageSize;
  1188. if(this.fireEvent('beforechange', this, o) !== false){
  1189. this.store.load({params:o});
  1190. }
  1191. },
  1192. /**
  1193. * Move to the first page, has the same effect as clicking the 'first' button.
  1194. */
  1195. moveFirst : function(){
  1196. this.doLoad(0);
  1197. },
  1198. /**
  1199. * Move to the previous page, has the same effect as clicking the 'previous' button.
  1200. */
  1201. movePrevious : function(){
  1202. this.doLoad(Math.max(0, this.cursor-this.pageSize));
  1203. },
  1204. /**
  1205. * Move to the next page, has the same effect as clicking the 'next' button.
  1206. */
  1207. moveNext : function(){
  1208. this.doLoad(this.cursor+this.pageSize);
  1209. },
  1210. /**
  1211. * Move to the last page, has the same effect as clicking the 'last' button.
  1212. */
  1213. moveLast : function(){
  1214. var total = this.store.getTotalCount(),
  1215. extra = total % this.pageSize;
  1216. this.doLoad(extra ? (total - extra) : total - this.pageSize);
  1217. },
  1218. /**
  1219. * Refresh the current page, has the same effect as clicking the 'refresh' button.
  1220. */
  1221. refresh : function(){
  1222. this.doLoad(this.cursor);
  1223. },
  1224. /**
  1225. * Binds the paging toolbar to the specified {@link Ext.data.Store}
  1226. * @param {Store} store The store to bind to this toolbar
  1227. * @param {Boolean} initial (Optional) true to not remove listeners
  1228. */
  1229. bindStore : function(store, initial){
  1230. var doLoad;
  1231. if(!initial && this.store){
  1232. this.store.un('beforeload', this.beforeLoad, this);
  1233. this.store.un('load', this.onLoad, this);
  1234. this.store.un('exception', this.onLoadError, this);
  1235. if(store !== this.store && this.store.autoDestroy){
  1236. this.store.destroy();
  1237. }
  1238. }
  1239. if(store){
  1240. store = Ext.StoreMgr.lookup(store);
  1241. store.on({
  1242. scope: this,
  1243. beforeload: this.beforeLoad,
  1244. load: this.onLoad,
  1245. exception: this.onLoadError
  1246. });
  1247. doLoad = store.getCount() > 0;
  1248. }
  1249. this.store = store;
  1250. if(doLoad){
  1251. this.onLoad(store, null, {});
  1252. }
  1253. },
  1254. /**
  1255. * Unbinds the paging toolbar from the specified {@link Ext.data.Store} <b>(deprecated)</b>
  1256. * @param {Ext.data.Store} store The data store to unbind
  1257. */
  1258. unbind : function(store){
  1259. this.bindStore(null);
  1260. },
  1261. /**
  1262. * Binds the paging toolbar to the specified {@link Ext.data.Store} <b>(deprecated)</b>
  1263. * @param {Ext.data.Store} store The data store to bind
  1264. */
  1265. bind : function(store){
  1266. this.bindStore(store);
  1267. },
  1268. // private
  1269. onDestroy : function(){
  1270. this.bindStore(null);
  1271. Ext.PagingToolbar.superclass.onDestroy.call(this);
  1272. }
  1273. });
  1274. })();
  1275. Ext.reg('paging', Ext.PagingToolbar);