jquery-atwho-rails 0.0.1 → 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
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'