source: Dev/trunk/src/client/dojox/grid/cells/_base.js

Last change on this file was 483, checked in by hendrikvanantwerpen, 11 years ago

Added Dojo 1.9.3 release.

File size: 13.4 KB
Line 
1define([
2        "dojo/_base/kernel",
3        "dojo/_base/declare",
4        "dojo/_base/lang",
5        "dojo/_base/event",
6        "dojo/_base/connect",
7        "dojo/_base/array",
8        "dojo/_base/sniff",
9        "dojo/dom",
10        "dojo/dom-attr",
11        "dojo/dom-construct",
12        "dijit/_Widget",
13        "../util"
14], function(dojo, declare, lang, event, connect, array, has, dom, domAttr, domConstruct, _Widget, util){
15
16        var _DeferredTextWidget = declare("dojox.grid._DeferredTextWidget", _Widget, {
17                deferred: null,
18                _destroyOnRemove: true,
19                postCreate: function(){
20                        if(this.deferred){
21                                this.deferred.addBoth(lang.hitch(this, function(text){
22                                        if(this.domNode){
23                                                this.domNode.innerHTML = text;
24                                        }
25                                }));
26                        }
27                }
28        });
29
30        var focusSelectNode = function(inNode){
31                try{
32                        util.fire(inNode, "focus");
33                        util.fire(inNode, "select");
34                }catch(e){// IE sux bad
35                }
36        };
37       
38        var whenIdle = function(/*inContext, inMethod, args ...*/){
39                setTimeout(lang.hitch.apply(dojo, arguments), 0);
40        };
41
42        var BaseCell = declare("dojox.grid.cells._Base", null, {
43                // summary:
44                //              Represents a grid cell and contains information about column options and methods
45                //              for retrieving cell related information.
46                //              Each column in a grid layout has a cell object and most events and many methods
47                //              provide access to these objects.
48                styles: '',
49                classes: '',
50                editable: false,
51                alwaysEditing: false,
52                formatter: null,
53                defaultValue: '...',
54                value: null,
55                hidden: false,
56                noresize: false,
57                draggable: true,
58                //private
59                _valueProp: "value",
60                _formatPending: false,
61
62                constructor: function(inProps){
63                        this._props = inProps || {};
64                        lang.mixin(this, inProps);
65                        if(this.draggable === undefined){
66                                this.draggable = true;
67                        }
68                },
69
70                _defaultFormat: function(inValue, callArgs){
71                        var s = this.grid.formatterScope || this;
72                        var f = this.formatter;
73                        if(f && s && typeof f == "string"){
74                                f = this.formatter = s[f];
75                        }
76                        var v = (inValue != this.defaultValue && f) ? f.apply(s, callArgs) : inValue;
77                        if(typeof v == "undefined"){
78                                return this.defaultValue;
79                        }
80                        if(v && v.addBoth){
81                                // Check if it's a deferred
82                                v = new _DeferredTextWidget({deferred: v},
83                                                                        domConstruct.create("span", {innerHTML: this.defaultValue}));
84                        }
85                        if(v && v.declaredClass && v.startup){
86                                return "<div class='dojoxGridStubNode' linkWidget='" +
87                                                v.id +
88                                                "' cellIdx='" +
89                                                this.index +
90                                                "'>" +
91                                                this.defaultValue +
92                                                "</div>";
93                        }
94                        return v;
95                },
96               
97                // data source
98                format: function(inRowIndex, inItem){
99                        // summary:
100                        //              provides the html for a given grid cell.
101                        // inRowIndex: int
102                        //              grid row index
103                        // returns:
104                        //              html for a given grid cell
105                        var f, i=this.grid.edit.info, d=this.get ? this.get(inRowIndex, inItem) : (this.value || this.defaultValue);
106                        d = (d && d.replace && this.grid.escapeHTMLInData) ? d.replace(/&/g, '&amp;').replace(/</g, '&lt;') : d;
107                        if(this.editable && (this.alwaysEditing || (i.rowIndex==inRowIndex && i.cell==this))){
108                                return this.formatEditing(i.value ? i.value : d, inRowIndex);
109                        }else{
110                                return this._defaultFormat(d, [d, inRowIndex, this]);
111                        }
112                },
113                formatEditing: function(inDatum, inRowIndex){
114                        // summary:
115                        //              formats the cell for editing
116                        // inDatum: anything
117                        //              cell data to edit
118                        // inRowIndex: int
119                        //              grid row index
120                        // returns:
121                        //              string of html to place in grid cell
122                },
123                // utility
124                getNode: function(inRowIndex){
125                        // summary:
126                        //              gets the dom node for a given grid cell.
127                        // inRowIndex: int
128                        //              grid row index
129                        // returns:
130                        //              dom node for a given grid cell
131                        return this.view.getCellNode(inRowIndex, this.index);
132                },
133                getHeaderNode: function(){
134                        return this.view.getHeaderCellNode(this.index);
135                },
136                getEditNode: function(inRowIndex){
137                        return (this.getNode(inRowIndex) || 0).firstChild || 0;
138                },
139                canResize: function(){
140                        var uw = this.unitWidth;
141                        return uw && (uw!=='auto');
142                },
143                isFlex: function(){
144                        var uw = this.unitWidth;
145                        return uw && lang.isString(uw) && (uw=='auto' || uw.slice(-1)=='%');
146                },
147                // edit support
148                applyEdit: function(inValue, inRowIndex){
149                        if(this.getNode(inRowIndex)){
150                                this.grid.edit.applyCellEdit(inValue, this, inRowIndex);
151                        }
152                },
153                cancelEdit: function(inRowIndex){
154                        this.grid.doCancelEdit(inRowIndex);
155                },
156                _onEditBlur: function(inRowIndex){
157                        if(this.grid.edit.isEditCell(inRowIndex, this.index)){
158                                //console.log('editor onblur', e);
159                                this.grid.edit.apply();
160                        }
161                },
162                registerOnBlur: function(inNode, inRowIndex){
163                        if(this.commitOnBlur){
164                                connect.connect(inNode, "onblur", function(e){
165                                        // hack: if editor still thinks this editor is current some ms after it blurs, assume we've focused away from grid
166                                        setTimeout(lang.hitch(this, "_onEditBlur", inRowIndex), 250);
167                                });
168                        }
169                },
170                //protected
171                needFormatNode: function(inDatum, inRowIndex){
172                        this._formatPending = true;
173                        whenIdle(this, "_formatNode", inDatum, inRowIndex);
174                },
175                cancelFormatNode: function(){
176                        this._formatPending = false;
177                },
178                //private
179                _formatNode: function(inDatum, inRowIndex){
180                        if(this._formatPending){
181                                this._formatPending = false;
182                                // make cell selectable
183                                if(!has('ie')){
184                                        dom.setSelectable(this.grid.domNode, true);
185                                }
186                                this.formatNode(this.getEditNode(inRowIndex), inDatum, inRowIndex);
187                        }
188                },
189                //protected
190                formatNode: function(inNode, inDatum, inRowIndex){
191                        // summary:
192                        //              format the editing dom node. Use when editor is a widget.
193                        // inNode: dom node
194                        //              dom node for the editor
195                        // inDatum: anything
196                        //              cell data to edit
197                        // inRowIndex: int
198                        //              grid row index
199                        if(has('ie')){
200                                // IE sux bad
201                                whenIdle(this, "focus", inRowIndex, inNode);
202                        }else{
203                                this.focus(inRowIndex, inNode);
204                        }
205                },
206                dispatchEvent: function(m, e){
207                        if(m in this){
208                                return this[m](e);
209                        }
210                },
211                //public
212                getValue: function(inRowIndex){
213                        // summary:
214                        //              returns value entered into editor
215                        // inRowIndex: int
216                        //              grid row index
217                        // returns:
218                        //              value of editor
219                        return this.getEditNode(inRowIndex)[this._valueProp];
220                },
221                setValue: function(inRowIndex, inValue){
222                        // summary:
223                        //              set the value of the grid editor
224                        // inRowIndex: int
225                        //              grid row index
226                        // inValue: anything
227                        //              value of editor
228                        var n = this.getEditNode(inRowIndex);
229                        if(n){
230                                n[this._valueProp] = inValue;
231                        }
232                },
233                focus: function(inRowIndex, inNode){
234                        // summary:
235                        //              focus the grid editor
236                        // inRowIndex: int
237                        //              grid row index
238                        // inNode: dom node
239                        //              editor node
240                        focusSelectNode(inNode || this.getEditNode(inRowIndex));
241                },
242                save: function(inRowIndex){
243                        // summary:
244                        //              save editor state
245                        // inRowIndex: int
246                        //              grid row index
247                        this.value = this.value || this.getValue(inRowIndex);
248                        //console.log("save", this.value, inCell.index, inRowIndex);
249                },
250                restore: function(inRowIndex){
251                        // summary:
252                        //              restore editor state
253                        // inRowIndex: int
254                        //              grid row index
255                        this.setValue(inRowIndex, this.value);
256                        //console.log("restore", this.value, inCell.index, inRowIndex);
257                },
258                //protected
259                _finish: function(inRowIndex){
260                        // summary:
261                        //              called when editing is completed to clean up editor
262                        // inRowIndex: int
263                        //              grid row index
264                        dom.setSelectable(this.grid.domNode, false);
265                        this.cancelFormatNode();
266                },
267                //public
268                apply: function(inRowIndex){
269                        // summary:
270                        //              apply edit from cell editor
271                        // inRowIndex: int
272                        //              grid row index
273                        this.applyEdit(this.getValue(inRowIndex), inRowIndex);
274                        this._finish(inRowIndex);
275                },
276                cancel: function(inRowIndex){
277                        // summary:
278                        //              cancel cell edit
279                        // inRowIndex: int
280                        //              grid row index
281                        this.cancelEdit(inRowIndex);
282                        this._finish(inRowIndex);
283                }
284        });
285        BaseCell.markupFactory = function(node, cellDef){
286                var formatter = lang.trim(domAttr.get(node, "formatter")||"");
287                if(formatter){
288                        cellDef.formatter = lang.getObject(formatter)||formatter;
289                }
290                var get = lang.trim(domAttr.get(node, "get")||"");
291                if(get){
292                        cellDef.get = lang.getObject(get);
293                }
294                var getBoolAttr = function(attr, cell, cellAttr){
295                        var value = lang.trim(domAttr.get(node, attr)||"");
296                        if(value){ cell[cellAttr||attr] = !(value.toLowerCase()=="false"); }
297                };
298                getBoolAttr("sortDesc", cellDef);
299                getBoolAttr("editable", cellDef);
300                getBoolAttr("alwaysEditing", cellDef);
301                getBoolAttr("noresize", cellDef);
302                getBoolAttr("draggable", cellDef);
303
304                var value = lang.trim(domAttr.get(node, "loadingText")||domAttr.get(node, "defaultValue")||"");
305                if(value){
306                        cellDef.defaultValue = value;
307                }
308
309                var getStrAttr = function(attr, cell, cellAttr){
310                        var value = lang.trim(domAttr.get(node, attr)||"")||undefined;
311                        if(value){ cell[cellAttr||attr] = value; }
312                };
313                getStrAttr("styles", cellDef);
314                getStrAttr("headerStyles", cellDef);
315                getStrAttr("cellStyles", cellDef);
316                getStrAttr("classes", cellDef);
317                getStrAttr("headerClasses", cellDef);
318                getStrAttr("cellClasses", cellDef);
319        };
320
321        var Cell = BaseCell.Cell = declare("dojox.grid.cells.Cell", BaseCell, {
322                // summary:
323                //              grid cell that provides a standard text input box upon editing
324                constructor: function(){
325                        this.keyFilter = this.keyFilter;
326                },
327                // keyFilter: RegExp
328                //              optional regex for disallowing keypresses
329                keyFilter: null,
330                formatEditing: function(inDatum, inRowIndex){
331                        this.needFormatNode(inDatum, inRowIndex);
332                        return '<input class="dojoxGridInput" type="text" value="' + inDatum + '">';
333                },
334                formatNode: function(inNode, inDatum, inRowIndex){
335                        this.inherited(arguments);
336                        // FIXME: feels too specific for this interface
337                        this.registerOnBlur(inNode, inRowIndex);
338                },
339                doKey: function(e){
340                        if(this.keyFilter){
341                                var key = String.fromCharCode(e.charCode);
342                                if(key.search(this.keyFilter) == -1){
343                                        event.stop(e);
344                                }
345                        }
346                },
347                _finish: function(inRowIndex){
348                        this.inherited(arguments);
349                        var n = this.getEditNode(inRowIndex);
350                        try{
351                                util.fire(n, "blur");
352                        }catch(e){}
353                }
354        });
355        Cell.markupFactory = function(node, cellDef){
356                BaseCell.markupFactory(node, cellDef);
357                var keyFilter = lang.trim(domAttr.get(node, "keyFilter")||"");
358                if(keyFilter){
359                        cellDef.keyFilter = new RegExp(keyFilter);
360                }
361        };
362
363        var RowIndex = BaseCell.RowIndex = declare("dojox.grid.cells.RowIndex", Cell, {
364                name: 'Row',
365
366                postscript: function(){
367                        this.editable = false;
368                },
369                get: function(inRowIndex){
370                        return inRowIndex + 1;
371                }
372        });
373        RowIndex.markupFactory = function(node, cellDef){
374                Cell.markupFactory(node, cellDef);
375        };
376
377        var Select = BaseCell.Select = declare("dojox.grid.cells.Select", Cell, {
378                // summary:
379                //              grid cell that provides a standard select for editing
380
381                // options: Array
382                //              text of each item
383                options: null,
384
385                // values: Array
386                //              value for each item
387                values: null,
388
389                // returnIndex: Integer
390                //              editor returns only the index of the selected option and not the value
391                returnIndex: -1,
392
393                constructor: function(inCell){
394                        this.values = this.values || this.options;
395                },
396                formatEditing: function(inDatum, inRowIndex){
397                        this.needFormatNode(inDatum, inRowIndex);
398                        var h = [ '<select class="dojoxGridSelect">' ];
399                        for (var i=0, o, v; ((o=this.options[i]) !== undefined)&&((v=this.values[i]) !== undefined); i++){
400                                v = v.replace ? v.replace(/&/g, '&amp;').replace(/</g, '&lt;') : v;
401                                o = o.replace ? o.replace(/&/g, '&amp;').replace(/</g, '&lt;') : o;
402                                h.push("<option", (inDatum==v ? ' selected' : ''), ' value="' + v + '"', ">", o, "</option>");
403                        }
404                        h.push('</select>');
405                        return h.join('');
406                },
407                _defaultFormat: function(inValue, callArgs){
408                        var v = this.inherited(arguments);
409                        // when 'values' and 'options' both provided and there is no cutomized formatter,
410                        // then we use 'options' as label in order to be consistent
411                        if(!this.formatter && this.values && this.options){
412                                var i = array.indexOf(this.values, v);
413                                if(i >= 0){
414                                        v = this.options[i];
415                                }
416                        }
417                        return v;
418                },
419                getValue: function(inRowIndex){
420                        var n = this.getEditNode(inRowIndex);
421                        if(n){
422                                var i = n.selectedIndex, o = n.options[i];
423                                return this.returnIndex > -1 ? i : o.value || o.innerHTML;
424                        }
425                }
426        });
427        Select.markupFactory = function(node, cell){
428                Cell.markupFactory(node, cell);
429                var options = lang.trim(domAttr.get(node, "options")||"");
430                if(options){
431                        var o = options.split(',');
432                        if(o[0] != options){
433                                cell.options = o;
434                        }
435                }
436                var values = lang.trim(domAttr.get(node, "values")||"");
437                if(values){
438                        var v = values.split(',');
439                        if(v[0] != values){
440                                cell.values = v;
441                        }
442                }
443        };
444
445        var AlwaysEdit = BaseCell.AlwaysEdit = declare("dojox.grid.cells.AlwaysEdit", Cell, {
446                // summary:
447                //              grid cell that is always in an editable state, regardless of grid editing state
448                alwaysEditing: true,
449                _formatNode: function(inDatum, inRowIndex){
450                        this.formatNode(this.getEditNode(inRowIndex), inDatum, inRowIndex);
451                },
452                applyStaticValue: function(inRowIndex){
453                        var e = this.grid.edit;
454                        e.applyCellEdit(this.getValue(inRowIndex), this, inRowIndex);
455                        e.start(this, inRowIndex, true);
456                }
457        });
458        AlwaysEdit.markupFactory = function(node, cell){
459                Cell.markupFactory(node, cell);
460        };
461
462        var Bool = BaseCell.Bool = declare("dojox.grid.cells.Bool", AlwaysEdit, {
463                // summary:
464                //              grid cell that provides a standard checkbox that is always on for editing
465                _valueProp: "checked",
466                formatEditing: function(inDatum, inRowIndex){
467                        return '<input class="dojoxGridInput" type="checkbox"' + (inDatum ? ' checked="checked"' : '') + ' style="width: auto" />';
468                },
469                doclick: function(e){
470                        if(e.target.tagName == 'INPUT'){
471                                this.applyStaticValue(e.rowIndex);
472                        }
473                }
474        });
475        Bool.markupFactory = function(node, cell){
476                AlwaysEdit.markupFactory(node, cell);
477        };
478
479        return BaseCell;
480
481});
Note: See TracBrowser for help on using the repository browser.