概述:
jQuery 作为一个轻量级框架,插件格式的控件使用起来非常方便,但是我们基于jQuery写一套控件,需要我们扩展一些函数,便于控件的继承和扩展。
扩展函数:
1. augment(Function r,Object s1): 将指定的方法或属性放到构造函数的原型链上, 函数支持多于2个变量,后面的变量同s1一样将其成员复制到构造函数的原型链上。
2. cloneObject(Object obj): 拷贝对象(深拷贝)
jQuery 有一个clone方法,但是只支持HTMLElement,而我们在很多时候需要的是深拷贝对象。
3. guid(prefix): 生成唯一的id。
用于控件生成时,需要用id管理控件
4. extend(Function subclass,Function superclass,Object overrides): 实现类的继承
这个方法是继承的核心方法,在前面讲过,具体的细节查看前面的博客。
5. merge(Object obj1,Object obj2....): 将多个对象的属性复制到一个新的对象上,如果第一个参数是true,那么实现的是深拷贝。
6. mix():封装 jQuery.extend 方法,将多个对象的属性merge到第一个对象中。
7. mixin(Function c,Array mixins,Array attrs): 将其他类作为扩展,集成到指定的类上面。
8. substitue(String str,Object o,[RegExp regexp]) : 替换字符串中的字段,用于简单模板
上面是为了实现控件继承而增加的一些帮助方法,还有一些辅助类的方法,具体代码如下:
1 $.extend(BUI,
2 {
3
/*
*
4
* 将指定的方法或属性放到构造函数的原型链上,
5
* 函数支持多于2个变量,后面的变量同s1一样将其成员复制到构造函数的原型链上。
6
* @param {Function} r 构造函数
7
* @param {Object} s1 将s1 的成员复制到构造函数的原型链上
8
* @example
9
* BUI.augment(class1,{
10
* method1: function(){
11
*
12
* }
13
* });
14
*/
15 augment :
function(r,s1){
16
if(!$.isFunction(r))
17 {
18
return r;
19 }
20
for (
var i = 1; i < arguments.length; i++) {
21 BUI.mix(r.prototype,arguments[i].prototype || arguments[i]);
22 };
23
return r;
24 },
25
/*
*
26
* 拷贝对象
27
* @param {Object} obj 要拷贝的对象
28
* @return {Object} 拷贝生成的对象
29
*/
30 cloneObject :
function(obj){
31
var result = $.isArray(obj) ? [] : {};
32
33
return BUI.mix(
true,result,obj);
34 },
35
/*
*
36
* 抛出错误
37
*/
38 error :
function(msg){
39
throw msg;
40 },
41
/*
*
42
* 实现类的继承,通过父类生成子类
43
* @param {Function} subclass
44
* @param {Function} superclass 父类构造函数
45
* @param {Object} overrides 子类的属性或者方法
46
* @return {Function} 返回的子类构造函数
47
* 示例:
48
* @example
49
* //父类
50
* function base(){
51
*
52
* }
53
*
54
* function sub(){
55
*
56
* }
57
* //子类
58
* BUI.extend(sub,base,{
59
* method : function(){
60
*
61
* }
62
* });
63
*
64
* //或者
65
* var sub = BUI.extend(base,{});
66
*/
67 extend :
function(subclass,superclass,overrides, staticOverrides){
68
//
如果只提供父类构造函数,则自动生成子类构造函数
69
if(!$.isFunction(superclass))
70 {
71
72 overrides = superclass;
73 superclass = subclass;
74 subclass =
function(){};
75 }
76
77
var create = Object.create ?
78
function (proto, c) {
79
return Object.create(proto, {
80 constructor: {
81 value: c
82 }
83 });
84 } :
85
function (proto, c) {
86
function F() {
87 }
88
89 F.prototype = proto;
90
91
var o =
new F();
92 o.constructor = c;
93
return o;
94 };
95
var superObj = create(superclass.prototype,subclass);
//
new superclass(),//实例化父类作为子类的prototype
96
//
superObj1 = new superclass();//作为superclass属性
97
subclass.prototype = BUI.mix(superObj,subclass.prototype);
//
指定子类的prototype
98
//
superObj1.constructor = superclass;
99
subclass.superclass = create(superclass.prototype,superclass);
100
//
subclass.prototype.constructor = subclass;
101
BUI.mix(superObj,overrides);
102 BUI.mix(subclass,staticOverrides);
103
return subclass;
104 },
105
/*
*
106
* 生成唯一的Id
107
* @method
108
* @param {String} prefix 前缀
109
* @default 'ks-guid'
110
* @return {String} 唯一的编号
111
*/
112 guid : (
function(){
113
var map = {};
114
return
function(prefix){
115 prefix = prefix || BUI.prefix + GUID_DEFAULT;
116
if(!map[prefix]){
117 map[prefix] = 1;
118 }
else{
119 map[prefix] += 1;
120 }
121
return prefix + map[prefix];
122 };
123 })(),
124
/*
*
125
* 判断是否是字符串
126
* @return {Boolean} 是否是字符串
127
*/
128 isString :
function(value){
129
return
typeof value === 'string';
130 },
131
/*
*
132
* 判断是否数字,由于$.isNumberic方法会把 '123'认为数字
133
* @return {Boolean} 是否数字
134
*/
135 isNumber :
function(value){
136
return
typeof value === 'number';
137 },
138
/*
*
139
* 控制台输出日志
140
* @param {Object} obj 输出的数据
141
*/
142 log :
function(obj){
143
if(win.console && win.console.log){
144 win.console.log(obj);
145 }
146 },
147
/*
*
148
* 将多个对象的属性复制到一个新的对象
149
*/
150 merge :
function(){
151
var args = $.makeArray(arguments);
152 args.unshift({});
153
return $.extend.apply(
null,args);
154
155 },
156
/*
*
157
* 封装 jQuery.extend 方法,将多个对象的属性merge到第一个对象中
158
* @return {Object}
159
*/
160 mix :
function(){
161
return $.extend.apply(
null,arguments);
162 },
163
/*
*
164
* 创造顶层的命名空间,附加到window对象上,
165
* 包含namespace方法
166
*/
167 app :
function(name){
168
if(!window[name]){
169 window[name] = {
170 namespace :
function(nsName){
171
return BUI.namespace(nsName,window[name]);
172 }
173 };
174 }
175
return window[name];
176 },
177
/*
*
178
* 将其他类作为mixin集成到指定类上面
179
* @param {Function} c 构造函数
180
* @param {Array} mixins 扩展类
181
* @param {Array} attrs 扩展的静态属性,默认为['ATTRS']
182
* @return {Function} 传入的构造函数
183
*/
184 mixin :
function(c,mixins,attrs){
185 attrs = attrs || [ATTRS];
186
var extensions = mixins;
187
if (extensions) {
188 c.mixins = extensions;
189
190
var desc = {
191
//
ATTRS:
192
//
HTML_PARSER:
193
}, constructors = extensions['concat'](c);
194
195
//
[ex1,ex2],扩展类后面的优先,ex2 定义的覆盖 ex1 定义的
196
//
主类最优先
197
$.each(constructors,
function (index,ext) {
198
if (ext) {
199
//
合并 ATTRS/HTML_PARSER 到主类
200
$.each(attrs,
function (i,K) {
201
if (ext[K]) {
202 desc[K] = desc[K] || {};
203
//
不覆盖主类上的定义,因为继承层次上扩展类比主类层次高
204
//
但是值是对象的话会深度合并
205
//
注意:最好值是简单对象,自定义 new 出来的对象就会有问题(用 function return 出来)!
206
BUI.mix(
true,desc[K], ext[K]);
207 }
208 });
209 }
210 });
211
212 $.each(desc,
function (k, v) {
213 c[k] = v;
214 });
215
216
var prototype = {};
217
218
//
主类最优先
219
$.each(constructors,
function (index,ext) {
220
if (ext) {
221
var proto = ext.prototype;
222
//
合并功能代码到主类,不覆盖
223
for (
var p
in proto) {
224
//
不覆盖主类,但是主类的父类还是覆盖吧
225
if (proto.hasOwnProperty(p)) {
226 prototype[p] = proto[p];
227 }
228 }
229 }
230 });
231
232 $.each(prototype,
function (k,v) {
233 c.prototype[k] = v;
234 });
235 }
236
return c;
237 },
238
/*
*
239
* 生成命名空间
240
* @param {String} name 命名空间的名称
241
* @param {Object} baseNS 在已有的命名空间上创建命名空间,默认“BUI”
242
* @return {Object} 返回的命名空间对象
243
* @example
244
* BUI.namespace("Grid"); // BUI.Grid
245
*/
246 namespace :
function(name,baseNS){
247 baseNS = baseNS || BUI;
248
if(!name){
249
return baseNS;
250 }
251
var list = name.split('.'),
252
//
firstNS = win[list[0]],
253
curNS = baseNS;
254
255
for (
var i = 0; i < list.length; i++) {
256
var nsName = list[i];
257
if(!curNS[nsName]){
258 curNS[nsName] = {};
259 }
260 curNS = curNS[nsName];
261 };
262
return curNS;
263 },
264 prefix : 'ks-',
265
/*
*
266
* 替换字符串中的字段.
267
* @param {String} str 模版字符串
268
* @param {Object} o json data
269
* @param {RegExp} [regexp] 匹配字符串的正则表达式
270
*/
271 substitute:
function (str, o, regexp) {
272
if (!BUI.isString(str)
273 || !$.isPlainObject(o)) {
274
return str;
275 }
276
277
return str.replace(regexp || /\\?\{([^{}]+)\}/g,
function (match, name) {
278
if (match.charAt(0) === '\\') {
279
return match.slice(1);
280 }
281
return (o[name] === undefined) ? '' : o[name];
282 });
283 },
284
/*
*
285
* 使第一个字母变成大写
286
* @param {String} s 字符串
287
* @return {String} 首字母大写后的字符串
288
*/
289 ucfirst :
function(s){
290 s += '';
291
return s.charAt(0).toUpperCase() + s.substring(1);
292 },
293
/*
*
294
* 页面上的一点是否在用户的视图内
295
* @param {Object} offset 坐标,left,top
296
* @return {Boolean} 是否在视图内
297
*/
298 isInView :
function(offset){
299
var left = offset.left,
300 top = offset.top,
301 viewWidth = BUI.viewportWidth(),
302 wiewHeight = BUI.viewportHeight(),
303 scrollTop = BUI.scrollTop(),
304 scrollLeft = BUI.scrollLeft();
305
//
判断横坐标
306
if(left < scrollLeft ||left > scrollLeft + viewWidth){
307
return
false;
308 }
309
//
判断纵坐标
310
if(top < scrollTop || top > scrollTop + wiewHeight){
311
return
false;
312 }
313
return
true;
314 },
315
/*
*
316
* 页面上的一点纵向坐标是否在用户的视图内
317
* @param {Object} top 纵坐标
318
* @return {Boolean} 是否在视图内
319
*/
320 isInVerticalView :
function(top){
321
var wiewHeight = BUI.viewportHeight(),
322 scrollTop = BUI.scrollTop();
323
324
//
判断纵坐标
325
if(top < scrollTop || top > scrollTop + wiewHeight){
326
return
false;
327 }
328
return
true;
329 },
330
/*
*
331
* 页面上的一点横向坐标是否在用户的视图内
332
* @param {Object} left 横坐标
333
* @return {Boolean} 是否在视图内
334
*/
335 isInHorizontalView :
function(left){
336
var viewWidth = BUI.viewportWidth(),
337 scrollLeft = BUI.scrollLeft();
338
//
判断横坐标
339
if(left < scrollLeft ||left > scrollLeft + viewWidth){
340
return
false;
341 }
342
return
true;
343 },
344
/*
*
345
* 获取窗口可视范围宽度
346
* @return {Number} 可视区宽度
347
*/
348 viewportWidth :
function(){
349
return $(window).width();
350 },
351
/*
*
352
* 获取窗口可视范围高度
353
* @return {Number} 可视区高度
354
*/
355 viewportHeight:
function(){
356
return $(window).height();
357 },
358
/*
*
359
* 滚动到窗口的left位置
360
*/
361 scrollLeft :
function(){
362
return $(window).scrollLeft();
363 },
364
/*
*
365
* 滚动到横向位置
366
*/
367 scrollTop :
function(){
368
return $(window).scrollTop();
369 },
370
/*
*
371
* 窗口宽度
372
* @return {Number} 窗口宽度
373
*/
374 docWidth :
function(){
375
var body = document.documentElement || document.body;
376
return $(body).width();
377 },
378
/*
*
379
* 窗口高度
380
* @return {Number} 窗口高度
381
*/
382 docHeight :
function(){
383
var body = document.documentElement || document.body;
384
return $(body).height();
385 }
386