diff options
Diffstat (limited to 'includes/js/dojox/grid/tests/databaseModel.js')
-rw-r--r-- | includes/js/dojox/grid/tests/databaseModel.js | 337 |
1 files changed, 337 insertions, 0 deletions
diff --git a/includes/js/dojox/grid/tests/databaseModel.js b/includes/js/dojox/grid/tests/databaseModel.js new file mode 100644 index 0000000..3c879eb --- /dev/null +++ b/includes/js/dojox/grid/tests/databaseModel.js @@ -0,0 +1,337 @@ +if(!dojo._hasResource["dojox.grid.tests.databaseModel"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code. +dojo._hasResource["dojox.grid.tests.databaseModel"] = true; +dojo.provide("dojox.grid.tests.databaseModel"); +dojo.require("dojox.grid._data.model"); + +// Provides a sparse array that is also traversable inorder +// with basic Array: +// - iterating by index is slow for large sparse arrays +// - for...in iteration is in order of element creation +// maintains a secondary index for interating +// over sparse elements inorder +dojo.declare("dojox.grid.Sparse", null, { + constructor: function() { + this.clear(); + }, + clear: function() { + this.indices = []; + this.values = []; + }, + length: function() { + return this.indices.length; + }, + set: function(inIndex, inValue) { + for (var i=0,l=this.indices.length; i<l; i++) { + if (this.indices[i] >= inIndex) + break; + } + if (this.indices[i] != inIndex) + this.indices.splice(i, 0, inIndex); + this.values[inIndex] = inValue; + }, + get: function(inIndex) { + return this.values[inIndex]; + }, + remove: function(inIndex) { + for (var i=0,l=this.indices.length; i<l; i++) + if (this.indices[i] == inIndex) { + this.indices.splice(i, 1); + break; + } + delete this.values[inIndex]; + }, + inorder: function(inFor) { + for (var i=0,l=this.indices.length, ix; i<l; i++) { + ix = this.indices[i]; + if (inFor(this.values[ix], ix) === false) + break; + } + } +}); + +// sample custom model implementation that works with mysql server. +dojo.declare("dojox.grid.data.DbTable", dojox.grid.data.Dynamic, { + delayedInsertCommit: true, + constructor: function(inFields, inData, inServer, inDatabase, inTable) { + this.server = inServer; + this.database = inDatabase; + this.table = inTable; + this.stateNames = ['inflight', 'inserting', 'removing', 'error']; + this.clearStates(); + this.clearSort(); + }, + clearData: function() { + this.cache = [ ]; + this.clearStates(); + this.inherited(arguments); + }, + clearStates: function() { + this.states = {}; + for (var i=0, s; (s=this.stateNames[i]); i++) { + delete this.states[s]; + this.states[s] = new dojox.grid.Sparse(); + } + }, + // row state information + getState: function(inRowIndex) { + for (var i=0, r={}, s; (s=this.stateNames[i]); i++) + r[s] = this.states[s].get(inRowIndex); + return r; + }, + setState: function(inRowIndex, inState, inValue) { + this.states[inState].set(inRowIndex, inValue||true); + }, + clearState: function(inRowIndex, inState) { + if (arguments.length == 1) { + for (var i=0, s; (s=this.stateNames[i]); i++) + this.states[s].remove(inRowIndex); + } else { + for (var i=1, l=arguments.length, arg; (i<l) &&((arg=arguments[i])!=undefined); i++) + this.states[arg].remove(inRowIndex); + } + }, + setStateForIndexes: function(inRowIndexes, inState, inValue) { + for (var i=inRowIndexes.length-1, k; (i>=0) && ((k=inRowIndexes[i])!=undefined); i--) + this.setState(k, inState, inValue); + }, + clearStateForIndexes: function(inRowIndexes, inState) { + for (var i=inRowIndexes.length-1, k; (i>=0) && ((k=inRowIndexes[i])!=undefined); i--) + this.clearState(k, inState); + }, + //$ Return boolean stating whether or not an operation is in progress that may change row indexing. + isAddRemoving: function() { + return Boolean(this.states['inserting'].length() || this.states['removing'].length()); + }, + isInflight: function() { + return Boolean(this.states['inflight'].length()); + }, + //$ Return boolean stating if the model is currently undergoing any type of edit. + isEditing: function() { + for (var i=0, r={}, s; (s=this.stateNames[i]); i++) + if (this.states[s].length()) + return true; + }, + //$ Return true if ok to modify the given row. Override as needed, using model editing state information. + canModify: function(inRowIndex) { + return !this.getState(inRowIndex).inflight && !(this.isInflight() && this.isAddRemoving()); + }, + // server send / receive + getSendParams: function(inParams) { + var p = { + database: this.database || '', + table: this.table || '' + } + return dojo.mixin(p, inParams || {}); + }, + send: function(inAsync, inParams, inCallbacks) { + //console.log('send', inParams.command); + var p = this.getSendParams(inParams); + var d = dojo.xhrPost({ + url: this.server, + content: p, + handleAs: 'json-comment-filtered', + contentType: "application/x-www-form-urlencoded; charset=utf-8", + sync: !inAsync + }); + d.addCallbacks(dojo.hitch(this, "receive", inCallbacks), dojo.hitch(this, "receiveError", inCallbacks)); + return d; + }, + _callback: function(cb, eb, data) { + try{ cb && cb(data); } + catch(e){ eb && eb(data, e); } + }, + receive: function(inCallbacks, inData) { + inCallbacks && this._callback(inCallbacks.callback, inCallbacks.errback, inData); + }, + receiveError: function(inCallbacks, inErr) { + this._callback(inCallbacks.errback, null, inErr) + }, + encodeRow: function(inParams, inRow, inPrefix) { + for (var i=0, l=inRow.length; i < l; i++) + inParams['_' + (inPrefix ? inPrefix : '') + i] = (inRow[i] ? inRow[i] : ''); + }, + measure: function() { + this.send(true, { command: 'info' }, { callback: dojo.hitch(this, this.callbacks.info) }); + }, + fetchRowCount: function(inCallbacks) { + this.send(true, { command: 'count' }, inCallbacks); + }, + // server commits + commitEdit: function(inOldData, inNewData, inRowIndex, inCallbacks) { + this.setState(inRowIndex, "inflight", true); + var params = {command: 'update'}; + this.encodeRow(params, inOldData, 'o'); + this.encodeRow(params, inNewData); + this.send(true, params, inCallbacks); + }, + commitInsert: function(inRowIndex, inNewData, inCallbacks) { + this.setState(inRowIndex, "inflight", true); + var params = {command: 'insert'}; + this.encodeRow(params, inNewData); + this.send(true, params, inCallbacks); + }, + // NOTE: supported only in tables with pk + commitDelete: function(inRows, inCallbacks) { + var params = { + command: 'delete', + count: inRows.length + } + var pk = this.getPkIndex(); + if (pk < 0) + return; + for (var i=0; i < inRows.length; i++) { + params['_' + i] = inRows[i][pk]; + } + this.send(true, params, inCallbacks); + }, + getUpdateCallbacks: function(inRowIndex) { + return { + callback: dojo.hitch(this, this.callbacks.update, inRowIndex), + errback: dojo.hitch(this, this.callbacks.updateError, inRowIndex) + }; + }, + // primary key from fields + getPkIndex: function() { + for (var i=0, l=this.fields.count(), f; (i<l) && (f=this.fields.get(i)); i++) + if (f.Key = 'PRI') + return i; + return -1; + }, + // model implementations + update: function(inOldData, inNewData, inRowIndex) { + var cbs = this.getUpdateCallbacks(inRowIndex); + if (this.getState(inRowIndex).inserting) + this.commitInsert(inRowIndex, inNewData, cbs); + else + this.commitEdit(this.cache[inRowIndex] || inOldData, inNewData, inRowIndex, cbs); + // set push data immediately to model so reflectd while committing + this.setRow(inNewData, inRowIndex); + }, + insert: function(inData, inRowIndex) { + this.setState(inRowIndex, 'inserting', true); + if (!this.delayedInsertCommit) + this.commitInsert(inRowIndex, inData, this.getUpdateCallbacks(inRowIndex)); + return this.inherited(arguments); + }, + remove: function(inRowIndexes) { + var rows = []; + for (var i=0, r=0, indexes=[]; (r=inRowIndexes[i]) !== undefined; i++) + if (!this.getState(r).inserting) { + rows.push(this.getRow(r)); + indexes.push(r); + this.setState(r, 'removing'); + } + var cbs = { + callback: dojo.hitch(this, this.callbacks.remove, indexes), + errback: dojo.hitch(this, this.callbacks.removeError, indexes) + }; + this.commitDelete(rows, cbs); + dojox.grid.data.Dynamic.prototype.remove.apply(this, arguments); + }, + cancelModifyRow: function(inRowIndex) { + if (this.isDelayedInsert(inRowIndex)) { + this.removeInsert(inRowIndex); + } else + this.finishUpdate(inRowIndex); + }, + finishUpdate: function(inRowIndex, inData) { + this.clearState(inRowIndex); + var d = (inData&&inData[0]) || this.cache[inRowIndex]; + if (d) + this.setRow(d, inRowIndex); + delete this.cache[inRowIndex]; + }, + isDelayedInsert: function(inRowIndex) { + return (this.delayedInsertCommit && this.getState(inRowIndex).inserting); + }, + removeInsert: function(inRowIndex) { + this.clearState(inRowIndex); + dojox.grid.data.Dynamic.prototype.remove.call(this, [inRowIndex]); + }, + // request data + requestRows: function(inRowIndex, inCount) { + var params = { + command: 'select', + orderby: this.sortField, + desc: (this.sortDesc ? "true" : ''), + offset: inRowIndex, + limit: inCount + } + this.send(true, params, {callback: dojo.hitch(this, this.callbacks.rows, inRowIndex)}); + }, + // sorting + canSort: function () { + return true; + }, + setSort: function(inSortIndex) { + this.sortField = this.fields.get(Math.abs(inSortIndex) - 1).name || inSortIndex; + this.sortDesc = (inSortIndex < 0); + }, + sort: function(inSortIndex) { + this.setSort(inSortIndex); + this.clearData(); + }, + clearSort: function(){ + this.sortField = ''; + this.sortDesc = false; + }, + endModifyRow: function(inRowIndex){ + var cache = this.cache[inRowIndex]; + var m = false; + if(cache){ + var data = this.getRow(inRowIndex); + if(!dojox.grid.arrayCompare(cache, data)){ + m = true; + this.update(cache, data, inRowIndex); + } + } + if (!m) + this.cancelModifyRow(inRowIndex); + }, + // server callbacks (called with this == model) + callbacks: { + update: function(inRowIndex, inData) { + console.log('received update', arguments); + if (inData.error) + this.updateError(inData) + else + this.finishUpdate(inRowIndex, inData); + }, + updateError: function(inRowIndex) { + this.clearState(inRowIndex, 'inflight'); + this.setState(inRowIndex, "error", "update failed: " + inRowIndex); + this.rowChange(this.getRow(inRowIndex), inRowIndex); + }, + remove: function(inRowIndexes) { + this.clearStateForIndexes(inRowIndexes); + }, + removeError: function(inRowIndexes) { + this.clearStateForIndexes(inRowIndexes); + alert('Removal error. Please refresh.'); + }, + rows: function(inRowIndex, inData) { + //this.beginUpdate(); + for (var i=0, l=inData.length; i<l; i++) + this.setRow(inData[i], inRowIndex + i); + //this.endUpdate(); + //this.allChange(); + }, + count: function(inRowCount) { + this.count = Number(inRowCount); + this.clearData(); + }, + info: function(inInfo) { + this.fields.clear(); + for (var i=0, c; (c=inInfo.columns[i]); i++) { + c.name = c.Field; + this.fields.set(i, c); + } + this.table = inInfo.table; + this.database = inInfo.database; + this.notify("MetaData", arguments); + this.callbacks.count.call(this, inInfo.count); + } + } +}); + +} |