New file |
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); |
} |
} |
}); |
|
} |