/* 数据表格 source: 除delete之外的所有 view: 当前数据视图,用于配合table,tree显示 1.source 是完整的数据表格 2.view 是过滤,排序后的数据表格 3.idHash 保存的是source的id引用? 是不是加一个原则: 1.source 是完整的数据, 可以增删改 2.view 只是数据视图,只能排序,过滤,但是不能进行增删改操作 就像sql2000数据库的逻辑一样 */ /** @name Edo.data.DataTable @class @typeName datatable @description 表格数据源 @extend Edo.core.Component @example */ Edo.data.DataTable = function(data){ Edo.data.DataTable.superclass.constructor.call(this); this.source = this.view = []; this.modified = {}; this.removed = {}; this.idHash = {}; //if(data) this.load(data); //this._setConn(new Edo.data.PagingConnection()); /** @name Edo.data.DataTable#datachange @event @description 数据改变事件 @property {String} action 数据改变动作(add,remove,update,move,clear,reset,resetfield,beforeload,load,refresh,filter,collapse,expand,sort) */ } Edo.data.DataTable.extend(Edo.core.Component, { componentMode: 'data', dataTable: true, /** @name Edo.data.DataTable#source @property @type Array @description 源Array数组对象 */ /** @name Edo.data.DataTable#view @property @type Array @description 数据视图(如过滤/排序/折叠后的数据视图) */ _setData: function(data){ this.load(data); }, refresh: function(view, action, event){ //刷新数据视图 if(view){ this.length = 0; this.view = view; } this.fire(action || 'refresh', event); //数据组件,只需要监听refresh事件即可! }, /** @name Edo.data.DataTable#load @function @description 加载数据 @param {Array} data 数组形式的数据 */ load: function(data, view){ if(!data) data = []; var e = {data: data}; if(this.fire('beforeload', e) !== false){ //这是属于"破坏"性的操作,如果有必要,要保存原来的操作结果,请使用beforeload事件 this._doLoad(data); this.view = this.source = data; //更新原始数据 this.modified = {}; this.removed = {}; //this.idHash = {}; if(view) this.view = view; this.changed = false; //修改changed标记(表示数据是没有经过任何数据操作:增,删,改) this.canFire = true; this.fire('load', e); } }, /** @name Edo.data.DataTable#reload @function @description 重加载数据, 去除新增/删除/修改的数据标记 */ reload: function(){ this.load(this.source, this.view); }, /** @name Edo.data.DataTable#add @function @description 增加数据 @param {Object} record 单个对象 */ add: function(record){ this.insert(this.view.length, record); }, /** @name Edo.data.DataTable#addRange @function @description 增加数据 @param {Array} records 多个对象 */ addRange: function(records){ this.insertRange(this.view.length, records); }, /** @name Edo.data.DataTable#insert @function @description 增加数据 @param {Number} index @param {Object} record 单个对象 */ insert: function(index, record){ this.insertRange(index, [record]); }, /** @name Edo.data.DataTable#insertRange @function @description 增加多个数据 @param {Number} index @param {Array} records 数组对象 */ insertRange: function(index, records){ if(!records || !(records instanceof Array)) return; var d = this.source, v = this.view; for(var i = 0, len = records.length; i < len; i++){ var r = records[i]; v.insert(index, r); if(d !== v) d.insert(index, r); //在源数据上也新增 this._doAdd(r); } this.fire('add', { records: records, index: index }); this.changed = true; }, /** @name Edo.data.DataTable#remove @function @description 删除数据 @param {Object} record 数据对象 */ remove: function(record){ this.removeRange([record]); }, /** @name Edo.data.DataTable#removeAt @function @description 根据索引删除数据 @param {Number} index */ removeAt: function(index){ this.remove(this.getAt(index)); }, /** @name Edo.data.DataTable#removeRange @function @description 删除数据 @param {Array} records 数据对象数组 */ removeRange: function(records){ if(!records || !(records instanceof Array)) return; records = records.clone(); for(var i=0,l=records.length; i -1){ this.view.removeAt(index); this.source.remove(record); //从源数据上也删除 // delete this.idHash[record.__id]; // delete this.modified[record.__id]; this._doRemove(record); } } this.fire('remove', {records: records}); this.changed = true; }, /** @name Edo.data.DataTable#updateRecord @function @description 批量更新数据对象属性值 @param {Object} record 数据对象 @param {Object} properties {key: value, ..}形式的对象 */ updateRecord: function(record, o){ var canFire = this.canFire; this.beginChange(); for(var p in o){ this.update(record, p, o[p]); } this.canFire = canFire; this.fire('update',{ record: record }); this.changed = true; }, /** @name Edo.data.DataTable#update @function @description 更新数据对象属性值 @param {Object} record 数据对象 @param {String} field 属性名 @param {Object} value 属性值 */ update: function(record, field, value){ var old = Edo.getValue(record, field); //var old = record[field]; //alert(old+":"+value); var type = typeof(old); if(type == 'object'){ if(old === value) return false; } else if(String(old) == String(value)) return false; //record[field] = value; Edo.setValue(record, field, value); //to data this._doUpdate(record, field, old); this.fire('update',{ record: record, field: field, value: value }); this.changed = true; return true; }, /** @name Edo.data.DataTable#move @function @description 移动数据对象 @param {Object} record 数据对象 @param {Number} index */ move: function(records, index){//index:数字, 行对象 var target = Edo.isInt(index) ? this.getAt(index) : index; if(!Edo.isArray(records)) records = [records]; for(var j=0,l=records.length; j v2 ? 1 : (v1 < v2 ? -1 : 0); }; }else{ fn = function(r1, r2){ var v1 = r1[f], v2 = r2[f]; return v1 < v2 ? 1 : (v1 > v2 ? -1 : 0); }; } this.sort(fn); }, /** @name Edo.data.DataTable#filter @function @description 过滤数据 @param {Function} fn 过滤算法函数 @param {Object} scope 过滤函数中的this指向对象 */ filter: function(fn, scope){ var view = this.view = []; var data = this.source; for (var i = 0, j = data.length; i < j; i++){ var record = data[i]; if (fn.call(scope, record, i, data) !== false) view[view.length] = record; } this.fire('filter'); }, /** @name Edo.data.DataTable#clearFilter @function @description 清除过滤, 还原数据视图 */ clearFilter : function(){ this.filterFn = null; if(this.isFiltered()){ this.view = this.source; this.fire('filter'); } }, /** @name Edo.data.DataTable#isFiltered @function @description 判断数据视图是否被过滤过 @return Boolean */ isFiltered: function(){ return this.view.length != this.source.length; }, //查找:传递一个object,找出属性符合最多的对象的Index. //这其实是个很复杂的概念:1)默认是从当前数据视图查找;2)如果传递source对象,就从source对象查找(并且如果是删除的数据,不会查找出来) /** @name Edo.data.DataTable#findIndex @function @description 查找一个符合特征的对象 @param {Object} attributes {key:value}形式的特性对象 @return {Number} */ findIndex: function(attribute, array){ if(array === true) array = this.source; array = array || this.view; for(var i=0,l=array.length; i