Grid.html 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370
  1. <!DOCTYPE html>
  2. <html>
  3. <head>
  4. <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
  5. <title>The source code</title>
  6. <link href="../resources/prettify/prettify.css" type="text/css" rel="stylesheet" />
  7. <script type="text/javascript" src="../resources/prettify/prettify.js"></script>
  8. <style type="text/css">
  9. .highlight { display: block; background-color: #ddd; }
  10. </style>
  11. <script type="text/javascript">
  12. function highlight() {
  13. document.getElementById(location.hash.replace(/#/, "")).className = "highlight";
  14. }
  15. </script>
  16. </head>
  17. <body onload="prettyPrint(); highlight();">
  18. <pre class="prettyprint lang-js"><span id='Ext-grid-property-Grid'>/**
  19. </span> * A specialized grid implementation intended to mimic the traditional property grid as typically seen in
  20. * development IDEs. Each row in the grid represents a property of some object, and the data is stored
  21. * as a set of name/value pairs in {@link Ext.grid.property.Property Properties}. Example usage:
  22. *
  23. * @example
  24. * Ext.create('Ext.grid.property.Grid', {
  25. * title: 'Properties Grid',
  26. * width: 300,
  27. * renderTo: Ext.getBody(),
  28. * source: {
  29. * &quot;(name)&quot;: &quot;My Object&quot;,
  30. * &quot;Created&quot;: Ext.Date.parse('10/15/2006', 'm/d/Y'),
  31. * &quot;Available&quot;: false,
  32. * &quot;Version&quot;: 0.01,
  33. * &quot;Description&quot;: &quot;A test object&quot;
  34. * }
  35. * });
  36. */
  37. Ext.define('Ext.grid.property.Grid', {
  38. extend: 'Ext.grid.Panel',
  39. alias: 'widget.propertygrid',
  40. alternateClassName: 'Ext.grid.PropertyGrid',
  41. uses: [
  42. 'Ext.grid.plugin.CellEditing',
  43. 'Ext.grid.property.Store',
  44. 'Ext.grid.property.HeaderContainer',
  45. 'Ext.XTemplate',
  46. 'Ext.grid.CellEditor',
  47. 'Ext.form.field.Date',
  48. 'Ext.form.field.Text',
  49. 'Ext.form.field.Number',
  50. 'Ext.form.field.ComboBox'
  51. ],
  52. <span id='Ext-grid-property-Grid-cfg-propertyNames'> /**
  53. </span> * @cfg {Object} propertyNames
  54. * An object containing custom property name/display name pairs.
  55. * If specified, the display name will be shown in the name column instead of the property name.
  56. */
  57. <span id='Ext-grid-property-Grid-cfg-source'> /**
  58. </span> * @cfg {Object} source
  59. * A data object to use as the data source of the grid (see {@link #setSource} for details).
  60. */
  61. <span id='Ext-grid-property-Grid-cfg-customEditors'> /**
  62. </span> * @cfg {Object} customEditors
  63. * An object containing name/value pairs of custom editor type definitions that allow
  64. * the grid to support additional types of editable fields. By default, the grid supports strongly-typed editing
  65. * of strings, dates, numbers and booleans using built-in form editors, but any custom type can be supported and
  66. * associated with a custom input control by specifying a custom editor. The name of the editor
  67. * type should correspond with the name of the property that will use the editor. Example usage:
  68. *
  69. * var grid = new Ext.grid.property.Grid({
  70. *
  71. * // Custom editors for certain property names
  72. * customEditors: {
  73. * evtStart: Ext.create('Ext.form.TimeField', {selectOnFocus: true})
  74. * },
  75. *
  76. * // Displayed name for property names in the source
  77. * propertyNames: {
  78. * evtStart: 'Start Time'
  79. * },
  80. *
  81. * // Data object containing properties to edit
  82. * source: {
  83. * evtStart: '10:00 AM'
  84. * }
  85. * });
  86. */
  87. <span id='Ext-grid-property-Grid-cfg-customRenderers'> /**
  88. </span> * @cfg {Object} customRenderers
  89. * An object containing name/value pairs of custom renderer type definitions that allow
  90. * the grid to support custom rendering of fields. By default, the grid supports strongly-typed rendering
  91. * of strings, dates, numbers and booleans using built-in form editors, but any custom type can be supported and
  92. * associated with the type of the value. The name of the renderer type should correspond with the name of the property
  93. * that it will render. Example usage:
  94. *
  95. * var grid = Ext.create('Ext.grid.property.Grid', {
  96. * customRenderers: {
  97. * Available: function(v){
  98. * if (v) {
  99. * return '&lt;span style=&quot;color: green;&quot;&gt;Yes&lt;/span&gt;';
  100. * } else {
  101. * return '&lt;span style=&quot;color: red;&quot;&gt;No&lt;/span&gt;';
  102. * }
  103. * }
  104. * },
  105. * source: {
  106. * Available: true
  107. * }
  108. * });
  109. */
  110. <span id='Ext-grid-property-Grid-cfg-valueField'> /**
  111. </span> * @cfg {String} valueField
  112. * The name of the field from the property store to use as the value field name.
  113. * This may be useful if you do not configure the property Grid from an object, but use your own store configuration.
  114. */
  115. valueField: 'value',
  116. <span id='Ext-grid-property-Grid-cfg-nameField'> /**
  117. </span> * @cfg {String} nameField
  118. * The name of the field from the property store to use as the property field name.
  119. * This may be useful if you do not configure the property Grid from an object, but use your own store configuration.
  120. */
  121. nameField: 'name',
  122. <span id='Ext-grid-property-Grid-cfg-nameColumnWidth'> /**
  123. </span> * @cfg {Number} [nameColumnWidth=115]
  124. * Specify the width for the name column. The value column will take any remaining space.
  125. */
  126. // private config overrides
  127. enableColumnMove: false,
  128. columnLines: true,
  129. stripeRows: false,
  130. trackMouseOver: false,
  131. clicksToEdit: 1,
  132. enableHdMenu: false,
  133. // private
  134. initComponent : function(){
  135. var me = this;
  136. me.addCls(Ext.baseCSSPrefix + 'property-grid');
  137. me.plugins = me.plugins || [];
  138. // Enable cell editing. Inject a custom startEdit which always edits column 1 regardless of which column was clicked.
  139. me.plugins.push(new Ext.grid.plugin.CellEditing({
  140. clicksToEdit: me.clicksToEdit,
  141. // Inject a startEdit which always edits the value column
  142. startEdit: function(record, column) {
  143. // Maintainer: Do not change this 'this' to 'me'! It is the CellEditing object's own scope.
  144. return this.self.prototype.startEdit.call(this, record, me.headerCt.child('#' + me.valueField));
  145. }
  146. }));
  147. me.selModel = {
  148. selType: 'cellmodel',
  149. onCellSelect: function(position) {
  150. if (position.column != 1) {
  151. position.column = 1;
  152. }
  153. return this.self.prototype.onCellSelect.call(this, position);
  154. }
  155. };
  156. me.customRenderers = me.customRenderers || {};
  157. me.customEditors = me.customEditors || {};
  158. // Create a property.Store from the source object unless configured with a store
  159. if (!me.store) {
  160. me.propStore = me.store = new Ext.grid.property.Store(me, me.source);
  161. }
  162. if (me.sortableColumns) {
  163. me.store.sort('name', 'ASC');
  164. }
  165. me.columns = new Ext.grid.property.HeaderContainer(me, me.store);
  166. me.addEvents(
  167. <span id='Ext-grid-property-Grid-event-beforepropertychange'> /**
  168. </span> * @event beforepropertychange
  169. * Fires before a property value changes. Handlers can return false to cancel the property change
  170. * (this will internally call {@link Ext.data.Model#reject} on the property's record).
  171. * @param {Object} source The source data object for the grid (corresponds to the same object passed in
  172. * as the {@link #source} config property).
  173. * @param {String} recordId The record's id in the data store
  174. * @param {Object} value The current edited property value
  175. * @param {Object} oldValue The original property value prior to editing
  176. */
  177. 'beforepropertychange',
  178. <span id='Ext-grid-property-Grid-event-propertychange'> /**
  179. </span> * @event propertychange
  180. * Fires after a property value has changed.
  181. * @param {Object} source The source data object for the grid (corresponds to the same object passed in
  182. * as the {@link #source} config property).
  183. * @param {String} recordId The record's id in the data store
  184. * @param {Object} value The current edited property value
  185. * @param {Object} oldValue The original property value prior to editing
  186. */
  187. 'propertychange'
  188. );
  189. me.callParent();
  190. // Inject a custom implementation of walkCells which only goes up or down
  191. me.getView().walkCells = this.walkCells;
  192. // Set up our default editor set for the 4 atomic data types
  193. me.editors = {
  194. 'date' : new Ext.grid.CellEditor({ field: new Ext.form.field.Date({selectOnFocus: true})}),
  195. 'string' : new Ext.grid.CellEditor({ field: new Ext.form.field.Text({selectOnFocus: true})}),
  196. 'number' : new Ext.grid.CellEditor({ field: new Ext.form.field.Number({selectOnFocus: true})}),
  197. 'boolean' : new Ext.grid.CellEditor({ field: new Ext.form.field.ComboBox({
  198. editable: false,
  199. store: [[ true, me.headerCt.trueText ], [false, me.headerCt.falseText ]]
  200. })})
  201. };
  202. // Track changes to the data so we can fire our events.
  203. me.store.on('update', me.onUpdate, me);
  204. },
  205. // private
  206. onUpdate : function(store, record, operation) {
  207. var me = this,
  208. v, oldValue;
  209. if (me.rendered &amp;&amp; operation == Ext.data.Model.EDIT) {
  210. v = record.get(me.valueField);
  211. oldValue = record.modified.value;
  212. if (me.fireEvent('beforepropertychange', me.source, record.getId(), v, oldValue) !== false) {
  213. if (me.source) {
  214. me.source[record.getId()] = v;
  215. }
  216. record.commit();
  217. me.fireEvent('propertychange', me.source, record.getId(), v, oldValue);
  218. } else {
  219. record.reject();
  220. }
  221. }
  222. },
  223. // Custom implementation of walkCells which only goes up and down.
  224. walkCells: function(pos, direction, e, preventWrap, verifierFn, scope) {
  225. if (direction == 'left') {
  226. direction = 'up';
  227. } else if (direction == 'right') {
  228. direction = 'down';
  229. }
  230. pos = Ext.view.Table.prototype.walkCells.call(this, pos, direction, e, preventWrap, verifierFn, scope);
  231. if (!pos.column) {
  232. pos.column = 1;
  233. }
  234. return pos;
  235. },
  236. // private
  237. // returns the correct editor type for the property type, or a custom one keyed by the property name
  238. getCellEditor : function(record, column) {
  239. var me = this,
  240. propName = record.get(me.nameField),
  241. val = record.get(me.valueField),
  242. editor = me.customEditors[propName];
  243. // A custom editor was found. If not already wrapped with a CellEditor, wrap it, and stash it back
  244. // If it's not even a Field, just a config object, instantiate it before wrapping it.
  245. if (editor) {
  246. if (!(editor instanceof Ext.grid.CellEditor)) {
  247. if (!(editor instanceof Ext.form.field.Base)) {
  248. editor = Ext.ComponentManager.create(editor, 'textfield');
  249. }
  250. editor = me.customEditors[propName] = new Ext.grid.CellEditor({ field: editor });
  251. }
  252. } else if (Ext.isDate(val)) {
  253. editor = me.editors.date;
  254. } else if (Ext.isNumber(val)) {
  255. editor = me.editors.number;
  256. } else if (Ext.isBoolean(val)) {
  257. editor = me.editors['boolean'];
  258. } else {
  259. editor = me.editors.string;
  260. }
  261. // Give the editor a unique ID because the CellEditing plugin caches them
  262. editor.editorId = propName;
  263. return editor;
  264. },
  265. beforeDestroy: function() {
  266. var me = this;
  267. me.callParent();
  268. me.destroyEditors(me.editors);
  269. me.destroyEditors(me.customEditors);
  270. delete me.source;
  271. },
  272. destroyEditors: function (editors) {
  273. for (var ed in editors) {
  274. if (editors.hasOwnProperty(ed)) {
  275. Ext.destroy(editors[ed]);
  276. }
  277. }
  278. },
  279. <span id='Ext-grid-property-Grid-method-setSource'> /**
  280. </span> * Sets the source data object containing the property data. The data object can contain one or more name/value
  281. * pairs representing all of the properties of an object to display in the grid, and this data will automatically
  282. * be loaded into the grid's {@link #store}. The values should be supplied in the proper data type if needed,
  283. * otherwise string type will be assumed. If the grid already contains data, this method will replace any
  284. * existing data. See also the {@link #source} config value. Example usage:
  285. *
  286. * grid.setSource({
  287. * &quot;(name)&quot;: &quot;My Object&quot;,
  288. * &quot;Created&quot;: Ext.Date.parse('10/15/2006', 'm/d/Y'), // date type
  289. * &quot;Available&quot;: false, // boolean type
  290. * &quot;Version&quot;: .01, // decimal type
  291. * &quot;Description&quot;: &quot;A test object&quot;
  292. * });
  293. *
  294. * @param {Object} source The data object
  295. */
  296. setSource: function(source) {
  297. this.source = source;
  298. this.propStore.setSource(source);
  299. },
  300. <span id='Ext-grid-property-Grid-method-getSource'> /**
  301. </span> * Gets the source data object containing the property data. See {@link #setSource} for details regarding the
  302. * format of the data object.
  303. * @return {Object} The data object
  304. */
  305. getSource: function() {
  306. return this.propStore.getSource();
  307. },
  308. <span id='Ext-grid-property-Grid-method-setProperty'> /**
  309. </span> * Sets the value of a property.
  310. * @param {String} prop The name of the property to set
  311. * @param {Object} value The value to test
  312. * @param {Boolean} [create=false] True to create the property if it doesn't already exist.
  313. */
  314. setProperty: function(prop, value, create) {
  315. this.propStore.setValue(prop, value, create);
  316. },
  317. <span id='Ext-grid-property-Grid-method-removeProperty'> /**
  318. </span> * Removes a property from the grid.
  319. * @param {String} prop The name of the property to remove
  320. */
  321. removeProperty: function(prop) {
  322. this.propStore.remove(prop);
  323. }
  324. <span id='Ext-grid-property-Grid-cfg-store'> /**
  325. </span> * @cfg store
  326. * @private
  327. */
  328. <span id='Ext-grid-property-Grid-cfg-columns'> /**
  329. </span> * @cfg columns
  330. * @private
  331. */
  332. });</pre>
  333. </body>
  334. </html>