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