jquery-atwho-rails 0.2.3 → 0.2.4
Sign up to get free protection for your applications and to get access to all the features.
- data/README.md +2 -2
- data/changelog.md +11 -0
- data/lib/assets/javascripts/jquery.atwho.js +271 -224
- data/lib/jquery-atwho-rails/version.rb +1 -1
- metadata +15 -13
data/README.md
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
### Notice
|
2
2
|
updated to `v0.2.0`.
|
3
3
|
The stable and old one would live in branch `stable-v0.1.x` branch taged `v0.1.7`
|
4
|
-
More details in [At.js](https://github.com/ichord/At.js) project.
|
4
|
+
**More details** in [At.js](https://github.com/ichord/At.js) project.
|
5
5
|
|
6
6
|
### Usage
|
7
7
|
---
|
@@ -9,7 +9,7 @@ bind your textarea
|
|
9
9
|
|
10
10
|
```javascript
|
11
11
|
data = ['tom','john'];
|
12
|
-
$('textarea').
|
12
|
+
$('textarea').atwho("@",{'data':data});
|
13
13
|
```
|
14
14
|
|
15
15
|
that's it, check it out!
|
data/changelog.md
CHANGED
@@ -1,3 +1,14 @@
|
|
1
|
+
|
2
|
+
#### 2013.4.15 - v0.2.4
|
3
|
+
|
4
|
+
* `data` setting will be used to load data either local or remote. If it's String as URL it will preload data from remote by launch a ajax request (every times At.js call `reg` to update settings)
|
5
|
+
|
6
|
+
* remove default `remote_filter` from callbacks list.
|
7
|
+
* add `get_data` and `save_data` function to contoller. They are used to get and save whole data for At.js
|
8
|
+
* `save_data` will invoke `data_refactor` everytime
|
9
|
+
|
10
|
+
* will filter local data which is set in `settings` first and if it get nothing then call `remote_filter` if it's exists in callbacks list that is set by user.
|
11
|
+
|
1
12
|
* 2013.3.12 - v0.2.3 fix some bugs
|
2
13
|
* 2013.3.1 - v0.2.2 fix some bugs.
|
3
14
|
* 2013.1.24 updated to v0.2.0.
|
@@ -17,55 +17,7 @@
|
|
17
17
|
return factory(window.jQuery);
|
18
18
|
}
|
19
19
|
})(function($) {
|
20
|
-
var Controller, DEFAULT_CALLBACKS, DEFAULT_TPL, KEY_CODE,
|
21
|
-
Mirror = (function() {
|
22
|
-
|
23
|
-
Mirror.prototype.css_attr = ["overflowY", "height", "width", "paddingTop", "paddingLeft", "paddingRight", "paddingBottom", "marginTop", "marginLeft", "marginRight", "marginBottom", "fontFamily", "borderStyle", "borderWidth", "wordWrap", "fontSize", "lineHeight", "overflowX", "text-align"];
|
24
|
-
|
25
|
-
function Mirror($inputor) {
|
26
|
-
this.$inputor = $inputor;
|
27
|
-
}
|
28
|
-
|
29
|
-
Mirror.prototype.copy_inputor_css = function() {
|
30
|
-
var css,
|
31
|
-
_this = this;
|
32
|
-
css = {
|
33
|
-
position: 'absolute',
|
34
|
-
left: -9999,
|
35
|
-
top: 0,
|
36
|
-
zIndex: -20000,
|
37
|
-
'white-space': 'pre-wrap'
|
38
|
-
};
|
39
|
-
$.each(this.css_attr, function(i, p) {
|
40
|
-
return css[p] = _this.$inputor.css(p);
|
41
|
-
});
|
42
|
-
return css;
|
43
|
-
};
|
44
|
-
|
45
|
-
Mirror.prototype.create = function(html) {
|
46
|
-
this.$mirror = $('<div></div>');
|
47
|
-
this.$mirror.css(this.copy_inputor_css());
|
48
|
-
this.$mirror.html(html);
|
49
|
-
this.$inputor.after(this.$mirror);
|
50
|
-
return this;
|
51
|
-
};
|
52
|
-
|
53
|
-
Mirror.prototype.get_flag_rect = function() {
|
54
|
-
var $flag, pos, rect;
|
55
|
-
$flag = this.$mirror.find("span#flag");
|
56
|
-
pos = $flag.position();
|
57
|
-
rect = {
|
58
|
-
left: pos.left,
|
59
|
-
top: pos.top,
|
60
|
-
bottom: $flag.height() + pos.top
|
61
|
-
};
|
62
|
-
this.$mirror.remove();
|
63
|
-
return rect;
|
64
|
-
};
|
65
|
-
|
66
|
-
return Mirror;
|
67
|
-
|
68
|
-
})();
|
20
|
+
var Controller, DEFAULT_CALLBACKS, DEFAULT_TPL, KEY_CODE, View;
|
69
21
|
KEY_CODE = {
|
70
22
|
DOWN: 40,
|
71
23
|
UP: 38,
|
@@ -107,14 +59,7 @@
|
|
107
59
|
}
|
108
60
|
});
|
109
61
|
},
|
110
|
-
remote_filter:
|
111
|
-
return $.ajax(url, {
|
112
|
-
data: params,
|
113
|
-
success: function(data) {
|
114
|
-
return render_view(data);
|
115
|
-
}
|
116
|
-
});
|
117
|
-
},
|
62
|
+
remote_filter: null,
|
118
63
|
sorter: function(query, items, search_key) {
|
119
64
|
var item, results, text, _i, _len;
|
120
65
|
if (!query) {
|
@@ -130,12 +75,22 @@
|
|
130
75
|
for (_i = 0, _len = items.length; _i < _len; _i++) {
|
131
76
|
item = items[_i];
|
132
77
|
text = item[search_key];
|
133
|
-
item.
|
78
|
+
item.atwho_order = text.toLowerCase().indexOf(query);
|
134
79
|
results.push(item);
|
135
80
|
}
|
136
|
-
|
137
|
-
return a.
|
81
|
+
results.sort(function(a, b) {
|
82
|
+
return a.atwho_order - b.atwho_order;
|
138
83
|
});
|
84
|
+
return results = (function() {
|
85
|
+
var _j, _len1, _results;
|
86
|
+
_results = [];
|
87
|
+
for (_j = 0, _len1 = results.length; _j < _len1; _j++) {
|
88
|
+
item = results[_j];
|
89
|
+
delete item["atwho_order"];
|
90
|
+
_results.push(item);
|
91
|
+
}
|
92
|
+
return _results;
|
93
|
+
})();
|
139
94
|
},
|
140
95
|
tpl_eval: function(tpl, map) {
|
141
96
|
var el;
|
@@ -165,14 +120,12 @@
|
|
165
120
|
|
166
121
|
function Controller(inputor) {
|
167
122
|
this.settings = {};
|
168
|
-
this.common_settings = {};
|
169
123
|
this.pos = 0;
|
170
124
|
this.flags = null;
|
171
125
|
this.current_flag = null;
|
172
126
|
this.query = null;
|
127
|
+
this._data_sets = {};
|
173
128
|
this.$inputor = $(inputor);
|
174
|
-
this.mirror = new Mirror(this.$inputor);
|
175
|
-
this.common_settings = $.extend({}, $.fn.atwho["default"]);
|
176
129
|
this.view = new View(this, this.$el);
|
177
130
|
this.listen();
|
178
131
|
}
|
@@ -192,10 +145,14 @@
|
|
192
145
|
|
193
146
|
Controller.prototype.reg = function(flag, settings) {
|
194
147
|
var current_settings, data;
|
195
|
-
|
196
|
-
current_settings =
|
197
|
-
data = current_settings
|
198
|
-
|
148
|
+
this.current_flag = flag;
|
149
|
+
current_settings = this.settings[flag] ? this.settings[flag] = $.extend({}, this.settings[flag], settings) : this.settings[flag] = $.extend({}, $.fn.atwho["default"], settings);
|
150
|
+
data = current_settings.data;
|
151
|
+
if (typeof data === "string") {
|
152
|
+
this.load_remote_data(data);
|
153
|
+
} else {
|
154
|
+
this.save_data(data);
|
155
|
+
}
|
199
156
|
return this;
|
200
157
|
};
|
201
158
|
|
@@ -205,78 +162,44 @@
|
|
205
162
|
return this.$inputor.trigger("" + name + ".atwho", data);
|
206
163
|
};
|
207
164
|
|
208
|
-
Controller.prototype.
|
209
|
-
|
210
|
-
|
211
|
-
|
212
|
-
|
213
|
-
|
165
|
+
Controller.prototype.get_data = function(key) {
|
166
|
+
return this._data_sets[key || (key = this.current_flag)];
|
167
|
+
};
|
168
|
+
|
169
|
+
Controller.prototype.save_data = function(data, key) {
|
170
|
+
return this._data_sets[key || (key = this.current_flag)] = this.callbacks("data_refactor").call(this, data);
|
214
171
|
};
|
215
172
|
|
216
173
|
Controller.prototype.callbacks = function(func_name) {
|
217
174
|
var func;
|
218
|
-
|
219
|
-
|
175
|
+
func = this.get_opt("callbacks")[func_name];
|
176
|
+
if (!func) {
|
177
|
+
func = DEFAULT_CALLBACKS[func_name];
|
220
178
|
}
|
221
179
|
return func;
|
222
180
|
};
|
223
181
|
|
224
182
|
Controller.prototype.get_opt = function(key, default_value) {
|
225
|
-
var value;
|
226
183
|
try {
|
227
|
-
|
228
|
-
value = this.settings[this.current_flag][key];
|
229
|
-
}
|
230
|
-
if (value === void 0) {
|
231
|
-
value = this.common_settings[key];
|
232
|
-
}
|
233
|
-
return value = value === void 0 ? default_value : value;
|
184
|
+
return this.settings[this.current_flag][key];
|
234
185
|
} catch (e) {
|
235
|
-
return
|
186
|
+
return null;
|
236
187
|
}
|
237
188
|
};
|
238
189
|
|
239
190
|
Controller.prototype.rect = function() {
|
240
|
-
var
|
241
|
-
|
191
|
+
var c, scale, scale_bottom;
|
192
|
+
c = this.$inputor.caret('offset', this.pos - 1);
|
242
193
|
if (document.selection) {
|
243
|
-
|
244
|
-
|
245
|
-
|
246
|
-
|
247
|
-
return {
|
248
|
-
top: y - 2,
|
249
|
-
left: x - 2,
|
250
|
-
bottom: bottom - 2
|
251
|
-
};
|
194
|
+
scale_bottom = scale = -2;
|
195
|
+
} else {
|
196
|
+
scale = 0;
|
197
|
+
scale_bottom = 2;
|
252
198
|
}
|
253
|
-
format = function(value) {
|
254
|
-
return value.replace(/</g, '<').replace(/>/g, '>').replace(/`/g, '`').replace(/"/g, '"').replace(/\r\n|\r|\n/g, "<br />");
|
255
|
-
};
|
256
|
-
/* 克隆完inputor后将原来的文本内容根据
|
257
|
-
@的位置进行分块,以获取@块在inputor(输入框)里的position
|
258
|
-
*/
|
259
|
-
|
260
|
-
start_range = $inputor.val().slice(0, this.pos - 1);
|
261
|
-
html = "<span>" + format(start_range) + "</span>";
|
262
|
-
html += "<span id='flag'>?</span>";
|
263
|
-
/*
|
264
|
-
将inputor的 offset(相对于document)
|
265
|
-
和@在inputor里的position相加
|
266
|
-
就得到了@相对于document的offset.
|
267
|
-
当然,还要加上行高和滚动条的偏移量.
|
268
|
-
*/
|
269
|
-
|
270
|
-
offset = $inputor.offset();
|
271
|
-
at_rect = this.mirror.create(html).get_flag_rect();
|
272
|
-
x = offset.left + at_rect.left - $inputor.scrollLeft();
|
273
|
-
y = offset.top - $inputor.scrollTop();
|
274
|
-
bottom = y + at_rect.bottom;
|
275
|
-
y += at_rect.top;
|
276
199
|
return {
|
277
|
-
|
278
|
-
|
279
|
-
bottom:
|
200
|
+
left: c.left + scale,
|
201
|
+
top: c.top + scale,
|
202
|
+
bottom: c.top + c.height + scale_bottom
|
280
203
|
};
|
281
204
|
};
|
282
205
|
|
@@ -284,11 +207,7 @@
|
|
284
207
|
var caret_pos, content, end, query, start, subtext,
|
285
208
|
_this = this;
|
286
209
|
content = this.$inputor.val();
|
287
|
-
caret_pos = this.$inputor.
|
288
|
-
/* 向在插入符前的的文本进行正则匹配
|
289
|
-
* 考虑会有多个 @ 的存在, 匹配离插入符最近的一个
|
290
|
-
*/
|
291
|
-
|
210
|
+
caret_pos = this.$inputor.caret('pos');
|
292
211
|
subtext = content.slice(0, caret_pos);
|
293
212
|
query = null;
|
294
213
|
$.each(this.settings, function(flag, settings) {
|
@@ -317,12 +236,13 @@
|
|
317
236
|
Controller.prototype.replace_str = function(str) {
|
318
237
|
var $inputor, flag_len, source, start_str, text;
|
319
238
|
$inputor = this.$inputor;
|
239
|
+
str = '' + str;
|
320
240
|
source = $inputor.val();
|
321
241
|
flag_len = this.get_opt("display_flag") ? 0 : this.current_flag.length;
|
322
242
|
start_str = source.slice(0, (this.query['head_pos'] || 0) - flag_len);
|
323
243
|
text = "" + start_str + str + " " + (source.slice(this.query['end_pos'] || 0));
|
324
244
|
$inputor.val(text);
|
325
|
-
$inputor.
|
245
|
+
$inputor.caret('pos', start_str.length + str.length + 1);
|
326
246
|
return $inputor.change();
|
327
247
|
};
|
328
248
|
|
@@ -377,22 +297,24 @@
|
|
377
297
|
var search_key;
|
378
298
|
search_key = this.get_opt("search_key");
|
379
299
|
data = this.callbacks("sorter").call(this, this.query.text, data, search_key);
|
380
|
-
data = data.
|
381
|
-
this.data(data);
|
300
|
+
data = data.slice(0, this.get_opt('limit'));
|
382
301
|
return this.view.render(data);
|
383
302
|
};
|
384
303
|
|
385
|
-
Controller.prototype.remote_call = function(
|
386
|
-
var
|
387
|
-
params = {
|
388
|
-
q: query.text,
|
389
|
-
limit: this.get_opt("limit")
|
390
|
-
};
|
304
|
+
Controller.prototype.remote_call = function(query) {
|
305
|
+
var _callback;
|
391
306
|
_callback = function(data) {
|
392
307
|
return this.render_view(data);
|
393
308
|
};
|
394
309
|
_callback = $.proxy(_callback, this);
|
395
|
-
return this.callbacks('remote_filter').call(this,
|
310
|
+
return this.callbacks('remote_filter').call(this, query.text, _callback);
|
311
|
+
};
|
312
|
+
|
313
|
+
Controller.prototype.load_remote_data = function(url) {
|
314
|
+
var _this = this;
|
315
|
+
return $.get(url).done(function(data) {
|
316
|
+
return _this.save_data(data);
|
317
|
+
});
|
396
318
|
};
|
397
319
|
|
398
320
|
Controller.prototype.look_up = function() {
|
@@ -401,12 +323,13 @@
|
|
401
323
|
if (!query) {
|
402
324
|
return false;
|
403
325
|
}
|
404
|
-
data = this.
|
326
|
+
data = this.get_data();
|
405
327
|
search_key = this.get_opt("search_key");
|
406
|
-
|
407
|
-
|
408
|
-
} else if ((data = this.callbacks('filter').call(this, query.text, data, search_key))) {
|
328
|
+
data = this.callbacks('filter').call(this, query.text, data || [], search_key);
|
329
|
+
if (data && data.length > 0) {
|
409
330
|
this.render_view(data);
|
331
|
+
} else if (this.callbacks('remote_filter')) {
|
332
|
+
this.remote_call(query);
|
410
333
|
} else {
|
411
334
|
this.view.hide();
|
412
335
|
}
|
@@ -420,7 +343,7 @@
|
|
420
343
|
|
421
344
|
function View(controller) {
|
422
345
|
this.controller = controller;
|
423
|
-
this.id = this.controller.get_opt("view_id"
|
346
|
+
this.id = this.controller.get_opt("view_id") || "at-view";
|
424
347
|
this.timeout_id = null;
|
425
348
|
this.$el = $("#" + this.id);
|
426
349
|
this.create_view();
|
@@ -565,7 +488,6 @@
|
|
565
488
|
};
|
566
489
|
$.fn.atwho.Controller = Controller;
|
567
490
|
$.fn.atwho.View = View;
|
568
|
-
$.fn.atwho.Mirror = Mirror;
|
569
491
|
return $.fn.atwho["default"] = {
|
570
492
|
data: null,
|
571
493
|
search_key: "name",
|
@@ -599,109 +521,234 @@
|
|
599
521
|
(function() {
|
600
522
|
|
601
523
|
(function(factory) {
|
602
|
-
if (typeof
|
603
|
-
return
|
604
|
-
} else if (typeof define === 'function' && define.amd) {
|
605
|
-
return define(['jquery']);
|
524
|
+
if (typeof define === 'function' && define.amd) {
|
525
|
+
return define(['jquery'], factory);
|
606
526
|
} else {
|
607
527
|
return factory(window.jQuery);
|
608
528
|
}
|
609
529
|
})(function($) {
|
610
|
-
|
611
|
-
|
612
|
-
|
613
|
-
|
614
|
-
|
615
|
-
#assume we select "HATE" in the inputor such as textarea -> { }.
|
616
|
-
* start end-point.
|
617
|
-
* /
|
618
|
-
* < I really [HATE] IE > between the brackets is the selection range.
|
619
|
-
* \
|
620
|
-
* end end-point.
|
621
|
-
*/
|
622
|
-
|
623
|
-
range = document.selection.createRange();
|
624
|
-
pos = 0;
|
625
|
-
if (range && range.parentElement() === inputor) {
|
626
|
-
normalizedValue = inputor.value.replace(/\r\n/g, "\n");
|
627
|
-
/* SOMETIME !!!
|
628
|
-
"/r/n" is counted as two char.
|
629
|
-
one line is two, two will be four. balalala.
|
630
|
-
so we have to using the normalized one's length.;
|
631
|
-
*/
|
530
|
+
"use strict";
|
531
|
+
|
532
|
+
var Caret, Mirror, methods, pluginName;
|
533
|
+
pluginName = 'caret';
|
534
|
+
Caret = (function() {
|
632
535
|
|
633
|
-
|
536
|
+
function Caret($inputor) {
|
537
|
+
this.$inputor = $inputor;
|
538
|
+
this.domInputor = this.$inputor[0];
|
539
|
+
}
|
540
|
+
|
541
|
+
Caret.prototype.getPos = function() {
|
542
|
+
var end, endRange, inputor, len, normalizedValue, pos, range, start, textInputRange;
|
543
|
+
inputor = this.domInputor;
|
544
|
+
inputor.focus();
|
545
|
+
if (document.selection) {
|
634
546
|
/*
|
635
|
-
|
636
|
-
|
547
|
+
#assume we select "HATE" in the inputor such as textarea -> { }.
|
548
|
+
* start end-point.
|
549
|
+
* /
|
550
|
+
* < I really [HATE] IE > between the brackets is the selection range.
|
551
|
+
* \
|
552
|
+
* end end-point.
|
637
553
|
*/
|
638
554
|
|
639
|
-
|
640
|
-
|
641
|
-
|
642
|
-
|
643
|
-
|
644
|
-
|
645
|
-
|
646
|
-
|
555
|
+
range = document.selection.createRange();
|
556
|
+
pos = 0;
|
557
|
+
if (range && range.parentElement() === inputor) {
|
558
|
+
normalizedValue = inputor.value.replace(/\r\n/g, "\n");
|
559
|
+
/* SOMETIME !!!
|
560
|
+
"/r/n" is counted as two char.
|
561
|
+
one line is two, two will be four. balalala.
|
562
|
+
so we have to using the normalized one's length.;
|
563
|
+
*/
|
647
564
|
|
648
|
-
|
649
|
-
|
650
|
-
|
651
|
-
|
652
|
-
|
565
|
+
len = normalizedValue.length;
|
566
|
+
/*
|
567
|
+
<[ I really HATE IE ]>:
|
568
|
+
the whole content in the inputor will be the textInputRange.
|
569
|
+
*/
|
653
570
|
|
654
|
-
|
655
|
-
|
656
|
-
|
657
|
-
|
658
|
-
|
659
|
-
|
660
|
-
|
661
|
-
|
662
|
-
|
663
|
-
|
571
|
+
textInputRange = inputor.createTextRange();
|
572
|
+
/* _here must be the position of bookmark.
|
573
|
+
/
|
574
|
+
<[ I really [HATE] IE ]>
|
575
|
+
[---------->[ ] : this is what moveToBookmark do.
|
576
|
+
< I really [[HATE] IE ]> : here is result.
|
577
|
+
\ two brackets in should be in line.
|
578
|
+
*/
|
579
|
+
|
580
|
+
textInputRange.moveToBookmark(range.getBookmark());
|
581
|
+
endRange = inputor.createTextRange();
|
582
|
+
/* [--------------------->[] : if set false all end-point goto end.
|
583
|
+
< I really [[HATE] IE []]>
|
584
|
+
*/
|
664
585
|
|
665
|
-
|
666
|
-
start = end = len;
|
667
|
-
} else {
|
586
|
+
endRange.collapse(false);
|
668
587
|
/*
|
669
|
-
|
670
|
-
|
671
|
-
|
672
|
-
|
673
|
-
I reall[y [HATE] IE ]>
|
588
|
+
___VS____
|
589
|
+
/ \
|
590
|
+
< I really [[HATE] IE []]>
|
591
|
+
\_endRange end-point.
|
674
592
|
|
675
|
-
|
593
|
+
" > -1" mean the start end-point will be the same or right to the end end-point
|
594
|
+
* simplelly, all in the end.
|
676
595
|
*/
|
677
596
|
|
678
|
-
|
679
|
-
|
597
|
+
if (textInputRange.compareEndPoints("StartToEnd", endRange) > -1) {
|
598
|
+
start = end = len;
|
599
|
+
} else {
|
600
|
+
/*
|
601
|
+
I really |HATE] IE ]>
|
602
|
+
<-|
|
603
|
+
I really[ [HATE] IE ]>
|
604
|
+
<-[
|
605
|
+
I reall[y [HATE] IE ]>
|
606
|
+
|
607
|
+
will return how many unit have moved.
|
608
|
+
*/
|
609
|
+
|
610
|
+
start = -textInputRange.moveStart("character", -len);
|
611
|
+
end = -textInputRange.moveEnd("character", -len);
|
612
|
+
}
|
680
613
|
}
|
614
|
+
} else {
|
615
|
+
start = inputor.selectionStart;
|
681
616
|
}
|
682
|
-
|
683
|
-
|
617
|
+
return start;
|
618
|
+
};
|
619
|
+
|
620
|
+
Caret.prototype.setPos = function(pos) {
|
621
|
+
var inputor, range;
|
622
|
+
inputor = this.domInputor;
|
623
|
+
if (document.selection) {
|
624
|
+
range = inputor.createTextRange();
|
625
|
+
range.move("character", pos);
|
626
|
+
return range.select();
|
627
|
+
} else {
|
628
|
+
return inputor.setSelectionRange(pos, pos);
|
629
|
+
}
|
630
|
+
};
|
631
|
+
|
632
|
+
Caret.prototype.getPosition = function(pos) {
|
633
|
+
var $inputor, at_rect, format, h, html, mirror, start_range, x, y;
|
634
|
+
$inputor = this.$inputor;
|
635
|
+
format = function(value) {
|
636
|
+
return value.replace(/</g, '<').replace(/>/g, '>').replace(/`/g, '`').replace(/"/g, '"').replace(/\r\n|\r|\n/g, "<br />");
|
637
|
+
};
|
638
|
+
pos = pos || this.getPos();
|
639
|
+
start_range = $inputor.val().slice(0, pos);
|
640
|
+
html = "<span>" + format(start_range) + "</span>";
|
641
|
+
html += "<span id='caret'>|</span>";
|
642
|
+
mirror = new Mirror($inputor);
|
643
|
+
at_rect = mirror.create(html).rect();
|
644
|
+
x = at_rect.left - $inputor.scrollLeft();
|
645
|
+
y = at_rect.top - $inputor.scrollTop();
|
646
|
+
h = at_rect.height;
|
647
|
+
return {
|
648
|
+
left: x,
|
649
|
+
top: y,
|
650
|
+
height: h
|
651
|
+
};
|
652
|
+
};
|
653
|
+
|
654
|
+
Caret.prototype.getOffset = function(pos) {
|
655
|
+
var $inputor, h, offset, position, range, x, y;
|
656
|
+
$inputor = this.$inputor;
|
657
|
+
if (document.selection) {
|
658
|
+
range = this.domInputor.createRange();
|
659
|
+
if (pos) {
|
660
|
+
range.move('character', pos);
|
661
|
+
}
|
662
|
+
x = range.boundingLeft + $inputor.scrollLeft();
|
663
|
+
y = range.boundingTop + $(window).scrollTop() + $inputor.scrollTop();
|
664
|
+
h = range.boundingHeight;
|
665
|
+
} else {
|
666
|
+
offset = $inputor.offset();
|
667
|
+
position = this.getPosition(pos);
|
668
|
+
x = offset.left + position.left;
|
669
|
+
y = offset.top + position.top;
|
670
|
+
h = position.height;
|
671
|
+
}
|
672
|
+
return {
|
673
|
+
left: x,
|
674
|
+
top: y,
|
675
|
+
height: h
|
676
|
+
};
|
677
|
+
};
|
678
|
+
|
679
|
+
return Caret;
|
680
|
+
|
681
|
+
})();
|
682
|
+
Mirror = (function() {
|
683
|
+
|
684
|
+
Mirror.prototype.css_attr = ["overflowY", "height", "width", "paddingTop", "paddingLeft", "paddingRight", "paddingBottom", "marginTop", "marginLeft", "marginRight", "marginBottom", "fontFamily", "borderStyle", "borderWidth", "wordWrap", "fontSize", "lineHeight", "overflowX", "text-align"];
|
685
|
+
|
686
|
+
function Mirror($inputor) {
|
687
|
+
this.$inputor = $inputor;
|
684
688
|
}
|
685
|
-
|
686
|
-
|
687
|
-
|
688
|
-
|
689
|
-
|
690
|
-
|
691
|
-
|
692
|
-
|
693
|
-
|
694
|
-
|
689
|
+
|
690
|
+
Mirror.prototype.mirrorCss = function() {
|
691
|
+
var css,
|
692
|
+
_this = this;
|
693
|
+
css = {
|
694
|
+
position: 'absolute',
|
695
|
+
left: -9999,
|
696
|
+
top: 0,
|
697
|
+
zIndex: -20000,
|
698
|
+
'white-space': 'pre-wrap'
|
699
|
+
};
|
700
|
+
$.each(this.css_attr, function(i, p) {
|
701
|
+
return css[p] = _this.$inputor.css(p);
|
702
|
+
});
|
703
|
+
return css;
|
704
|
+
};
|
705
|
+
|
706
|
+
Mirror.prototype.create = function(html) {
|
707
|
+
this.$mirror = $('<div></div>');
|
708
|
+
this.$mirror.css(this.mirrorCss());
|
709
|
+
this.$mirror.html(html);
|
710
|
+
this.$inputor.after(this.$mirror);
|
711
|
+
return this;
|
712
|
+
};
|
713
|
+
|
714
|
+
Mirror.prototype.rect = function() {
|
715
|
+
var $flag, pos, rect;
|
716
|
+
$flag = this.$mirror.find("#caret");
|
717
|
+
pos = $flag.position();
|
718
|
+
rect = {
|
719
|
+
left: pos.left,
|
720
|
+
top: pos.top,
|
721
|
+
height: $flag.height()
|
722
|
+
};
|
723
|
+
this.$mirror.remove();
|
724
|
+
return rect;
|
725
|
+
};
|
726
|
+
|
727
|
+
return Mirror;
|
728
|
+
|
729
|
+
})();
|
730
|
+
methods = {
|
731
|
+
pos: function(pos) {
|
732
|
+
if (pos) {
|
733
|
+
return this.setPos(pos);
|
734
|
+
} else {
|
735
|
+
return this.getPos();
|
736
|
+
}
|
737
|
+
},
|
738
|
+
position: function(pos) {
|
739
|
+
return this.getPosition(pos);
|
740
|
+
},
|
741
|
+
offset: function(pos) {
|
742
|
+
return this.getOffset(pos);
|
695
743
|
}
|
696
744
|
};
|
697
|
-
return $.fn.
|
698
|
-
var
|
699
|
-
|
700
|
-
|
701
|
-
|
702
|
-
return setCaretPos(inputor, pos);
|
745
|
+
return $.fn.caret = function(method) {
|
746
|
+
var caret;
|
747
|
+
caret = new Caret(this);
|
748
|
+
if (methods[method]) {
|
749
|
+
return methods[method].apply(caret, Array.prototype.slice.call(arguments, 1));
|
703
750
|
} else {
|
704
|
-
return
|
751
|
+
return $.error("Method " + method + " does not exist on jQuery.caret");
|
705
752
|
}
|
706
753
|
};
|
707
754
|
});
|
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.2.
|
4
|
+
version: 0.2.4
|
5
5
|
prerelease:
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
@@ -9,14 +9,14 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date: 2013-
|
12
|
+
date: 2013-04-15 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: rspec
|
16
16
|
requirement: !ruby/object:Gem::Requirement
|
17
17
|
none: false
|
18
18
|
requirements:
|
19
|
-
- -
|
19
|
+
- - '>='
|
20
20
|
- !ruby/object:Gem::Version
|
21
21
|
version: '0'
|
22
22
|
type: :development
|
@@ -24,7 +24,7 @@ dependencies:
|
|
24
24
|
version_requirements: !ruby/object:Gem::Requirement
|
25
25
|
none: false
|
26
26
|
requirements:
|
27
|
-
- -
|
27
|
+
- - '>='
|
28
28
|
- !ruby/object:Gem::Version
|
29
29
|
version: '0'
|
30
30
|
- !ruby/object:Gem::Dependency
|
@@ -32,7 +32,7 @@ dependencies:
|
|
32
32
|
requirement: !ruby/object:Gem::Requirement
|
33
33
|
none: false
|
34
34
|
requirements:
|
35
|
-
- -
|
35
|
+
- - '>='
|
36
36
|
- !ruby/object:Gem::Version
|
37
37
|
version: '0'
|
38
38
|
type: :development
|
@@ -40,10 +40,12 @@ dependencies:
|
|
40
40
|
version_requirements: !ruby/object:Gem::Requirement
|
41
41
|
none: false
|
42
42
|
requirements:
|
43
|
-
- -
|
43
|
+
- - '>='
|
44
44
|
- !ruby/object:Gem::Version
|
45
45
|
version: '0'
|
46
|
-
description:
|
46
|
+
description: |-
|
47
|
+
This is a jQuery plugin
|
48
|
+
that implement Github-like mentions.
|
47
49
|
email:
|
48
50
|
- chord.luo@gmail.com
|
49
51
|
executables: []
|
@@ -72,27 +74,27 @@ require_paths:
|
|
72
74
|
required_ruby_version: !ruby/object:Gem::Requirement
|
73
75
|
none: false
|
74
76
|
requirements:
|
75
|
-
- -
|
77
|
+
- - '>='
|
76
78
|
- !ruby/object:Gem::Version
|
77
79
|
version: '0'
|
78
80
|
segments:
|
79
81
|
- 0
|
80
|
-
hash:
|
82
|
+
hash: -3109051973216094172
|
81
83
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
82
84
|
none: false
|
83
85
|
requirements:
|
84
|
-
- -
|
86
|
+
- - '>='
|
85
87
|
- !ruby/object:Gem::Version
|
86
88
|
version: '0'
|
87
89
|
segments:
|
88
90
|
- 0
|
89
|
-
hash:
|
91
|
+
hash: -3109051973216094172
|
90
92
|
requirements: []
|
91
93
|
rubyforge_project: jquery-atwho-rails
|
92
|
-
rubygems_version: 1.8.
|
94
|
+
rubygems_version: 1.8.25
|
93
95
|
signing_key:
|
94
96
|
specification_version: 3
|
95
|
-
summary:
|
97
|
+
summary: 'jquery plugin: @mentions'
|
96
98
|
test_files:
|
97
99
|
- spec/generators/install_generator_spec.rb
|
98
100
|
- spec/spec_helper.rb
|