RangeMenu.js 6.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256
  1. /**
  2. * @class Ext.ux.grid.menu.RangeMenu
  3. * @extends Ext.menu.Menu
  4. * Custom implementation of {@link Ext.menu.Menu} that has preconfigured items for entering numeric
  5. * range comparison values: less-than, greater-than, and equal-to. This is used internally
  6. * by {@link Ext.ux.grid.filter.NumericFilter} to create its menu.
  7. */
  8. Ext.define('Ext.ux.grid.menu.RangeMenu', {
  9. extend: 'Ext.menu.Menu',
  10. /**
  11. * @cfg {String} fieldCls
  12. * The Class to use to construct each field item within this menu
  13. * Defaults to:<pre>
  14. * fieldCls : Ext.form.field.Number
  15. * </pre>
  16. */
  17. fieldCls : 'Ext.form.field.Number',
  18. /**
  19. * @cfg {Object} fieldCfg
  20. * The default configuration options for any field item unless superseded
  21. * by the <code>{@link #fields}</code> configuration.
  22. * Defaults to:<pre>
  23. * fieldCfg : {}
  24. * </pre>
  25. * Example usage:
  26. * <pre><code>
  27. fieldCfg : {
  28. width: 150,
  29. },
  30. * </code></pre>
  31. */
  32. /**
  33. * @cfg {Object} fields
  34. * The field items may be configured individually
  35. * Defaults to <tt>undefined</tt>.
  36. * Example usage:
  37. * <pre><code>
  38. fields : {
  39. gt: { // override fieldCfg options
  40. width: 200,
  41. fieldCls: Ext.ux.form.CustomNumberField // to override default {@link #fieldCls}
  42. }
  43. },
  44. * </code></pre>
  45. */
  46. /**
  47. * @cfg {Object} iconCls
  48. * The iconCls to be applied to each comparator field item.
  49. * Defaults to:<pre>
  50. iconCls : {
  51. gt : 'ux-rangemenu-gt',
  52. lt : 'ux-rangemenu-lt',
  53. eq : 'ux-rangemenu-eq'
  54. }
  55. * </pre>
  56. */
  57. iconCls : {
  58. gt : 'ux-rangemenu-gt',
  59. lt : 'ux-rangemenu-lt',
  60. eq : 'ux-rangemenu-eq'
  61. },
  62. /**
  63. * @cfg {Object} fieldLabels
  64. * Accessible label text for each comparator field item. Can be overridden by localization
  65. * files. Defaults to:<pre>
  66. fieldLabels : {
  67. gt: 'Greater Than',
  68. lt: 'Less Than',
  69. eq: 'Equal To'
  70. }</pre>
  71. */
  72. fieldLabels: {
  73. gt: 'Greater Than',
  74. lt: 'Less Than',
  75. eq: 'Equal To'
  76. },
  77. /**
  78. * @cfg {Object} menuItemCfgs
  79. * Default configuration options for each menu item
  80. * Defaults to:<pre>
  81. menuItemCfgs : {
  82. emptyText: 'Enter Filter Text...',
  83. selectOnFocus: true,
  84. width: 125
  85. }
  86. * </pre>
  87. */
  88. menuItemCfgs : {
  89. emptyText: 'Enter Number...',
  90. selectOnFocus: false,
  91. width: 155
  92. },
  93. /**
  94. * @cfg {Array} menuItems
  95. * The items to be shown in this menu. Items are added to the menu
  96. * according to their position within this array. Defaults to:<pre>
  97. * menuItems : ['lt','gt','-','eq']
  98. * </pre>
  99. */
  100. menuItems : ['lt', 'gt', '-', 'eq'],
  101. constructor : function (config) {
  102. var me = this,
  103. fields, fieldCfg, i, len, item, cfg, Cls;
  104. me.callParent(arguments);
  105. fields = me.fields = me.fields || {};
  106. fieldCfg = me.fieldCfg = me.fieldCfg || {};
  107. me.addEvents(
  108. /**
  109. * @event update
  110. * Fires when a filter configuration has changed
  111. * @param {Ext.ux.grid.filter.Filter} this The filter object.
  112. */
  113. 'update'
  114. );
  115. me.updateTask = Ext.create('Ext.util.DelayedTask', me.fireUpdate, me);
  116. for (i = 0, len = me.menuItems.length; i < len; i++) {
  117. item = me.menuItems[i];
  118. if (item !== '-') {
  119. // defaults
  120. cfg = {
  121. itemId: 'range-' + item,
  122. enableKeyEvents: true,
  123. hideLabel: false,
  124. fieldLabel: me.iconTpl.apply({
  125. cls: me.iconCls[item] || 'no-icon',
  126. text: me.fieldLabels[item] || '',
  127. src: Ext.BLANK_IMAGE_URL
  128. }),
  129. labelSeparator: '',
  130. labelWidth: 29,
  131. listeners: {
  132. scope: me,
  133. change: me.onInputChange,
  134. keyup: me.onInputKeyUp,
  135. el: {
  136. click: function(e) {
  137. e.stopPropagation();
  138. }
  139. }
  140. },
  141. activate: Ext.emptyFn,
  142. deactivate: Ext.emptyFn
  143. };
  144. Ext.apply(
  145. cfg,
  146. // custom configs
  147. Ext.applyIf(fields[item] || {}, fieldCfg[item]),
  148. // configurable defaults
  149. me.menuItemCfgs
  150. );
  151. Cls = cfg.fieldCls || me.fieldCls;
  152. item = fields[item] = Ext.create(Cls, cfg);
  153. }
  154. me.add(item);
  155. }
  156. },
  157. /**
  158. * @private
  159. * called by this.updateTask
  160. */
  161. fireUpdate : function () {
  162. this.fireEvent('update', this);
  163. },
  164. /**
  165. * Get and return the value of the filter.
  166. * @return {String} The value of this filter
  167. */
  168. getValue : function () {
  169. var result = {}, key, field;
  170. for (key in this.fields) {
  171. field = this.fields[key];
  172. if (field.isValid() && field.getValue() !== null) {
  173. result[key] = field.getValue();
  174. }
  175. }
  176. return result;
  177. },
  178. /**
  179. * Set the value of this menu and fires the 'update' event.
  180. * @param {Object} data The data to assign to this menu
  181. */
  182. setValue : function (data) {
  183. var key;
  184. for (key in this.fields) {
  185. this.fields[key].setValue(key in data ? data[key] : '');
  186. }
  187. this.fireEvent('update', this);
  188. },
  189. /**
  190. * @private
  191. * Handler method called when there is a keyup event on an input
  192. * item of this menu.
  193. */
  194. onInputKeyUp: function(field, e) {
  195. if (e.getKey() === e.RETURN && field.isValid()) {
  196. e.stopEvent();
  197. this.hide();
  198. }
  199. },
  200. /**
  201. * @private
  202. * Handler method called when the user changes the value of one of the input
  203. * items in this menu.
  204. */
  205. onInputChange: function(field) {
  206. var me = this,
  207. fields = me.fields,
  208. eq = fields.eq,
  209. gt = fields.gt,
  210. lt = fields.lt;
  211. if (field == eq) {
  212. if (gt) {
  213. gt.setValue(null);
  214. }
  215. if (lt) {
  216. lt.setValue(null);
  217. }
  218. }
  219. else {
  220. eq.setValue(null);
  221. }
  222. // restart the timer
  223. this.updateTask.delay(this.updateBuffer);
  224. }
  225. }, function() {
  226. /**
  227. * @cfg {Ext.XTemplate} iconTpl
  228. * A template for generating the label for each field in the menu
  229. */
  230. this.prototype.iconTpl = Ext.create('Ext.XTemplate',
  231. '<img src="{src}" alt="{text}" class="' + Ext.baseCSSPrefix + 'menu-item-icon ux-rangemenu-icon {cls}" />'
  232. );
  233. });