1 /** 2 * @version 1.1 3 * @author ideawu@163.com 4 * @link http://www.ideawu.net/ 5 * @class 6 * 用于显示排序按钮/链接的控件, 并包含 js 排序功能. 这些排序控件附加在指定的 HTMLElement 里. 7 * @requires jQuery {@link PagerView} {@link SortView} 8 * @returns {SortView}: 返回排序控件实例. 9 * 10 * @example 11 * var rows = []; // datasource 12 * 13 * var sort = new SortView(); 14 * sort.fields = { 15 * 'id' : ['int', null], 16 * 'name' : [null, null] 17 * }; 18 * 19 * var elements = {}; 20 * var ths = $('table th').each(function(i, th){ 21 * var k = $(th).attr('field'); 22 * if(k != undefined){ 23 * elements[k] = th; 24 * } 25 * }); 26 * sort.onclick = function(){ 27 * sort.sort(rows); 28 * // do with rows... 29 * } 30 * 31 * sort.render(elements); 32 */ 33 var SortView = function(){ 34 var self = this; 35 36 this._elements = {}; 37 38 /** 39 * 排序字段的名字. 40 * @type String 41 */ 42 this.field = null; 43 /** 44 * 排序方向, 取值为: asc|desc. 45 * @type String 46 */ 47 this.order = null; 48 /** 49 * 可供排序的字段哈希表, 字段对应一个数组, 数组格式为[类型, 比较函数]. 50 * 当类型为: null|int|date|text|string|float 且不指定比较函数时, 使用默认的比较函数. 51 * @type Object 52 */ 53 this.fields = { 54 //'id' : ['int', null] // type, comparer 55 }; 56 57 /** 58 * 默认的排序函数. 59 */ 60 this._default_comparefuncs = {}; 61 this._default_comparefuncs['int'] = function(a, b){ 62 //return parseInt(a - b); 63 return (a - b)>=0? 1 : -1; 64 }; 65 this._default_comparefuncs['float'] = function(a, b){ 66 return (a - b)>=0? 1 : -1; 67 }; 68 this._default_comparefuncs['text'] = function(a, b){ 69 if(a > b){ 70 return 1; 71 }else if(a == b){ 72 return 0; 73 }else{ 74 return -1; 75 } 76 }; 77 this._default_comparefuncs['string'] = this._default_comparefuncs['string']; 78 this._default_comparefuncs['date'] = this._default_comparefuncs['date']; 79 80 81 /** 82 * 根据当前的字段和方向, 对对象数组进行排序. 83 */ 84 this.sort = function(rows){ 85 if(self.field == undefined){ 86 for(var i in self.fields){ 87 self.field = i; 88 break; 89 } 90 } 91 if(self.order == undefined){ 92 self.order = 'asc'; 93 } 94 95 var type = null; 96 var func = null; 97 var f = self.fields[self.field]; 98 if(f instanceof Array){ 99 type = f[0]; 100 func = f[1]; 101 } 102 if(type == null || type == undefined){ 103 func = this._default_comparefuncs['text']; 104 }else if(type == 'int' || type == 'string' 105 || type == 'text' || type == 'date' || type == 'float'){ 106 func = this._default_comparefuncs[type]; 107 } 108 109 var sign = self.order == 'desc'? -1 : 1; 110 var k = self.field; 111 rows.sort(function(a, b){ 112 return sign * func(a[k], b[k]); 113 }); 114 }; 115 116 /** 117 * 用户重写本方法, 获取排序事件. 118 * @param {String} field 排序字段. 119 * @param {String} order 排序方向. 120 * @returns {Boolean} 返回false表示取消本次排序事件. 121 */ 122 this.onclick = function(field, order){ 123 }; 124 125 /** 126 * 内部方法. 127 */ 128 this._onclick = function(field){ 129 var old_field = self.field; 130 var old_order = self.order; 131 132 var order = 'asc'; 133 if(self.field == field && self.order == 'asc'){ 134 order = 'desc'; 135 } 136 self.field = field; 137 self.order = order; 138 139 var ret = self.onclick(field, order); 140 if(ret === false){ 141 self.field = old_field; 142 self.order = old_order; 143 } 144 145 self.render(self._elements); 146 //alert(field + ':' + order); 147 }; 148 149 /** 150 * 进行渲染. 151 * @param {Object} elements 哈希表, 字段名与HTMLElement的对应关系. 152 */ 153 this.render = function(elements){ 154 self._elements = elements; 155 //alert(self.field + ':' + self.order); 156 157 for(var k in self.fields){ 158 var ele = elements[k]; 159 if(ele == undefined){ 160 continue; 161 } 162 ele = $(ele); 163 164 ele.find('span[class=sign]').remove(); 165 var html = '<a href="javascript://' + k + '" sort="' + k + '" class="SortView">'; 166 html += ele.html(); 167 html += '</a>'; 168 169 html = $(html); 170 html.click(function(a){ 171 self._onclick($(this).attr('sort')); 172 }); 173 174 ele.html(html); 175 if(k == self.field){ 176 var sign = self.order == 'asc'? '↑' : '↓'; 177 ele.append('<span class="sign">' + sign + '</span>'); 178 } 179 } 180 }; 181 }; 182 183