jquery-atwho-rails 0.3.3 → 0.4.1

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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: f23f3dd69a13e3d32ba15c24cf482ae50f7c25de
4
- data.tar.gz: 515be810af285936cdb4bf39a92f6a0c9b831f96
3
+ metadata.gz: ee0d4a6e119e2f77127b810901f3572f95cf1d62
4
+ data.tar.gz: 02c7cea94f2a89ff6eff5ffdeb74eb57b3dc1c64
5
5
  SHA512:
6
- metadata.gz: b65e6355e267e761c7235fafcff88510a3fa3e7453fb40be0d726351875bcbe7ac6805a268172af0af53412939b99c5421d227df286c455ad9ff410467109af1
7
- data.tar.gz: 93d434497c9da9508767bf21bf7c1fe673f869f1e25abfc35ce1d3426d732499273c3d96467887d55fedb1d15341a6131e1e725a9e33757f6af38b7e9ab04a09
6
+ metadata.gz: 37fb91bd4a88c5dae9c152eda4cedf20be7270b3a567581e51e510f791b4c44cae23c53a42c502a1342f8f89ff13b67a3a035780689b3e28caf20a4a56e2e64e
7
+ data.tar.gz: b65c453e756f540f774b5cc32e6d9ef9b9c402852fbb3528432c1f2ada50a89ef154e648552a36d0bb2204144cd5855ecd8b42519f75f89f573d4880c75c8f89
@@ -24,110 +24,196 @@
24
24
  }
25
25
  })(function($) {
26
26
  "use strict";
27
- var Caret, Mirror, methods, pluginName;
27
+ var EditableCaret, InputCaret, Mirror, Utils, methods, pluginName;
28
28
 
29
29
  pluginName = 'caret';
30
- Caret = (function() {
31
- function Caret($inputor) {
30
+ EditableCaret = (function() {
31
+ function EditableCaret($inputor) {
32
32
  this.$inputor = $inputor;
33
33
  this.domInputor = this.$inputor[0];
34
34
  }
35
35
 
36
- Caret.prototype.getPos = function() {
37
- var end, endRange, inputor, len, normalizedValue, pos, range, start, textInputRange;
36
+ EditableCaret.prototype.setPos = function(pos) {
37
+ return this.domInputor;
38
+ };
38
39
 
39
- inputor = this.domInputor;
40
- inputor.focus();
41
- if (document.selection) {
42
- /*
43
- #assume we select "HATE" in the inputor such as textarea -> { }.
44
- * start end-point.
45
- * /
46
- * < I really [HATE] IE > between the brackets is the selection range.
47
- * \
48
- * end end-point.
49
- */
40
+ EditableCaret.prototype.getIEPosition = function() {
41
+ return $.noop();
42
+ };
50
43
 
51
- range = document.selection.createRange();
52
- pos = 0;
53
- if (range && range.parentElement() === inputor) {
54
- normalizedValue = inputor.value.replace(/\r\n/g, "\n");
55
- /* SOMETIME !!!
56
- "/r/n" is counted as two char.
57
- one line is two, two will be four. balalala.
58
- so we have to using the normalized one's length.;
59
- */
60
-
61
- len = normalizedValue.length;
62
- /*
63
- <[ I really HATE IE ]>:
64
- the whole content in the inputor will be the textInputRange.
65
- */
66
-
67
- textInputRange = inputor.createTextRange();
68
- /* _here must be the position of bookmark.
69
- /
70
- <[ I really [HATE] IE ]>
71
- [---------->[ ] : this is what moveToBookmark do.
72
- < I really [[HATE] IE ]> : here is result.
73
- \ two brackets in should be in line.
74
- */
75
-
76
- textInputRange.moveToBookmark(range.getBookmark());
77
- endRange = inputor.createTextRange();
78
- /* [--------------------->[] : if set false all end-point goto end.
79
- < I really [[HATE] IE []]>
80
- */
81
-
82
- endRange.collapse(false);
83
- /*
84
- ___VS____
85
- / \
86
- < I really [[HATE] IE []]>
87
- \_endRange end-point.
88
-
89
- " > -1" mean the start end-point will be the same or right to the end end-point
90
- * simplelly, all in the end.
91
- */
92
-
93
- if (textInputRange.compareEndPoints("StartToEnd", endRange) > -1) {
94
- start = end = len;
95
- } else {
96
- /*
97
- I really |HATE] IE ]>
98
- <-|
99
- I really[ [HATE] IE ]>
100
- <-[
101
- I reall[y [HATE] IE ]>
102
-
103
- will return how many unit have moved.
104
- */
105
-
106
- start = -textInputRange.moveStart("character", -len);
107
- end = -textInputRange.moveEnd("character", -len);
108
- }
44
+ EditableCaret.prototype.getPosition = function() {
45
+ return $.noop();
46
+ };
47
+
48
+ EditableCaret.prototype.getOldIEPos = function() {
49
+ var preCaretTextRange, textRange;
50
+
51
+ textRange = document.selection.createRange();
52
+ preCaretTextRange = document.body.createTextRange();
53
+ preCaretTextRange.moveToElementText(this.domInputor);
54
+ preCaretTextRange.setEndPoint("EndToEnd", textRange);
55
+ return preCaretTextRange.text.length;
56
+ };
57
+
58
+ EditableCaret.prototype.getPos = function() {
59
+ var clonedRange, pos, range;
60
+
61
+ if (range = this.range()) {
62
+ clonedRange = range.cloneRange();
63
+ clonedRange.selectNodeContents(this.domInputor);
64
+ clonedRange.setEnd(range.endContainer, range.endOffset);
65
+ pos = clonedRange.toString().length;
66
+ clonedRange.detach();
67
+ return pos;
68
+ } else if (document.selection) {
69
+ return this.getOldIEPos();
70
+ }
71
+ };
72
+
73
+ EditableCaret.prototype.getOldIEOffset = function() {
74
+ var range, rect;
75
+
76
+ range = document.selection.createRange().duplicate();
77
+ range.moveStart("character", -1);
78
+ rect = range.getBoundingClientRect();
79
+ return {
80
+ height: rect.bottom - rect.top,
81
+ left: rect.left,
82
+ top: rect.top
83
+ };
84
+ };
85
+
86
+ EditableCaret.prototype.getOffset = function(pos) {
87
+ var clonedRange, offset, range, rect;
88
+
89
+ offset = null;
90
+ if (window.getSelection && (range = this.range())) {
91
+ if (range.endOffset - 1 < 0) {
92
+ return null;
93
+ }
94
+ clonedRange = range.cloneRange();
95
+ clonedRange.setStart(range.endContainer, range.endOffset - 1);
96
+ clonedRange.setEnd(range.endContainer, range.endOffset);
97
+ rect = clonedRange.getBoundingClientRect();
98
+ offset = {
99
+ height: rect.height,
100
+ left: rect.left + rect.width,
101
+ top: rect.top
102
+ };
103
+ clonedRange.detach();
104
+ offset;
105
+ } else if (document.selection) {
106
+ this.getOldIEOffset();
107
+ }
108
+ return Utils.adjustOffset(offset, this.$inputor);
109
+ };
110
+
111
+ EditableCaret.prototype.range = function() {
112
+ var sel;
113
+
114
+ if (!window.getSelection) {
115
+ return;
116
+ }
117
+ sel = window.getSelection();
118
+ if (sel.rangeCount > 0) {
119
+ return sel.getRangeAt(0);
120
+ } else {
121
+ return null;
122
+ }
123
+ };
124
+
125
+ return EditableCaret;
126
+
127
+ })();
128
+ InputCaret = (function() {
129
+ function InputCaret($inputor) {
130
+ this.$inputor = $inputor;
131
+ this.domInputor = this.$inputor[0];
132
+ }
133
+
134
+ InputCaret.prototype.getIEPos = function() {
135
+ var endRange, inputor, len, normalizedValue, pos, range, textInputRange;
136
+
137
+ inputor = this.domInputor;
138
+ range = document.selection.createRange();
139
+ pos = 0;
140
+ if (range && range.parentElement() === inputor) {
141
+ normalizedValue = inputor.value.replace(/\r\n/g, "\n");
142
+ len = normalizedValue.length;
143
+ textInputRange = inputor.createTextRange();
144
+ textInputRange.moveToBookmark(range.getBookmark());
145
+ endRange = inputor.createTextRange();
146
+ endRange.collapse(false);
147
+ if (textInputRange.compareEndPoints("StartToEnd", endRange) > -1) {
148
+ pos = len;
149
+ } else {
150
+ pos = -textInputRange.moveStart("character", -len);
109
151
  }
152
+ }
153
+ return pos;
154
+ };
155
+
156
+ InputCaret.prototype.getPos = function() {
157
+ if (document.selection) {
158
+ return this.getIEPos();
110
159
  } else {
111
- start = inputor.selectionStart;
160
+ return this.domInputor.selectionStart;
112
161
  }
113
- return start;
114
162
  };
115
163
 
116
- Caret.prototype.setPos = function(pos) {
164
+ InputCaret.prototype.setPos = function(pos) {
117
165
  var inputor, range;
118
166
 
119
167
  inputor = this.domInputor;
120
168
  if (document.selection) {
121
169
  range = inputor.createTextRange();
122
170
  range.move("character", pos);
123
- return range.select();
171
+ range.select();
172
+ } else if (inputor.setSelectionRange) {
173
+ inputor.setSelectionRange(pos, pos);
174
+ }
175
+ return inputor;
176
+ };
177
+
178
+ InputCaret.prototype.getIEOffset = function(pos) {
179
+ var h, range, textRange, x, y;
180
+
181
+ textRange = this.domInputor.createTextRange();
182
+ if (pos) {
183
+ textRange.move('character', pos);
184
+ } else {
185
+ range = document.selection.createRange();
186
+ textRange.moveToBookmark(range.getBookmark());
187
+ }
188
+ x = textRange.boundingLeft;
189
+ y = textRange.boundingTop;
190
+ h = textRange.boundingHeight;
191
+ return {
192
+ left: x,
193
+ top: y,
194
+ height: h
195
+ };
196
+ };
197
+
198
+ InputCaret.prototype.getOffset = function(pos) {
199
+ var $inputor, offset, position;
200
+
201
+ $inputor = this.$inputor;
202
+ if (document.selection) {
203
+ return Utils.adjustOffset(this.getIEOffset(pos), $inputor);
124
204
  } else {
125
- return inputor.setSelectionRange(pos, pos);
205
+ offset = $inputor.offset();
206
+ position = this.getPosition(pos);
207
+ return offset = {
208
+ left: offset.left + position.left,
209
+ top: offset.top + position.top,
210
+ height: position.height
211
+ };
126
212
  }
127
213
  };
128
214
 
129
- Caret.prototype.getPosition = function(pos) {
130
- var $inputor, at_rect, format, h, html, mirror, start_range, x, y;
215
+ InputCaret.prototype.getPosition = function(pos) {
216
+ var $inputor, at_rect, format, html, mirror, start_range;
131
217
 
132
218
  $inputor = this.$inputor;
133
219
  format = function(value) {
@@ -140,34 +226,10 @@
140
226
  html = "<span>" + format(start_range) + "</span>";
141
227
  html += "<span id='caret'>|</span>";
142
228
  mirror = new Mirror($inputor);
143
- at_rect = mirror.create(html).rect();
144
- x = at_rect.left - $inputor.scrollLeft();
145
- y = at_rect.top - $inputor.scrollTop();
146
- h = at_rect.height;
147
- return {
148
- left: x,
149
- top: y,
150
- height: h
151
- };
152
- };
153
-
154
- Caret.prototype.getOffset = function(pos) {
155
- var $inputor, h, offset, position, x, y;
156
-
157
- $inputor = this.$inputor;
158
- offset = $inputor.offset();
159
- position = this.getPosition(pos);
160
- x = offset.left + position.left;
161
- y = offset.top + position.top;
162
- h = position.height;
163
- return {
164
- left: x,
165
- top: y,
166
- height: h
167
- };
229
+ return at_rect = mirror.create(html).rect();
168
230
  };
169
231
 
170
- Caret.prototype.getIEPosition = function(pos) {
232
+ InputCaret.prototype.getIEPosition = function(pos) {
171
233
  var h, inputorOffset, offset, x, y;
172
234
 
173
235
  offset = this.getIEOffset(pos);
@@ -182,27 +244,7 @@
182
244
  };
183
245
  };
184
246
 
185
- Caret.prototype.getIEOffset = function(pos) {
186
- var h, range, textRange, x, y;
187
-
188
- textRange = this.domInputor.createTextRange();
189
- if (pos) {
190
- textRange.move('character', pos);
191
- } else {
192
- range = document.selection.createRange();
193
- textRange.moveToBookmark(range.getBookmark());
194
- }
195
- x = textRange.boundingLeft + this.$inputor.scrollLeft();
196
- y = textRange.boundingTop + $(window).scrollTop() + this.$inputor.scrollTop();
197
- h = textRange.boundingHeight;
198
- return {
199
- left: x,
200
- top: y,
201
- height: h
202
- };
203
- };
204
-
205
- return Caret;
247
+ return InputCaret;
206
248
 
207
249
  })();
208
250
  Mirror = (function() {
@@ -254,6 +296,19 @@
254
296
  return Mirror;
255
297
 
256
298
  })();
299
+ Utils = {
300
+ adjustOffset: function(offset, $inputor) {
301
+ if (!offset) {
302
+ return;
303
+ }
304
+ offset.top += $(window).scrollTop() + $inputor.scrollTop();
305
+ offset.left += +$(window).scrollLeft() + $inputor.scrollLeft();
306
+ return offset;
307
+ },
308
+ contentEditable: function($inputor) {
309
+ return !!($inputor[0].contentEditable && $inputor[0].contentEditable === 'true');
310
+ }
311
+ };
257
312
  methods = {
258
313
  pos: function(pos) {
259
314
  if (pos) {
@@ -270,23 +325,23 @@
270
325
  }
271
326
  },
272
327
  offset: function(pos) {
273
- if (document.selection) {
274
- return this.getIEOffset(pos);
275
- } else {
276
- return this.getOffset(pos);
277
- }
328
+ return this.getOffset(pos);
278
329
  }
279
330
  };
280
- return $.fn.caret = function(method) {
331
+ $.fn.caret = function(method) {
281
332
  var caret;
282
333
 
283
- caret = new Caret(this);
334
+ caret = Utils.contentEditable(this) ? new EditableCaret(this) : new InputCaret(this);
284
335
  if (methods[method]) {
285
336
  return methods[method].apply(caret, Array.prototype.slice.call(arguments, 1));
286
337
  } else {
287
338
  return $.error("Method " + method + " does not exist on jQuery.caret");
288
339
  }
289
340
  };
341
+ $.fn.caret.EditableCaret = EditableCaret;
342
+ $.fn.caret.InputCaret = InputCaret;
343
+ $.fn.caret.Utils = Utils;
344
+ return $.fn.caret.apis = methods;
290
345
  });
291
346
 
292
347
  }).call(this);
@@ -311,7 +366,7 @@
311
366
  return factory(window.jQuery);
312
367
  }
313
368
  })(function($) {
314
- var $CONTAINER, Api, App, Controller, DEFAULT_CALLBACKS, DEFAULT_TPL, KEY_CODE, Model, View;
369
+ var $CONTAINER, Api, App, Atwho, Controller, DEFAULT_CALLBACKS, KEY_CODE, Model, View;
315
370
  App = (function() {
316
371
 
317
372
  function App(inputor) {
@@ -321,12 +376,12 @@
321
376
  this.listen();
322
377
  }
323
378
 
324
- App.prototype.controller = function(key) {
325
- return this.controllers[key || this.current_flag];
379
+ App.prototype.controller = function(at) {
380
+ return this.controllers[at || this.current_flag];
326
381
  };
327
382
 
328
- App.prototype.set_context_for = function(key) {
329
- this.current_flag = key;
383
+ App.prototype.set_context_for = function(at) {
384
+ this.current_flag = at;
330
385
  return this;
331
386
  };
332
387
 
@@ -361,7 +416,7 @@
361
416
  var _this = this;
362
417
  return $.map(this.controllers, function(c) {
363
418
  if (c.look_up()) {
364
- return _this.set_context_for(c.key);
419
+ return _this.set_context_for(c.at);
365
420
  }
366
421
  });
367
422
  };
@@ -428,14 +483,16 @@
428
483
  return _uuid += 1;
429
484
  };
430
485
 
431
- function Controller(app, key) {
486
+ function Controller(app, at) {
432
487
  this.app = app;
433
- this.key = key;
488
+ this.at = at;
434
489
  this.$inputor = this.app.$inputor;
435
490
  this.id = this.$inputor[0].id || uuid();
436
491
  this.setting = null;
437
492
  this.query = null;
438
493
  this.pos = 0;
494
+ this.cur_rect = null;
495
+ this.range = null;
439
496
  $CONTAINER.append(this.$el = $("<div id='atwho-ground-" + this.id + "'></div>"));
440
497
  this.model = new Model(this);
441
498
  this.view = new View(this);
@@ -443,6 +500,7 @@
443
500
 
444
501
  Controller.prototype.init = function(setting) {
445
502
  this.setting = $.extend({}, this.setting || $.fn.atwho["default"], setting);
503
+ this.view.init();
446
504
  return this.model.reload(this.setting.data);
447
505
  };
448
506
 
@@ -468,20 +526,28 @@
468
526
  return this.get_opt("callbacks")[func_name] || DEFAULT_CALLBACKS[func_name];
469
527
  };
470
528
 
471
- Controller.prototype.get_opt = function(key, default_value) {
529
+ Controller.prototype.get_opt = function(at, default_value) {
472
530
  try {
473
- return this.setting[key];
531
+ return this.setting[at];
474
532
  } catch (e) {
475
533
  return null;
476
534
  }
477
535
  };
478
536
 
537
+ Controller.prototype.content = function() {
538
+ if (this.$inputor.is('textarea, input')) {
539
+ return this.$inputor.val();
540
+ } else {
541
+ return this.$inputor.text();
542
+ }
543
+ };
544
+
479
545
  Controller.prototype.catch_query = function() {
480
546
  var caret_pos, content, end, query, start, subtext;
481
- content = this.$inputor.val();
547
+ content = this.content();
482
548
  caret_pos = this.$inputor.caret('pos');
483
549
  subtext = content.slice(0, caret_pos);
484
- query = this.callbacks("matcher").call(this, this.key, subtext, this.get_opt('start_with_space'));
550
+ query = this.callbacks("matcher").call(this, this.at, subtext, this.get_opt('start_with_space'));
485
551
  if (typeof query === "string" && query.length <= this.get_opt('max_len', 20)) {
486
552
  start = caret_pos - query.length;
487
553
  end = start + query.length;
@@ -491,7 +557,7 @@
491
557
  'head_pos': start,
492
558
  'end_pos': end
493
559
  };
494
- this.trigger("matched", [this.key, query.text]);
560
+ this.trigger("matched", [this.at, query.text]);
495
561
  } else {
496
562
  this.view.hide();
497
563
  }
@@ -500,7 +566,12 @@
500
566
 
501
567
  Controller.prototype.rect = function() {
502
568
  var c, scale_bottom;
503
- c = this.$inputor.caret('offset', this.pos - 1);
569
+ if (!(c = this.$inputor.caret('offset', this.pos - 1))) {
570
+ return;
571
+ }
572
+ if (this.$inputor.attr('contentEditable') === 'true') {
573
+ c = (this.cur_rect || (this.cur_rect = c)) || c;
574
+ }
504
575
  scale_bottom = document.selection ? 0 : 2;
505
576
  return {
506
577
  left: c.left,
@@ -509,15 +580,78 @@
509
580
  };
510
581
  };
511
582
 
512
- Controller.prototype.insert = function(str) {
513
- var $inputor, source, start_str, text;
583
+ Controller.prototype.reset_rect = function() {
584
+ if (this.$inputor.attr('contentEditable') === 'true') {
585
+ return this.cur_rect = null;
586
+ }
587
+ };
588
+
589
+ Controller.prototype.mark_range = function() {
590
+ return this.range = this.get_range() || this.get_ie_range();
591
+ };
592
+
593
+ Controller.prototype.clear_range = function() {
594
+ return this.range = null;
595
+ };
596
+
597
+ Controller.prototype.get_range = function() {
598
+ return this.range || (window.getSelection ? window.getSelection().getRangeAt(0) : void 0);
599
+ };
600
+
601
+ Controller.prototype.get_ie_range = function() {
602
+ return this.range || (document.selection ? document.selection.createRange() : void 0);
603
+ };
604
+
605
+ Controller.prototype.insert_content_for = function($li) {
606
+ var data, data_value, tpl;
607
+ data_value = $li.data('value');
608
+ tpl = this.get_opt('insert_tpl');
609
+ if (this.$inputor.is('textarea, input') || !tpl) {
610
+ return data_value;
611
+ }
612
+ data = $.extend({}, $li.data('item-data'), {
613
+ 'atwho-data-value': data_value,
614
+ 'atwho-at': this.at
615
+ });
616
+ return this.callbacks("tpl_eval").call(this, tpl, data);
617
+ };
618
+
619
+ Controller.prototype.insert = function(content, $li) {
620
+ var $inputor, $insert_node, class_name, content_node, insert_node, pos, range, sel, source, start_str, text;
514
621
  $inputor = this.$inputor;
515
- str = '' + str;
516
- source = $inputor.val();
517
- start_str = source.slice(0, this.query['head_pos'] || 0);
518
- text = "" + start_str + str + " " + (source.slice(this.query['end_pos'] || 0));
519
- $inputor.val(text);
520
- $inputor.caret('pos', start_str.length + str.length + 1);
622
+ if ($inputor.attr('contentEditable') === 'true') {
623
+ class_name = "atwho-view-flag atwho-view-flag-" + (this.get_opt('alias') || this.at);
624
+ content_node = "" + content + "<span contenteditable='false'>&nbsp;<span>";
625
+ insert_node = "<span contenteditable='false' class='" + class_name + "'>" + content_node + "</span>";
626
+ $insert_node = $(insert_node).data('atwho-data-item', $li.data('item-data'));
627
+ if (document.selection) {
628
+ $insert_node = $("<span contenteditable='true'></span>").html($insert_node);
629
+ }
630
+ }
631
+ if ($inputor.is('textarea, input')) {
632
+ content = '' + content;
633
+ source = $inputor.val();
634
+ start_str = source.slice(0, Math.max(this.query.head_pos - this.at.length, 0));
635
+ text = "" + start_str + content + " " + (source.slice(this.query['end_pos'] || 0));
636
+ $inputor.val(text);
637
+ $inputor.caret('pos', start_str.length + content.length + 1);
638
+ } else if (range = this.get_range()) {
639
+ pos = range.startOffset - (this.query.end_pos - this.query.head_pos) - this.at.length;
640
+ range.setStart(range.endContainer, Math.max(pos, 0));
641
+ range.setEnd(range.endContainer, range.endOffset);
642
+ range.deleteContents();
643
+ range.insertNode($insert_node[0]);
644
+ range.collapse(false);
645
+ sel = window.getSelection();
646
+ sel.removeAllRanges();
647
+ sel.addRange(range);
648
+ } else if (range = this.get_ie_range()) {
649
+ range.moveStart('character', this.query.end_pos - this.query.head_pos - this.at.length);
650
+ range.pasteHTML($insert_node[0]);
651
+ range.collapse(false);
652
+ range.select();
653
+ }
654
+ $inputor.focus();
521
655
  return $inputor.change();
522
656
  };
523
657
 
@@ -554,7 +688,7 @@
554
688
 
555
689
  function Model(context) {
556
690
  this.context = context;
557
- this.key = this.context.key;
691
+ this.at = this.context.at;
558
692
  }
559
693
 
560
694
  Model.prototype.saved = function() {
@@ -572,11 +706,11 @@
572
706
  };
573
707
 
574
708
  Model.prototype.fetch = function() {
575
- return _storage[this.key] || [];
709
+ return _storage[this.at] || [];
576
710
  };
577
711
 
578
712
  Model.prototype.save = function(data) {
579
- return _storage[this.key] = this.context.callbacks("before_save").call(this.context, data || []);
713
+ return _storage[this.at] = this.context.callbacks("before_save").call(this.context, data || []);
580
714
  };
581
715
 
582
716
  Model.prototype.load = function(data) {
@@ -609,25 +743,36 @@
609
743
 
610
744
  function View(context) {
611
745
  this.context = context;
612
- this.key = this.context.key;
613
- this.id = this.context.get_opt("alias") || ("at-view-" + (this.key.charCodeAt(0)));
614
- this.$el = $("<div id='" + this.id + "' class='atwho-view'><ul id='" + this.id + "-ul' class='atwho-view-url'></ul></div>");
746
+ this.$el = $("<div class='atwho-view'><ul class='atwho-view-ul'></ul></div>");
615
747
  this.timeout_id = null;
616
748
  this.context.$el.append(this.$el);
617
749
  this.bind_event();
618
750
  }
619
751
 
752
+ View.prototype.init = function() {
753
+ var id;
754
+ id = this.context.get_opt("alias") || this.context.at.charCodeAt(0);
755
+ return this.$el.attr({
756
+ 'id': "at-view-" + id
757
+ });
758
+ };
759
+
620
760
  View.prototype.bind_event = function() {
621
761
  var $menu,
622
762
  _this = this;
623
763
  $menu = this.$el.find('ul');
624
- return $menu.on('mouseenter.view', 'li', function(e) {
764
+ $menu.on('mouseenter.atwho-view', 'li', function(e) {
625
765
  $menu.find('.cur').removeClass('cur');
626
766
  return $(e.currentTarget).addClass('cur');
627
767
  }).on('click', function(e) {
628
768
  _this.choose();
629
769
  return e.preventDefault();
630
770
  });
771
+ return this.$el.on('mouseenter.atwho-view', 'ul', function(e) {
772
+ return _this.context.mark_range();
773
+ }).on('mouseleave.atwho-view', 'ul', function(e) {
774
+ return _this.context.clear_range();
775
+ });
631
776
  };
632
777
 
633
778
  View.prototype.visible = function() {
@@ -635,16 +780,16 @@
635
780
  };
636
781
 
637
782
  View.prototype.choose = function() {
638
- var $li;
783
+ var $li, content;
639
784
  $li = this.$el.find(".cur");
640
- this.context.insert(this.context.callbacks("before_insert").call(this.context, $li.data("value"), $li));
785
+ content = this.context.insert_content_for($li);
786
+ this.context.insert(this.context.callbacks("before_insert").call(this.context, content, $li), $li);
641
787
  this.context.trigger("inserted", [$li]);
642
788
  return this.hide();
643
789
  };
644
790
 
645
- View.prototype.reposition = function() {
646
- var offset, rect;
647
- rect = this.context.rect();
791
+ View.prototype.reposition = function(rect) {
792
+ var offset;
648
793
  if (rect.bottom + this.$el.height() - $(window).scrollTop() > $(window).height()) {
649
794
  rect.bottom = rect.top - this.$el.height();
650
795
  }
@@ -677,16 +822,20 @@
677
822
  };
678
823
 
679
824
  View.prototype.show = function() {
825
+ var rect;
680
826
  if (!this.visible()) {
681
827
  this.$el.show();
682
828
  }
683
- return this.reposition();
829
+ if (rect = this.context.rect()) {
830
+ return this.reposition(rect);
831
+ }
684
832
  };
685
833
 
686
834
  View.prototype.hide = function(time) {
687
835
  var callback,
688
836
  _this = this;
689
837
  if (isNaN(time && this.visible())) {
838
+ this.context.reset_rect();
690
839
  return this.$el.hide();
691
840
  } else {
692
841
  callback = function() {
@@ -705,12 +854,15 @@
705
854
  }
706
855
  this.$el.find('ul').empty();
707
856
  $ul = this.$el.find('ul');
708
- tpl = this.context.get_opt('tpl', DEFAULT_TPL);
857
+ tpl = this.context.get_opt('tpl');
709
858
  for (_i = 0, _len = list.length; _i < _len; _i++) {
710
859
  item = list[_i];
860
+ item = $.extend({}, item, {
861
+ 'atwho-at': this.context.at
862
+ });
711
863
  li = this.context.callbacks("tpl_eval").call(this.context, tpl, item);
712
864
  $li = $(this.context.callbacks("highlighter").call(this.context, li, this.context.query.text));
713
- $li.data("atwho-info", item);
865
+ $li.data("item-data", item);
714
866
  $ul.append($li);
715
867
  }
716
868
  this.show();
@@ -812,54 +964,87 @@
812
964
  return value;
813
965
  }
814
966
  };
815
- DEFAULT_TPL = "<li data-value='${name}'>${name}</li>";
816
967
  Api = {
817
- init: function(options) {
818
- var $this, app;
819
- app = ($this = $(this)).data("atwho");
820
- if (!app) {
821
- $this.data('atwho', (app = new App(this)));
822
- }
823
- return app.reg(options.at, options);
824
- },
825
- load: function(key, data) {
968
+ load: function(at, data) {
826
969
  var c;
827
- if (c = this.controller(key)) {
970
+ if (c = this.controller(at)) {
828
971
  return c.model.load(data);
829
972
  }
830
973
  },
974
+ getInsertedItemsWithIDs: function(at) {
975
+ var c, ids, items;
976
+ if (!(c = this.controller(at))) {
977
+ return [null, null];
978
+ }
979
+ if (at) {
980
+ at = "-" + (c.get_opt('alias') || c.at);
981
+ }
982
+ ids = [];
983
+ items = $.map(this.$inputor.find("span.atwho-view-flag" + (at || "")), function(item) {
984
+ var data;
985
+ data = $(item).data('atwho-data-item');
986
+ if (ids.indexOf(data.id) > -1) {
987
+ return;
988
+ }
989
+ if (data.id) {
990
+ ids.push = data.id;
991
+ }
992
+ return data;
993
+ });
994
+ return [ids, items];
995
+ },
996
+ getInsertedItems: function(at) {
997
+ return Api.getInsertedItemsWithIDs.apply(this, [at])[1];
998
+ },
999
+ getInsertedIDs: function(at) {
1000
+ return Api.getInsertedItemsWithIDs.apply(this, [at])[0];
1001
+ },
831
1002
  run: function() {
832
1003
  return this.dispatch();
833
1004
  }
834
1005
  };
1006
+ Atwho = {
1007
+ init: function(options) {
1008
+ var $this, app;
1009
+ app = ($this = $(this)).data("atwho");
1010
+ if (!app) {
1011
+ $this.data('atwho', (app = new App(this)));
1012
+ }
1013
+ app.reg(options.at, options);
1014
+ return this;
1015
+ }
1016
+ };
835
1017
  $CONTAINER = $("<div id='atwho-container'></div>");
836
1018
  $.fn.atwho = function(method) {
837
- var _args;
1019
+ var result, _args;
838
1020
  _args = arguments;
839
1021
  $('body').append($CONTAINER);
840
- return this.filter('textarea, input').each(function() {
1022
+ result = null;
1023
+ this.filter('textarea, input, [contenteditable=true]').each(function() {
841
1024
  var app;
842
1025
  if (typeof method === 'object' || !method) {
843
- return Api.init.apply(this, _args);
1026
+ return Atwho.init.apply(this, _args);
844
1027
  } else if (Api[method]) {
845
1028
  if (app = $(this).data('atwho')) {
846
- return Api[method].apply(app, Array.prototype.slice.call(_args, 1));
1029
+ return result = Api[method].apply(app, Array.prototype.slice.call(_args, 1));
847
1030
  }
848
1031
  } else {
849
1032
  return $.error("Method " + method + " does not exist on jQuery.caret");
850
1033
  }
851
1034
  });
1035
+ return result || this;
852
1036
  };
853
1037
  return $.fn.atwho["default"] = {
854
1038
  at: void 0,
855
1039
  alias: void 0,
856
1040
  data: null,
857
- tpl: DEFAULT_TPL,
1041
+ tpl: "<li data-value='${atwho-at}${name}'>${name}</li>",
1042
+ insert_tpl: "<span>${atwho-data-value}</span>",
858
1043
  callbacks: DEFAULT_CALLBACKS,
859
1044
  search_key: "name",
1045
+ start_with_space: true,
860
1046
  limit: 5,
861
1047
  max_len: 20,
862
- start_with_space: true,
863
1048
  display_timeout: 300
864
1049
  };
865
1050
  });
@@ -1,7 +1,7 @@
1
1
  module Jquery
2
2
  module Atwho
3
3
  module Rails
4
- VERSION = "0.3.3"
4
+ VERSION = "0.4.1"
5
5
  end
6
6
  end
7
7
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: jquery-atwho-rails
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.3.3
4
+ version: 0.4.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - ichord
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2013-08-24 00:00:00.000000000 Z
11
+ date: 2013-09-28 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: rspec
@@ -87,4 +87,3 @@ summary: 'jquery plugin: @mentions'
87
87
  test_files:
88
88
  - spec/generators/install_generator_spec.rb
89
89
  - spec/spec_helper.rb
90
- has_rdoc: