jquery-atwho-rails 0.1.7 → 0.2.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.
- data/README.md +6 -1
- data/Rakefile +11 -15
- data/changelog.md +1 -0
- data/jquery-atwho-rails.gemspec +2 -2
- data/lib/assets/javascripts/jquery.atwho.js +435 -439
- data/lib/assets/stylesheets/jquery.atwho.css +1 -47
- data/lib/jquery-atwho-rails/version.rb +1 -1
- data/lib/jquery-atwho-rails.rb +1 -0
- metadata +9 -5
data/README.md
CHANGED
@@ -1,3 +1,8 @@
|
|
1
|
+
### Notice
|
2
|
+
updated to `v0.2.0`.
|
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.
|
5
|
+
|
1
6
|
### Usage
|
2
7
|
---
|
3
8
|
bind your textarea
|
@@ -8,7 +13,7 @@ $('textarea').atWho("@",{'data':data});
|
|
8
13
|
```
|
9
14
|
|
10
15
|
that's it, check it out!
|
11
|
-
more details in [At.js](
|
16
|
+
more details in [At.js Home Page](http://ichord.github.com/At.js/)
|
12
17
|
|
13
18
|
### Installtion
|
14
19
|
---
|
data/Rakefile
CHANGED
@@ -1,27 +1,23 @@
|
|
1
1
|
require "bundler/gem_tasks"
|
2
|
-
#require "uglifier"
|
3
2
|
|
4
3
|
desc "sync from At.js"
|
5
4
|
task :sync do
|
5
|
+
puts " * syncing..."
|
6
6
|
at_dir = "tmp/At.js"
|
7
|
-
FileUtils.mkdir_p("tmp")
|
8
|
-
|
7
|
+
FileUtils.mkdir_p("tmp") unless Dir.exist? "tmp"
|
8
|
+
unless Dir.exist? at_dir
|
9
9
|
system "git clone git://github.com/ichord/At.js.git #{at_dir}"
|
10
10
|
else
|
11
|
-
Dir.chdir(at_dir)
|
12
|
-
puts %x{git pull}
|
13
|
-
end
|
11
|
+
Dir.chdir(at_dir) { puts %x{git pull -X theirs} }
|
14
12
|
end
|
15
13
|
end
|
16
14
|
|
17
|
-
desc "
|
15
|
+
desc "copy assets"
|
18
16
|
task :fresh => :sync do
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
#
|
23
|
-
|
24
|
-
#}
|
25
|
-
FileUtils.copy_file "tmp/atwho.js", the_js
|
26
|
-
FileUtils.copy_file "#{at_dir}/css/jquery.atwho.css", "lib/assets/stylesheets/jquery.atwho.css"
|
17
|
+
puts "", " * Copying..."
|
18
|
+
source_dir = "tmp/At.js/dist"
|
19
|
+
dist_dir = "lib/assets"
|
20
|
+
FileUtils.copy "#{source_dir}/js/jquery.atwho.js", "#{dist_dir}/javascripts/"
|
21
|
+
FileUtils.copy "#{source_dir}/css/jquery.atwho.css", "#{dist_dir}/stylesheets/"
|
22
|
+
puts `ls -R #{dist_dir}`
|
27
23
|
end
|
data/changelog.md
CHANGED
data/jquery-atwho-rails.gemspec
CHANGED
@@ -9,8 +9,8 @@ Gem::Specification.new do |s|
|
|
9
9
|
s.email = ["chord.luo@gmail.com"]
|
10
10
|
s.homepage = "http://ichord.github.com/jquery-atwho-rails"
|
11
11
|
s.summary = %q{jquery plugin: @mentions}
|
12
|
-
s.description = %q{This is a jQuery plugin
|
13
|
-
that implement
|
12
|
+
s.description = %q{This is a jQuery plugin
|
13
|
+
that implement Github-like mentions.}
|
14
14
|
|
15
15
|
s.rubyforge_project = "jquery-atwho-rails"
|
16
16
|
|
@@ -1,41 +1,34 @@
|
|
1
|
-
// Generated by CoffeeScript 1.3.3
|
2
1
|
|
3
2
|
/*
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
a copy of this software and associated documentation files (the
|
10
|
-
"Software"), to deal in the Software without restriction, including
|
11
|
-
without limitation the rights to use, copy, modify, merge, publish,
|
12
|
-
distribute, sublicense, and/or sell copies of the Software, and to
|
13
|
-
permit persons to whom the Software is furnished to do so, subject to
|
14
|
-
the following conditions:
|
15
|
-
|
16
|
-
The above copyright notice and this permission notice shall be
|
17
|
-
included in all copies or substantial portions of the Software.
|
18
|
-
|
19
|
-
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
20
|
-
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
21
|
-
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
22
|
-
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
23
|
-
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
24
|
-
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
25
|
-
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
3
|
+
Implement Github like autocomplete mentions
|
4
|
+
http://ichord.github.com/At.js
|
5
|
+
|
6
|
+
Copyright (c) 2013 chord.luo@gmail.com
|
7
|
+
Licensed under the MIT license.
|
26
8
|
*/
|
27
9
|
|
28
10
|
|
29
11
|
(function() {
|
30
12
|
|
31
|
-
(function(
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
13
|
+
(function(factory) {
|
14
|
+
if (typeof define === 'function' && define.amd) {
|
15
|
+
return define(['jquery'], factory);
|
16
|
+
} else {
|
17
|
+
return factory(window.jQuery);
|
18
|
+
}
|
19
|
+
})(function($) {
|
20
|
+
var Controller, DEFAULT_CALLBACKS, DEFAULT_TPL, KEY_CODE, Mirror, View;
|
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'];
|
24
|
+
|
25
|
+
function Mirror($inputor) {
|
26
|
+
this.$inputor = $inputor;
|
27
|
+
}
|
28
|
+
|
29
|
+
Mirror.prototype.copy_inputor_css = function() {
|
30
|
+
var css,
|
31
|
+
_this = this;
|
39
32
|
css = {
|
40
33
|
position: 'absolute',
|
41
34
|
left: -9999,
|
@@ -43,19 +36,21 @@
|
|
43
36
|
zIndex: -20000,
|
44
37
|
'white-space': 'pre-wrap'
|
45
38
|
};
|
46
|
-
$.each(this.
|
47
|
-
return css[p] =
|
39
|
+
$.each(this.css_attr, function(i, p) {
|
40
|
+
return css[p] = _this.$inputor.css(p);
|
48
41
|
});
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
42
|
+
return css;
|
43
|
+
};
|
44
|
+
|
45
|
+
Mirror.prototype.create = function(html) {
|
46
|
+
this.$mirror = $('<div></div>');
|
47
|
+
this.$mirror.css(this.copy_inputor_css());
|
55
48
|
this.$mirror.html(html);
|
49
|
+
this.$inputor.after(this.$mirror);
|
56
50
|
return this;
|
57
|
-
}
|
58
|
-
|
51
|
+
};
|
52
|
+
|
53
|
+
Mirror.prototype.get_flag_rect = function() {
|
59
54
|
var $flag, pos, rect;
|
60
55
|
$flag = this.$mirror.find("span#flag");
|
61
56
|
pos = $flag.position();
|
@@ -66,83 +61,174 @@
|
|
66
61
|
};
|
67
62
|
this.$mirror.remove();
|
68
63
|
return rect;
|
69
|
-
}
|
70
|
-
};
|
71
|
-
At = function(inputor) {
|
72
|
-
var $inputor,
|
73
|
-
_this = this;
|
74
|
-
$inputor = this.$inputor = $(inputor);
|
75
|
-
this.options = {};
|
76
|
-
this.query = {
|
77
|
-
text: "",
|
78
|
-
start: 0,
|
79
|
-
stop: 0
|
80
64
|
};
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
|
88
|
-
|
89
|
-
|
90
|
-
|
91
|
-
lookup = !(stop && _this.view.isShowing());
|
92
|
-
if (lookup) {
|
93
|
-
return _this.lookup();
|
94
|
-
}
|
95
|
-
}).on("mouseup.inputor", function(e) {
|
96
|
-
return _this.lookup();
|
97
|
-
});
|
98
|
-
this.init();
|
99
|
-
log("At.new", $inputor[0]);
|
100
|
-
return this;
|
65
|
+
|
66
|
+
return Mirror;
|
67
|
+
|
68
|
+
})();
|
69
|
+
KEY_CODE = {
|
70
|
+
DOWN: 40,
|
71
|
+
UP: 38,
|
72
|
+
ESC: 27,
|
73
|
+
TAB: 9,
|
74
|
+
ENTER: 13
|
101
75
|
};
|
102
|
-
|
103
|
-
|
104
|
-
|
105
|
-
|
106
|
-
|
107
|
-
|
108
|
-
|
109
|
-
|
110
|
-
|
111
|
-
return _this.view.hide();
|
112
|
-
}).on('blur.inputor', function(e) {
|
113
|
-
return _this.view.hide(1000);
|
76
|
+
DEFAULT_CALLBACKS = {
|
77
|
+
data_refactor: function(data) {
|
78
|
+
return $.map(data, function(item, k) {
|
79
|
+
if (!$.isPlainObject(item)) {
|
80
|
+
item = {
|
81
|
+
name: item
|
82
|
+
};
|
83
|
+
}
|
84
|
+
return item;
|
114
85
|
});
|
115
|
-
return log("At.init", this.$inputor[0]);
|
116
86
|
},
|
117
|
-
|
118
|
-
var
|
119
|
-
|
120
|
-
|
121
|
-
|
122
|
-
|
123
|
-
|
87
|
+
matcher: function(flag, subtext) {
|
88
|
+
var match, matched, regexp;
|
89
|
+
regexp = new RegExp(flag + '([A-Za-z0-9_\+\-]*)$|' + flag + '([^\\x00-\\xff]*)$', 'gi');
|
90
|
+
match = regexp.exec(subtext);
|
91
|
+
matched = null;
|
92
|
+
if (match) {
|
93
|
+
matched = match[2] ? match[2] : match[1];
|
124
94
|
}
|
125
|
-
|
126
|
-
|
127
|
-
|
95
|
+
return matched;
|
96
|
+
},
|
97
|
+
filter: function(query, data, search_key) {
|
98
|
+
var _this = this;
|
99
|
+
return $.map(data, function(item, i) {
|
100
|
+
var name;
|
101
|
+
name = $.isPlainObject(item) ? item[search_key] : item;
|
102
|
+
if (name.toLowerCase().indexOf(query) >= 0) {
|
103
|
+
return item;
|
104
|
+
}
|
105
|
+
});
|
106
|
+
},
|
107
|
+
remote_filter: function(params, url, render_view) {
|
108
|
+
return $.ajax(url, {
|
109
|
+
data: params,
|
110
|
+
success: function(data) {
|
111
|
+
return render_view(data);
|
112
|
+
}
|
113
|
+
});
|
128
114
|
},
|
129
|
-
|
130
|
-
var
|
131
|
-
|
132
|
-
|
133
|
-
|
115
|
+
sorter: function(query, items, search_key) {
|
116
|
+
var item, results, text, _i, _len;
|
117
|
+
if (!query) {
|
118
|
+
items;
|
119
|
+
|
134
120
|
}
|
135
|
-
|
136
|
-
|
121
|
+
results = [];
|
122
|
+
for (_i = 0, _len = items.length; _i < _len; _i++) {
|
123
|
+
item = items[_i];
|
124
|
+
text = item[search_key];
|
125
|
+
item.order = text.toLowerCase().indexOf(query);
|
126
|
+
results.push(item);
|
127
|
+
}
|
128
|
+
return results.sort(function(a, b) {
|
129
|
+
return a.order - b.order;
|
130
|
+
});
|
137
131
|
},
|
138
|
-
|
132
|
+
tpl_eval: function(tpl, map) {
|
133
|
+
var el;
|
139
134
|
try {
|
140
|
-
return
|
135
|
+
return el = tpl.replace(/\$\{([^\}]*)\}/g, function(tag, key, pos) {
|
136
|
+
return map[key];
|
137
|
+
});
|
141
138
|
} catch (error) {
|
142
|
-
return
|
139
|
+
return "";
|
143
140
|
}
|
144
141
|
},
|
145
|
-
|
142
|
+
highlighter: function(li, query) {
|
143
|
+
if (!query) {
|
144
|
+
return li;
|
145
|
+
}
|
146
|
+
return li.replace(new RegExp(">\\s*(\\w*)(" + query.replace("+", "\\+") + ")(\\w*)\\s*<", 'ig'), function(str, $1, $2, $3) {
|
147
|
+
return '> ' + $1 + '<strong>' + $2 + '</strong>' + $3 + ' <';
|
148
|
+
});
|
149
|
+
},
|
150
|
+
selector: function($li) {
|
151
|
+
if ($li.length > 0) {
|
152
|
+
return this.replace_str($li.data("value") || "");
|
153
|
+
}
|
154
|
+
}
|
155
|
+
};
|
156
|
+
Controller = (function() {
|
157
|
+
|
158
|
+
function Controller(inputor) {
|
159
|
+
this.settings = {};
|
160
|
+
this.common_settings = {};
|
161
|
+
this.pos = 0;
|
162
|
+
this.flags = null;
|
163
|
+
this.current_flag = null;
|
164
|
+
this.query = null;
|
165
|
+
this.$inputor = $(inputor);
|
166
|
+
this.mirror = new Mirror(this.$inputor);
|
167
|
+
this.common_settings = $.extend({}, $.fn.atwho["default"]);
|
168
|
+
this.view = new View(this, this.$el);
|
169
|
+
this.listen();
|
170
|
+
}
|
171
|
+
|
172
|
+
Controller.prototype.listen = function() {
|
173
|
+
var _this = this;
|
174
|
+
return this.$inputor.on('keyup.atwho', function(e) {
|
175
|
+
return _this.on_keyup(e);
|
176
|
+
}).on('keydown.atwho', function(e) {
|
177
|
+
return _this.on_keydown(e);
|
178
|
+
}).on('scroll.atwho', function(e) {
|
179
|
+
return _this.view.hide();
|
180
|
+
}).on('blur.atwho', function(e) {
|
181
|
+
return _this.view.hide(_this.get_opt("display_timeout"));
|
182
|
+
});
|
183
|
+
};
|
184
|
+
|
185
|
+
Controller.prototype.reg = function(flag, settings) {
|
186
|
+
var current_settings, data;
|
187
|
+
current_settings = {};
|
188
|
+
current_settings = $.isPlainObject(flag) ? this.common_settings = $.extend({}, this.common_settings, flag) : !this.settings[flag] ? this.settings[flag] = $.extend({}, settings) : this.settings[flag] = $.extend({}, this.settings[flag], settings);
|
189
|
+
data = current_settings["data"];
|
190
|
+
if (typeof data === "string") {
|
191
|
+
current_settings["data"] = data;
|
192
|
+
} else if (data) {
|
193
|
+
current_settings["data"] = this.callbacks("data_refactor").call(this, data);
|
194
|
+
}
|
195
|
+
return this;
|
196
|
+
};
|
197
|
+
|
198
|
+
Controller.prototype.trigger = function(name, data) {
|
199
|
+
data || (data = []);
|
200
|
+
data.push(this);
|
201
|
+
return this.$inputor.trigger("" + name + ".atwho", data);
|
202
|
+
};
|
203
|
+
|
204
|
+
Controller.prototype.data = function() {
|
205
|
+
return this.get_opt("data");
|
206
|
+
};
|
207
|
+
|
208
|
+
Controller.prototype.callbacks = function(func_name) {
|
209
|
+
var func;
|
210
|
+
if (!(func = this.get_opt("callbacks", {})[func_name])) {
|
211
|
+
func = this.common_settings["callbacks"][func_name];
|
212
|
+
}
|
213
|
+
return func;
|
214
|
+
};
|
215
|
+
|
216
|
+
Controller.prototype.get_opt = function(key, default_value) {
|
217
|
+
var value;
|
218
|
+
try {
|
219
|
+
if (this.current_flag) {
|
220
|
+
value = this.settings[this.current_flag][key];
|
221
|
+
}
|
222
|
+
if (value === void 0) {
|
223
|
+
value = this.common_settings[key];
|
224
|
+
}
|
225
|
+
return value = value === void 0 ? default_value : value;
|
226
|
+
} catch (e) {
|
227
|
+
return value = default_value === void 0 ? null : default_value;
|
228
|
+
}
|
229
|
+
};
|
230
|
+
|
231
|
+
Controller.prototype.rect = function() {
|
146
232
|
var $inputor, Sel, at_rect, bottom, format, html, offset, start_range, x, y;
|
147
233
|
$inputor = this.$inputor;
|
148
234
|
if (document.selection) {
|
@@ -165,16 +251,16 @@
|
|
165
251
|
|
166
252
|
start_range = $inputor.val().slice(0, this.pos - 1);
|
167
253
|
html = "<span>" + format(start_range) + "</span>";
|
168
|
-
html += "<span id='flag'
|
254
|
+
html += "<span id='flag'>?</span>";
|
169
255
|
/*
|
170
|
-
|
171
|
-
|
172
|
-
|
173
|
-
|
256
|
+
将inputor的 offset(相对于document)
|
257
|
+
和@在inputor里的position相加
|
258
|
+
就得到了@相对于document的offset.
|
259
|
+
当然,还要加上行高和滚动条的偏移量.
|
174
260
|
*/
|
175
261
|
|
176
262
|
offset = $inputor.offset();
|
177
|
-
at_rect = this.mirror.
|
263
|
+
at_rect = this.mirror.create(html).get_flag_rect();
|
178
264
|
x = offset.left + at_rect.left - $inputor.scrollLeft();
|
179
265
|
y = offset.top - $inputor.scrollTop();
|
180
266
|
bottom = y + at_rect.bottom;
|
@@ -184,263 +270,244 @@
|
|
184
270
|
left: x,
|
185
271
|
bottom: bottom + 2
|
186
272
|
};
|
187
|
-
}
|
188
|
-
|
189
|
-
|
190
|
-
|
191
|
-
if (!this.getOpt("cache") || !key) {
|
192
|
-
return null;
|
193
|
-
}
|
194
|
-
return (_base = this._cache)[key] || (_base[key] = value);
|
195
|
-
},
|
196
|
-
getKeyname: function() {
|
197
|
-
var $inputor, caret_pos, end, key, matched, start, subtext, text,
|
273
|
+
};
|
274
|
+
|
275
|
+
Controller.prototype.catch_query = function() {
|
276
|
+
var caret_pos, content, end, query, start, subtext,
|
198
277
|
_this = this;
|
199
|
-
|
200
|
-
|
201
|
-
caret_pos = $inputor.caretPos();
|
278
|
+
content = this.$inputor.val();
|
279
|
+
caret_pos = this.$inputor.caretPos();
|
202
280
|
/* 向在插入符前的的文本进行正则匹配
|
203
281
|
* 考虑会有多个 @ 的存在, 匹配离插入符最近的一个
|
204
282
|
*/
|
205
283
|
|
206
|
-
subtext =
|
207
|
-
|
208
|
-
$.each(this.
|
209
|
-
|
210
|
-
|
211
|
-
|
212
|
-
if (!_isNil(match)) {
|
213
|
-
matched = match[2] ? match[2] : match[1];
|
214
|
-
_this.theflag = flag;
|
284
|
+
subtext = content.slice(0, caret_pos);
|
285
|
+
query = null;
|
286
|
+
$.each(this.settings, function(flag, settings) {
|
287
|
+
query = _this.callbacks("matcher").call(_this, flag, subtext);
|
288
|
+
if (query != null) {
|
289
|
+
_this.current_flag = flag;
|
215
290
|
return false;
|
216
291
|
}
|
217
292
|
});
|
218
|
-
if (typeof
|
219
|
-
start = caret_pos -
|
220
|
-
end = start +
|
293
|
+
if (typeof query === "string" && query.length <= 20) {
|
294
|
+
start = caret_pos - query.length;
|
295
|
+
end = start + query.length;
|
221
296
|
this.pos = start;
|
222
|
-
|
223
|
-
'text':
|
224
|
-
'
|
225
|
-
'
|
297
|
+
query = {
|
298
|
+
'text': query.toLowerCase(),
|
299
|
+
'head_pos': start,
|
300
|
+
'end_pos': end
|
226
301
|
};
|
302
|
+
this.trigger("matched", [this.current_flag, query.text]);
|
227
303
|
} else {
|
228
304
|
this.view.hide();
|
229
305
|
}
|
230
|
-
|
231
|
-
|
232
|
-
|
233
|
-
|
234
|
-
var $inputor, flag_len,
|
306
|
+
return this.query = query;
|
307
|
+
};
|
308
|
+
|
309
|
+
Controller.prototype.replace_str = function(str) {
|
310
|
+
var $inputor, flag_len, source, start_str, text;
|
235
311
|
$inputor = this.$inputor;
|
236
|
-
key = this.query;
|
237
312
|
source = $inputor.val();
|
238
|
-
flag_len = this.
|
239
|
-
start_str = source.slice(0,
|
240
|
-
text = start_str + str + source.slice(
|
313
|
+
flag_len = this.get_opt("display_flag") ? 0 : this.current_flag.length;
|
314
|
+
start_str = source.slice(0, (this.query['head_pos'] || 0) - flag_len);
|
315
|
+
text = "" + start_str + str + " " + (source.slice(this.query['end_pos'] || 0));
|
241
316
|
$inputor.val(text);
|
242
|
-
$inputor.caretPos(start_str.length + str.length);
|
243
|
-
$inputor.change();
|
244
|
-
|
245
|
-
|
246
|
-
|
247
|
-
var view;
|
248
|
-
view = this.view;
|
249
|
-
if (!view.isShowing()) {
|
250
|
-
return;
|
251
|
-
}
|
317
|
+
$inputor.caretPos(start_str.length + str.length + 1);
|
318
|
+
return $inputor.change();
|
319
|
+
};
|
320
|
+
|
321
|
+
Controller.prototype.on_keyup = function(e) {
|
252
322
|
switch (e.keyCode) {
|
253
|
-
case
|
323
|
+
case KEY_CODE.ESC:
|
254
324
|
e.preventDefault();
|
255
|
-
view.hide();
|
325
|
+
this.view.hide();
|
256
326
|
break;
|
257
|
-
|
327
|
+
case KEY_CODE.DOWN:
|
328
|
+
case KEY_CODE.UP:
|
258
329
|
$.noop();
|
330
|
+
break;
|
331
|
+
default:
|
332
|
+
this.look_up();
|
259
333
|
}
|
260
334
|
return e.stopPropagation();
|
261
|
-
}
|
262
|
-
|
263
|
-
|
264
|
-
|
265
|
-
if (!view.isShowing()) {
|
335
|
+
};
|
336
|
+
|
337
|
+
Controller.prototype.on_keydown = function(e) {
|
338
|
+
if (!this.view.visible()) {
|
266
339
|
return;
|
267
340
|
}
|
268
341
|
switch (e.keyCode) {
|
269
|
-
case
|
342
|
+
case KEY_CODE.ESC:
|
270
343
|
e.preventDefault();
|
271
|
-
view.hide();
|
344
|
+
this.view.hide();
|
272
345
|
break;
|
273
|
-
case
|
346
|
+
case KEY_CODE.UP:
|
274
347
|
e.preventDefault();
|
275
|
-
view.prev();
|
348
|
+
this.view.prev();
|
276
349
|
break;
|
277
|
-
case
|
350
|
+
case KEY_CODE.DOWN:
|
278
351
|
e.preventDefault();
|
279
|
-
view.next();
|
352
|
+
this.view.next();
|
280
353
|
break;
|
281
|
-
case
|
282
|
-
case
|
283
|
-
if (!view.
|
354
|
+
case KEY_CODE.TAB:
|
355
|
+
case KEY_CODE.ENTER:
|
356
|
+
if (!this.view.visible()) {
|
284
357
|
return;
|
285
358
|
}
|
286
359
|
e.preventDefault();
|
287
|
-
view.choose();
|
360
|
+
this.view.choose();
|
288
361
|
break;
|
289
362
|
default:
|
290
363
|
$.noop();
|
291
364
|
}
|
292
365
|
return e.stopPropagation();
|
293
|
-
}
|
294
|
-
|
295
|
-
|
296
|
-
|
297
|
-
|
298
|
-
|
299
|
-
|
300
|
-
return this.view.render(
|
301
|
-
}
|
302
|
-
|
303
|
-
|
304
|
-
|
305
|
-
|
366
|
+
};
|
367
|
+
|
368
|
+
Controller.prototype.render_view = function(data) {
|
369
|
+
var search_key;
|
370
|
+
search_key = this.get_opt("search_key");
|
371
|
+
data = this.callbacks("sorter").call(this, this.query.text, data, search_key);
|
372
|
+
data = data.splice(0, this.get_opt('limit'));
|
373
|
+
return this.view.render(data);
|
374
|
+
};
|
375
|
+
|
376
|
+
Controller.prototype.look_up = function() {
|
377
|
+
var data, origin_data, params, query, search_key;
|
378
|
+
query = this.catch_query();
|
379
|
+
if (!query) {
|
306
380
|
return false;
|
307
381
|
}
|
308
|
-
|
309
|
-
|
310
|
-
|
311
|
-
|
312
|
-
|
313
|
-
|
314
|
-
|
382
|
+
origin_data = this.get_opt("data");
|
383
|
+
search_key = this.get_opt("search_key");
|
384
|
+
if (typeof origin_data === "string") {
|
385
|
+
params = {
|
386
|
+
q: query.text,
|
387
|
+
limit: this.get_opt("limit")
|
388
|
+
};
|
389
|
+
this.callbacks('remote_filter').call(this, params, origin_data, $.proxy(this.render_view, this));
|
390
|
+
} else if ((data = this.callbacks('filter').call(this, query.text, origin_data, search_key))) {
|
391
|
+
this.render_view(data);
|
315
392
|
} else {
|
316
393
|
this.view.hide();
|
317
394
|
}
|
318
395
|
return $.noop();
|
319
|
-
}
|
320
|
-
|
321
|
-
|
322
|
-
|
323
|
-
|
324
|
-
|
325
|
-
|
326
|
-
|
327
|
-
|
328
|
-
|
329
|
-
|
330
|
-
|
331
|
-
|
332
|
-
return null;
|
333
|
-
}
|
334
|
-
if (match) {
|
335
|
-
return item;
|
336
|
-
} else {
|
337
|
-
return null;
|
338
|
-
}
|
339
|
-
});
|
340
|
-
}
|
341
|
-
return items;
|
396
|
+
};
|
397
|
+
|
398
|
+
return Controller;
|
399
|
+
|
400
|
+
})();
|
401
|
+
View = (function() {
|
402
|
+
|
403
|
+
function View(controller) {
|
404
|
+
this.controller = controller;
|
405
|
+
this.id = this.controller.get_opt("view_id", "at-view");
|
406
|
+
this.timeout_id = null;
|
407
|
+
this.$el = $("#" + this.id);
|
408
|
+
this.create_view();
|
342
409
|
}
|
343
|
-
|
344
|
-
|
345
|
-
timeout_id: null,
|
346
|
-
id: '#at-view',
|
347
|
-
holder: null,
|
348
|
-
_jqo: null,
|
349
|
-
jqo: function() {
|
350
|
-
var jqo;
|
351
|
-
jqo = this._jqo;
|
352
|
-
return jqo = _isNil(jqo) ? (this._jqo = $(this.id)) : jqo;
|
353
|
-
},
|
354
|
-
init: function() {
|
410
|
+
|
411
|
+
View.prototype.create_view = function() {
|
355
412
|
var $menu, tpl,
|
356
413
|
_this = this;
|
357
|
-
if (
|
414
|
+
if (this.exist()) {
|
358
415
|
return;
|
359
416
|
}
|
360
|
-
tpl = "<div id='" + this.id
|
417
|
+
tpl = "<div id='" + this.id + "' class='at-view'><ul id='" + this.id + "-ul'></ul></div>";
|
361
418
|
$("body").append(tpl);
|
362
|
-
|
419
|
+
this.$el = $("#" + this.id);
|
420
|
+
$menu = this.$el.find('ul');
|
363
421
|
return $menu.on('mouseenter.view', 'li', function(e) {
|
364
422
|
$menu.find('.cur').removeClass('cur');
|
365
423
|
return $(e.currentTarget).addClass('cur');
|
366
424
|
}).on('click', function(e) {
|
367
425
|
e.stopPropagation();
|
368
426
|
e.preventDefault();
|
369
|
-
return _this.choose();
|
427
|
+
return _this.$el.data("_view").choose();
|
370
428
|
});
|
371
|
-
}
|
372
|
-
|
373
|
-
|
374
|
-
|
375
|
-
|
376
|
-
|
377
|
-
|
378
|
-
|
379
|
-
|
429
|
+
};
|
430
|
+
|
431
|
+
View.prototype.exist = function() {
|
432
|
+
return $("#" + this.id).length > 0;
|
433
|
+
};
|
434
|
+
|
435
|
+
View.prototype.visible = function() {
|
436
|
+
return this.$el.is(":visible");
|
437
|
+
};
|
438
|
+
|
439
|
+
View.prototype.choose = function() {
|
440
|
+
var $li;
|
441
|
+
$li = this.$el.find(".cur");
|
442
|
+
this.controller.callbacks("selector").call(this.controller, $li);
|
443
|
+
this.controller.trigger("choose", [$li]);
|
380
444
|
return this.hide();
|
381
|
-
}
|
382
|
-
|
383
|
-
|
384
|
-
|
385
|
-
|
386
|
-
|
445
|
+
};
|
446
|
+
|
447
|
+
View.prototype.reposition = function() {
|
448
|
+
var offset, rect;
|
449
|
+
rect = this.controller.rect();
|
450
|
+
if (rect.bottom + this.$el.height() - $(window).scrollTop() > $(window).height()) {
|
451
|
+
rect.bottom = rect.top - this.$el.height();
|
387
452
|
}
|
388
|
-
|
389
|
-
left: rect.left,
|
390
|
-
top: rect.bottom
|
391
|
-
});
|
392
|
-
return this.jqo().offset({
|
453
|
+
offset = {
|
393
454
|
left: rect.left,
|
394
455
|
top: rect.bottom
|
395
|
-
}
|
396
|
-
|
397
|
-
|
456
|
+
};
|
457
|
+
this.$el.offset(offset);
|
458
|
+
return this.controller.trigger("reposition", [offset]);
|
459
|
+
};
|
460
|
+
|
461
|
+
View.prototype.next = function() {
|
398
462
|
var cur, next;
|
399
|
-
cur = this.
|
463
|
+
cur = this.$el.find('.cur').removeClass('cur');
|
400
464
|
next = cur.next();
|
401
465
|
if (!next.length) {
|
402
|
-
next = $(this.
|
466
|
+
next = $(this.$el.find('li')[0]);
|
403
467
|
}
|
404
468
|
return next.addClass('cur');
|
405
|
-
}
|
406
|
-
|
469
|
+
};
|
470
|
+
|
471
|
+
View.prototype.prev = function() {
|
407
472
|
var cur, prev;
|
408
|
-
cur = this.
|
473
|
+
cur = this.$el.find('.cur').removeClass('cur');
|
409
474
|
prev = cur.prev();
|
410
475
|
if (!prev.length) {
|
411
|
-
prev = this.
|
476
|
+
prev = this.$el.find('li').last();
|
412
477
|
}
|
413
478
|
return prev.addClass('cur');
|
414
|
-
}
|
415
|
-
|
416
|
-
|
417
|
-
|
479
|
+
};
|
480
|
+
|
481
|
+
View.prototype.show = function() {
|
482
|
+
if (!this.visible()) {
|
483
|
+
this.$el.show();
|
418
484
|
}
|
419
|
-
return this.
|
420
|
-
}
|
421
|
-
|
485
|
+
return this.reposition();
|
486
|
+
};
|
487
|
+
|
488
|
+
View.prototype.hide = function(time) {
|
422
489
|
var callback,
|
423
490
|
_this = this;
|
424
491
|
if (isNaN(time)) {
|
425
|
-
if (this.
|
426
|
-
return this.
|
492
|
+
if (this.visible()) {
|
493
|
+
return this.$el.hide();
|
427
494
|
}
|
428
495
|
} else {
|
429
496
|
callback = function() {
|
430
497
|
return _this.hide();
|
431
498
|
};
|
432
499
|
clearTimeout(this.timeout_id);
|
433
|
-
return this.timeout_id = setTimeout(callback,
|
434
|
-
}
|
435
|
-
},
|
436
|
-
clear: function(clear_all) {
|
437
|
-
if (clear_all === true) {
|
438
|
-
this._cache = {};
|
500
|
+
return this.timeout_id = setTimeout(callback, time);
|
439
501
|
}
|
440
|
-
|
441
|
-
|
442
|
-
|
443
|
-
|
502
|
+
};
|
503
|
+
|
504
|
+
View.prototype.clear = function() {
|
505
|
+
return this.$el.find('ul').empty();
|
506
|
+
};
|
507
|
+
|
508
|
+
View.prototype.render = function(list) {
|
509
|
+
var $ul, tpl,
|
510
|
+
_this = this;
|
444
511
|
if (!$.isArray(list)) {
|
445
512
|
return false;
|
446
513
|
}
|
@@ -448,169 +515,98 @@
|
|
448
515
|
this.hide();
|
449
516
|
return true;
|
450
517
|
}
|
451
|
-
this.holder = holder;
|
452
|
-
holder.cache(list);
|
453
518
|
this.clear();
|
454
|
-
|
455
|
-
|
519
|
+
this.$el.data("_view", this);
|
520
|
+
$ul = this.$el.find('ul');
|
521
|
+
tpl = this.controller.get_opt('tpl', DEFAULT_TPL);
|
456
522
|
$.each(list, function(i, item) {
|
457
|
-
var li;
|
458
|
-
|
459
|
-
li =
|
460
|
-
|
461
|
-
return $ul.append(
|
523
|
+
var $li, li;
|
524
|
+
li = _this.controller.callbacks("tpl_eval").call(_this.controller, tpl, item);
|
525
|
+
$li = $(_this.controller.callbacks("highlighter").call(_this.controller, li, _this.controller.query.text));
|
526
|
+
$li.data("info", item);
|
527
|
+
return $ul.append($li);
|
462
528
|
});
|
463
529
|
this.show();
|
464
530
|
return $ul.find("li:eq(0)").addClass("cur");
|
465
|
-
}
|
466
|
-
|
467
|
-
|
468
|
-
|
469
|
-
|
470
|
-
|
471
|
-
|
472
|
-
name: item
|
473
|
-
};
|
474
|
-
}
|
475
|
-
return item;
|
476
|
-
});
|
477
|
-
};
|
478
|
-
_evalTpl = function(tpl, map) {
|
479
|
-
var el;
|
480
|
-
try {
|
481
|
-
return el = tpl.replace(/\$\{([^\}]*)\}/g, function(tag, key, pos) {
|
482
|
-
return map[key];
|
483
|
-
});
|
484
|
-
} catch (error) {
|
485
|
-
return "";
|
486
|
-
}
|
487
|
-
};
|
488
|
-
_highlighter = function(li, query) {
|
489
|
-
if (_isNil(query)) {
|
490
|
-
return li;
|
491
|
-
}
|
492
|
-
return li.replace(new RegExp(">\\s*(\\w*)(" + query.replace("+", "\\+") + ")(\\w*)\\s*<", 'ig'), function(str, $1, $2, $3) {
|
493
|
-
return '> ' + $1 + '<strong>' + $2 + '</strong>' + $3 + ' <';
|
494
|
-
});
|
495
|
-
};
|
496
|
-
_sorter = function(items) {
|
497
|
-
var data_value, item, query, results, text, _i, _len;
|
498
|
-
data_value = this.dataValue();
|
499
|
-
query = this.query.text;
|
500
|
-
results = [];
|
501
|
-
for (_i = 0, _len = items.length; _i < _len; _i++) {
|
502
|
-
item = items[_i];
|
503
|
-
text = item[data_value];
|
504
|
-
if (text.toLowerCase().indexOf(query) === -1) {
|
505
|
-
continue;
|
506
|
-
}
|
507
|
-
item.order = text.toLowerCase().indexOf(query);
|
508
|
-
results.push(item);
|
509
|
-
}
|
510
|
-
results.sort(function(a, b) {
|
511
|
-
return a.order - b.order;
|
512
|
-
});
|
513
|
-
return results;
|
514
|
-
};
|
515
|
-
/*
|
516
|
-
maybe we can use $._unique.
|
517
|
-
But i don't know it will delete li element frequently or not.
|
518
|
-
I think we should not change DOM element frequently.
|
519
|
-
more, It seems batter not to call evalTpl function too much times.
|
520
|
-
*/
|
521
|
-
|
522
|
-
_unique = function(list, query) {
|
523
|
-
var record;
|
524
|
-
record = [];
|
525
|
-
return $.map(list, function(v, id) {
|
526
|
-
var value;
|
527
|
-
value = $.isPlainObject(v) ? v[query] : v;
|
528
|
-
if ($.inArray(value, record) < 0) {
|
529
|
-
record.push(value);
|
530
|
-
return v;
|
531
|
-
}
|
532
|
-
});
|
533
|
-
};
|
534
|
-
_isNil = function(target) {
|
535
|
-
return !target || ($.isPlainObject(target) && $.isEmptyObject(target)) || ($.isArray(target) && target.length === 0) || (target instanceof $ && target.length === 0) || target === void 0;
|
536
|
-
};
|
537
|
-
_DEFAULT_TPL = "<li id='${id}' data-value='${name}'>${name}</li>";
|
538
|
-
log = function() {};
|
539
|
-
$.fn.atWho = function(flag, options) {
|
540
|
-
AtView.init();
|
531
|
+
};
|
532
|
+
|
533
|
+
return View;
|
534
|
+
|
535
|
+
})();
|
536
|
+
DEFAULT_TPL = "<li data-value='${name}'>${name}</li>";
|
537
|
+
$.fn.atwho = function(flag, options) {
|
541
538
|
return this.filter('textarea, input').each(function() {
|
542
539
|
var $this, data;
|
543
540
|
$this = $(this);
|
544
|
-
data = $this.data("
|
541
|
+
data = $this.data("atwho");
|
545
542
|
if (!data) {
|
546
|
-
$this.data('
|
543
|
+
$this.data('atwho', (data = new Controller(this)));
|
547
544
|
}
|
548
545
|
return data.reg(flag, options);
|
549
546
|
});
|
550
547
|
};
|
551
|
-
|
552
|
-
|
553
|
-
|
554
|
-
|
555
|
-
|
548
|
+
$.fn.atwho.Controller = Controller;
|
549
|
+
$.fn.atwho.View = View;
|
550
|
+
$.fn.atwho.Mirror = Mirror;
|
551
|
+
return $.fn.atwho["default"] = {
|
552
|
+
data: null,
|
553
|
+
search_key: "name",
|
554
|
+
callbacks: DEFAULT_CALLBACKS,
|
556
555
|
limit: 5,
|
557
556
|
display_flag: true,
|
558
|
-
|
557
|
+
display_timeout: 300,
|
558
|
+
tpl: DEFAULT_TPL
|
559
559
|
};
|
560
|
-
})
|
561
|
-
|
562
|
-
|
563
|
-
|
564
|
-
|
565
|
-
|
566
|
-
|
567
|
-
|
568
|
-
|
569
|
-
|
570
|
-
|
571
|
-
|
572
|
-
|
573
|
-
|
574
|
-
|
575
|
-
|
576
|
-
|
577
|
-
|
578
|
-
|
579
|
-
|
580
|
-
|
581
|
-
|
582
|
-
|
583
|
-
|
584
|
-
|
585
|
-
|
586
|
-
|
587
|
-
|
588
|
-
|
589
|
-
|
590
|
-
|
591
|
-
|
592
|
-
*/
|
593
|
-
|
594
|
-
|
595
|
-
(function($) {
|
560
|
+
});
|
561
|
+
|
562
|
+
}).call(this);
|
563
|
+
|
564
|
+
|
565
|
+
/*
|
566
|
+
Implement Github like autocomplete mentions
|
567
|
+
http://ichord.github.com/At.js
|
568
|
+
|
569
|
+
Copyright (c) 2013 chord.luo@gmail.com
|
570
|
+
Licensed under the MIT license.
|
571
|
+
*/
|
572
|
+
|
573
|
+
|
574
|
+
/*
|
575
|
+
本插件操作 textarea 或者 input 内的插入符
|
576
|
+
只实现了获得插入符在文本框中的位置,我设置
|
577
|
+
插入符的位置.
|
578
|
+
*/
|
579
|
+
|
580
|
+
|
581
|
+
(function() {
|
582
|
+
|
583
|
+
(function(factory) {
|
584
|
+
if (typeof exports === 'object') {
|
585
|
+
return factory(require('jquery'));
|
586
|
+
} else if (typeof define === 'function' && define.amd) {
|
587
|
+
return define(['jquery']);
|
588
|
+
} else {
|
589
|
+
return factory(window.jQuery);
|
590
|
+
}
|
591
|
+
})(function($) {
|
596
592
|
var getCaretPos, setCaretPos;
|
597
593
|
getCaretPos = function(inputor) {
|
598
594
|
var end, endRange, len, normalizedValue, pos, range, start, textInputRange;
|
599
595
|
if (document.selection) {
|
600
596
|
/*
|
601
|
-
|
602
|
-
|
603
|
-
|
604
|
-
|
605
|
-
|
606
|
-
|
597
|
+
#assume we select "HATE" in the inputor such as textarea -> { }.
|
598
|
+
* start end-point.
|
599
|
+
* /
|
600
|
+
* < I really [HATE] IE > between the brackets is the selection range.
|
601
|
+
* \
|
602
|
+
* end end-point.
|
607
603
|
*/
|
608
604
|
|
609
605
|
range = document.selection.createRange();
|
610
606
|
pos = 0;
|
611
607
|
if (range && range.parentElement() === inputor) {
|
612
608
|
normalizedValue = inputor.value.replace(/\r\n/g, "\n");
|
613
|
-
/* SOMETIME !!!
|
609
|
+
/* SOMETIME !!!
|
614
610
|
"/r/n" is counted as two char.
|
615
611
|
one line is two, two will be four. balalala.
|
616
612
|
so we have to using the normalized one's length.;
|
@@ -618,8 +614,8 @@
|
|
618
614
|
|
619
615
|
len = normalizedValue.length;
|
620
616
|
/*
|
621
|
-
|
622
|
-
|
617
|
+
<[ I really HATE IE ]>:
|
618
|
+
the whole content in the inputor will be the textInputRange.
|
623
619
|
*/
|
624
620
|
|
625
621
|
textInputRange = inputor.createTextRange();
|
@@ -639,26 +635,26 @@
|
|
639
635
|
|
640
636
|
endRange.collapse(false);
|
641
637
|
/*
|
642
|
-
|
643
|
-
|
644
|
-
|
645
|
-
|
646
|
-
|
647
|
-
|
648
|
-
|
638
|
+
___VS____
|
639
|
+
/ \
|
640
|
+
< I really [[HATE] IE []]>
|
641
|
+
\_endRange end-point.
|
642
|
+
|
643
|
+
" > -1" mean the start end-point will be the same or right to the end end-point
|
644
|
+
* simplelly, all in the end.
|
649
645
|
*/
|
650
646
|
|
651
647
|
if (textInputRange.compareEndPoints("StartToEnd", endRange) > -1) {
|
652
648
|
start = end = len;
|
653
649
|
} else {
|
654
650
|
/*
|
655
|
-
|
656
|
-
|
657
|
-
|
658
|
-
|
659
|
-
|
660
|
-
|
661
|
-
|
651
|
+
I really |HATE] IE ]>
|
652
|
+
<-|
|
653
|
+
I really[ [HATE] IE ]>
|
654
|
+
<-[
|
655
|
+
I reall[y [HATE] IE ]>
|
656
|
+
|
657
|
+
will return how many unit have moved.
|
662
658
|
*/
|
663
659
|
|
664
660
|
start = -textInputRange.moveStart("character", -len);
|
@@ -690,6 +686,6 @@
|
|
690
686
|
return getCaretPos(inputor);
|
691
687
|
}
|
692
688
|
};
|
693
|
-
})
|
689
|
+
});
|
694
690
|
|
695
691
|
}).call(this);
|
@@ -1,47 +1 @@
|
|
1
|
-
#at-view {
|
2
|
-
position:absolute;
|
3
|
-
top: 0;
|
4
|
-
left: 0;
|
5
|
-
display: none;
|
6
|
-
margin-top: 18px;
|
7
|
-
background: white;
|
8
|
-
border: 1px solid #DDD;
|
9
|
-
border-radius: 3px;
|
10
|
-
box-shadow: 0 0 5px rgba(0,0,0,0.1);
|
11
|
-
min-width: 120px;
|
12
|
-
}
|
13
|
-
|
14
|
-
#at-view .cur {
|
15
|
-
background: #3366FF;
|
16
|
-
color: white;
|
17
|
-
}
|
18
|
-
#at-view .cur small {
|
19
|
-
color: white;
|
20
|
-
}
|
21
|
-
#at-view strong {
|
22
|
-
color: #3366FF;
|
23
|
-
}
|
24
|
-
#at-view .cur strong {
|
25
|
-
color: white;
|
26
|
-
font:bold;
|
27
|
-
}
|
28
|
-
#at-view ul {
|
29
|
-
/* width: 100px; */
|
30
|
-
list-style:none;
|
31
|
-
padding:0;
|
32
|
-
margin:auto;
|
33
|
-
}
|
34
|
-
#at-view ul li {
|
35
|
-
display: block;
|
36
|
-
padding: 5px 10px;
|
37
|
-
border-bottom: 1px solid #DDD;
|
38
|
-
cursor: pointer;
|
39
|
-
/* border-top: 1px solid #C8C8C8; */
|
40
|
-
}
|
41
|
-
#at-view small {
|
42
|
-
font-size: smaller;
|
43
|
-
color: #777;
|
44
|
-
font-weight: normal;
|
45
|
-
}
|
46
|
-
|
47
|
-
|
1
|
+
#at-view{position:absolute;top:0;left:0;display:none;margin-top:18px;background:#fff;border:1px solid #DDD;border-radius:3px;box-shadow:0 0 5px rgba(0,0,0,.1);min-width:120px;z-index:10}#at-view .cur{background:#36F;color:#fff}#at-view .cur small{color:#fff}#at-view strong{color:#36F}#at-view .cur strong{color:#fff;font:bold}#at-view ul{list-style:none;padding:0;margin:auto}#at-view ul li{display:block;padding:5px 10px;border-bottom:1px solid #DDD;cursor:pointer}#at-view small{font-size:smaller;color:#777;font-weight:400}
|
data/lib/jquery-atwho-rails.rb
CHANGED
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.1
|
4
|
+
version: 0.2.1
|
5
5
|
prerelease:
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
@@ -9,7 +9,7 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date:
|
12
|
+
date: 2013-01-24 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: rspec
|
@@ -43,8 +43,7 @@ dependencies:
|
|
43
43
|
- - ! '>='
|
44
44
|
- !ruby/object:Gem::Version
|
45
45
|
version: '0'
|
46
|
-
description: ! "This is a jQuery plugin
|
47
|
-
mentions."
|
46
|
+
description: ! "This is a jQuery plugin\n that implement Github-like mentions."
|
48
47
|
email:
|
49
48
|
- chord.luo@gmail.com
|
50
49
|
executables: []
|
@@ -76,12 +75,18 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
76
75
|
- - ! '>='
|
77
76
|
- !ruby/object:Gem::Version
|
78
77
|
version: '0'
|
78
|
+
segments:
|
79
|
+
- 0
|
80
|
+
hash: -3411578706402898122
|
79
81
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
80
82
|
none: false
|
81
83
|
requirements:
|
82
84
|
- - ! '>='
|
83
85
|
- !ruby/object:Gem::Version
|
84
86
|
version: '0'
|
87
|
+
segments:
|
88
|
+
- 0
|
89
|
+
hash: -3411578706402898122
|
85
90
|
requirements: []
|
86
91
|
rubyforge_project: jquery-atwho-rails
|
87
92
|
rubygems_version: 1.8.24
|
@@ -91,4 +96,3 @@ summary: ! 'jquery plugin: @mentions'
|
|
91
96
|
test_files:
|
92
97
|
- spec/generators/install_generator_spec.rb
|
93
98
|
- spec/spec_helper.rb
|
94
|
-
has_rdoc:
|