awesomplete 0.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,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 8bc888afcc2ca4a3fb55078e2a8d1b7cbc881d00
4
+ data.tar.gz: cf91eb1821b5042bb612a0cbcd519881044c8c64
5
+ SHA512:
6
+ metadata.gz: 2f084423cc21279899d57af715b5d37b868d67d7a58ea232d5fe4b4ebefe635506d9aa88a4bd4f701074c6686c64d7b5607d1ebeb0e6ee1f876d5cab60f4094a
7
+ data.tar.gz: d4fd43cccab1963e5d6413df6d46f3e86abcd53bed39928de1ac883367a0bc7029408eb386a0168381f5b5666f72a766727875cd5cd03b3c5c744f20b7d32c2f
@@ -0,0 +1,20 @@
1
+ Copyright 2015 fishbullet
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,58 @@
1
+ ## [Awesomplete](http://leaverou.github.io/awesomplete) For Rails ##
2
+
3
+ This is small gem add to your Rails app [Awesomplete](https://github.com/LeaVerou/awesomplete) autocomplete.
4
+
5
+ This is the working version.
6
+ ```rbcon
7
+ # Developed and tested on:
8
+ Ruby 2.1.0
9
+ Rails ~> 4.0.0
10
+ ```
11
+ ## Getting started
12
+ 1. Add to `Gemfile` and `bundle install`.
13
+
14
+ ```ruby
15
+ gem 'awesomplete'
16
+ ```
17
+
18
+ 2. Add to `app/assets/javascripts/application.js`:
19
+
20
+ ```js
21
+ //=require awesomplete
22
+ ```
23
+
24
+ 3. Add to `app/assets/stylesheets/application.css`
25
+
26
+ ```css
27
+ *= require awesomplete
28
+ ```
29
+
30
+ Restart server. That's it.
31
+
32
+ ## Helpers
33
+ Now you can write small and awesomplete inputs.
34
+ I find it is very cool for small collections, check it out:
35
+
36
+ ```erb
37
+
38
+ ```
39
+
40
+ ## Configure module
41
+ You can configurate this autocomplete by two ways:
42
+
43
+ 1. In `data-` options in views:
44
+
45
+ ```erb
46
+ #TODO
47
+ ```
48
+
49
+ 2. In `javascripts` initializer (e.g. `app/assets/javascripts/some_script.js`):
50
+
51
+ ```javascript
52
+ #TODO
53
+ ```
54
+ * * *
55
+
56
+ Kiselenko Roman
57
+
58
+ This project rocks and uses MIT-LICENSE.
@@ -0,0 +1,8 @@
1
+ begin
2
+ require 'bundler/setup'
3
+ rescue LoadError
4
+ puts 'You must `gem install bundler` and `bundle install` to run rake tasks'
5
+ end
6
+
7
+ Bundler::GemHelper.install_tasks
8
+
@@ -0,0 +1,359 @@
1
+ /**
2
+ * Simple, lightweight, usable local autocomplete library for modern browsers
3
+ * Because there weren’t enough autocomplete scripts in the world? Because I’m completely insane and have NIH syndrome? Probably both. :P
4
+ * @author Lea Verou http://leaverou.github.io/awesomplete
5
+ * MIT license
6
+ */
7
+
8
+ (function () {
9
+
10
+ var _ = self.Awesomplete = function (input, o) {
11
+ var me = this;
12
+
13
+ // Setup
14
+
15
+ this.input = input;
16
+ input.setAttribute("aria-autocomplete", "list");
17
+
18
+ o = o || {};
19
+
20
+ configure.call(this, {
21
+ minChars: 2,
22
+ maxItems: 10,
23
+ autoFirst: false,
24
+ filter: _.FILTER_CONTAINS,
25
+ sort: _.SORT_BYLENGTH,
26
+ item: function (text, input) {
27
+ return $.create("li", {
28
+ innerHTML: text.replace(RegExp($.regExpEscape(input.trim()), "gi"), "<mark>$&</mark>"),
29
+ "aria-selected": "false"
30
+ });
31
+ },
32
+ replace: function (text) {
33
+ this.input.value = text;
34
+ }
35
+ }, o);
36
+
37
+ this.index = -1;
38
+
39
+ // Create necessary elements
40
+
41
+ this.container = $.create("div", {
42
+ className: "awesomplete",
43
+ around: input
44
+ });
45
+
46
+ this.ul = $.create("ul", {
47
+ hidden: "",
48
+ inside: this.container
49
+ });
50
+
51
+ this.status = $.create("span", {
52
+ className: "visually-hidden",
53
+ role: "status",
54
+ "aria-live": "assertive",
55
+ "aria-relevant": "additions",
56
+ inside: this.container
57
+ });
58
+
59
+ // Bind events
60
+
61
+ $.bind(this.input, {
62
+ "input": this.evaluate.bind(this),
63
+ "blur": this.close.bind(this),
64
+ "keydown": function(evt) {
65
+ var c = evt.keyCode;
66
+
67
+ if (c === 13 && me.selected) { // Enter
68
+ evt.preventDefault();
69
+ me.select();
70
+ }
71
+ else if (c === 27) { // Esc
72
+ me.close();
73
+ }
74
+ else if (c === 38 || c === 40) { // Down/Up arrow
75
+ evt.preventDefault();
76
+ me[c === 38? "previous" : "next"]();
77
+ }
78
+ }
79
+ });
80
+
81
+ $.bind(this.input.form, {"submit": me.close.bind(me)});
82
+
83
+ $.bind(this.ul, {"mousedown": function(evt) {
84
+ var li = evt.target;
85
+
86
+ if (li !== this) {
87
+
88
+ while (li && !/li/i.test(li.nodeName)) {
89
+ li = li.parentNode;
90
+ }
91
+
92
+ if (li) {
93
+ me.select(li);
94
+ }
95
+ }
96
+ }});
97
+
98
+ if (input.hasAttribute("list")) {
99
+ this.list = "#" + input.getAttribute("list");
100
+ input.removeAttribute("list");
101
+ }
102
+ else {
103
+ this.list = input.getAttribute("data-list") || o.list || [];
104
+ }
105
+
106
+ _.all.push(this);
107
+ };
108
+
109
+ _.prototype = {
110
+ set list(list) {
111
+ if (Array.isArray(list)) {
112
+ this._list = list;
113
+ }
114
+ else if (typeof list === "string" && list.indexOf(",") > -1) {
115
+ this._list = list.split(/\s*,\s*/);
116
+ }
117
+ else { // Element or CSS selector
118
+ list = $(list);
119
+
120
+ if (list && list.children) {
121
+ this._list = slice.apply(list.children).map(function (el) {
122
+ return el.innerHTML.trim();
123
+ });
124
+ }
125
+ }
126
+
127
+ if (document.activeElement === this.input) {
128
+ this.evaluate();
129
+ }
130
+ },
131
+
132
+ get selected() {
133
+ return this.index > -1;
134
+ },
135
+
136
+ close: function () {
137
+ this.ul.setAttribute("hidden", "");
138
+ this.index = -1;
139
+
140
+ $.fire(this.input, "awesomplete-close");
141
+ },
142
+
143
+ open: function () {
144
+ this.ul.removeAttribute("hidden");
145
+
146
+ if (this.autoFirst && this.index === -1) {
147
+ this.goto(0);
148
+ }
149
+
150
+ $.fire(this.input, "awesomplete-open");
151
+ },
152
+
153
+ next: function () {
154
+ var count = this.ul.children.length;
155
+
156
+ this.goto(this.index < count - 1? this.index + 1 : -1);
157
+ },
158
+
159
+ previous: function () {
160
+ var count = this.ul.children.length;
161
+
162
+ this.goto(this.selected? this.index - 1 : count - 1);
163
+ },
164
+
165
+ // Should not be used, highlights specific item without any checks!
166
+ goto: function (i) {
167
+ var lis = this.ul.children;
168
+
169
+ if (this.selected) {
170
+ lis[this.index].setAttribute("aria-selected", "false");
171
+ }
172
+
173
+ this.index = i;
174
+
175
+ if (i > -1 && lis.length > 0) {
176
+ lis[i].setAttribute("aria-selected", "true");
177
+ this.status.textContent = lis[i].textContent;
178
+ }
179
+ },
180
+
181
+ select: function (selected) {
182
+ selected = selected || this.ul.children[this.index];
183
+
184
+ if (selected) {
185
+ var prevented;
186
+
187
+ $.fire(this.input, "awesomplete-select", {
188
+ text: selected.textContent,
189
+ preventDefault: function () {
190
+ prevented = true;
191
+ }
192
+ });
193
+
194
+ if (!prevented) {
195
+ this.replace(selected.textContent);
196
+ this.close();
197
+ $.fire(this.input, "awesomplete-selectcomplete");
198
+ }
199
+ }
200
+ },
201
+
202
+ evaluate: function() {
203
+ var me = this;
204
+ var value = this.input.value;
205
+
206
+ if (value.length >= this.minChars && this._list.length > 0) {
207
+ this.index = -1;
208
+ // Populate list with options that match
209
+ this.ul.innerHTML = "";
210
+
211
+ this._list
212
+ .filter(function(item) {
213
+ return me.filter(item, value);
214
+ })
215
+ .sort(this.sort)
216
+ .every(function(text, i) {
217
+ me.ul.appendChild(me.item(text, value));
218
+
219
+ return i < me.maxItems - 1;
220
+ });
221
+
222
+ this.open();
223
+ }
224
+ else {
225
+ this.close();
226
+ }
227
+ }
228
+ };
229
+
230
+ // Static methods/properties
231
+
232
+ _.all = [];
233
+
234
+ _.FILTER_CONTAINS = function (text, input) {
235
+ return RegExp($.regExpEscape(input.trim()), "i").test(text);
236
+ };
237
+
238
+ _.FILTER_STARTSWITH = function (text, input) {
239
+ return RegExp("^" + $.regExpEscape(input.trim()), "i").test(text);
240
+ };
241
+
242
+ _.SORT_BYLENGTH = function (a, b) {
243
+ if (a.length !== b.length) {
244
+ return a.length - b.length;
245
+ }
246
+
247
+ return a < b? -1 : 1;
248
+ };
249
+
250
+ // Private functions
251
+
252
+ function configure(properties, o) {
253
+ for (var i in properties) {
254
+ var initial = properties[i],
255
+ attrValue = this.input.getAttribute("data-" + i.toLowerCase());
256
+
257
+ if (typeof initial === "number") {
258
+ this[i] = +attrValue;
259
+ }
260
+ else if (initial === false) { // Boolean options must be false by default anyway
261
+ this[i] = attrValue !== null;
262
+ }
263
+ else if (initial instanceof Function) {
264
+ this[i] = null;
265
+ }
266
+ else {
267
+ this[i] = attrValue;
268
+ }
269
+
270
+ this[i] = this[i] || o[i] || initial;
271
+ }
272
+ }
273
+
274
+ // Helpers
275
+
276
+ var slice = Array.prototype.slice;
277
+
278
+ function $(expr, con) {
279
+ return typeof expr === "string"? (con || document).querySelector(expr) : expr || null;
280
+ }
281
+
282
+ function $$(expr, con) {
283
+ return slice.call((con || document).querySelectorAll(expr));
284
+ }
285
+
286
+ $.create = function(tag, o) {
287
+ var element = document.createElement(tag);
288
+
289
+ for (var i in o) {
290
+ var val = o[i];
291
+
292
+ if (i === "inside") {
293
+ $(val).appendChild(element);
294
+ }
295
+ else if (i === "around") {
296
+ var ref = $(val);
297
+ ref.parentNode.insertBefore(element, ref);
298
+ element.appendChild(ref);
299
+ }
300
+ else if (i in element) {
301
+ element[i] = val;
302
+ }
303
+ else {
304
+ element.setAttribute(i, val);
305
+ }
306
+ }
307
+
308
+ return element;
309
+ };
310
+
311
+ $.bind = function(element, o) {
312
+ if (element) {
313
+ for (var event in o) {
314
+ var callback = o[event];
315
+
316
+ event.split(/\s+/).forEach(function (event) {
317
+ element.addEventListener(event, callback);
318
+ });
319
+ }
320
+ }
321
+ };
322
+
323
+ $.fire = function(target, type, properties) {
324
+ var evt = document.createEvent("HTMLEvents");
325
+
326
+ evt.initEvent(type, true, true );
327
+
328
+ for (var j in properties) {
329
+ evt[j] = properties[j];
330
+ }
331
+
332
+ target.dispatchEvent(evt);
333
+ };
334
+
335
+ $.regExpEscape = function (s) {
336
+ return s.replace(/[-\\^$*+?.()|[\]{}]/g, "\\$&");
337
+ }
338
+
339
+ // Initialization
340
+
341
+ function init() {
342
+ $$("input.awesomplete").forEach(function (input) {
343
+ new Awesomplete(input);
344
+ });
345
+ }
346
+
347
+ // DOM already loaded?
348
+ if (document.readyState !== "loading") {
349
+ init();
350
+ }
351
+ else {
352
+ // Wait for it
353
+ document.addEventListener("DOMContentLoaded", init);
354
+ }
355
+
356
+ _.$ = $;
357
+ _.$$ = $$;
358
+
359
+ })();
@@ -0,0 +1,97 @@
1
+ [hidden] { display: none; }
2
+
3
+ .visually-hidden {
4
+ position: absolute;
5
+ clip: rect(0, 0, 0, 0);
6
+ }
7
+
8
+ div.awesomplete {
9
+ display: inline-block;
10
+ position: relative;
11
+ }
12
+
13
+ div.awesomplete > input {
14
+ display: block;
15
+ }
16
+
17
+ div.awesomplete > ul {
18
+ position: absolute;
19
+ left: 0;
20
+ z-index: 1;
21
+ min-width: 100%;
22
+ box-sizing: border-box;
23
+ list-style: none;
24
+ padding: 0;
25
+ border-radius: .3em;
26
+ margin: .2em 0 0;
27
+ background: hsla(0,0%,100%,.9);
28
+ background: linear-gradient(to bottom right, white, hsla(0,0%,100%,.8));
29
+ border: 1px solid rgba(0,0,0,.3);
30
+ box-shadow: .05em .2em .6em rgba(0,0,0,.2);
31
+ text-shadow: none;
32
+ }
33
+
34
+ div.awesomplete > ul[hidden],
35
+ div.awesomplete > ul:empty {
36
+ display: none;
37
+ }
38
+
39
+ @supports (transform: scale(0)) {
40
+ div.awesomplete > ul {
41
+ transition: .3s cubic-bezier(.4,.2,.5,1.4);
42
+ transform-origin: 1.43em -.43em;
43
+ }
44
+
45
+ div.awesomplete > ul[hidden],
46
+ div.awesomplete > ul:empty {
47
+ opacity: 0;
48
+ transform: scale(0);
49
+ display: block;
50
+ transition-timing-function: ease;
51
+ }
52
+ }
53
+
54
+ /* Pointer */
55
+ div.awesomplete > ul:before {
56
+ content: "";
57
+ position: absolute;
58
+ top: -.43em;
59
+ left: 1em;
60
+ width: 0; height: 0;
61
+ padding: .4em;
62
+ background: white;
63
+ border: inherit;
64
+ border-right: 0;
65
+ border-bottom: 0;
66
+ -webkit-transform: rotate(45deg);
67
+ transform: rotate(45deg);
68
+ }
69
+
70
+ div.awesomplete > ul > li {
71
+ position: relative;
72
+ padding: .2em .5em;
73
+ cursor: pointer;
74
+ }
75
+
76
+ div.awesomplete > ul > li:hover {
77
+ background: hsl(200, 40%, 80%);
78
+ color: black;
79
+ }
80
+
81
+ div.awesomplete > ul > li[aria-selected="true"] {
82
+ background: hsl(205, 40%, 40%);
83
+ color: white;
84
+ }
85
+
86
+ div.awesomplete mark {
87
+ background: hsl(65, 100%, 50%);
88
+ }
89
+
90
+ div.awesomplete li:hover mark {
91
+ background: hsl(68, 101%, 41%);
92
+ }
93
+
94
+ div.awesomplete li[aria-selected="true"] mark {
95
+ background: hsl(86, 102%, 21%);
96
+ color: inherit;
97
+ }
@@ -0,0 +1,5 @@
1
+ module Awesomplete
2
+ class Engine < ::Rails::Engine
3
+ config.assets.paths << "app/assets"
4
+ end
5
+ end
@@ -0,0 +1,3 @@
1
+ module Awesomplete
2
+ VERSION = "0.0.1"
3
+ end
@@ -0,0 +1,4 @@
1
+ # desc "Explaining what the task does"
2
+ # task :awesomplete do
3
+ # # Task goes here
4
+ # end
metadata ADDED
@@ -0,0 +1,66 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: awesomplete
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.1
5
+ platform: ruby
6
+ authors:
7
+ - fishbullet
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2015-02-28 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: rails
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - ~>
18
+ - !ruby/object:Gem::Version
19
+ version: 4.0.0
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - ~>
25
+ - !ruby/object:Gem::Version
26
+ version: 4.0.0
27
+ description: Add assets to your Rails app assets path. Based on http://leaverou.github.io/awesomplete
28
+ email:
29
+ - shindu666@gmail.com
30
+ executables: []
31
+ extensions: []
32
+ extra_rdoc_files: []
33
+ files:
34
+ - MIT-LICENSE
35
+ - README.md
36
+ - Rakefile
37
+ - app/assets/javascripts/awesomplete.js
38
+ - app/assets/stylesheets/awesomplete.css
39
+ - lib/awesomplete.rb
40
+ - lib/awesomplete/version.rb
41
+ - lib/tasks/awesomplete_tasks.rake
42
+ homepage: http://www.some.com
43
+ licenses:
44
+ - MIT
45
+ metadata: {}
46
+ post_install_message:
47
+ rdoc_options: []
48
+ require_paths:
49
+ - lib
50
+ required_ruby_version: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - '>='
53
+ - !ruby/object:Gem::Version
54
+ version: '0'
55
+ required_rubygems_version: !ruby/object:Gem::Requirement
56
+ requirements:
57
+ - - '>='
58
+ - !ruby/object:Gem::Version
59
+ version: '0'
60
+ requirements: []
61
+ rubyforge_project:
62
+ rubygems_version: 2.4.3
63
+ signing_key:
64
+ specification_version: 4
65
+ summary: This is small gem add to your Rails app awesomplete autocomplete.
66
+ test_files: []