better_select 0.0.3 → 0.0.4

Sign up to get free protection for your applications and to get access to all the features.
@@ -6,12 +6,14 @@ Gem::Specification.new do |gem|
6
6
  gem.email = ["bennyjbergstein@gmail.com"]
7
7
  gem.description = "A better HTMLSelectElement replacement"
8
8
  gem.summary = "A better HTMLSelectElement replacement, for Rails"
9
- gem.homepage = "http://www.benjaminbergstein.com"
9
+ gem.homepage = "http://www.benjaminberstein.com"
10
10
 
11
11
  gem.executables = gem.files.grep(%r{^bin/}).map{ |f| File.basename(f) }
12
12
  gem.test_files = gem.files.grep(%r{^(test|spec|features)/})
13
13
  gem.name = "better_select"
14
14
  gem.require_paths = ["lib", "vendor"]
15
- gem.files = `git ls-files`.split($\) + ['vendor/javascripts/better-select.js.coffee', 'vendor/stylesheets/better-select.css.scss']
15
+ gem.files = `git ls-files`.split($\) + Dir["vendor/**/*"]
16
16
  gem.version = BetterSelect::VERSION
17
+
18
+ gem.add_dependency "railties", "~> 3.1"
17
19
  end
@@ -1,3 +1,3 @@
1
1
  module BetterSelect
2
- VERSION = "0.0.3"
2
+ VERSION = "0.0.4"
3
3
  end
data/lib/better_select.rb CHANGED
@@ -1,38 +1,5 @@
1
1
  require "better_select/version"
2
+ require "better_select/engine"
2
3
 
3
4
  module BetterSelect
4
- class FrameworkNotFound < StandardError; end
5
-
6
- def self.load!
7
- if compass? && asset_pipeline?
8
- register_compass_extension
9
- register_rails_engine
10
- elsif compass?
11
- register_rails_engine
12
- elsif asset_pipeline?
13
- register_compass_extension
14
- else
15
- raise BetterSelect::FrameworkNotFound < StandardError
16
- end
17
- end
18
-
19
- private
20
-
21
- def self.asset_pipeline?
22
- defined?(::Rails) && ::Rails.version >= '3.1.0'
23
- end
24
-
25
- def self.compass?
26
- defined?(::Compass)
27
- end
28
-
29
- def self.register_compass_extension
30
- base = File.join(File.dirname(__FILE__), '..')
31
- styles = File.join(base, 'vendor', 'assets', 'stylesheets')
32
- ::Compass::Frameworks.register('better_select', :stylesheets_directory => styles)
33
- end
34
-
35
- def self.register_rails_engine
36
- require 'better_select/engine'
37
- end
38
5
  end
data/vendor/LICENSE ADDED
@@ -0,0 +1,22 @@
1
+ Copyright (c) 2012 benastan
2
+
3
+ MIT License
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining
6
+ a copy of this software and associated documentation files (the
7
+ "Software"), to deal in the Software without restriction, including
8
+ without limitation the rights to use, copy, modify, merge, publish,
9
+ distribute, sublicense, and/or sell copies of the Software, and to
10
+ permit persons to whom the Software is furnished to do so, subject to
11
+ the following conditions:
12
+
13
+ The above copyright notice and this permission notice shall be
14
+ included in all copies or substantial portions of the Software.
15
+
16
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
20
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
21
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
22
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/vendor/Makefile ADDED
@@ -0,0 +1,8 @@
1
+ compile:
2
+ coffee -co ./build ./lib/better-select.coffee
3
+ sass lib/better-select.css.scss > ./build/better-select.css
4
+
5
+ rails:
6
+ cp lib/better-select.coffee javascripts/better-select.js.coffee
7
+ cp lib/better-select.css.scss stylesheets/better-select.css.scss
8
+
data/vendor/README.md ADDED
@@ -0,0 +1,29 @@
1
+ # BetterSelect
2
+
3
+ TODO: Write a gem description
4
+
5
+ ## Installation
6
+
7
+ Add this line to your application's Gemfile:
8
+
9
+ gem 'better_select'
10
+
11
+ And then execute:
12
+
13
+ $ bundle
14
+
15
+ Or install it yourself as:
16
+
17
+ $ gem install better_select
18
+
19
+ ## Usage
20
+
21
+ TODO: Write usage instructions here
22
+
23
+ ## Contributing
24
+
25
+ 1. Fork it
26
+ 2. Create your feature branch (`git checkout -b my-new-feature`)
27
+ 3. Commit your changes (`git commit -am 'Added some feature'`)
28
+ 4. Push to the branch (`git push origin my-new-feature`)
29
+ 5. Create new Pull Request
@@ -0,0 +1,22 @@
1
+ Copyright (c) 2012 benastan
2
+
3
+ MIT License
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining
6
+ a copy of this software and associated documentation files (the
7
+ "Software"), to deal in the Software without restriction, including
8
+ without limitation the rights to use, copy, modify, merge, publish,
9
+ distribute, sublicense, and/or sell copies of the Software, and to
10
+ permit persons to whom the Software is furnished to do so, subject to
11
+ the following conditions:
12
+
13
+ The above copyright notice and this permission notice shall be
14
+ included in all copies or substantial portions of the Software.
15
+
16
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
20
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
21
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
22
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
@@ -0,0 +1,8 @@
1
+ compile:
2
+ coffee -co ./build ./lib/better-select.coffee
3
+ sass lib/better-select.css.scss > ./build/better-select.css
4
+
5
+ rails:
6
+ cp lib/better-select.coffee javascripts/better-select.js.coffee
7
+ cp lib/better-select.css.scss stylesheets/better-select.css.scss
8
+
@@ -0,0 +1,29 @@
1
+ # BetterSelect
2
+
3
+ TODO: Write a gem description
4
+
5
+ ## Installation
6
+
7
+ Add this line to your application's Gemfile:
8
+
9
+ gem 'better_select'
10
+
11
+ And then execute:
12
+
13
+ $ bundle
14
+
15
+ Or install it yourself as:
16
+
17
+ $ gem install better_select
18
+
19
+ ## Usage
20
+
21
+ TODO: Write usage instructions here
22
+
23
+ ## Contributing
24
+
25
+ 1. Fork it
26
+ 2. Create your feature branch (`git checkout -b my-new-feature`)
27
+ 3. Commit your changes (`git commit -am 'Added some feature'`)
28
+ 4. Push to the branch (`git push origin my-new-feature`)
29
+ 5. Create new Pull Request
@@ -0,0 +1,17 @@
1
+ # -*- encoding: utf-8 -*-
2
+ require File.expand_path('../lib/better_select/version', __FILE__)
3
+
4
+ Gem::Specification.new do |gem|
5
+ gem.authors = ["benastan"]
6
+ gem.email = ["bennyjbergstein@gmail.com"]
7
+ gem.description = %q{TODO: Write a gem description}
8
+ gem.summary = %q{TODO: Write a gem summary}
9
+ gem.homepage = ""
10
+
11
+ gem.files = `git ls-files`.split($\)
12
+ gem.executables = gem.files.grep(%r{^bin/}).map{ |f| File.basename(f) }
13
+ gem.test_files = gem.files.grep(%r{^(test|spec|features)/})
14
+ gem.name = "better_select"
15
+ gem.require_paths = ["lib"]
16
+ gem.version = BetterSelect::VERSION
17
+ end
@@ -0,0 +1,16 @@
1
+ .better-select-dropdown {
2
+ position: fixed; }
3
+ .better-select-dropdown .option {
4
+ cursor: pointer; }
5
+
6
+ .select {
7
+ position: static; }
8
+ .select.dont-position-dropdown {
9
+ position: relative; }
10
+ .select.dont-position-dropdown .dropdown {
11
+ top: 100%;
12
+ left: -99999px; }
13
+ .select.open.dont-position-dropdown .dropdown {
14
+ left: 0px; }
15
+ .select .selected-option {
16
+ cursor: pointer; }
@@ -0,0 +1,330 @@
1
+ // Generated by CoffeeScript 1.3.3
2
+ (function() {
3
+ var $$, BetterSelect, addClass, build_element, getClasses, getLeft, getPos, getTop, letters, numbers, removeClass, renderOption, renderOptionGroup, setClasses;
4
+
5
+ $$ = function(html) {
6
+ var elm;
7
+ elm = document.createElement('div');
8
+ elm.innerHTML = html;
9
+ if (elm.children.length > 1) {
10
+ return elm.children;
11
+ } else {
12
+ return elm.children[0];
13
+ }
14
+ };
15
+
16
+ getPos = function(tgt, method) {
17
+ var pos;
18
+ pos = 0;
19
+ while (tgt) {
20
+ pos += tgt[method];
21
+ tgt = tgt.offsetParent;
22
+ }
23
+ return pos;
24
+ };
25
+
26
+ getTop = function(tgt) {
27
+ return getPos(tgt, 'offsetTop');
28
+ };
29
+
30
+ getLeft = function(tgt) {
31
+ return getPos(tgt, 'offsetLeft');
32
+ };
33
+
34
+ getClasses = function(tgt) {
35
+ return tgt.getAttribute('class').split(' ');
36
+ };
37
+
38
+ setClasses = function(tgt, classes) {
39
+ tgt.setAttribute('class', classes.join(' '));
40
+ return tgt;
41
+ };
42
+
43
+ addClass = function(tgt, className) {
44
+ var classes;
45
+ classes = getClasses(tgt);
46
+ if (classes.indexOf(className) === -1) {
47
+ classes.push(className);
48
+ }
49
+ return setClasses(tgt, classes);
50
+ };
51
+
52
+ removeClass = function(tgt, className) {
53
+ var classes, index;
54
+ if (!(index = (classes = getClasses(tgt)).indexOf(className === -1))) {
55
+ classes.splice(index, 1);
56
+ }
57
+ return setClasses(tgt, classes);
58
+ };
59
+
60
+ letters = 'a b c d e f g h i j k l m n o p q r s t u v w x y z'.split(' ');
61
+
62
+ numbers = '0 1 2 3 4 5 6 7 8 9 0'.split(' ');
63
+
64
+ build_element = function(what, orig, obj) {
65
+ var elm;
66
+ elm = $$(_.template(obj["" + what + "_template"])(obj["process_" + what](orig)));
67
+ elm.orig = orig;
68
+ orig.better_version = elm;
69
+ elm.better_select = obj;
70
+ return elm;
71
+ };
72
+
73
+ renderOption = function(orig_option, bs) {
74
+ var first_char, option;
75
+ option = build_element('option', orig_option, bs);
76
+ option.reset = function() {
77
+ this.orig.selected = void 0;
78
+ this.setAttribute('class', 'option');
79
+ return bs.reset(this);
80
+ };
81
+ option.select = function() {
82
+ this.orig.selected = 'selected';
83
+ this.setAttribute('class', 'option selected');
84
+ if (bs.select.getAttribute('class').indexOf('open') !== -1) {
85
+ bs.toggle();
86
+ }
87
+ return bs.set_selected(option);
88
+ };
89
+ option.addEventListener('click', function() {
90
+ return option.select();
91
+ });
92
+ option.addEventListener('mouseover', function() {
93
+ return option.better_select.set_focused(option);
94
+ });
95
+ bs.options.push(option);
96
+ first_char = option.innerHTML.substr(0, 1).toLowerCase();
97
+ if (!bs.options_by_first_char[first_char]) {
98
+ bs.options_by_first_char[first_char] = [];
99
+ }
100
+ bs.options_by_first_char[first_char].push(option);
101
+ bs.options_by_first_char[first_char].sort();
102
+ return option;
103
+ };
104
+
105
+ renderOptionGroup = function(orig_group, bs) {
106
+ var child, group, _i, _len, _ref;
107
+ group = build_element('option_group', orig_group, bs);
108
+ _ref = orig_group.children;
109
+ for (_i = 0, _len = _ref.length; _i < _len; _i++) {
110
+ child = _ref[_i];
111
+ group.appendChild(renderOption(child, bs));
112
+ }
113
+ bs.option_groups.push(group);
114
+ return group;
115
+ };
116
+
117
+ BetterSelect = (function() {
118
+
119
+ BetterSelect.prototype.defaults = {
120
+ positionDropdown: true
121
+ };
122
+
123
+ function BetterSelect(elm, options) {
124
+ var child, children, last_char, method, selected, _i, _len, _ref,
125
+ _this = this;
126
+ if (!(elm && elm.tagName && elm.tagName === 'SELECT')) {
127
+ return;
128
+ }
129
+ this.settings = _.extend({}, this.defaults, options);
130
+ this.options = [];
131
+ this.options_by_first_char = {};
132
+ this.option_groups = [];
133
+ selected = elm.selectedOptions;
134
+ this.select = build_element('select', elm, this);
135
+ _ref = this.select.children, this.selected_option = _ref[0], this.dropdown = _ref[1];
136
+ if (elm.id) {
137
+ this.select.id = "" + elm.id + "-better-select";
138
+ this.dropdown.id = "" + elm.id + "-better-select-dropdown";
139
+ }
140
+ this.default_selected = [elm.children[elm.selectedIndex]];
141
+ elm.parentNode.insertBefore(this.select, elm);
142
+ elm.parentNode.insertBefore(elm, this.select);
143
+ elm.style.display = 'none';
144
+ children = elm.children;
145
+ if (this.settings.positionDropdown) {
146
+ document.body.appendChild(this.dropdown);
147
+ this.dropdown.style.left = '-9999px';
148
+ }
149
+ for (_i = 0, _len = children.length; _i < _len; _i++) {
150
+ child = children[_i];
151
+ switch (child.tagName) {
152
+ case 'OPTION':
153
+ method = renderOption;
154
+ break;
155
+ case 'OPTGROUP':
156
+ method = renderOptionGroup;
157
+ }
158
+ this.dropdown.appendChild(method(child, this));
159
+ }
160
+ if (this.default_selected) {
161
+ this.default_selected[0].better_version.select();
162
+ }
163
+ this.selected_option.addEventListener('click', function() {
164
+ _this.toggle();
165
+ return _this.set_selected(_this.dropdown_selected_option);
166
+ });
167
+ window.addEventListener('click', function(e) {
168
+ if (!(e.target === _this.selected_option || e.target === _this.select || _this.options.indexOf(e.target) !== -1)) {
169
+ if (_this.open) {
170
+ return _this.toggle();
171
+ }
172
+ }
173
+ });
174
+ last_char = false;
175
+ this.selected_option.addEventListener('focus', function() {
176
+ document.body.style.overflow = 'hidden';
177
+ return addClass(_this.select, 'focus');
178
+ });
179
+ this.selected_option.addEventListener('blur', function() {
180
+ removeClass(_this.select, 'focus');
181
+ document.body.style.overflow = 'auto';
182
+ if (_this.open === true) {
183
+ _this.toggle();
184
+ }
185
+ return true;
186
+ });
187
+ this.selected_option.addEventListener('keydown', function(e) {
188
+ if ([38, 40].indexOf(e.keyCode) !== -1) {
189
+ return e.preventDefault();
190
+ }
191
+ });
192
+ this.selected_option.addEventListener('keyup', function(e) {
193
+ var char, keyCode, last_character, option;
194
+ if (_this.open === false) {
195
+ _this.toggle();
196
+ }
197
+ keyCode = e.keyCode;
198
+ switch (keyCode) {
199
+ case 38:
200
+ _this.set_focused(_this.options[(_this.focus_index -= 1) < 0 ? _this.focus_index = _this.options.length - 1 : _this.focus_index]);
201
+ break;
202
+ case 40:
203
+ _this.set_focused(_this.options[(_this.focus_index += 1) >= _this.options.length ? _this.focus_index = 0 : _this.focus_index]);
204
+ break;
205
+ case 13:
206
+ _this.focused_option.select();
207
+ break;
208
+ default:
209
+ if (keyCode > 47 && keyCode < 58) {
210
+ char = numbers[keyCode - 47];
211
+ } else if (keyCode > 64 && keyCode < 91) {
212
+ char = letters[keyCode - 65];
213
+ } else {
214
+ if (_this.focused_option) {
215
+ removeClass(_this.focused_option, 'focus');
216
+ _this.focused_option = false;
217
+ _this.focus_index = -1;
218
+ }
219
+ _this.toggle();
220
+ }
221
+ if (char && _this.options_by_first_char[char]) {
222
+ if (last_char !== char) {
223
+ _this.options_by_first_char[char].sort();
224
+ }
225
+ option = _this.options_by_first_char[char].shift();
226
+ _this.options_by_first_char[char].push(option);
227
+ _this.set_focused(option);
228
+ _this.focus_index = _this.options.indexOf(option);
229
+ last_character = char;
230
+ }
231
+ }
232
+ _this.dropdown.addEventListener('click', function() {
233
+ return console.log(arguments);
234
+ });
235
+ e.preventDefault();
236
+ e.stopPropagation();
237
+ e.returnValue = false;
238
+ return false;
239
+ });
240
+ }
241
+
242
+ BetterSelect.prototype.focused_option = false;
243
+
244
+ BetterSelect.prototype.focus_index = -1;
245
+
246
+ BetterSelect.prototype.set_focused = function(option) {
247
+ var class_for_selected,
248
+ _this = this;
249
+ class_for_selected = function(option) {
250
+ if (_this.selected_option && option.innerHTML === _this.selected_option.innerHTML) {
251
+ return " selected";
252
+ } else {
253
+ return "";
254
+ }
255
+ };
256
+ if (this.focused_option) {
257
+ this.focused_option.setAttribute('class', "option" + (class_for_selected(this.focused_option)));
258
+ }
259
+ this.focused_option = option;
260
+ this.focused_option.setAttribute("class", "option focus" + (class_for_selected(option)));
261
+ return this.focus_index = this.options.indexOf(this.focused_option);
262
+ };
263
+
264
+ BetterSelect.prototype.open = false;
265
+
266
+ BetterSelect.prototype.toggle = function() {
267
+ var height, top;
268
+ ((this.open = !this.open) ? addClass : removeClass)(this.select, 'open');
269
+ if (this.settings.positionDropdown) {
270
+ if (this.dropdown.offsetHeight > window.innerHeight) {
271
+ height = window.innerHeight * .50;
272
+ this.dropdown.style.height = height + 'px';
273
+ this.dropdown.style['overflow-y'] = 'auto';
274
+ if (this.dropdown_selected_option.offsetTop > height || this.adjust_height) {
275
+ this.dropdown_selected_option.scrollIntoView();
276
+ this.adjust_height = true;
277
+ }
278
+ }
279
+ top = top || (getTop(this.select) - this.dropdown_selected_option.offsetTop);
280
+ top = getTop(this.select) - (this.dropdown_selected_option.offsetTop - this.dropdown.scrollTop);
281
+ this.dropdown.style.top = (top < 0 ? 0 : top) + 'px';
282
+ return this.dropdown.style.left = this.open ? getLeft(this.select) + 'px' : '-9999px';
283
+ }
284
+ };
285
+
286
+ BetterSelect.prototype.reset = function(option) {
287
+ if (this.default_selected) {
288
+ return this.default_selected[0].better_version.select();
289
+ }
290
+ };
291
+
292
+ BetterSelect.prototype.set_selected = function(option) {
293
+ var e;
294
+ if (this.selected_option.innerHTML !== option.innerHTML) {
295
+ if (this.dropdown_selected_option) {
296
+ removeClass(this.dropdown_selected_option, 'selected');
297
+ }
298
+ addClass(this.dropdown_selected_option = option, 'selected');
299
+ this.selected_option.innerHTML = option.innerHTML;
300
+ e = document.createEvent('Event');
301
+ e.initEvent('change', true, true);
302
+ return this.select.orig.dispatchEvent(e);
303
+ }
304
+ };
305
+
306
+ BetterSelect.prototype.option_template = '<div class="option"><%= innerHTML %></div>';
307
+
308
+ BetterSelect.prototype.option_group_template = '<div class="optgroup"><div class="option-group-label"><%= label %></div></div>';
309
+
310
+ BetterSelect.prototype.select_template = '<div class="select"><a href="javascript:void(0)" class="selected-option"></a><div class="better-select-dropdown dropdown"></div></div>';
311
+
312
+ BetterSelect.prototype.process_option = function(option) {
313
+ return option;
314
+ };
315
+
316
+ BetterSelect.prototype.process_option_group = function(option_group) {
317
+ return option_group;
318
+ };
319
+
320
+ BetterSelect.prototype.process_select = function(select) {
321
+ return select;
322
+ };
323
+
324
+ return BetterSelect;
325
+
326
+ })();
327
+
328
+ window.BetterSelect = BetterSelect;
329
+
330
+ }).call(this);