dojo.provide("dojox.grid.cells._base"); dojo.require("dojox.grid.util"); (function(){ var focusSelectNode = function(inNode){ try{ dojox.grid.util.fire(inNode, "focus"); dojox.grid.util.fire(inNode, "select"); }catch(e){// IE sux bad } }; var whenIdle = function(/*inContext, inMethod, args ...*/){ setTimeout(dojo.hitch.apply(dojo, arguments), 0); }; var dgc = dojox.grid.cells; dojo.declare("dojox.grid.cells._Base", null, { // summary: // Respresents a grid cell and contains information about column options and methods // for retrieving cell related information. // Each column in a grid layout has a cell object and most events and many methods // provide access to these objects. styles: '', classes: '', editable: false, alwaysEditing: false, formatter: null, defaultValue: '...', value: null, hidden: false, //private _valueProp: "value", _formatPending: false, constructor: function(inProps){ this._props = inProps || {}; dojo.mixin(this, inProps); }, // data source format: function(inRowIndex, inItem){ // summary: // provides the html for a given grid cell. // inRowIndex: int // grid row index // returns: html for a given grid cell var f, i=this.grid.edit.info, d=this.get ? this.get(inRowIndex, inItem) : (this.value || this.defaultValue); if(this.editable && (this.alwaysEditing || (i.rowIndex==inRowIndex && i.cell==this))){ return this.formatEditing(d, inRowIndex); }else{ var v = (d != this.defaultValue && (f = this.formatter)) ? f.call(this, d, inRowIndex) : d; return (typeof v == "undefined" ? this.defaultValue : v); } }, formatEditing: function(inDatum, inRowIndex){ // summary: // formats the cell for editing // inDatum: anything // cell data to edit // inRowIndex: int // grid row index // returns: string of html to place in grid cell }, // utility getNode: function(inRowIndex){ // summary: // gets the dom node for a given grid cell. // inRowIndex: int // grid row index // returns: dom node for a given grid cell return this.view.getCellNode(inRowIndex, this.index); }, getHeaderNode: function(){ return this.view.getHeaderCellNode(this.index); }, getEditNode: function(inRowIndex){ return (this.getNode(inRowIndex) || 0).firstChild || 0; }, canResize: function(){ var uw = this.unitWidth; return uw && (uw=='auto'); }, isFlex: function(){ var uw = this.unitWidth; return uw && (uw=='auto' || uw.slice(-1)=='%'); }, // edit support applyEdit: function(inValue, inRowIndex){ this.grid.edit.applyCellEdit(inValue, this, inRowIndex); }, cancelEdit: function(inRowIndex){ this.grid.doCancelEdit(inRowIndex); }, _onEditBlur: function(inRowIndex){ if(this.grid.edit.isEditCell(inRowIndex, this.index)){ //console.log('editor onblur', e); this.grid.edit.apply(); } }, registerOnBlur: function(inNode, inRowIndex){ if(this.commitOnBlur){ dojo.connect(inNode, "onblur", function(e){ // hack: if editor still thinks this editor is current some ms after it blurs, assume we've focused away from grid setTimeout(dojo.hitch(this, "_onEditBlur", inRowIndex), 250); }); } }, //protected needFormatNode: function(inDatum, inRowIndex){ this._formatPending = true; whenIdle(this, "_formatNode", inDatum, inRowIndex); }, cancelFormatNode: function(){ this._formatPending = false; }, //private _formatNode: function(inDatum, inRowIndex){ if(this._formatPending){ this._formatPending = false; // make cell selectable dojo.setSelectable(this.grid.domNode, true); this.formatNode(this.getEditNode(inRowIndex), inDatum, inRowIndex); } }, //protected formatNode: function(inNode, inDatum, inRowIndex){ // summary: // format the editing dom node. Use when editor is a widget. // inNode: dom node // dom node for the editor // inDatum: anything // cell data to edit // inRowIndex: int // grid row index if(dojo.isIE){ // IE sux bad whenIdle(this, "focus", inRowIndex, inNode); }else{ this.focus(inRowIndex, inNode); } }, dispatchEvent: function(m, e){ if(m in this){ return this[m](e); } }, //public getValue: function(inRowIndex){ // summary: // returns value entered into editor // inRowIndex: int // grid row index // returns: // value of editor return this.getEditNode(inRowIndex)[this._valueProp]; }, setValue: function(inRowIndex, inValue){ // summary: // set the value of the grid editor // inRowIndex: int // grid row index // inValue: anything // value of editor var n = this.getEditNode(inRowIndex); if(n){ n[this._valueProp] = inValue }; }, focus: function(inRowIndex, inNode){ // summary: // focus the grid editor // inRowIndex: int // grid row index // inNode: dom node // editor node focusSelectNode(inNode || this.getEditNode(inRowIndex)); }, save: function(inRowIndex){ // summary: // save editor state // inRowIndex: int // grid row index this.value = this.value || this.getValue(inRowIndex); //console.log("save", this.value, inCell.index, inRowIndex); }, restore: function(inRowIndex){ // summary: // restore editor state // inRowIndex: int // grid row index this.setValue(inRowIndex, this.value); //console.log("restore", this.value, inCell.index, inRowIndex); }, //protected _finish: function(inRowIndex){ // summary: // called when editing is completed to clean up editor // inRowIndex: int // grid row index dojo.setSelectable(this.grid.domNode, false); this.cancelFormatNode(); }, //public apply: function(inRowIndex){ // summary: // apply edit from cell editor // inRowIndex: int // grid row index this.applyEdit(this.getValue(inRowIndex), inRowIndex); this._finish(inRowIndex); }, cancel: function(inRowIndex){ // summary: // cancel cell edit // inRowIndex: int // grid row index this.cancelEdit(inRowIndex); this._finish(inRowIndex); } }); dgc._Base.markupFactory = function(node, cellDef){ var d = dojo; var formatter = d.trim(d.attr(node, "formatter")||""); if(formatter){ cellDef.formatter = dojo.getObject(formatter); } var get = d.trim(d.attr(node, "get")||""); if(get){ cellDef.get = dojo.getObject(get); } var sortDesc = d.trim(d.attr(node, "sortDesc")||""); if(sortDesc){ cellDef.sortDesc = !(sortDesc.toLowerCase()=="false"); } var value = d.trim(d.attr(node, "loadingText")||d.attr(node, "defaultValue")||""); if(value){ cellDef.defaultValue = value; } var editable = d.trim(d.attr(node, "editable")||""); if(editable){ cellDef.editable = !(editable.toLowerCase()=="false"); } var alwaysEditing = d.trim(d.attr(node, "alwaysEditing")||""); if(alwaysEditing){ cellDef.alwaysEditing = !(alwaysEditing.toLowerCase()=="false"); } var styles = d.trim(d.attr(node, "styles")||""); if(styles){ cellDef.styles = styles; } var classes = d.trim(d.attr(node, "classes")||""); if(classes){ cellDef.classes = classes; } } dojo.declare("dojox.grid.cells.Cell", dgc._Base, { // summary // grid cell that provides a standard text input box upon editing constructor: function(){ this.keyFilter = this.keyFilter; }, // keyFilter: RegExp // optional regex for disallowing keypresses keyFilter: null, formatEditing: function(inDatum, inRowIndex){ this.needFormatNode(inDatum, inRowIndex); return ''; }, formatNode: function(inNode, inDatum, inRowIndex){ this.inherited(arguments); // FIXME: feels too specific for this interface this.registerOnBlur(inNode, inRowIndex); }, doKey: function(e){ if(this.keyFilter){ var key = String.fromCharCode(e.charCode); if(key.search(this.keyFilter) == -1){ dojo.stopEvent(e); } } }, _finish: function(inRowIndex){ this.inherited(arguments); var n = this.getEditNode(inRowIndex); try{ dojox.grid.util.fire(n, "blur"); }catch(e){} } }); dgc.Cell.markupFactory = function(node, cellDef){ dgc._Base.markupFactory(node, cellDef); var d = dojo; var keyFilter = d.trim(d.attr(node, "keyFilter")||""); if(keyFilter){ cellDef.keyFilter = new RegExp(keyFilter); } } dojo.declare("dojox.grid.cells.RowIndex", dgc.Cell, { name: 'Row', postscript: function(){ this.editable = false; }, get: function(inRowIndex){ return inRowIndex + 1; } }); dgc.RowIndex.markupFactory = function(node, cellDef){ dgc.Cell.markupFactory(node, cellDef); } dojo.declare("dojox.grid.cells.Select", dgc.Cell, { // summary: // grid cell that provides a standard select for editing // options: Array // text of each item options: null, // values: Array // value for each item values: null, // returnIndex: Integer // editor returns only the index of the selected option and not the value returnIndex: -1, constructor: function(inCell){ this.values = this.values || this.options; }, formatEditing: function(inDatum, inRowIndex){ this.needFormatNode(inDatum, inRowIndex); var h = [ ''); return h.join(''); }, getValue: function(inRowIndex){ var n = this.getEditNode(inRowIndex); if(n){ var i = n.selectedIndex, o = n.options[i]; return this.returnIndex > -1 ? i : o.value || o.innerHTML; } } }); dgc.Select.markupFactory = function(node, cell){ dgc.Cell.markupFactory(node, cell); var d=dojo; var options = d.trim(d.attr(node, "options")||""); if(options){ var o = options.split(','); if(o[0] != options){ cell.options = o; } } var values = d.trim(d.attr(node, "values")||""); if(values){ var v = values.split(','); if(v[0] != values){ cell.values = v; } } } dojo.declare("dojox.grid.cells.AlwaysEdit", dgc.Cell, { // summary: // grid cell that is always in an editable state, regardless of grid editing state alwaysEditing: true, _formatNode: function(inDatum, inRowIndex){ this.formatNode(this.getEditNode(inRowIndex), inDatum, inRowIndex); }, applyStaticValue: function(inRowIndex){ var e = this.grid.edit; e.applyCellEdit(this.getValue(inRowIndex), this, inRowIndex); e.start(this, inRowIndex, true); } }); dgc.AlwaysEdit.markupFactory = function(node, cell){ dgc.Cell.markupFactory(node, cell); } dojo.declare("dojox.grid.cells.Bool", dgc.AlwaysEdit, { // summary: // grid cell that provides a standard checkbox that is always on for editing _valueProp: "checked", formatEditing: function(inDatum, inRowIndex){ return ''; }, doclick: function(e){ if(e.target.tagName == 'INPUT'){ this.applyStaticValue(e.rowIndex); } } }); dgc.Bool.markupFactory = function(node, cell){ dgc.AlwaysEdit.markupFactory(node, cell); } })();