jquery-atwho-rails 0.0.1 → 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
data/.gitignore CHANGED
@@ -4,3 +4,4 @@ Gemfile.lock
4
4
  pkg/*
5
5
  *.swp
6
6
  tmp/*
7
+ build/*
@@ -63,7 +63,6 @@
63
63
  };
64
64
  At = {
65
65
  keyword : {'text':"",'start':0,'stop':0},
66
- search_word: "",
67
66
  _cache : {},
68
67
  // textarea, input.
69
68
  $inputor : null,
@@ -72,11 +71,27 @@
72
71
  lenght : 0,
73
72
  /* @ position in inputor */
74
73
  pos: 0,
74
+ flags:{},
75
+ theflag:null,
76
+ options:{},
77
+ searchWord:function() {
78
+ // just used in At.watchWithData
79
+ var match = /data-keyname=['?]\$\{(\w+)\}/g.exec(this.getOpt('tpl'));
80
+ return !_isNil(match) ? match[1] : null;
81
+ },
82
+ getOpt: function(key) {
83
+ var flag = this.theflag;
84
+ try {
85
+ return this.options[flag][key];
86
+ } catch (e) {
87
+ return null
88
+ }
89
+ },
75
90
  /* @ offset*/
76
91
  offset: function() {
77
92
  $inputor = this.$inputor;
78
93
  mirror = $inputor.data("mirror");
79
- if (isNil(mirror)) {
94
+ if (_isNil(mirror)) {
80
95
  mirror = new Mirror($inputor);
81
96
  $inputor.data("mirror",mirror);
82
97
  }
@@ -128,13 +143,13 @@
128
143
  return {'top':y,'left':x};
129
144
  },
130
145
  cache: function(key,value) {
131
- if (!settings['cache']) return null;
132
- log("cacheing",key,value);
146
+ if (!this.getOpt('cache')) return null;
147
+ _log("cacheing",key,value);
133
148
  if (value)
134
149
  this._cache[key] = value;
135
150
  return this._cache[key];
136
151
  },
137
- getKey: function() {
152
+ getKeyname: function() {
138
153
  $inputor = this.$inputor;
139
154
  text = $inputor.val();
140
155
  //获得inputor中插入符的position.
@@ -143,17 +158,29 @@
143
158
  * 考虑会有多个 @ 的存在, 匹配离插入符最近的一个*/
144
159
  subtext = text.slice(0,caret_pos);
145
160
  // word = subtext.exec(/@(\w+)$|@[^\x00-\xff]+$/g);
146
- matched = /@(\w+)$|@([^\x00-\xff]+)$/g.exec(subtext);
147
- key = null;
148
- if (matched && (word = matched[1]).length < 20) {
149
- start = caret_pos - word.length;
150
- end = start + word.length;
161
+ var self = this;
162
+ var matched = null;
163
+ $.each(this.options,function(flag) {
164
+ regexp = new RegExp(flag+'(\\w*)$|'+flag+'([^\\x00-\\xff]*)$','gi');
165
+ match = regexp.exec(subtext);
166
+ if (!_isNil(match)) {
167
+ matched = match[1] == undefined ? match[2] : match[1];
168
+ self.theflag = flag;
169
+ return false;
170
+ }
171
+ });
172
+ var key = null;
173
+ _log("matched",matched);
174
+ if (typeof matched == "string" && matched.length <= 20) {
175
+ start = caret_pos - matched.length;
176
+ end = start + matched.length;
151
177
  this.pos = start;
152
- key = {'text':word, 'start':start, 'end':end};
178
+ key = {'text':matched, 'start':start, 'end':end};
153
179
  } else
154
180
  this.view.hide();
181
+
155
182
  this.keyword = key;
156
- log("getKey",key);
183
+ _log("getKeyname",key);
157
184
  return key;
158
185
  },
159
186
  /* 捕捉inputor的上下回车键.
@@ -163,7 +190,7 @@
163
190
  onkeydown:function(e) {
164
191
  view = this.view;
165
192
  // 当列表没显示时不捕捉inputor相关事件.
166
- if (!view.running()) return true;
193
+ if (!view.watching()) return true;
167
194
  last_idx = view.items.length - 1;
168
195
  var return_val = false;
169
196
  switch (e.keyCode) {
@@ -214,7 +241,7 @@
214
241
  this.$inputor.caretPos(start_str.length + str.length);
215
242
  },
216
243
  choose: function($li) {
217
- str = isNil($li) ? this.keyword.text+" " : $li.attr("data-insert")+" ";
244
+ str = _isNil($li) ? this.keyword.text+" " : $li.attr("data-keyname")+" ";
218
245
  this.replaceStr(str);
219
246
  this.view.hide();
220
247
  },
@@ -226,11 +253,13 @@
226
253
  * 注册过的key将不再进行绑定
227
254
  * */
228
255
  key = $inputor.data("@reg-key");
229
- log("reg",inputor,key);
230
256
  if ($.inArray(key,this.inputor_keys) >= 0)
231
257
  return null;
258
+ _log("reg",inputor,key);
259
+
232
260
  key = "@-"+$.now();
233
- this.inputor_keys[key];
261
+ $inputor.data("@reg-key",key);
262
+ this.inputor_keys.push(key);
234
263
  // 捕捉inputor事件
235
264
  var self = this;
236
265
  $inputor.bind("keydown",function(e) {
@@ -244,40 +273,41 @@
244
273
  });
245
274
  return key;
246
275
  },
247
- run: function(inputor) {
276
+ watch: function(inputor) {
248
277
  this.$inputor = $(inputor);
249
- key = this.getKey();
278
+ key = this.getKeyname();
250
279
  if (!key) return false;
251
280
  /*
252
281
  * 支持多渠道获得用户数据.
253
282
  * 可以设置静态数据的同时从服务器动态获取.
254
283
  * 获取级别从先到后: cache -> statis data -> ajax.
255
284
  */
256
- if (!isNil(names = this.cache(this.keyword.text))) {
257
- log("cache data",names);
285
+ if (!_isNil(names = this.cache(this.keyword.text))) {
286
+ _log("cache data",names);
258
287
  this.view.load(names,false);
259
- } else if (!isNil(names = this.runWithData(key,settings['data']))) {
260
- log("statis data",names);
288
+ } else if (!_isNil(names = this.watchWithData(key))) {
289
+ _log("statis data",names);
261
290
  this.view.load(names,false);
262
- } else {
263
- callback = settings['callback'];
264
- log("callbacking",callback);
265
- if($.isFunction(callback)) {
266
- callback(At);
267
- }
268
- }
291
+ } else if ($.isFunction(callback = this.getOpt('callback'))){
292
+ _log("callbacking",callback);
293
+ callback(At);
294
+ } else
295
+ this.view.hide();
269
296
  },
270
- runWithData:function(key,data) {
297
+ watchWithData:function(key) {
298
+ data = this.getOpt("data");
299
+ _log("watchWithData",data);
271
300
  var items = null;
272
301
  var self = this;
273
302
  if($.isArray(data) && data.length != 0) {
274
303
  items = $.map(data,function(item,i) {
275
304
  //support plain object also
276
- var name = $.isPlainObject(item) ? item[self.search_word] : item;
305
+ var name = $.isPlainObject(item) ? item[self.searchWord()] : item;
277
306
  match = name.match((new RegExp(key.text,"i")));
278
307
  return match ? item : null;
279
308
  });
280
309
  }
310
+ _log("watch with data.item",items)
281
311
  return items;
282
312
  }
283
313
  };
@@ -288,25 +318,19 @@
288
318
  cur_li_idx : 0,
289
319
  timeout_id : null,
290
320
  id : '#at-view',
291
- //at view jquery object
292
- jqo : null,
293
321
  items : [],
294
322
  // 列表框是否显示中.
295
- running :function() {
323
+ watching :function() {
296
324
  return $(this.id).is(":visible");
297
325
  },
298
326
  evalTpl: function(tpl,map) {
299
- if(isNil(tpl)) return;
327
+ if(_isNil(tpl)) return;
300
328
  el = tpl.replace(/\$\{([^\}]*)\}/g,function(tag,key,pos){
301
329
  return map[key];
302
330
  });
303
- log("evalTpl",el);
331
+ _log("evalTpl",el);
304
332
  return el;
305
333
  },
306
- jqObject : function(o) {
307
- if (!isNil(o)) this.jqo = o;
308
- return isNil(this.jqo) ? $(this.id) : this.jqo;
309
- },
310
334
  onLoaded: function($view) {
311
335
  $view.find('li').live('click',function(e) {
312
336
  At.choose($(this));
@@ -323,23 +347,21 @@
323
347
  $view.offset(At.offset());
324
348
  },
325
349
  show: function(){
326
- if (!this.running())
350
+ if (!this.watching())
327
351
  $view = $(this.id).show();
328
352
  this.rePosition($view);
329
353
  },
330
354
  hide: function() {
331
- if (!this.running()) return;
355
+ if (!this.watching()) return;
332
356
  this.cur_li_idx = 0;
333
357
  $(this.id).hide();
334
358
  },
335
359
  load: function(list,cacheable) {
336
360
  // 是否已经加载了列表视图
337
- if (isNil(this.jqObject())) {
338
- tpl = "<div id='"+this.id.slice(1)+"' class='at-view'><span id='title'>@who?</span><ul id='"+this.id.slice(1)+"-ul'></ul></div>";
339
- $at_view = $(tpl);
340
- $('body').append($at_view);
341
- this.jqObject($at_view = $(this.id));
342
- this.onLoaded($at_view);
361
+ if (_isNil($(this.id))) {
362
+ tpl = "<div id='"+this.id.slice(1)+"' class='at-view'><ul id='"+this.id.slice(1)+"-ul'></ul></div>";
363
+ $('body').append(tpl);
364
+ this.onLoaded($(this.id));
343
365
  }
344
366
  return this.update(list,cacheable);
345
367
  },
@@ -347,19 +369,19 @@
347
369
  if (clear_all == true)
348
370
  this._cache = {};
349
371
  this.items = [];
350
- this.jqObject().find('ul').empty();
372
+ $(this.id).find('ul').empty();
351
373
  },
352
374
  update: function(list,cacheable) {
353
375
  if (!$.isArray(list)) return false;
354
376
  if (cacheable != false) At.cache(At.keyword.text,list);
355
377
 
356
- $ul = this.jqObject().find('ul');
378
+ $ul = $(this.id).find('ul');
357
379
  this.clear();
358
380
  $.merge(this.items,list);
359
- var tpl = settings['tpl'];
381
+ var tpl = At.getOpt('tpl');
360
382
  var self = this;
361
- var list = unique(list,At.search_word);
362
- $.each(list.splice(0,settings['limit']), function(i,item) {
383
+ var list = _unique(list,At.searchWord());
384
+ $.each(list.splice(0, At.getOpt('limit')), function(i,item) {
363
385
  if (!$.isPlainObject(item)) {
364
386
  item = {'id':i,'name':item};
365
387
  tpl = DEFAULT_TPL;
@@ -371,14 +393,14 @@
371
393
  }
372
394
  };
373
395
 
374
- /* maybe we can use $.unique.
396
+ /* maybe we can use $._unique.
375
397
  * But i don't know it will delete li element frequently or not.
376
398
  * I think we should not change DOM element frequently.
377
399
  * more, It seems batter not to call evalTpl function too much times.
378
400
  * */
379
- function unique(list,keyword) {
401
+ function _unique(list,keyword) {
380
402
  var record = [];
381
- log(list,keyword);
403
+ _log(list,keyword);
382
404
  return $.map(list,function(v,idx){
383
405
  var value = $.isPlainObject(v) ? v[keyword] : v;
384
406
  if ($.inArray(value,record) < 0) {
@@ -388,7 +410,7 @@
388
410
  });
389
411
  }
390
412
 
391
- function isNil(target) {
413
+ function _isNil(target) {
392
414
  return !target
393
415
  //empty_object =
394
416
  || ($.isPlainObject(target) && $.isEmptyObject(target))
@@ -399,52 +421,46 @@
399
421
  || target === undefined;
400
422
  }
401
423
 
402
- function log() {
403
- if (!settings['debug'] || $.browser.msie)
424
+ function _log() {
425
+ if (!At.getOpt('debug') || $.browser.msie)
404
426
  return;
405
427
  console.log(arguments);
406
428
  }
407
429
 
408
- function setSettings(options) {
430
+ function _setSettings(options) {
409
431
  opt = {};
410
432
  if ($.isFunction(options))
411
433
  opt['callback'] = options;
412
434
  else
413
435
  opt = options;
414
436
  return $.extend({
415
- //must return array;
416
- 'callback': function(context) {return []},
417
437
  'cache' : true,
418
- 'debug' : false,
419
- 'tpl' : DEFAULT_TPL,
420
- 'limit' : 5,
421
- 'data':[]
438
+ 'debug' : false,
439
+ 'limit' : 5,
440
+ 'tpl' : DEFAULT_TPL
422
441
  },opt);
423
442
  }
424
443
 
425
- DEFAULT_TPL = "<li id='${id}' data-insert='${name}'>${name}</li>";
426
-
427
- $.fn.atWho = function (options) {
428
- settings = setSettings(options);
429
- log("settings",settings);
430
- // just used in At.runWithData
431
- var match = /data-insert=['?]\$\{(\w+)\}/g.exec(settings['tpl']);
432
- At.search_word = match[1];
444
+ DEFAULT_TPL = "<li id='${id}' data-keyname='${name}'>${name}</li>";
445
+
446
+ $.fn.atWho = function (flag,options) {
447
+ At.options[flag] = _setSettings(options);
448
+ _log("options",At.options);
433
449
  return this.filter('textarea, input').each(function() {
434
450
  if (!At.reg(this)) return;
435
451
  $(this).bind("keyup",function(e) {
436
452
  /* 当用户列表框显示时, 上下键不触发查询 */
437
453
  var stop_key = e.keyCode == 40 || e.keyCode == 38;
438
- run = !(At.view.running() && stop_key);
439
- if (run) At.run(this);
454
+ watch = !(At.view.watching() && stop_key);
455
+ if (watch) At.watch(this);
440
456
  })
441
457
  .mouseup(function(e) {
442
- At.run(this);
458
+ At.watch(this);
443
459
  });
444
460
  });
461
+ return At;
445
462
  }
446
- })(jQuery);
447
-
463
+ })(window.jQuery);
448
464
  /* 本插件操作 textarea 或者 input 内的插入符
449
465
  * 只实现了获得插入符在文本框中的位置,我设置
450
466
  * 插入符的位置.
@@ -544,4 +560,4 @@
544
560
  return getCaretPos(inputor);
545
561
  }
546
562
  }
547
- })(jQuery);
563
+ })(window.jQuery);
@@ -1,7 +1,7 @@
1
1
  module Jquery
2
2
  module Atwho
3
3
  module Rails
4
- VERSION = "0.0.1"
4
+ VERSION = "0.1.0"
5
5
  end
6
6
  end
7
7
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: jquery-atwho-rails
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.1
4
+ version: 0.1.0
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -9,11 +9,11 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2012-02-09 00:00:00.000000000 Z
12
+ date: 2012-03-19 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: rspec
16
- requirement: &76937320 !ruby/object:Gem::Requirement
16
+ requirement: !ruby/object:Gem::Requirement
17
17
  none: false
18
18
  requirements:
19
19
  - - ! '>='
@@ -21,10 +21,15 @@ dependencies:
21
21
  version: '0'
22
22
  type: :development
23
23
  prerelease: false
24
- version_requirements: *76937320
24
+ version_requirements: !ruby/object:Gem::Requirement
25
+ none: false
26
+ requirements:
27
+ - - ! '>='
28
+ - !ruby/object:Gem::Version
29
+ version: '0'
25
30
  - !ruby/object:Gem::Dependency
26
31
  name: generator_spec
27
- requirement: &76937010 !ruby/object:Gem::Requirement
32
+ requirement: !ruby/object:Gem::Requirement
28
33
  none: false
29
34
  requirements:
30
35
  - - ! '>='
@@ -32,7 +37,12 @@ dependencies:
32
37
  version: '0'
33
38
  type: :development
34
39
  prerelease: false
35
- version_requirements: *76937010
40
+ version_requirements: !ruby/object:Gem::Requirement
41
+ none: false
42
+ requirements:
43
+ - - ! '>='
44
+ - !ruby/object:Gem::Version
45
+ version: '0'
36
46
  description: ! "This is a jQuery plugin \n that implement Twitter/Weibo like @
37
47
  mentions."
38
48
  email:
@@ -73,7 +83,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
73
83
  version: '0'
74
84
  requirements: []
75
85
  rubyforge_project: jquery-atwho-rails
76
- rubygems_version: 1.8.12
86
+ rubygems_version: 1.8.19
77
87
  signing_key:
78
88
  specification_version: 3
79
89
  summary: ! 'jquery plugin: @mentions'