summaryrefslogtreecommitdiff
path: root/includes/js/dojox/grid/tests/databaseModel.js
diff options
context:
space:
mode:
Diffstat (limited to 'includes/js/dojox/grid/tests/databaseModel.js')
-rw-r--r--includes/js/dojox/grid/tests/databaseModel.js337
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);
+ }
+ }
+});
+
+}