e44a7e37b6
git-svn-id: https://semanticscuttle.svn.sourceforge.net/svnroot/semanticscuttle/trunk@151 b3834d28-1941-0410-a4f8-b48e95affb8f
337 lines
10 KiB
JavaScript
337 lines
10 KiB
JavaScript
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);
|
|
}
|
|
}
|
|
});
|
|
|
|
}
|