Blame | Last modification | View Log | RSS feed
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 inorderdojo.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 informationgetState: 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 / receivegetSendParams: 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 commitscommitEdit: 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 pkcommitDelete: 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 fieldsgetPkIndex: 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 implementationsupdate: function(inOldData, inNewData, inRowIndex) {var cbs = this.getUpdateCallbacks(inRowIndex);if (this.getState(inRowIndex).inserting)this.commitInsert(inRowIndex, inNewData, cbs);elsethis.commitEdit(this.cache[inRowIndex] || inOldData, inNewData, inRowIndex, cbs);// set push data immediately to model so reflectd while committingthis.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);} elsethis.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 datarequestRows: 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)});},// sortingcanSort: 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)elsethis.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);}}});}