initial import
[roojs1] / Roo / grid / PropertyGrid.js
1 /*
2  * Based on:
3  * Ext JS Library 1.1.1
4  * Copyright(c) 2006-2007, Ext JS, LLC.
5  *
6  * Originally Released Under LGPL - original licence link has changed is not relivant.
7  *
8  * Fork - LGPL
9  * <script type="text/javascript">
10  */
11   
12
13   
14 Roo.grid.PropertyRecord = Roo.data.Record.create([
15     {name:'name',type:'string'},  'value'
16 ]);
17
18
19 Roo.grid.PropertyStore = function(grid, source){
20     this.grid = grid;
21     this.store = new Roo.data.Store({
22         recordType : Roo.grid.PropertyRecord
23     });
24     this.store.on('update', this.onUpdate,  this);
25     if(source){
26         this.setSource(source);
27     }
28     Roo.grid.PropertyStore.superclass.constructor.call(this);
29 };
30
31
32
33 Roo.extend(Roo.grid.PropertyStore, Roo.util.Observable, {
34     setSource : function(o){
35         this.source = o;
36         this.store.removeAll();
37         var data = [];
38         for(var k in o){
39             if(this.isEditableValue(o[k])){
40                 data.push(new Roo.grid.PropertyRecord({name: k, value: o[k]}, k));
41             }
42         }
43         this.store.loadRecords({records: data}, {}, true);
44     },
45
46     onUpdate : function(ds, record, type){
47         if(type == Roo.data.Record.EDIT){
48             var v = record.data['value'];
49             var oldValue = record.modified['value'];
50             if(this.grid.fireEvent('beforepropertychange', this.source, record.id, v, oldValue) !== false){
51                 this.source[record.id] = v;
52                 record.commit();
53                 this.grid.fireEvent('propertychange', this.source, record.id, v, oldValue);
54             }else{
55                 record.reject();
56             }
57         }
58     },
59
60     getProperty : function(row){
61        return this.store.getAt(row);
62     },
63
64     isEditableValue: function(val){
65         if(val && val instanceof Date){
66             return true;
67         }else if(typeof val == 'object' || typeof val == 'function'){
68             return false;
69         }
70         return true;
71     },
72
73     setValue : function(prop, value){
74         this.source[prop] = value;
75         this.store.getById(prop).set('value', value);
76     },
77
78     getSource : function(){
79         return this.source;
80     }
81 });
82
83 Roo.grid.PropertyColumnModel = function(grid, store){
84     this.grid = grid;
85     var g = Roo.grid;
86     g.PropertyColumnModel.superclass.constructor.call(this, [
87         {header: this.nameText, sortable: true, dataIndex:'name', id: 'name'},
88         {header: this.valueText, resizable:false, dataIndex: 'value', id: 'value'}
89     ]);
90     this.store = store;
91     this.bselect = Roo.DomHelper.append(document.body, {
92         tag: 'select', style:'display:none', cls: 'x-grid-editor', children: [
93             {tag: 'option', value: 'true', html: 'true'},
94             {tag: 'option', value: 'false', html: 'false'}
95         ]
96     });
97     Roo.id(this.bselect);
98     var f = Roo.form;
99     this.editors = {
100         'date' : new g.GridEditor(new f.DateField({selectOnFocus:true})),
101         'string' : new g.GridEditor(new f.TextField({selectOnFocus:true})),
102         'number' : new g.GridEditor(new f.NumberField({selectOnFocus:true, style:'text-align:left;'})),
103         'int' : new g.GridEditor(new f.NumberField({selectOnFocus:true, allowDecimals:false, style:'text-align:left;'})),
104         'boolean' : new g.GridEditor(new f.Field({el:this.bselect,selectOnFocus:true}))
105     };
106     this.renderCellDelegate = this.renderCell.createDelegate(this);
107     this.renderPropDelegate = this.renderProp.createDelegate(this);
108 };
109
110 Roo.extend(Roo.grid.PropertyColumnModel, Roo.grid.ColumnModel, {
111     
112     
113     nameText : 'Name',
114     valueText : 'Value',
115     
116     dateFormat : 'm/j/Y',
117     
118     
119     renderDate : function(dateVal){
120         return dateVal.dateFormat(this.dateFormat);
121     },
122
123     renderBool : function(bVal){
124         return bVal ? 'true' : 'false';
125     },
126
127     isCellEditable : function(colIndex, rowIndex){
128         return colIndex == 1;
129     },
130
131     getRenderer : function(col){
132         return col == 1 ?
133             this.renderCellDelegate : this.renderPropDelegate;
134     },
135
136     renderProp : function(v){
137         return this.getPropertyName(v);
138     },
139
140     renderCell : function(val){
141         var rv = val;
142         if(val instanceof Date){
143             rv = this.renderDate(val);
144         }else if(typeof val == 'boolean'){
145             rv = this.renderBool(val);
146         }
147         return Roo.util.Format.htmlEncode(rv);
148     },
149
150     getPropertyName : function(name){
151         var pn = this.grid.propertyNames;
152         return pn && pn[name] ? pn[name] : name;
153     },
154
155     getCellEditor : function(colIndex, rowIndex){
156         var p = this.store.getProperty(rowIndex);
157         var n = p.data['name'], val = p.data['value'];
158         
159         if(typeof(this.grid.customEditors[n]) == 'string'){
160             return this.editors[this.grid.customEditors[n]];
161         }
162         if(typeof(this.grid.customEditors[n]) != 'undefined'){
163             return this.grid.customEditors[n];
164         }
165         if(val instanceof Date){
166             return this.editors['date'];
167         }else if(typeof val == 'number'){
168             return this.editors['number'];
169         }else if(typeof val == 'boolean'){
170             return this.editors['boolean'];
171         }else{
172             return this.editors['string'];
173         }
174     }
175 });
176
177 /**
178  * @class Roo.grid.PropertyGrid
179  * @extends Roo.grid.EditorGrid
180  * This class represents the  interface of a component based property grid control.
181  * <br><br>Usage:<pre><code>
182  var grid = new Roo.grid.PropertyGrid("my-container-id", {
183       
184  });
185  // set any options
186  grid.render();
187  * </code></pre>
188   
189  * @constructor
190  * @param {String/HTMLElement/Roo.Element} container The element into which this grid will be rendered -
191  * The container MUST have some type of size defined for the grid to fill. The container will be
192  * automatically set to position relative if it isn't already.
193  * @param {Object} config A config object that sets properties on this grid.
194  */
195 Roo.grid.PropertyGrid = function(container, config){
196     config = config || {};
197     var store = new Roo.grid.PropertyStore(this);
198     this.store = store;
199     var cm = new Roo.grid.PropertyColumnModel(this, store);
200     store.store.sort('name', 'ASC');
201     Roo.grid.PropertyGrid.superclass.constructor.call(this, container, Roo.apply({
202         ds: store.store,
203         cm: cm,
204         enableColLock:false,
205         enableColumnMove:false,
206         stripeRows:false,
207         trackMouseOver: false,
208         clicksToEdit:1
209     }, config));
210     this.getGridEl().addClass('x-props-grid');
211     this.lastEditRow = null;
212     this.on('columnresize', this.onColumnResize, this);
213     this.addEvents({
214          /**
215              * @event beforepropertychange
216              * Fires before a property changes (return false to stop?)
217              * @param {Roo.grid.PropertyGrid} grid property grid? (check could be store)
218              * @param {String} id Record Id
219              * @param {String} newval New Value
220          * @param {String} oldval Old Value
221              */
222         "beforepropertychange": true,
223         /**
224              * @event propertychange
225              * Fires after a property changes
226              * @param {Roo.grid.PropertyGrid} grid property grid? (check could be store)
227              * @param {String} id Record Id
228              * @param {String} newval New Value
229          * @param {String} oldval Old Value
230              */
231         "propertychange": true
232     });
233     this.customEditors = this.customEditors || {};
234 };
235 Roo.extend(Roo.grid.PropertyGrid, Roo.grid.EditorGrid, {
236     
237      /**
238      * @cfg {Object} customEditors map of colnames=> custom editors.
239      * the custom editor can be one of the standard ones (date|string|number|int|boolean), or a
240      * grid editor eg. Roo.grid.GridEditor(new Roo.form.TextArea({selectOnFocus:true})),
241      * false disables editing of the field.
242          */
243     
244       /**
245      * @cfg {Object} propertyNames map of property Names to their displayed value
246          */
247     
248     render : function(){
249         Roo.grid.PropertyGrid.superclass.render.call(this);
250         this.autoSize.defer(100, this);
251     },
252
253     autoSize : function(){
254         Roo.grid.PropertyGrid.superclass.autoSize.call(this);
255         if(this.view){
256             this.view.fitColumns();
257         }
258     },
259
260     onColumnResize : function(){
261         this.colModel.setColumnWidth(1, this.container.getWidth(true)-this.colModel.getColumnWidth(0));
262         this.autoSize();
263     },
264     /**
265      * Sets the data for the Grid
266      * accepts a Key => Value object of all the elements avaiable.
267      * @param {Object} data  to appear in grid.
268      */
269     setSource : function(source){
270         this.store.setSource(source);
271         //this.autoSize();
272     },
273     /**
274      * Gets all the data from the grid.
275      * @return {Object} data  data stored in grid
276      */
277     getSource : function(){
278         return this.store.getSource();
279     }
280 });