/** * @version 1.1 * @author ideawu@163.com * @link http://www.ideawu.net/ * @class * 用于显示数据表格的javascript控件. 集成的分页控件, 可对表格中的数据集进行客户端分页. * * @param {string} id: html节点的id, 控件将显示在该节点中. * @returns {tableview}: 返回分页控件实例. * @requires jquery {@link pagerview} {@link sortview} * * @example * ### html代码: * <div id="my_div"></div> * * ### javascript代码: * var table = new tableview('my_div'); * table.datakey = 'id'; * table.header = { * 'id' : 'id', * 'name' : 'name', * }; * * table.add({id:1, name:'tom'}); * table.render(); */ var tableview = function(id){ // todo: 实现有序哈希类. /* 因为哈希表的实现可能是元素无序的, 所以使用数组代替. 为此, 定义了数据操作方法. */ function array_index_of_key(arr, key, val){ for(var i in arr){ if(arr[i][key] == val){ return parseint(i); } } return -1; } function array_index_of_item(arr, item){ for(var i in arr){ if(arr[i] == item){ return parseint(i); } } return -1; } function array_get(arr, key, val){ var index = array_index_of_key(arr, key, val); if(index != -1){ return arr[index]; } return false; } function array_del(arr, key, val){ var index = array_index_of_key(arr, key, val); if(index != -1){ var a1 = arr.slice(0, index); var a2 = arr.slice(index + 1); return a1.concat(a2); } return arr; } var self = this; this.id = id; this._rendered = false; this._filter_text = ''; this.rows = []; this._display_rows = []; // 过滤后的数据集 /** * 当前控件所处的html节点引用. * @type domelement */ this.container = null; /** * 数据集的每一条记录的唯一标识字段名. 类似数据库表的主键字段名. * @type string */ this.datakey = ''; /** * 要显示的数据表格的标题. * @type string */ this.title = ''; /** * 要显示的记录的字段, 以及所对应的字段名. 如 'id' : '编号'. * @type object */ this.header = {}; /** * 集成的分页控件, 可对表格中的数据集进行客户端分页. * @type pagerview */ this.pager = {}; /** * 集成的排序控件, 用于显示分页按钮/链接. * @type sortview */ this.sort = {}; /** * @class * 用于确定要显示哪些内部控件, 控件对应的属性为boolean类型, 取值为true时显示. */ function displayoptions(){ /** * 标题 * @type boolean */ this.title = false; /** * 计数 * @type boolean */ this.count = false; /** * 行选择框 * @type boolean */ this.marker = false; /** * 过滤器 * @type boolean */ this.filter = true; /** * 分页 * @type boolean */ this.pager = true; /** * 排序 * @type boolean */ this.sort = false; /** * 是否多选 * @type boolean */ this.multiple = false; /** * 调试 * @type boolean */ this.debug = false; }; /** * 用于确定要显示哪些内部控件. * @type tableview-displayoptions */ this.display = new displayoptions(); /** * 获取数据集指定id一条记录. * @returns {object} 数据集中的一条记录. */ this.get = function(id){ return array_get(this.rows, self.datakey, id); }; /** * 添加一条记录, 如果控件已经被渲染, 会导致一次刷新. * @param {object} row: 记录对象. */ this.add = function(row){ var index = array_index_of_item(self.rows, row); if(index != -1){ return; } this.rows.push(row); this._display_rows.push(row); if(self._rendered){ self.render(); } }; /* var timer = function(){ this.times = []; this.timeit = function(){ var d = new date(); var t = d.getminutes() * 60 * 1000 + d.getseconds() * 1000 + d.getmilliseconds(); this.times.push(t); } this.alert = function(){ var str='', t0; t0 = this.times[0]; for(var i=1; i'; str += '(0/0)'; str += ''; str += ''; str += '\n'; str += '\n'; //var datagrid_div_id = self.id + '_datagrid_div__'; //str += '
\n'; str += '
\n'; str += '
\n'; var pager_id = self.id + '_pager__'; str += '
\n'; // debug var debug_div_id = self.id + '_debug'; str += '
\n'; str += '
\n'; var div = document.getelementbyid(self.id); div.view = self; self.container = div; self.container.innerhtml = str; // debug self._debug = $('#' + debug_div_id); // 捕获异常, 可以不需要pagerview工作 try{ self.pager = new pagerview(pager_id); self.pager.onclick = function(index){ self.render(); }; self.sort = new sortview(); self.sort.onclick = function(field, order){ self.sort.sort(self._display_rows); self.render(); }; }catch(e){ } }; self._render_framework(); /** * 更新统计数据. */ this._update_meta = function(){ if(!self.display.count){ return; } var marked_count = 0; marked_count = $(self.container).find('table.datagrid td.marker input[value!=""]:checked').length; $(self.container).find('div.datagrid_meta span.marked_count').html(marked_count); $(self.container).find('div.datagrid_meta span.row_count').html(self.rowcount()); } /** * 内部方法. 绑定事件, 设置外观. */ this._after_render = function(){ var trs = $(self.container).find('table.datagrid>tbody>tr.tv_row'); trs.each(function(i, tr){ var cb = tr.getelementsbytagname('input')[0]; var clz = i%2==0? 'odd' : 'even'; // 标记已选的行 if(cb.checked){ clz += ' marked'; } $(tr).removeclass('odd even marked'); $(tr).addclass(clz); cb.onclick = function(){ cb.checked = !cb.checked; }; tr.onclick = function(){ if(!cb.checked){ if(!self.display.multiple){ self.unselectall(); } } cb.checked = !cb.checked; if(cb.checked){ $(this).addclass('marked'); }else{ $(this).removeclass('marked'); } self._update_meta(); //var pp = new bmap.point(113.064136,25.783525); //地图点 //map.centerandzoom(pp, 18); //alert(cb.value); map_init(cb.value); }; tr.onmouseover = function(){ $(this).addclass('hover'); }; tr.onmouseout = function(){ $(this).removeclass('hover'); }; tr.ondblclick = function(){ self._dblclick(cb.value); }; }); self._update_meta(); if(!self.display.title){ $(self.container).find('div.datagrid_meta span.title').hide(); }else{ $(self.container).find('div.datagrid_meta span.title').show(); } if(!self.display.count){ $(self.container).find('div.datagrid_meta span.count').hide(); }else{ $(self.container).find('div.datagrid_meta span.count').show(); } if(!self.display.filter){ $(self.container).find('div.datagrid_meta span.filter').hide(); }else{ $(self.container).find('div.datagrid_meta span.filter').show(); } if(!self.display.pager){ $('#' + self.pager.id).hide(); }else{ $('#' + self.pager.id).show(); } if(!self.display.marker){ $(self.container).find('td.marker, th.marker').hide(); }else{ $(self.container).find('td.marker, th.marker').show(); } }; // debug function debug(str){ if(self.display.debug){ self._debug.css('border', '2px solid #f00'); self._debug.append(str + '
'); } } /** * 渲染控件. */ this.render = function(){ var buf = []; buf.push('\n'); buf.push('\n'); buf.push('\n'); var count = 0; for(var k in this.header){ count ++; } var width = parseint(100/count); for(var k in this.header){ buf.push('\n'); } buf.push("\n\n"); if(self.display.sort){ self.sort.sort(self._display_rows); } if(self.display.pager){ self.pager.itemcount = self._display_rows.length; var rows = self.pager.page(self._display_rows); }else{ var rows = self._display_rows; } buf.push("\n"); for(var i in rows){ var row = rows[i]; var rid = row[self.datakey]; buf.push('\n\n'); for(var k in self.header){ buf.push('\n'); } buf.push('\n'); } buf.push("
'); if(self.display.multiple){ buf.push(''); } buf.push('' + self.header[k] + '
'); buf.push(row[k]); buf.push('
\n"); $(self.container).find('div.datagrid_meta span.title').html(this.title); // $.html() is really slow in ie //$(self.container).find('div.datagrid_div').html(buf.join('')); $(self.container).find('div.datagrid_div').each(function(i, e){ e.innerhtml = buf.join(''); }); self._after_render(); if(self.display.pager){ self.pager.render(); } if(self.display.sort){ var is_empty = true; if(self.sort.fields){ for(var i in self.sort.fields){ is_empty = false; } } if(is_empty){ var fields = {}; for(var k in self.header){ fields[k] = [null, null]; } self.sort.fields = fields; } var elements = {}; $(self.container).find('table.datagrid th[field]').each(function(i, th){ var k = $(th).attr('field'); if(k != undefined){ elements[k] = th; } }); self.sort.render(elements); } //$('.datagrid').fixedtableheader(); self._rendered = true; }; /** * 设置所有行的选择标记. 如果设置了分页, 则只对当前页有效. */ this.selectall = function(){ $(self.container).find('th.marker input, td.marker input').each(function(i, e){ e.checked = true; }); self._after_render(); }; /** * 取消所有行的选择标记. 如果设置了分页, 则只对当前页有效. */ this.unselectall = function(){ $(self.container).find('th.marker input, td.marker input').each(function(i, e){ e.checked = false; }); self._after_render(); }; /** * 返回所有的记录的列表. * @returns {array[object]} */ this.getdatasource = function(){ return self.rows; } /** * 获取所有标记为选择的行对应的记录的列表. * @returns {array[object]} */ this.getselected = function(){ var items = []; $(self.container).find('.datagrid td.marker input[value!=""]:checked').each(function(i, cb){ if(cb.checked){ // 注意, 不要作为hash使用, 否则会导致使用者判断选中个数时错误. var row = array_get(self.rows, self.datakey, cb.value); items.push(row); } }); return items; }; /** * 获取所有已选择的数据对象键值的列表. * @returns {array[key]} */ this.getselectedkeys = function(){ var keys = []; var rows = self.getselected(); for(var i in rows){ keys.push(rows[i][self.datakey]); } return keys; }; /** * 进行模糊过滤. * @param {string} text: regex字符串. */ this.filter = function(text){ self._filter_text = text; self._display_rows = []; var regex = new regexp(text, 'i'); for(var key in self.rows){ var row = self.rows[key]; if(text == ''){ self._display_rows.push(row); }else{ // 只对看到的进行过滤 for(var k in self.header){ var find = string(row[k]).replace(/<[^>]*>/g, ''); if(regex.test(find)){ self._display_rows.push(row); break; } } } } if(self.display.pager){ self.pager.index = 1; } self.render(); }; /** * 清空所有行. */ this.clear = function(){ self.rows = []; self._display_rows = []; if(self.display.pager){ self.pager.index = 1; } self.render(); }; }