autocomplete 1.0.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.
@@ -0,0 +1,20 @@
1
+ Copyright (c) 2010 [name of plugin creator]
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining
4
+ a copy of this software and associated documentation files (the
5
+ "Software"), to deal in the Software without restriction, including
6
+ without limitation the rights to use, copy, modify, merge, publish,
7
+ distribute, sublicense, and/or sell copies of the Software, and to
8
+ permit persons to whom the Software is furnished to do so, subject to
9
+ the following conditions:
10
+
11
+ The above copyright notice and this permission notice shall be
12
+ included in all copies or substantial portions of the Software.
13
+
14
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
15
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
17
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
18
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
19
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
20
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
@@ -0,0 +1,16 @@
1
+ MIT-LICENSE
2
+ README.rdoc
3
+ Rakefile
4
+ assets/autocomplete-loading.gif
5
+ assets/autocomplete.css
6
+ assets/autocomplete.js
7
+ autocomplete.gemspec
8
+ id_rsa.pub
9
+ init.rb
10
+ install.rb
11
+ lib/autocomplete.rb
12
+ lib/autocomplete_controller.rb
13
+ lib/autocomplete_helper.rb
14
+ tasks/autocomplete_tasks.rake
15
+ test/autocomplete_test.rb
16
+ Manifest
@@ -0,0 +1,10 @@
1
+ Autocomplete
2
+ ============
3
+ Introduction goes here.
4
+
5
+ Example
6
+ =======
7
+ Example goes here.
8
+
9
+
10
+ Copyright (c) 2010 [name of plugin creator], released under the MIT license
@@ -0,0 +1,14 @@
1
+ require 'rubygems'
2
+ require 'rake'
3
+ require "echoe"
4
+
5
+ Echoe.new('autocomplete', '1.0.1') do |p|
6
+ p.description = "Insert an autocomplete-search-box inside your view"
7
+ p.url = "http://www.voja-jovanovic.info"
8
+ p.author = "Voislav Jovanovic"
9
+ p.email = "voislavj@gmail.com"
10
+ p.ignore_pattern = ["tmp/*", "script/*"]
11
+ p.development_dependencies = []
12
+ end
13
+
14
+ Dir["#{File.dirname(__FILE__)}/tasks/*.rake"].sort.each {|ext| load ext}
@@ -0,0 +1,74 @@
1
+ .autocomplete-loading {
2
+ background-image:url(/images/autocomplete-loading.gif);
3
+ background-repeat: no-repeat;
4
+ background-position: 98% center;
5
+ }
6
+ .autocomplete-multi-controls .autocomplete-remove {
7
+ float:right;
8
+ margin-bottom:5px;
9
+ }
10
+ .autocomplete-multi-controls a {
11
+ outline:none;
12
+ }
13
+ .autocomplete-multi-container {
14
+ width:200px;
15
+ clear:both;
16
+ border:1px solid #ccc;
17
+ overflow:auto;
18
+ }
19
+ .autocomplete-multi-rowset {
20
+ padding:2px 4px;
21
+ border-bottom:1px dotted #ddd;
22
+ cursor:default;
23
+ }
24
+ .autocomplete-multi-rowset:hover {
25
+ background-color:#E8730C;
26
+ color:#fff;
27
+ }
28
+ .autocomplete-multi-rowset.selected,
29
+ .autocomplete-multi-rowset.selected:hover {
30
+ background:#eee;color:#000
31
+ }
32
+ .autocomplete-multi-rowset label{margin-left:5px;}
33
+ .autocomplete-multi-rowset:hover label{color:#fff}
34
+ .autocomplete-multi-rowset.selected:hover label{color:#000}
35
+
36
+ .autocomplete-list {
37
+ list-style-type:none;
38
+ position:absolute;
39
+ background:#fff;
40
+ border:1px solid #ccc;
41
+ width:300px;
42
+ max-height:200px;
43
+ overflow:auto;
44
+ }
45
+ .autocomplete-list li{
46
+ margin:0;
47
+ padding:0;
48
+ }
49
+ .autocomplete-list li.empty{
50
+ padding:2px 4px;
51
+ color:#777;
52
+ }
53
+ .autocomplete-list li.odd {
54
+ background:#eee;
55
+ }
56
+ .autocomplete-list a {
57
+ display:block;
58
+ text-decoration:none;
59
+ padding:2px 4px;
60
+ outline:none;
61
+ }
62
+ .autocomplete-list a:focus,
63
+ .autocomplete-list a:hover {
64
+ background:Highlight;
65
+ color:HighlightText;
66
+ }
67
+ .autocomplete-multi-status {
68
+ width:192px;
69
+ background:#ccc;
70
+ font-size:10px;
71
+ color:#555;
72
+ padding:2px 5px;
73
+ text-align:right;
74
+ }
@@ -0,0 +1,320 @@
1
+ /**
2
+ * @author Voislav Voja Jovanovic
3
+ * @version 1.0.0
4
+ */
5
+
6
+
7
+ function Autocomplete(element, options) {
8
+
9
+ // if autocomplete is already initialized, just return
10
+ if(element.hasAttribute("ready")) {
11
+ return;
12
+ }
13
+ element.writeAttribute("ready", "ready");
14
+
15
+ // patch element's name if `multi` is on
16
+ if(options["multi"] && !options["name"].match(/\[\]$/)) {
17
+ options["name"] += "[]";
18
+ }
19
+
20
+ // Attach Events
21
+ document.body.observe("click", function(){
22
+ Autocomplete_RemoveList(element);
23
+ });
24
+
25
+ element.adjacent(".autocomplete-multi-controls").each(function(ctrl){
26
+ ctrl.select(".autocomplete-select-all")[0].observe("click", function(){
27
+ Autocomplete_getCheckboxes(element).each(function(cb){
28
+ cb.checked = true;
29
+ cb.parentNode.addClassName("selected");
30
+ });
31
+ });
32
+ ctrl.select(".autocomplete-select-none")[0].observe("click", function(){
33
+ Autocomplete_getCheckboxes(element).each(function(cb){
34
+ cb.checked = false;
35
+ cb.parentNode.removeClassName("selected");
36
+ });
37
+ });
38
+ ctrl.select(".autocomplete-remove")[0].observe("click",function(){
39
+ var rows = Autocomplete_getCheckedRows(element);
40
+ if(rows.length>0) {
41
+ if(confirm("You are about to remove " + rows.length + " item(s).\nDo you want to proceed?")) {
42
+ rows.each(function(r){r.remove();})
43
+ Autocomplete_UpdateStatus(element);
44
+ }
45
+ }
46
+ });
47
+ });
48
+
49
+ element.observe("keyup", function(e){
50
+ var el = e.target;
51
+
52
+ // special keys
53
+ switch(e.keyCode) {
54
+
55
+ case 27: // Esc
56
+ Autocomplete_RemoveList(el);
57
+
58
+ case 40: // Arrow Down
59
+ // focus into list
60
+ el.adjacent("ul.autocomplete-list li:first-child a").each(function(a){
61
+ a.focus();
62
+ a.select();
63
+ });
64
+
65
+ case 9: // Tab
66
+ case 13: // Enter
67
+ case 17: // Ctrl
68
+ case 18: // Alt
69
+ case 19: // Pause/Break
70
+ case 20: // Caps Lock
71
+ case 33: // PageUp
72
+ case 34: // PageDown
73
+ case 35: // End
74
+ case 36: // Home
75
+ case 37: // Arrow Left
76
+ case 38: // Arrow Up
77
+ case 39: // Arrow Right
78
+ case 44: // PrintScreen
79
+ case 45: // Insert
80
+ case 92: // Win
81
+ case 93: // Context
82
+ // do nothing
83
+ return;
84
+ break;
85
+ }
86
+
87
+ Autocomplete_Stop(el);
88
+
89
+ el.timeout = setTimeout(function(){
90
+ // check keyword length
91
+ el.value = el.value.replace(/^[\s\r\n\t]+|[\s\r\n\t]+$/g, "")
92
+ if(el.value.length<3) return;
93
+
94
+ // build POST params
95
+ var data = "";
96
+ if (typeof(options.glue) != "undefined") {
97
+ data += "&glue="+escape(options.glue);
98
+ }
99
+ if(typeof(options.map) != "undefined") {
100
+ if(typeof(options.map.value) != "object") {
101
+ options.map.value = [options.map.value];
102
+ }
103
+ for(var i=0; i<options.map.value.length; i++) {
104
+ data += "&map[value][]=" + options.map.value[i];
105
+ }
106
+ if(typeof(options.map.label) != "object") {
107
+ options.map.label = [options.map.label];
108
+ }
109
+ for(var i=0; i<options.map.label.length; i++) {
110
+ data += "&map[label][]=" + options.map.label[i];
111
+ }
112
+ for(var i=0; i<options.map.search.length; i++) {
113
+ data += "&map[search][]=" + options.map.search[i];
114
+ }
115
+ for(var i=0; i<options.joins.length; i++) {
116
+ data += "&joins[]=" + options.joins[i];
117
+ }
118
+ }
119
+ if (options["multi"]) {
120
+ el.next(".autocomplete-multi-container").select("input[type=checkbox]").each(function(e){
121
+ data += "&skip[]=" + e.value
122
+ });
123
+ }
124
+
125
+ // remove previous list if there's one
126
+ Autocomplete_RemoveList(el);
127
+
128
+ // reset hidden input before sending new request
129
+ if(!options["multi"]) {
130
+ el.parentNode.select("input[type=hidden]").first().value = "";
131
+ }
132
+
133
+ // make Request
134
+ new Ajax.Request("/autocomplete/find/" + options.model + "/" + _esc(el.value), {
135
+ method: "post",
136
+ parameters: data.substr(1),
137
+ onCreate: function(){
138
+ el.addClassName("autocomplete-loading");
139
+ },
140
+ onComplete: function(req){
141
+ el.removeClassName("autocomplete-loading");
142
+ if(req.status==200) {
143
+ var response = eval('(' + req.responseText + ')');
144
+
145
+ var ul = new Element("ul", {
146
+ "class": "autocomplete-list"
147
+ });
148
+ var position = el.positionedOffset()
149
+ ul.setStyle({
150
+ left: position[0] + "px",
151
+ top: position[1] + el.getHeight() + "px"
152
+ });
153
+ el.insert({
154
+ before: ul
155
+ });
156
+ if (response.length > 0) {
157
+ var li, a, rem;
158
+ for (var i = 0; i < response.length; i++) {
159
+ // list-item
160
+ li = new Element("li");
161
+ if (i % 2) {
162
+ li.addClassName("odd");
163
+ }
164
+ // item-value
165
+ a = new Element("a");
166
+ a.href = "javascript:void(0);";
167
+ a.r = response[i];
168
+
169
+ a.observe("keyup", function(e){
170
+ switch(e.keyCode) {
171
+ case 27: // Esc
172
+ Autocomplete_RemoveList(el);
173
+ break;
174
+ case 40: // Arrow Down
175
+ this.parentNode.next("li").select("a")[0].focus();
176
+ break;
177
+ case 38: // Arrow Up
178
+ this.parentNode.previous("li").select("a")[0].focus();
179
+ break;
180
+ }
181
+ });
182
+
183
+ a.observe("click", function(e){
184
+ var next = this.parentNode.previous("li");
185
+ if(next) {
186
+ next = next.select("a")[0];
187
+ }else{
188
+ next = this.parentNode.next("li");
189
+ if(next) {
190
+ next = next.select("a")[0];
191
+ }
192
+ }
193
+ if (options["multi"]) {
194
+ var c = el.next(".autocomplete-multi-container");
195
+ if (c.select("div.ac-" + this.r["value"]).length == 0) {
196
+ span = new Element("div", {
197
+ "class": "autocomplete-multi-rowset ac-" + this.r["value"]
198
+ });
199
+ span.observe("click", function(e){
200
+ var chk = this.select("input[type=checkbox]")[0];
201
+ if(e.target.hasClassName("autocomplete-multi-rowset")) {
202
+ chk.checked = chk.checked?false:true;
203
+ }
204
+ if(chk.checked) {
205
+ this.addClassName("selected");
206
+ }else{
207
+ this.removeClassName("selected");
208
+ }
209
+ });
210
+ var id = "ac_input_" + this.r["value"];
211
+ inpt = new Element("input", {
212
+ "type": "checkbox",
213
+ "name": options["name"],
214
+ "id": id,
215
+ "value": this.r["value"]
216
+ });
217
+ span.insert(inpt);
218
+
219
+ label = new Element("label", {"for":id}).update(this.r["label"]);
220
+ span.insert(label)
221
+
222
+ c.insert(span);
223
+
224
+ if (this.parentNode.parentNode.select("li").length == 1) {
225
+ Autocomplete_RemoveList(el);
226
+ }
227
+ else {
228
+ this.parentNode.remove();
229
+ }
230
+ Autocomplete_UpdateStatus(el);
231
+ }
232
+ Event.stop(e);
233
+ }
234
+ else {
235
+ el.value = this.r["label"];
236
+ el.title = "value: " + this.r["value"];
237
+ el.parentNode.select("input[type=hidden]").first().value = this.r["value"];
238
+ }
239
+
240
+ // focus to previous
241
+ if(next) next.focus()
242
+ });
243
+ a.innerHTML = response[i]["label"];
244
+ li.insert(a);
245
+
246
+ ul.insert(li);
247
+ }
248
+ }else{
249
+ var empty = new Element("li", {"class": "empty"}).update("No results.");
250
+ ul.insert(empty);
251
+ setTimeout(function(){
252
+ Autocomplete_RemoveList(el);
253
+ }, 2000);
254
+ }
255
+ }else{
256
+ //alert(req.status + ". " + req.statusText);
257
+ }
258
+ }
259
+ });
260
+
261
+ }, 800);
262
+
263
+ });
264
+ element.observe("keypress", function(e){
265
+ Autocomplete_Stop(e.target);
266
+ });
267
+
268
+
269
+ }
270
+ function Autocomplete_Stop(element) {
271
+ var to = element.timeout;
272
+ if(to) {
273
+ clearTimeout(to);
274
+ element.timeout = null;
275
+ }
276
+ }
277
+ function Autocomplete_RemoveList(element) {
278
+ var list = $$(".autocomplete-list");
279
+ list.each(function(el){el.remove();});
280
+ element.focus();
281
+ }
282
+ function Autocomplete_UpdateStatus(element) {
283
+ var container = element.next(".autocomplete-multi-container");
284
+ if (container) {
285
+ element.next(".autocomplete-multi-status").select(".length").each(function(s){
286
+ s.innerHTML = container.select(".autocomplete-multi-rowset").length+"";
287
+ });
288
+ }
289
+
290
+ }
291
+ function Autocomplete_getCheckboxes(element) {
292
+ ret = [];
293
+ element.adjacent(".autocomplete-multi-container")[0].select("input[type=checkbox]").each(function(cb){
294
+ ret.push(cb);
295
+ });
296
+ return ret;
297
+ }
298
+ function Autocomplete_getCheckedRows(element) {
299
+ ret = [];
300
+ element.adjacent(".autocomplete-multi-container")[0].select("input[type=checkbox]").each(function(cb){
301
+ if(cb.checked) {
302
+ ret.push(cb.parentNode);
303
+ }
304
+ });
305
+ return ret;
306
+ }
307
+
308
+ function _esc(str) {
309
+ str = str + ""
310
+ var ret = "", c;
311
+ for(var i=0; i<str.length; i++) {
312
+ c = str[i];
313
+ if(!c.match(/[a-z0-9]/i)) {
314
+ c = c.charCodeAt(0);
315
+ c = "%" + c.toString(16);
316
+ }
317
+ ret += c;
318
+ }
319
+ return ret;
320
+ }
@@ -0,0 +1,31 @@
1
+ # -*- encoding: utf-8 -*-
2
+
3
+ Gem::Specification.new do |s|
4
+ s.name = %q{autocomplete}
5
+ s.version = "1.0.1"
6
+
7
+ s.required_rubygems_version = Gem::Requirement.new(">= 1.2") if s.respond_to? :required_rubygems_version=
8
+ s.authors = ["Voislav Jovanovic"]
9
+ s.date = %q{2010-07-23}
10
+ s.description = %q{Insert an autocomplete-search-box inside your view}
11
+ s.email = %q{voislavj@gmail.com}
12
+ s.extra_rdoc_files = ["README.rdoc", "lib/autocomplete.rb", "lib/autocomplete_controller.rb", "lib/autocomplete_helper.rb", "tasks/autocomplete_tasks.rake"]
13
+ s.files = ["MIT-LICENSE", "README.rdoc", "Rakefile", "assets/autocomplete-loading.gif", "assets/autocomplete.css", "assets/autocomplete.js", "autocomplete.gemspec", "id_rsa.pub", "init.rb", "install.rb", "lib/autocomplete.rb", "lib/autocomplete_controller.rb", "lib/autocomplete_helper.rb", "tasks/autocomplete_tasks.rake", "test/autocomplete_test.rb", "Manifest"]
14
+ s.homepage = %q{http://www.voja-jovanovic.info}
15
+ s.rdoc_options = ["--line-numbers", "--inline-source", "--title", "Autocomplete", "--main", "README.rdoc"]
16
+ s.require_paths = ["lib"]
17
+ s.rubyforge_project = %q{autocomplete}
18
+ s.rubygems_version = %q{1.3.7}
19
+ s.summary = %q{Insert an autocomplete-search-box inside your view}
20
+ s.test_files = ["test/autocomplete_test.rb"]
21
+
22
+ if s.respond_to? :specification_version then
23
+ current_version = Gem::Specification::CURRENT_SPECIFICATION_VERSION
24
+ s.specification_version = 3
25
+
26
+ if Gem::Version.new(Gem::VERSION) >= Gem::Version.new('1.2.0') then
27
+ else
28
+ end
29
+ else
30
+ end
31
+ end
@@ -0,0 +1 @@
1
+ ssh-rsa AAAAB3NzaC1yc2EAAAABIwAAAQEAxm7FhP0LM71UVtxZLiZdmx0cyzj2cNCqE4UOD+JF5HvkbAmv2ySIqyO4NMSq9Ww96P+GW8o6UlnhzhziNMRoeon2b59AsjV5d8q8rlOKGT5z7zkN8VpoT8iht+wpQrZX4SLshlmwR90nP4ygDWh9Z9wZ1GVje36GqVUdYAKh0c2zYH5MZrfEuTIIMzaMJm6faRE/MG1Gx/Lqo+0mGw6k1Uz4Y7j8M/rm+SDC6Ws0TotKnnHkvhT2ZDi8ZB0Qvf7Zz0U/oamKYArXeLAeR6U+ytNozXq9lWvB15wKzLFYEHJonpmh3IH2oazfvksE1nzBlMGF37oHTJCDZ/hsQ+yAiQ== User@VOJA
data/init.rb ADDED
@@ -0,0 +1,5 @@
1
+ # Include hook code here
2
+ require 'autocomplete_controller'
3
+ require 'autocomplete_helper'
4
+
5
+ ActionView::Base.send(:include, AutocompleteHelper)
@@ -0,0 +1,10 @@
1
+ # Install hook code here
2
+ #require 'ftools'
3
+ #
4
+ #plugins_dir = File.expand_path(".")
5
+ #autocomplete_dir = File.join(plugins_dir, 'autocomplete')
6
+ #root_dir = File.join(autocomplete_dir, '..', '..', '..')
7
+ #
8
+ #File.copy File.join(autocomplete_dir, 'assets', 'autocomplete.js'), File.join(root_dir, 'public', 'javascripts', 'autocomplete.js')
9
+ #File.copy File.join(autocomplete_dir, 'assets', 'autocomplete.css'), File.join(root_dir, 'public', 'stylesheets', 'autocomplete.css')
10
+ #File.copy File.join(autocomplete_dir, 'assets', 'autocomplete-loading.gif'), File.join(root_dir, 'public', 'images', 'autocomplete-loading.gif')
@@ -0,0 +1,9 @@
1
+ # Autocomplete
2
+ %w{ models controllers }.each do |dir|
3
+ path = File.join(File.dirname(__FILE__), 'app', dir)
4
+ $LOAD_PATH << path
5
+ ActiveSupport::Dependencies.load_paths << path
6
+ ActiveSupport::Dependencies.load_once_paths.delete(path)
7
+ end
8
+
9
+ require "autocomplete/routing"
@@ -0,0 +1,78 @@
1
+ class AutocompleteController < ActionController::Base
2
+
3
+ def find
4
+ params[:map] = {:value=>[:id], :label=>[:name], :search=>[:name]} unless params[:map]
5
+ params[:limit] ||= 50
6
+ params[:skip] ||= []
7
+ params[:map][:search] ||= []
8
+ params[:glue] ||= " "
9
+
10
+ params[:joins] ||= []
11
+
12
+ @modelname = params[:model]
13
+ @model = params[:model].constantize
14
+
15
+ params[:map][:label] = parse_table_fields(params[:map][:label])
16
+ params[:map][:value] = parse_table_fields(params[:map][:value])
17
+ params[:map][:search] = parse_table_fields(params[:map][:search])
18
+
19
+ params[:joins].each_with_index do |v,k|
20
+ params[:joins][k] = eval(":#{v}")
21
+ end
22
+
23
+ value = "CONCAT_WS(' ',#{params[:map][:value].join(",")})"
24
+ label = "CONCAT_WS('#{params[:glue]}',#{params[:map][:label].join(",")})"
25
+ search = "CONCAT_WS(' ',#{(params[:map][:label]|params[:map][:search]).join(",")})"
26
+
27
+ skip = ""
28
+ toskip = ""
29
+
30
+ params[:skip].each do |s|
31
+ toskip += ","
32
+ unless s.to_s.match(/^\d+$/i)
33
+ s = "'#{s}'"
34
+ end
35
+ toskip += s
36
+ end
37
+
38
+ toskip = toskip.gsub(/^,/, "")
39
+ if params[:skip].length>0
40
+ skip = "AND #{value} NOT IN(#{toskip})"
41
+ end
42
+
43
+ debug params[:joins]
44
+
45
+ result = @model.find(
46
+ :all, {
47
+ :select => "#{value} as `value`, #{label} as `label`",
48
+ :conditions => ["#{search} LIKE ? #{skip}", "%" + params[:keyword].gsub("%", "\%") + "%"],
49
+ :joins => params[:joins],
50
+ :order => "label",
51
+ :limit => params[:limit]
52
+ }
53
+ );
54
+ render :text => result.to_json
55
+ end
56
+
57
+ def debug(var, mode="w")
58
+ File.open("D:\\voja.log", mode) {|f| f.write(var.to_yaml); f.close}
59
+ end
60
+
61
+ def parse_table_fields(arr)
62
+ single = false
63
+ unless arr.is_a?(Array)
64
+ arr = [arr]
65
+ single = true
66
+ end
67
+
68
+ arr.each_with_index do |v,k|
69
+ puts v.inspect + " => " + v.to_s.inspect
70
+ if v.to_s.match(/\./)
71
+ items = v.to_s.split(".",2)
72
+ arr[k] = "#{items[0].constantize.table_name}.#{items[1]}"
73
+ end
74
+ end
75
+ return single ? arr[0] : arr;
76
+ end
77
+
78
+ end
@@ -0,0 +1,43 @@
1
+ module AutocompleteHelper
2
+
3
+ # generate autocomplete text-field
4
+ def autocomplete(options={})
5
+ return nil unless options[:model]
6
+
7
+ options[:name] ||= :autocomplete_keyword
8
+ options[:multi] ||= false;
9
+
10
+ options[:multi_height] ||= 150
11
+ options[:uuid] = _uuid
12
+
13
+ options[:map][:value] ||= :id
14
+ options[:map][:label] ||= [:name]
15
+ options[:map][:search] ||= []
16
+
17
+ #txt_name = options[:multi] ? "autocomplete-keyword-#{options[:uuid]}" : options[:name]
18
+ txt_name = "autocomplete-keyword-#{options[:uuid]}"
19
+
20
+ ret = []
21
+ ret << javascript_include_tag("autocomplete")
22
+ ret << stylesheet_link_tag("autocomplete")
23
+ ret << label_tag(txt_name, options[:model].camelize)
24
+ ret << text_field_tag(txt_name, nil, {
25
+ :onfocus => "Autocomplete(this, " + options.to_json.to_s + ")"
26
+ })
27
+
28
+ if options[:multi]
29
+ ret << content_tag(:div, '<a class="autocomplete-remove" href="javascript:void(0);">remove selected</a> select <a href="javascript:void(0)" class="autocomplete-select-all">all</a> / <a href="javascript:void(0)" class="autocomplete-select-none">none</a>', :class=>"autocomplete-multi-controls")
30
+ ret << content_tag(:div, "", :class=>"autocomplete-multi-container", :style=>"height: #{options[:multi_height]}px")
31
+ ret << content_tag(:div, "<span class=\"length\">0</span> items", :class=>"autocomplete-multi-status")
32
+ else
33
+ ret << hidden_field_tag(options[:name], "")
34
+ end
35
+
36
+ return ret.join("\r\n")
37
+ end
38
+
39
+ def _uuid
40
+ o = [('a'..'z'),('A'..'Z'),(0..9)].map{|i| i.to_a}.flatten;
41
+ string = (0..10).map{ o[rand(o.length)] }.join;
42
+ end
43
+ end
@@ -0,0 +1,15 @@
1
+ # desc "Explaining what the task does"
2
+ # task :autocomplete do
3
+ # # Task goes here
4
+ # end
5
+ desc 'Update autocomplete JavaScripts and CSSs'
6
+ task :update_scripts => [] do |t|
7
+
8
+ autocomplete_dir = File.expand_path(".")
9
+ [["javascripts","autocomplete.js"], ["stylesheets","autocomplete.css"]].each do |file|
10
+ unless File.exists?(File.join(RAILS_ROOT, "public", file[0], file[1]))
11
+ File.copy(File.join("assets", file[1]), File.join(RAILS_ROOT, "public", file[0], file[1]))
12
+ end
13
+ end
14
+ puts "JavaScripts and CSSs updated."
15
+ end
@@ -0,0 +1,8 @@
1
+ require 'test/unit'
2
+
3
+ class AutocompleteTest < Test::Unit::TestCase
4
+ # Replace this with your real tests.
5
+ def test_this_plugin
6
+ flunk
7
+ end
8
+ end
metadata ADDED
@@ -0,0 +1,92 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: autocomplete
3
+ version: !ruby/object:Gem::Version
4
+ hash: 21
5
+ prerelease: false
6
+ segments:
7
+ - 1
8
+ - 0
9
+ - 1
10
+ version: 1.0.1
11
+ platform: ruby
12
+ authors:
13
+ - Voislav Jovanovic
14
+ autorequire:
15
+ bindir: bin
16
+ cert_chain: []
17
+
18
+ date: 2010-07-23 00:00:00 +02:00
19
+ default_executable:
20
+ dependencies: []
21
+
22
+ description: Insert an autocomplete-search-box inside your view
23
+ email: voislavj@gmail.com
24
+ executables: []
25
+
26
+ extensions: []
27
+
28
+ extra_rdoc_files:
29
+ - README.rdoc
30
+ - lib/autocomplete.rb
31
+ - lib/autocomplete_controller.rb
32
+ - lib/autocomplete_helper.rb
33
+ - tasks/autocomplete_tasks.rake
34
+ files:
35
+ - MIT-LICENSE
36
+ - README.rdoc
37
+ - Rakefile
38
+ - assets/autocomplete-loading.gif
39
+ - assets/autocomplete.css
40
+ - assets/autocomplete.js
41
+ - autocomplete.gemspec
42
+ - id_rsa.pub
43
+ - init.rb
44
+ - install.rb
45
+ - lib/autocomplete.rb
46
+ - lib/autocomplete_controller.rb
47
+ - lib/autocomplete_helper.rb
48
+ - tasks/autocomplete_tasks.rake
49
+ - test/autocomplete_test.rb
50
+ - Manifest
51
+ has_rdoc: true
52
+ homepage: http://www.voja-jovanovic.info
53
+ licenses: []
54
+
55
+ post_install_message:
56
+ rdoc_options:
57
+ - --line-numbers
58
+ - --inline-source
59
+ - --title
60
+ - Autocomplete
61
+ - --main
62
+ - README.rdoc
63
+ require_paths:
64
+ - lib
65
+ required_ruby_version: !ruby/object:Gem::Requirement
66
+ none: false
67
+ requirements:
68
+ - - ">="
69
+ - !ruby/object:Gem::Version
70
+ hash: 3
71
+ segments:
72
+ - 0
73
+ version: "0"
74
+ required_rubygems_version: !ruby/object:Gem::Requirement
75
+ none: false
76
+ requirements:
77
+ - - ">="
78
+ - !ruby/object:Gem::Version
79
+ hash: 11
80
+ segments:
81
+ - 1
82
+ - 2
83
+ version: "1.2"
84
+ requirements: []
85
+
86
+ rubyforge_project: autocomplete
87
+ rubygems_version: 1.3.7
88
+ signing_key:
89
+ specification_version: 3
90
+ summary: Insert an autocomplete-search-box inside your view
91
+ test_files:
92
+ - test/autocomplete_test.rb