jquery-atwho-rails 0.4.5 → 0.4.7

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: d2dd59a48f6a65bb4ecd8be26f8375c12aae7c0b
4
- data.tar.gz: 7663cd82b31f3989bfa58fbc785cceaebff87e81
3
+ metadata.gz: f4711b0cee4422713ce5672944e44588dcc560e8
4
+ data.tar.gz: a96d6fc2ee15c7d549f55e83aa855793f801b73b
5
5
  SHA512:
6
- metadata.gz: c4ba905d140575cf2c20de6d3bbf625fee4defdc2c0d97b4d9ebb05466f0fffba8bcbd62730daa98f79c57a556facc79d25bb2f7b07f23d9f08a3720839e3edd
7
- data.tar.gz: 3116c072145617a20e6ee19797dc1a07cb9e9ab02749543d5f8a7d2ab1df809c8f2c32a6b1774dd5e73d0c47685525f020ff5e4942f147f2bcb0484ddd16bf37
6
+ metadata.gz: da25e5bd13ae5af69b9037d6851c498ce3febed96b2074dbf2d6ab98132c74ae7b8118f9a2a15aab50fe48a06f107bc80e04162b32b8a2521021a8167afe46b4
7
+ data.tar.gz: 8c71f0f82b185ead06af5a8c3311b1e59192fe451e8dcede7be675ae41668b158c082489b48ebbe6ac9c2f402475e3bc35d29ff99ceb4f93882884b685d62726
data/Rakefile CHANGED
@@ -1,9 +1,11 @@
1
1
  require "bundler/gem_tasks"
2
2
 
3
+ at_dir = "tmp/At.js"
4
+ bower_dir = "#{at_dir}/bower_components/"
5
+
3
6
  desc "sync from At.js"
4
7
  task :sync do
5
8
  puts " * syncing..."
6
- at_dir = "tmp/At.js"
7
9
  FileUtils.mkdir_p("tmp") unless Dir.exist? "tmp"
8
10
  unless Dir.exist? at_dir
9
11
  system "git clone git://github.com/ichord/At.js.git #{at_dir}"
@@ -12,12 +14,23 @@ task :sync do
12
14
  end
13
15
  end
14
16
 
17
+ desc "load dependences"
18
+ task :bower_install => :sync do
19
+ unless Dir.exist? bower_dir
20
+ Dir.chdir(at_dir) { puts %x{bower install} }
21
+ end
22
+ end
23
+
15
24
  desc "copy assets"
16
- task :fresh => :sync do
25
+ task :fresh => [:bower_install, :sync] do
17
26
  puts "", " * Copying..."
18
27
  source_dir = "tmp/At.js/dist"
19
28
  dist_dir = "lib/assets"
20
- FileUtils.copy "#{source_dir}/js/jquery.atwho.js", "#{dist_dir}/javascripts/"
29
+
30
+ js_dist_dir = "#{dist_dir}/javascripts/jquery.atwho/"
31
+ FileUtils.copy "#{bower_dir}/Caret.js/src/jquery.caret.js", js_dist_dir
32
+ FileUtils.copy "#{source_dir}/js/jquery.atwho.js", js_dist_dir
33
+
21
34
  FileUtils.copy "#{source_dir}/css/jquery.atwho.css", "#{dist_dir}/stylesheets/"
22
35
  puts `ls -R #{dist_dir}`
23
36
  end
@@ -0,0 +1,2 @@
1
+ //= require ./jquery.caret
2
+ //= require ./jquery.atwho
@@ -0,0 +1,752 @@
1
+ /*! jquery.atwho - v0.4.7 - 2014-02-22
2
+ * Copyright (c) 2014 chord.luo <chord.luo@gmail.com>;
3
+ * homepage: http://ichord.github.com/At.js
4
+ * Licensed MIT
5
+ */
6
+
7
+ (function() {
8
+ (function(factory) {
9
+ if (typeof define === 'function' && define.amd) {
10
+ return define(['jquery'], factory);
11
+ } else {
12
+ return factory(window.jQuery);
13
+ }
14
+ })(function($) {
15
+
16
+ var $CONTAINER, Api, App, Atwho, Controller, DEFAULT_CALLBACKS, KEY_CODE, Model, View,
17
+ __slice = [].slice;
18
+
19
+ App = (function() {
20
+ function App(inputor) {
21
+ this.current_flag = null;
22
+ this.controllers = {};
23
+ this.alias_maps = {};
24
+ this.$inputor = $(inputor);
25
+ this.listen();
26
+ }
27
+
28
+ App.prototype.controller = function(at) {
29
+ return this.controllers[this.alias_maps[at] || at || this.current_flag];
30
+ };
31
+
32
+ App.prototype.set_context_for = function(at) {
33
+ this.current_flag = at;
34
+ return this;
35
+ };
36
+
37
+ App.prototype.reg = function(flag, setting) {
38
+ var controller, _base;
39
+ controller = (_base = this.controllers)[flag] || (_base[flag] = new Controller(this, flag));
40
+ if (setting.alias) {
41
+ this.alias_maps[setting.alias] = flag;
42
+ }
43
+ controller.init(setting);
44
+ return this;
45
+ };
46
+
47
+ App.prototype.listen = function() {
48
+ return this.$inputor.on('keyup.atwhoInner', (function(_this) {
49
+ return function(e) {
50
+ return _this.on_keyup(e);
51
+ };
52
+ })(this)).on('keydown.atwhoInner', (function(_this) {
53
+ return function(e) {
54
+ return _this.on_keydown(e);
55
+ };
56
+ })(this)).on('scroll.atwhoInner', (function(_this) {
57
+ return function(e) {
58
+ var _ref;
59
+ return (_ref = _this.controller()) != null ? _ref.view.hide() : void 0;
60
+ };
61
+ })(this)).on('blur.atwhoInner', (function(_this) {
62
+ return function(e) {
63
+ var c;
64
+ if (c = _this.controller()) {
65
+ return c.view.hide(c.get_opt("display_timeout"));
66
+ }
67
+ };
68
+ })(this));
69
+ };
70
+
71
+ App.prototype.shutdown = function() {
72
+ var c, _, _ref;
73
+ _ref = this.controllers;
74
+ for (_ in _ref) {
75
+ c = _ref[_];
76
+ c.destroy();
77
+ }
78
+ return this.$inputor.off('.atwhoInner');
79
+ };
80
+
81
+ App.prototype.dispatch = function() {
82
+ return $.map(this.controllers, (function(_this) {
83
+ return function(c) {
84
+ if (c.look_up()) {
85
+ return _this.set_context_for(c.at);
86
+ }
87
+ };
88
+ })(this));
89
+ };
90
+
91
+ App.prototype.on_keyup = function(e) {
92
+ var _ref;
93
+ switch (e.keyCode) {
94
+ case KEY_CODE.ESC:
95
+ e.preventDefault();
96
+ if ((_ref = this.controller()) != null) {
97
+ _ref.view.hide();
98
+ }
99
+ break;
100
+ case KEY_CODE.DOWN:
101
+ case KEY_CODE.UP:
102
+ $.noop();
103
+ break;
104
+ default:
105
+ this.dispatch();
106
+ }
107
+ };
108
+
109
+ App.prototype.on_keydown = function(e) {
110
+ var view, _ref;
111
+ view = (_ref = this.controller()) != null ? _ref.view : void 0;
112
+ if (!(view && view.visible())) {
113
+ return;
114
+ }
115
+ switch (e.keyCode) {
116
+ case KEY_CODE.ESC:
117
+ e.preventDefault();
118
+ view.hide();
119
+ break;
120
+ case KEY_CODE.UP:
121
+ e.preventDefault();
122
+ view.prev();
123
+ break;
124
+ case KEY_CODE.DOWN:
125
+ e.preventDefault();
126
+ view.next();
127
+ break;
128
+ case KEY_CODE.TAB:
129
+ case KEY_CODE.ENTER:
130
+ if (!view.visible()) {
131
+ return;
132
+ }
133
+ e.preventDefault();
134
+ view.choose();
135
+ break;
136
+ default:
137
+ $.noop();
138
+ }
139
+ };
140
+
141
+ return App;
142
+
143
+ })();
144
+
145
+ Controller = (function() {
146
+ var uuid, _uuid;
147
+
148
+ _uuid = 0;
149
+
150
+ uuid = function() {
151
+ return _uuid += 1;
152
+ };
153
+
154
+ function Controller(app, at) {
155
+ this.app = app;
156
+ this.at = at;
157
+ this.$inputor = this.app.$inputor;
158
+ this.oDocument = this.$inputor[0].ownerDocument;
159
+ this.oWindow = this.oDocument.defaultView || this.oDocument.parentWindow;
160
+ this.id = this.$inputor[0].id || uuid();
161
+ this.setting = null;
162
+ this.query = null;
163
+ this.pos = 0;
164
+ this.cur_rect = null;
165
+ this.range = null;
166
+ $CONTAINER.append(this.$el = $("<div id='atwho-ground-" + this.id + "'></div>"));
167
+ this.model = new Model(this);
168
+ this.view = new View(this);
169
+ }
170
+
171
+ Controller.prototype.init = function(setting) {
172
+ this.setting = $.extend({}, this.setting || $.fn.atwho["default"], setting);
173
+ this.view.init();
174
+ return this.model.reload(this.setting.data);
175
+ };
176
+
177
+ Controller.prototype.destroy = function() {
178
+ this.trigger('beforeDestroy');
179
+ this.model.destroy();
180
+ return this.view.destroy();
181
+ };
182
+
183
+ Controller.prototype.call_default = function() {
184
+ var args, error, func_name;
185
+ func_name = arguments[0], args = 2 <= arguments.length ? __slice.call(arguments, 1) : [];
186
+ try {
187
+ return DEFAULT_CALLBACKS[func_name].apply(this, args);
188
+ } catch (_error) {
189
+ error = _error;
190
+ return $.error("" + error + " Or maybe At.js doesn't have function " + func_name);
191
+ }
192
+ };
193
+
194
+ Controller.prototype.trigger = function(name, data) {
195
+ var alias, event_name;
196
+ if (data == null) {
197
+ data = [];
198
+ }
199
+ data.push(this);
200
+ alias = this.get_opt('alias');
201
+ event_name = alias ? "" + name + "-" + alias + ".atwho" : "" + name + ".atwho";
202
+ return this.$inputor.trigger(event_name, data);
203
+ };
204
+
205
+ Controller.prototype.callbacks = function(func_name) {
206
+ return this.get_opt("callbacks")[func_name] || DEFAULT_CALLBACKS[func_name];
207
+ };
208
+
209
+ Controller.prototype.get_opt = function(at, default_value) {
210
+ var e;
211
+ try {
212
+ return this.setting[at];
213
+ } catch (_error) {
214
+ e = _error;
215
+ return null;
216
+ }
217
+ };
218
+
219
+ Controller.prototype.content = function() {
220
+ if (this.$inputor.is('textarea, input')) {
221
+ return this.$inputor.val();
222
+ } else {
223
+ return this.$inputor.text();
224
+ }
225
+ };
226
+
227
+ Controller.prototype.catch_query = function() {
228
+ var caret_pos, content, end, query, start, subtext;
229
+ content = this.content();
230
+ caret_pos = this.$inputor.caret('pos');
231
+ subtext = content.slice(0, caret_pos);
232
+ query = this.callbacks("matcher").call(this, this.at, subtext, this.get_opt('start_with_space'));
233
+ if (typeof query === "string" && query.length <= this.get_opt('max_len', 20)) {
234
+ start = caret_pos - query.length;
235
+ end = start + query.length;
236
+ this.pos = start;
237
+ query = {
238
+ 'text': query.toLowerCase(),
239
+ 'head_pos': start,
240
+ 'end_pos': end
241
+ };
242
+ this.trigger("matched", [this.at, query.text]);
243
+ } else {
244
+ this.view.hide();
245
+ }
246
+ return this.query = query;
247
+ };
248
+
249
+ Controller.prototype.rect = function() {
250
+ var c, scale_bottom;
251
+ if (!(c = this.$inputor.caret('offset', this.pos - 1))) {
252
+ return;
253
+ }
254
+ if (this.$inputor.attr('contentEditable') === 'true') {
255
+ c = (this.cur_rect || (this.cur_rect = c)) || c;
256
+ }
257
+ scale_bottom = document.selection ? 0 : 2;
258
+ return {
259
+ left: c.left,
260
+ top: c.top,
261
+ bottom: c.top + c.height + scale_bottom
262
+ };
263
+ };
264
+
265
+ Controller.prototype.reset_rect = function() {
266
+ if (this.$inputor.attr('contentEditable') === 'true') {
267
+ return this.cur_rect = null;
268
+ }
269
+ };
270
+
271
+ Controller.prototype.mark_range = function() {
272
+ if (this.$inputor.attr('contentEditable') === 'true') {
273
+ if (this.oWindow.getSelection) {
274
+ this.range = this.oWindow.getSelection().getRangeAt(0);
275
+ }
276
+ if (this.oDocument.selection) {
277
+ return this.ie8_range = this.oDocument.selection.createRange();
278
+ }
279
+ }
280
+ };
281
+
282
+ Controller.prototype.insert_content_for = function($li) {
283
+ var data, data_value, tpl;
284
+ data_value = $li.data('value');
285
+ tpl = this.get_opt('insert_tpl');
286
+ if (this.$inputor.is('textarea, input') || !tpl) {
287
+ return data_value;
288
+ }
289
+ data = $.extend({}, $li.data('item-data'), {
290
+ 'atwho-data-value': data_value,
291
+ 'atwho-at': this.at
292
+ });
293
+ return this.callbacks("tpl_eval").call(this, tpl, data);
294
+ };
295
+
296
+ Controller.prototype.insert = function(content, $li) {
297
+ var $inputor, $insert_node, class_name, content_node, insert_node, pos, range, sel, source, start_str, text;
298
+ $inputor = this.$inputor;
299
+ if ($inputor.attr('contentEditable') === 'true') {
300
+ class_name = "atwho-view-flag atwho-view-flag-" + (this.get_opt('alias') || this.at);
301
+ content_node = "" + content + "<span contenteditable='false'>&nbsp;<span>";
302
+ insert_node = "<span contenteditable='false' class='" + class_name + "'>" + content_node + "</span>";
303
+ $insert_node = $(insert_node, this.oDocument).data('atwho-data-item', $li.data('item-data'));
304
+ if (this.oDocument.selection) {
305
+ $insert_node = $("<span contenteditable='true'></span>", this.oDocument).html($insert_node);
306
+ }
307
+ }
308
+ if ($inputor.is('textarea, input')) {
309
+ content = '' + content;
310
+ source = $inputor.val();
311
+ start_str = source.slice(0, Math.max(this.query.head_pos - this.at.length, 0));
312
+ text = "" + start_str + content + " " + (source.slice(this.query['end_pos'] || 0));
313
+ $inputor.val(text);
314
+ $inputor.caret('pos', start_str.length + content.length + 1);
315
+ } else if (range = this.range) {
316
+ pos = range.startOffset - (this.query.end_pos - this.query.head_pos) - this.at.length;
317
+ range.setStart(range.endContainer, Math.max(pos, 0));
318
+ range.setEnd(range.endContainer, range.endOffset);
319
+ range.deleteContents();
320
+ range.insertNode($insert_node[0]);
321
+ range.collapse(false);
322
+ sel = this.oWindow.getSelection();
323
+ sel.removeAllRanges();
324
+ sel.addRange(range);
325
+ } else if (range = this.ie8_range) {
326
+ range.moveStart('character', this.query.end_pos - this.query.head_pos - this.at.length);
327
+ range.pasteHTML(content_node);
328
+ range.collapse(false);
329
+ range.select();
330
+ }
331
+ if (!$inputor.is(':focus')) {
332
+ $inputor.focus();
333
+ }
334
+ return $inputor.change();
335
+ };
336
+
337
+ Controller.prototype.render_view = function(data) {
338
+ var search_key;
339
+ search_key = this.get_opt("search_key");
340
+ data = this.callbacks("sorter").call(this, this.query.text, data.slice(0, 1001), search_key);
341
+ return this.view.render(data.slice(0, this.get_opt('limit')));
342
+ };
343
+
344
+ Controller.prototype.look_up = function() {
345
+ var query, _callback;
346
+ if (!(query = this.catch_query())) {
347
+ return;
348
+ }
349
+ _callback = function(data) {
350
+ if (data && data.length > 0) {
351
+ return this.render_view(data);
352
+ } else {
353
+ return this.view.hide();
354
+ }
355
+ };
356
+ this.model.query(query.text, $.proxy(_callback, this));
357
+ return query;
358
+ };
359
+
360
+ return Controller;
361
+
362
+ })();
363
+
364
+ Model = (function() {
365
+ function Model(context) {
366
+ this.context = context;
367
+ this.at = this.context.at;
368
+ this.storage = this.context.$inputor;
369
+ }
370
+
371
+ Model.prototype.destroy = function() {
372
+ return this.storage.data(this.at, null);
373
+ };
374
+
375
+ Model.prototype.saved = function() {
376
+ return this.fetch() > 0;
377
+ };
378
+
379
+ Model.prototype.query = function(query, callback) {
380
+ var data, search_key, _remote_filter;
381
+ data = this.fetch();
382
+ search_key = this.context.get_opt("search_key");
383
+ data = this.context.callbacks('filter').call(this.context, query, data, search_key) || [];
384
+ _remote_filter = this.context.callbacks('remote_filter');
385
+ if (data.length > 0 || (!_remote_filter && data.length === 0)) {
386
+ return callback(data);
387
+ } else {
388
+ return _remote_filter.call(this.context, query, callback);
389
+ }
390
+ };
391
+
392
+ Model.prototype.fetch = function() {
393
+ return this.storage.data(this.at) || [];
394
+ };
395
+
396
+ Model.prototype.save = function(data) {
397
+ return this.storage.data(this.at, this.context.callbacks("before_save").call(this.context, data || []));
398
+ };
399
+
400
+ Model.prototype.load = function(data) {
401
+ if (!(this.saved() || !data)) {
402
+ return this._load(data);
403
+ }
404
+ };
405
+
406
+ Model.prototype.reload = function(data) {
407
+ return this._load(data);
408
+ };
409
+
410
+ Model.prototype._load = function(data) {
411
+ if (typeof data === "string") {
412
+ return $.ajax(data, {
413
+ dataType: "json"
414
+ }).done((function(_this) {
415
+ return function(data) {
416
+ return _this.save(data);
417
+ };
418
+ })(this));
419
+ } else {
420
+ return this.save(data);
421
+ }
422
+ };
423
+
424
+ return Model;
425
+
426
+ })();
427
+
428
+ View = (function() {
429
+ function View(context) {
430
+ this.context = context;
431
+ this.$el = $("<div class='atwho-view'><ul class='atwho-view-ul'></ul></div>");
432
+ this.timeout_id = null;
433
+ this.context.$el.append(this.$el);
434
+ this.bind_event();
435
+ }
436
+
437
+ View.prototype.init = function() {
438
+ var id;
439
+ id = this.context.get_opt("alias") || this.context.at.charCodeAt(0);
440
+ return this.$el.attr({
441
+ 'id': "at-view-" + id
442
+ });
443
+ };
444
+
445
+ View.prototype.destroy = function() {
446
+ return this.$el.remove();
447
+ };
448
+
449
+ View.prototype.bind_event = function() {
450
+ var $menu;
451
+ $menu = this.$el.find('ul');
452
+ return $menu.on('mouseenter.atwho-view', 'li', function(e) {
453
+ $menu.find('.cur').removeClass('cur');
454
+ return $(e.currentTarget).addClass('cur');
455
+ }).on('click', (function(_this) {
456
+ return function(e) {
457
+ _this.choose();
458
+ return e.preventDefault();
459
+ };
460
+ })(this));
461
+ };
462
+
463
+ View.prototype.visible = function() {
464
+ return this.$el.is(":visible");
465
+ };
466
+
467
+ View.prototype.choose = function() {
468
+ var $li, content;
469
+ $li = this.$el.find(".cur");
470
+ content = this.context.insert_content_for($li);
471
+ this.context.insert(this.context.callbacks("before_insert").call(this.context, content, $li), $li);
472
+ this.context.trigger("inserted", [$li]);
473
+ return this.hide();
474
+ };
475
+
476
+ View.prototype.reposition = function(rect) {
477
+ var offset;
478
+ if (rect.bottom + this.$el.height() - $(window).scrollTop() > $(window).height()) {
479
+ rect.bottom = rect.top - this.$el.height();
480
+ }
481
+ offset = {
482
+ left: rect.left,
483
+ top: rect.bottom
484
+ };
485
+ this.$el.offset(offset);
486
+ return this.context.trigger("reposition", [offset]);
487
+ };
488
+
489
+ View.prototype.next = function() {
490
+ var cur, next;
491
+ cur = this.$el.find('.cur').removeClass('cur');
492
+ next = cur.next();
493
+ if (!next.length) {
494
+ next = this.$el.find('li:first');
495
+ }
496
+ return next.addClass('cur');
497
+ };
498
+
499
+ View.prototype.prev = function() {
500
+ var cur, prev;
501
+ cur = this.$el.find('.cur').removeClass('cur');
502
+ prev = cur.prev();
503
+ if (!prev.length) {
504
+ prev = this.$el.find('li:last');
505
+ }
506
+ return prev.addClass('cur');
507
+ };
508
+
509
+ View.prototype.show = function() {
510
+ var rect;
511
+ this.context.mark_range();
512
+ if (!this.visible()) {
513
+ this.$el.show();
514
+ }
515
+ if (rect = this.context.rect()) {
516
+ return this.reposition(rect);
517
+ }
518
+ };
519
+
520
+ View.prototype.hide = function(time) {
521
+ var callback;
522
+ if (isNaN(time && this.visible())) {
523
+ this.context.reset_rect();
524
+ return this.$el.hide();
525
+ } else {
526
+ callback = (function(_this) {
527
+ return function() {
528
+ return _this.hide();
529
+ };
530
+ })(this);
531
+ clearTimeout(this.timeout_id);
532
+ return this.timeout_id = setTimeout(callback, time);
533
+ }
534
+ };
535
+
536
+ View.prototype.render = function(list) {
537
+ var $li, $ul, item, li, tpl, _i, _len;
538
+ if (!($.isArray(list) && list.length > 0)) {
539
+ this.hide();
540
+ return;
541
+ }
542
+ this.$el.find('ul').empty();
543
+ $ul = this.$el.find('ul');
544
+ tpl = this.context.get_opt('tpl');
545
+ for (_i = 0, _len = list.length; _i < _len; _i++) {
546
+ item = list[_i];
547
+ item = $.extend({}, item, {
548
+ 'atwho-at': this.context.at
549
+ });
550
+ li = this.context.callbacks("tpl_eval").call(this.context, tpl, item);
551
+ $li = $(this.context.callbacks("highlighter").call(this.context, li, this.context.query.text));
552
+ $li.data("item-data", item);
553
+ $ul.append($li);
554
+ }
555
+ this.show();
556
+ return $ul.find("li:first").addClass("cur");
557
+ };
558
+
559
+ return View;
560
+
561
+ })();
562
+
563
+ KEY_CODE = {
564
+ DOWN: 40,
565
+ UP: 38,
566
+ ESC: 27,
567
+ TAB: 9,
568
+ ENTER: 13
569
+ };
570
+
571
+ DEFAULT_CALLBACKS = {
572
+ before_save: function(data) {
573
+ var item, _i, _len, _results;
574
+ if (!$.isArray(data)) {
575
+ return data;
576
+ }
577
+ _results = [];
578
+ for (_i = 0, _len = data.length; _i < _len; _i++) {
579
+ item = data[_i];
580
+ if ($.isPlainObject(item)) {
581
+ _results.push(item);
582
+ } else {
583
+ _results.push({
584
+ name: item
585
+ });
586
+ }
587
+ }
588
+ return _results;
589
+ },
590
+ matcher: function(flag, subtext, should_start_with_space) {
591
+ var match, regexp;
592
+ flag = flag.replace(/[\-\[\]\/\{\}\(\)\*\+\?\.\\\^\$\|]/g, "\\$&");
593
+ if (should_start_with_space) {
594
+ flag = '(?:^|\\s)' + flag;
595
+ }
596
+ regexp = new RegExp(flag + '([A-Za-z0-9_\+\-]*)$|' + flag + '([^\\x00-\\xff]*)$', 'gi');
597
+ match = regexp.exec(subtext);
598
+ if (match) {
599
+ return match[2] || match[1];
600
+ } else {
601
+ return null;
602
+ }
603
+ },
604
+ filter: function(query, data, search_key) {
605
+ var item, _i, _len, _results;
606
+ _results = [];
607
+ for (_i = 0, _len = data.length; _i < _len; _i++) {
608
+ item = data[_i];
609
+ if (~item[search_key].toLowerCase().indexOf(query)) {
610
+ _results.push(item);
611
+ }
612
+ }
613
+ return _results;
614
+ },
615
+ remote_filter: null,
616
+ sorter: function(query, items, search_key) {
617
+ var item, _i, _len, _results;
618
+ if (!query) {
619
+ return items;
620
+ }
621
+ _results = [];
622
+ for (_i = 0, _len = items.length; _i < _len; _i++) {
623
+ item = items[_i];
624
+ item.atwho_order = item[search_key].toLowerCase().indexOf(query);
625
+ if (item.atwho_order > -1) {
626
+ _results.push(item);
627
+ }
628
+ }
629
+ return _results.sort(function(a, b) {
630
+ return a.atwho_order - b.atwho_order;
631
+ });
632
+ },
633
+ tpl_eval: function(tpl, map) {
634
+ var error;
635
+ try {
636
+ return tpl.replace(/\$\{([^\}]*)\}/g, function(tag, key, pos) {
637
+ return map[key];
638
+ });
639
+ } catch (_error) {
640
+ error = _error;
641
+ return "";
642
+ }
643
+ },
644
+ highlighter: function(li, query) {
645
+ var regexp;
646
+ if (!query) {
647
+ return li;
648
+ }
649
+ regexp = new RegExp(">\\s*(\\w*)(" + query.replace("+", "\\+") + ")(\\w*)\\s*<", 'ig');
650
+ return li.replace(regexp, function(str, $1, $2, $3) {
651
+ return '> ' + $1 + '<strong>' + $2 + '</strong>' + $3 + ' <';
652
+ });
653
+ },
654
+ before_insert: function(value, $li) {
655
+ return value;
656
+ }
657
+ };
658
+
659
+ Api = {
660
+ load: function(at, data) {
661
+ var c;
662
+ if (c = this.controller(at)) {
663
+ return c.model.load(data);
664
+ }
665
+ },
666
+ getInsertedItemsWithIDs: function(at) {
667
+ var c, ids, items;
668
+ if (!(c = this.controller(at))) {
669
+ return [null, null];
670
+ }
671
+ if (at) {
672
+ at = "-" + (c.get_opt('alias') || c.at);
673
+ }
674
+ ids = [];
675
+ items = $.map(this.$inputor.find("span.atwho-view-flag" + (at || "")), function(item) {
676
+ var data;
677
+ data = $(item).data('atwho-data-item');
678
+ if (ids.indexOf(data.id) > -1) {
679
+ return;
680
+ }
681
+ if (data.id) {
682
+ ids.push = data.id;
683
+ }
684
+ return data;
685
+ });
686
+ return [ids, items];
687
+ },
688
+ getInsertedItems: function(at) {
689
+ return Api.getInsertedItemsWithIDs.apply(this, [at])[1];
690
+ },
691
+ getInsertedIDs: function(at) {
692
+ return Api.getInsertedItemsWithIDs.apply(this, [at])[0];
693
+ },
694
+ run: function() {
695
+ return this.dispatch();
696
+ },
697
+ destroy: function() {
698
+ this.shutdown();
699
+ return this.$inputor.data('atwho', null);
700
+ }
701
+ };
702
+
703
+ Atwho = {
704
+ init: function(options) {
705
+ var $this, app;
706
+ app = ($this = $(this)).data("atwho");
707
+ if (!app) {
708
+ $this.data('atwho', (app = new App(this)));
709
+ }
710
+ app.reg(options.at, options);
711
+ return this;
712
+ }
713
+ };
714
+
715
+ $CONTAINER = $("<div id='atwho-container'></div>");
716
+
717
+ $.fn.atwho = function(method) {
718
+ var result, _args;
719
+ _args = arguments;
720
+ $('body').append($CONTAINER);
721
+ result = null;
722
+ this.filter('textarea, input, [contenteditable=true]').each(function() {
723
+ var app;
724
+ if (typeof method === 'object' || !method) {
725
+ return Atwho.init.apply(this, _args);
726
+ } else if (Api[method]) {
727
+ if (app = $(this).data('atwho')) {
728
+ return result = Api[method].apply(app, Array.prototype.slice.call(_args, 1));
729
+ }
730
+ } else {
731
+ return $.error("Method " + method + " does not exist on jQuery.caret");
732
+ }
733
+ });
734
+ return result || this;
735
+ };
736
+
737
+ $.fn.atwho["default"] = {
738
+ at: void 0,
739
+ alias: void 0,
740
+ data: null,
741
+ tpl: "<li data-value='${atwho-at}${name}'>${name}</li>",
742
+ insert_tpl: "<span>${atwho-data-value}</span>",
743
+ callbacks: DEFAULT_CALLBACKS,
744
+ search_key: "name",
745
+ start_with_space: true,
746
+ limit: 5,
747
+ max_len: 20,
748
+ display_timeout: 300
749
+ };
750
+
751
+ });
752
+ }).call(this);