selectivity-rails 0.0.9 → 0.1.0

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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: f193b5755b553f98fc709e5290054ec9f02d6b19
4
- data.tar.gz: e0df86c48b839a856bce58f13d4a3239416e3032
3
+ metadata.gz: f21a7721f33a3ddc9a7058bfaeceabca54710d98
4
+ data.tar.gz: 5fc4d027995d1eb62b7e1459c3af1ab8ee63e867
5
5
  SHA512:
6
- metadata.gz: 5b70b0fe542ad62b62bc52c13004bce87aecb11c7fa15f572667c49b81f2ce2479b3f7559953730b2ce3bf8a4ef365c77bda5cb0f258eeb7fefc644b4f772ec1
7
- data.tar.gz: 568502d3cb475107c5c3d2d04fb7e0656c6a27a326eb21a07f5a4b312e8e2e537bd7c83917a0d3c515ff1ffc3923ff2589b17b5ffb54f77f3d318f6526162f9a
6
+ metadata.gz: dab56b3d161184d8de361c509f12f7ab4d3073c52219a84e8b2eec9875abac2b14e4e809e06e0822afb368539b9cb0e8cbf2bf4b70e6bfb3bfc08677525c49a1
7
+ data.tar.gz: 118e473372f92de9992e9c2ac277efb57736bc33a3a89bc578a6916c6e47b355122f01834000c7f63eade59dff7f73bdf81959d645706e95c10c0bed814cee2f
data/Rakefile CHANGED
@@ -1 +1,28 @@
1
1
  require "bundler/gem_tasks"
2
+
3
+ namespace :vendor do
4
+ desc 'Update vendored selectivity'
5
+ task :update do
6
+ require 'open-uri'
7
+
8
+ root = 'https://raw.githubusercontent.com/arendjr/selectivity/master'
9
+
10
+ src_uri = File.join(root, 'dist/selectivity-full.js')
11
+
12
+ open(src_uri) do |f|
13
+ dest_file = File.expand_path('../vendor/assets/javascripts/selectivity.js', __FILE__)
14
+ puts "Writing `#{dest_file}' from `#{src_uri}'"
15
+ File.write dest_file, f.read
16
+ end
17
+
18
+ Dir['vendor/assets/stylesheets/selectivity/*.sass'].each do |file|
19
+ src_uri = File.join(root, "styles/selectivity/#{File.basename(file)}")
20
+
21
+ open(src_uri) do |f|
22
+ dest_file = File.expand_path("../#{file}", __FILE__)
23
+ puts "Writing `#{dest_file}' from `#{src_uri}'"
24
+ File.write dest_file, f.read
25
+ end
26
+ end
27
+ end
28
+ end
@@ -1,5 +1,5 @@
1
1
  module Selectivity
2
2
  module Rails
3
- VERSION = '0.0.9'
3
+ VERSION = '0.1.0'
4
4
  end
5
5
  end
@@ -8,7 +8,7 @@ module Selectivity
8
8
  fail('Selectivity input not set!') unless options.has_key?(:from)
9
9
 
10
10
  from = options.delete(:from)
11
- input = find(:div, from, options)
11
+ input = find_selectivity_input(from, options)
12
12
  items = multiselect?(input) ? args.unshift(value).uniq : [value]
13
13
 
14
14
  items.each do |item|
@@ -22,7 +22,7 @@ module Selectivity
22
22
  fail('Selectivity input not set!') unless options.has_key?(:from)
23
23
 
24
24
  from = options.delete(:from)
25
- input = find(:div, from, options)
25
+ input = find_selectivity_input(from, options)
26
26
  items = multiselect?(input) ? args.unshift(value).uniq : [value]
27
27
 
28
28
  items.each do |item|
@@ -36,6 +36,14 @@ module Selectivity
36
36
 
37
37
  private
38
38
 
39
+ def find_selectivity_input(from, options)
40
+ find(:div, from, options)
41
+ rescue Capybara::ElementNotFound
42
+ label = find('label', { text: from }.merge(options))
43
+
44
+ find(:div, "##{label[:for]}", options)
45
+ end
46
+
39
47
  def multiselect?(input)
40
48
  input.first('.selectivity-multiple-input-container').present?
41
49
  end
@@ -1,6 +1,79 @@
1
1
  !function(e){if("object"==typeof exports&&"undefined"!=typeof module)module.exports=e();else if("function"==typeof define&&define.amd)define([],e);else{var f;"undefined"!=typeof window?f=window:"undefined"!=typeof global?f=global:"undefined"!=typeof self&&(f=self),f.selectivity=e()}}(function(){var define,module,exports;return (function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require=="function"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);var f=new Error("Cannot find module '"+o+"'");throw f.code="MODULE_NOT_FOUND",f}var l=n[o]={exports:{}};t[o][0].call(l.exports,function(e){var n=t[o][1][e];return s(n?n:e)},l,l.exports,e,t,n,r)}return n[o].exports}var i=typeof require=="function"&&require;for(var o=0;o<r.length;o++)s(r[o]);return s})({1:[function(_dereq_,module,exports){
2
- _dereq_(4);_dereq_(5);_dereq_(6);_dereq_(8);_dereq_(9);_dereq_(10);_dereq_(11);_dereq_(12);_dereq_(13);_dereq_(14);_dereq_(15);_dereq_(16);_dereq_(17);_dereq_(18);module.exports=_dereq_(7);
3
- },{"10":10,"11":11,"12":12,"13":13,"14":14,"15":15,"16":16,"17":17,"18":18,"4":4,"5":5,"6":6,"7":7,"8":8,"9":9}],2:[function(_dereq_,module,exports){
2
+ _dereq_(5);_dereq_(6);_dereq_(7);_dereq_(9);_dereq_(10);_dereq_(11);_dereq_(12);_dereq_(13);_dereq_(14);_dereq_(15);_dereq_(16);_dereq_(17);_dereq_(18);_dereq_(19);module.exports=_dereq_(8);
3
+ },{"10":10,"11":11,"12":12,"13":13,"14":14,"15":15,"16":16,"17":17,"18":18,"19":19,"5":5,"6":6,"7":7,"8":8,"9":9}],2:[function(_dereq_,module,exports){
4
+ 'use strict';
5
+
6
+ var $ = window.jQuery || window.Zepto;
7
+
8
+ /**
9
+ * Event Delegator Constructor.
10
+ */
11
+ function EventDelegator() {
12
+
13
+ this._events = [];
14
+
15
+ this.delegateEvents();
16
+ }
17
+
18
+ /**
19
+ * Methods.
20
+ */
21
+ $.extend(EventDelegator.prototype, {
22
+
23
+ /**
24
+ * Attaches all listeners from the events map to the instance's element.
25
+ *
26
+ * Normally, you should not have to call this method yourself as it's called automatically in
27
+ * the constructor.
28
+ */
29
+ delegateEvents: function() {
30
+
31
+ this.undelegateEvents();
32
+
33
+ $.each(this.events, function(event, listener) {
34
+ var selector, index = event.indexOf(' ');
35
+ if (index > -1) {
36
+ selector = event.slice(index + 1);
37
+ event = event.slice(0, index);
38
+ }
39
+
40
+ if ($.type(listener) === 'string') {
41
+ listener = this[listener];
42
+ }
43
+
44
+ listener = listener.bind(this);
45
+
46
+ if (selector) {
47
+ this.$el.on(event, selector, listener);
48
+ } else {
49
+ this.$el.on(event, listener);
50
+ }
51
+
52
+ this._events.push({ event: event, selector: selector, listener: listener });
53
+ }.bind(this));
54
+ },
55
+
56
+ /**
57
+ * Detaches all listeners from the events map from the instance's element.
58
+ */
59
+ undelegateEvents: function() {
60
+
61
+ this._events.forEach(function(event) {
62
+ if (event.selector) {
63
+ this.$el.off(event.event, event.selector, event.listener);
64
+ } else {
65
+ this.$el.off(event.event, event.listener);
66
+ }
67
+ }, this);
68
+
69
+ this._events = [];
70
+ }
71
+
72
+ });
73
+
74
+ module.exports = EventDelegator;
75
+
76
+ },{"jquery":"jquery"}],3:[function(_dereq_,module,exports){
4
77
  'use strict';
5
78
 
6
79
  /**
@@ -88,7 +161,7 @@ function debounce(func, wait) {
88
161
 
89
162
  module.exports = debounce;
90
163
 
91
- },{}],3:[function(_dereq_,module,exports){
164
+ },{}],4:[function(_dereq_,module,exports){
92
165
  'use strict';
93
166
 
94
167
  /**
@@ -141,16 +214,16 @@ function escape(string) {
141
214
 
142
215
  module.exports = escape;
143
216
 
144
- },{}],4:[function(_dereq_,module,exports){
217
+ },{}],5:[function(_dereq_,module,exports){
145
218
  'use strict';
146
219
 
147
220
  var $ = window.jQuery || window.Zepto;
148
221
 
149
- var debounce = _dereq_(2);
222
+ var debounce = _dereq_(3);
150
223
 
151
- var Selectivity = _dereq_(7);
224
+ var Selectivity = _dereq_(8);
152
225
 
153
- _dereq_(12);
226
+ _dereq_(13);
154
227
 
155
228
  /**
156
229
  * Option listener that implements a convenience query function for performing AJAX requests.
@@ -216,10 +289,10 @@ Selectivity.OptionListeners.unshift(function(selectivity, options) {
216
289
  }
217
290
  });
218
291
 
219
- },{"12":12,"2":2,"7":7,"jquery":"jquery"}],5:[function(_dereq_,module,exports){
292
+ },{"13":13,"3":3,"8":8,"jquery":"jquery"}],6:[function(_dereq_,module,exports){
220
293
  'use strict';
221
294
 
222
- var Selectivity = _dereq_(7);
295
+ var Selectivity = _dereq_(8);
223
296
 
224
297
  var latestQueryNum = 0;
225
298
 
@@ -252,12 +325,12 @@ Selectivity.OptionListeners.push(function(selectivity, options) {
252
325
  }
253
326
  });
254
327
 
255
- },{"7":7}],6:[function(_dereq_,module,exports){
328
+ },{"8":8}],7:[function(_dereq_,module,exports){
256
329
  'use strict';
257
330
 
258
331
  var $ = window.jQuery || window.Zepto;
259
332
 
260
- var SelectivityDropdown = _dereq_(9);
333
+ var SelectivityDropdown = _dereq_(10);
261
334
 
262
335
  /**
263
336
  * Methods.
@@ -296,11 +369,13 @@ $.extend(SelectivityDropdown.prototype, {
296
369
 
297
370
  });
298
371
 
299
- },{"9":9,"jquery":"jquery"}],7:[function(_dereq_,module,exports){
372
+ },{"10":10,"jquery":"jquery"}],8:[function(_dereq_,module,exports){
300
373
  'use strict';
301
374
 
302
375
  var $ = window.jQuery || window.Zepto;
303
376
 
377
+ var EventDelegator = _dereq_(2);
378
+
304
379
  /**
305
380
  * Create a new Selectivity instance or invoke a method on an instance.
306
381
  *
@@ -487,19 +562,17 @@ function Selectivity(options) {
487
562
  this.data(options.data || null, { triggerChange: false });
488
563
  }
489
564
 
490
- this._events = [];
491
-
492
565
  this._$searchInputs = [];
493
566
 
494
567
  this.$el.on('selectivity-close', this._closed.bind(this));
495
568
 
496
- this.delegateEvents();
569
+ EventDelegator.call(this);
497
570
  }
498
571
 
499
572
  /**
500
573
  * Methods.
501
574
  */
502
- $.extend(Selectivity.prototype, {
575
+ $.extend(Selectivity.prototype, EventDelegator.prototype, {
503
576
 
504
577
  /**
505
578
  * Convenience shortcut for this.$el.find(selector).
@@ -552,39 +625,6 @@ $.extend(Selectivity.prototype, {
552
625
  }
553
626
  },
554
627
 
555
- /**
556
- * Attaches all listeners from the events map to the instance's element.
557
- *
558
- * Normally, you should not have to call this method yourself as it's called automatically in
559
- * the constructor.
560
- */
561
- delegateEvents: function() {
562
-
563
- this.undelegateEvents();
564
-
565
- $.each(this.events, function(event, listener) {
566
- var selector, index = event.indexOf(' ');
567
- if (index > -1) {
568
- selector = event.slice(index + 1);
569
- event = event.slice(0, index);
570
- }
571
-
572
- if ($.type(listener) === 'string') {
573
- listener = this[listener];
574
- }
575
-
576
- listener = listener.bind(this);
577
-
578
- if (selector) {
579
- this.$el.on(event, selector, listener);
580
- } else {
581
- this.$el.on(event, listener);
582
- }
583
-
584
- this._events.push({ event: event, selector: selector, listener: listener });
585
- }.bind(this));
586
- },
587
-
588
628
  /**
589
629
  * Destroys the Selectivity instance.
590
630
  */
@@ -971,25 +1011,6 @@ $.extend(Selectivity.prototype, {
971
1011
  return !event.isDefaultPrevented();
972
1012
  },
973
1013
 
974
- /**
975
- * Detaches all listeners from the events map from the instance's element.
976
- *
977
- * Normally, you should not have to call this method yourself as it's called automatically in
978
- * the destroy() method.
979
- */
980
- undelegateEvents: function() {
981
-
982
- this._events.forEach(function(event) {
983
- if (event.selector) {
984
- this.$el.off(event.event, event.selector, event.listener);
985
- } else {
986
- this.$el.off(event.event, event.listener);
987
- }
988
- }, this);
989
-
990
- this._events = [];
991
- },
992
-
993
1014
  /**
994
1015
  * Shorthand for value().
995
1016
  */
@@ -1393,7 +1414,7 @@ Selectivity.transformText = function(string) {
1393
1414
 
1394
1415
  module.exports = $.fn.selectivity = Selectivity;
1395
1416
 
1396
- },{"jquery":"jquery"}],8:[function(_dereq_,module,exports){
1417
+ },{"2":2,"jquery":"jquery"}],9:[function(_dereq_,module,exports){
1397
1418
  'use strict';
1398
1419
 
1399
1420
  var DIACRITICS = {
@@ -2238,7 +2259,7 @@ var DIACRITICS = {
2238
2259
  '\u03C2': '\u03C3'
2239
2260
  };
2240
2261
 
2241
- var Selectivity = _dereq_(7);
2262
+ var Selectivity = _dereq_(8);
2242
2263
  var previousTransform = Selectivity.transformText;
2243
2264
 
2244
2265
  /**
@@ -2257,14 +2278,16 @@ Selectivity.transformText = function(string) {
2257
2278
  return previousTransform(result);
2258
2279
  };
2259
2280
 
2260
- },{"7":7}],9:[function(_dereq_,module,exports){
2281
+ },{"8":8}],10:[function(_dereq_,module,exports){
2261
2282
  'use strict';
2262
2283
 
2263
2284
  var $ = window.jQuery || window.Zepto;
2264
2285
 
2265
- var debounce = _dereq_(2);
2286
+ var debounce = _dereq_(3);
2266
2287
 
2267
- var Selectivity = _dereq_(7);
2288
+ var EventDelegator = _dereq_(2);
2289
+
2290
+ var Selectivity = _dereq_(8);
2268
2291
 
2269
2292
  /**
2270
2293
  * selectivity Dropdown Constructor.
@@ -2324,6 +2347,8 @@ function SelectivityDropdown(options) {
2324
2347
  selectivity.$el.on('selectivity-selecting', this._closeProxy);
2325
2348
  }
2326
2349
 
2350
+ this._lastMousePosition = {};
2351
+
2327
2352
  this.addToDom();
2328
2353
  this.position();
2329
2354
  this.setupCloseHandler();
@@ -2337,7 +2362,7 @@ function SelectivityDropdown(options) {
2337
2362
  selectivity.focus();
2338
2363
  }
2339
2364
 
2340
- this._delegateEvents();
2365
+ EventDelegator.call(this);
2341
2366
 
2342
2367
  this.showLoading();
2343
2368
 
@@ -2347,7 +2372,7 @@ function SelectivityDropdown(options) {
2347
2372
  /**
2348
2373
  * Methods.
2349
2374
  */
2350
- $.extend(SelectivityDropdown.prototype, {
2375
+ $.extend(SelectivityDropdown.prototype, EventDelegator.prototype, {
2351
2376
 
2352
2377
  /**
2353
2378
  * Convenience shortcut for this.$el.find(selector).
@@ -2362,7 +2387,12 @@ $.extend(SelectivityDropdown.prototype, {
2362
2387
  */
2363
2388
  addToDom: function() {
2364
2389
 
2365
- this.$el.appendTo(this.selectivity.$el[0].ownerDocument.body);
2390
+ var $next;
2391
+ var $anchor = this.selectivity.$el;
2392
+ while (($next = $anchor.next('.selectivity-dropdown')).length) {
2393
+ $anchor = $next;
2394
+ }
2395
+ this.$el.insertAfter($anchor);
2366
2396
  },
2367
2397
 
2368
2398
  /**
@@ -2391,8 +2421,9 @@ $.extend(SelectivityDropdown.prototype, {
2391
2421
  events: {
2392
2422
  'click .selectivity-load-more': '_loadMoreClicked',
2393
2423
  'click .selectivity-result-item': '_resultClicked',
2394
- 'mouseenter .selectivity-load-more': 'highlightLoadMore',
2395
- 'mouseenter .selectivity-result-item': '_resultHovered'
2424
+ 'mouseenter .selectivity-load-more': '_loadMoreHovered',
2425
+ 'mouseenter .selectivity-result-item': '_resultHovered',
2426
+ 'mousemove': '_recordMousePosition'
2396
2427
  },
2397
2428
 
2398
2429
  /**
@@ -2610,28 +2641,6 @@ $.extend(SelectivityDropdown.prototype, {
2610
2641
  this.selectivity.$el.trigger('selectivity-open');
2611
2642
  },
2612
2643
 
2613
- /**
2614
- * @private
2615
- */
2616
- _delegateEvents: function() {
2617
-
2618
- $.each(this.events, function(event, listener) {
2619
- var index = event.indexOf(' ');
2620
- var selector = event.slice(index + 1);
2621
- event = event.slice(0, index);
2622
-
2623
- if ($.type(listener) === 'string') {
2624
- listener = this[listener];
2625
- }
2626
-
2627
- listener = listener.bind(this);
2628
-
2629
- this.$el.on(event, selector, listener);
2630
- }.bind(this));
2631
-
2632
- this.$results.on('scroll touchmove touchend', this._scrolledProxy);
2633
- },
2634
-
2635
2644
  /**
2636
2645
  * @private
2637
2646
  */
@@ -2674,6 +2683,27 @@ $.extend(SelectivityDropdown.prototype, {
2674
2683
  return false;
2675
2684
  },
2676
2685
 
2686
+ /**
2687
+ * @private
2688
+ */
2689
+ _loadMoreHovered: function(event) {
2690
+
2691
+ if (event.screenX === undefined || event.screenX !== this._lastMousePosition.x ||
2692
+ event.screenY === undefined || event.screenY !== this._lastMousePosition.y) {
2693
+ this.highlightLoadMore();
2694
+
2695
+ this._recordMousePosition(event);
2696
+ }
2697
+ },
2698
+
2699
+ /**
2700
+ * @private
2701
+ */
2702
+ _recordMousePosition: function(event) {
2703
+
2704
+ this._lastMousePosition = { x: event.screenX, y: event.screenY };
2705
+ },
2706
+
2677
2707
  /**
2678
2708
  * @private
2679
2709
  */
@@ -2689,10 +2719,15 @@ $.extend(SelectivityDropdown.prototype, {
2689
2719
  */
2690
2720
  _resultHovered: function(event) {
2691
2721
 
2692
- var id = this.selectivity._getItemId(event);
2693
- var item = Selectivity.findNestedById(this.results, id);
2694
- if (item) {
2695
- this.highlight(item);
2722
+ if (event.screenX === undefined || event.screenX !== this._lastMousePosition.x ||
2723
+ event.screenY === undefined || event.screenY !== this._lastMousePosition.y) {
2724
+ var id = this.selectivity._getItemId(event);
2725
+ var item = Selectivity.findNestedById(this.results, id);
2726
+ if (item) {
2727
+ this.highlight(item);
2728
+ }
2729
+
2730
+ this._recordMousePosition(event);
2696
2731
  }
2697
2732
  },
2698
2733
 
@@ -2782,13 +2817,13 @@ $.extend(SelectivityDropdown.prototype, {
2782
2817
 
2783
2818
  module.exports = Selectivity.Dropdown = SelectivityDropdown;
2784
2819
 
2785
- },{"2":2,"7":7,"jquery":"jquery"}],10:[function(_dereq_,module,exports){
2820
+ },{"2":2,"3":3,"8":8,"jquery":"jquery"}],11:[function(_dereq_,module,exports){
2786
2821
  'use strict';
2787
2822
 
2788
2823
  var $ = window.jQuery || window.Zepto;
2789
2824
 
2790
- var Selectivity = _dereq_(7);
2791
- var MultipleSelectivity = _dereq_(13);
2825
+ var Selectivity = _dereq_(8);
2826
+ var MultipleSelectivity = _dereq_(14);
2792
2827
 
2793
2828
  function isValidEmail(email) {
2794
2829
 
@@ -2947,10 +2982,10 @@ var callSuper = Selectivity.inherits(Emailselectivity, MultipleSelectivity, {
2947
2982
 
2948
2983
  module.exports = Selectivity.InputTypes.Email = Emailselectivity;
2949
2984
 
2950
- },{"13":13,"7":7,"jquery":"jquery"}],11:[function(_dereq_,module,exports){
2985
+ },{"14":14,"8":8,"jquery":"jquery"}],12:[function(_dereq_,module,exports){
2951
2986
  'use strict';
2952
2987
 
2953
- var Selectivity = _dereq_(7);
2988
+ var Selectivity = _dereq_(8);
2954
2989
 
2955
2990
  var KEY_BACKSPACE = 8;
2956
2991
  var KEY_DOWN_ARROW = 40;
@@ -3030,7 +3065,7 @@ function listener(selectivity, $input) {
3030
3065
  var result = Selectivity.findNestedById(results,
3031
3066
  selectivity._getItemId($results[index]));
3032
3067
  if (result) {
3033
- dropdown.highlight(result);
3068
+ dropdown.highlight(result, { delay: !!result.submenu });
3034
3069
  scrollToHighlight();
3035
3070
  }
3036
3071
  }
@@ -3080,8 +3115,13 @@ function listener(selectivity, $input) {
3080
3115
 
3081
3116
  if (closeSubmenu) {
3082
3117
  closeSubmenu.close();
3118
+ selectivity.focus();
3083
3119
  closeSubmenu = null;
3084
3120
  }
3121
+ } else if (event.keyCode === KEY_BACKSPACE) {
3122
+ if (!dropdown && selectivity.options.allowClear) {
3123
+ selectivity.clear();
3124
+ }
3085
3125
  } else if (event.keyCode === KEY_ENTER && !event.ctrlKey) {
3086
3126
  if (dropdown) {
3087
3127
  dropdown.selectHighlight();
@@ -3111,11 +3151,11 @@ function listener(selectivity, $input) {
3111
3151
 
3112
3152
  Selectivity.SearchInputListeners.push(listener);
3113
3153
 
3114
- },{"7":7}],12:[function(_dereq_,module,exports){
3154
+ },{"8":8}],13:[function(_dereq_,module,exports){
3115
3155
  'use strict';
3116
3156
 
3117
- var escape = _dereq_(3);
3118
- var Selectivity = _dereq_(7);
3157
+ var escape = _dereq_(4);
3158
+ var Selectivity = _dereq_(8);
3119
3159
 
3120
3160
  /**
3121
3161
  * Localizable elements of the Selectivity Templates.
@@ -3136,12 +3176,12 @@ Selectivity.Locale = {
3136
3176
 
3137
3177
  };
3138
3178
 
3139
- },{"3":3,"7":7}],13:[function(_dereq_,module,exports){
3179
+ },{"4":4,"8":8}],14:[function(_dereq_,module,exports){
3140
3180
  'use strict';
3141
3181
 
3142
3182
  var $ = window.jQuery || window.Zepto;
3143
3183
 
3144
- var Selectivity = _dereq_(7);
3184
+ var Selectivity = _dereq_(8);
3145
3185
 
3146
3186
  var KEY_BACKSPACE = 8;
3147
3187
  var KEY_DELETE = 46;
@@ -3167,16 +3207,21 @@ function MultipleSelectivity(options) {
3167
3207
  this._rerenderSelection();
3168
3208
 
3169
3209
  if (!options.positionDropdown) {
3210
+ // dropdowns for multiple-value inputs should open below the select box,
3211
+ // unless there is not enough space below, but there is space enough above, then it should
3212
+ // open upwards
3170
3213
  this.options.positionDropdown = function($el, $selectEl) {
3171
- var offset = $selectEl.offset(),
3172
- elHeight = $el.height(),
3214
+ var position = $selectEl.position(),
3215
+ dropdownHeight = $el.height(),
3173
3216
  selectHeight = $selectEl.height(),
3174
- bottom = $selectEl[0].getBoundingClientRect().top + selectHeight + elHeight;
3217
+ top = $selectEl[0].getBoundingClientRect().top,
3218
+ bottom = top + selectHeight + dropdownHeight,
3219
+ openUpwards = (typeof window !== 'undefined' && bottom > $(window).height() &&
3220
+ top - dropdownHeight > 0);
3175
3221
 
3176
3222
  $el.css({
3177
- left: offset.left + 'px',
3178
- top: offset.top + (typeof window !== 'undefined' &&
3179
- bottom > $(window).height() ? -elHeight : selectHeight) + 'px'
3223
+ left: position.left + 'px',
3224
+ top: position.top + (openUpwards ? -dropdownHeight : selectHeight) + 'px'
3180
3225
  }).width($selectEl.width());
3181
3226
  };
3182
3227
  }
@@ -3683,12 +3728,12 @@ var callSuper = Selectivity.inherits(MultipleSelectivity, {
3683
3728
 
3684
3729
  module.exports = Selectivity.InputTypes.Multiple = MultipleSelectivity;
3685
3730
 
3686
- },{"7":7,"jquery":"jquery"}],14:[function(_dereq_,module,exports){
3731
+ },{"8":8,"jquery":"jquery"}],15:[function(_dereq_,module,exports){
3687
3732
  'use strict';
3688
3733
 
3689
3734
  var $ = window.jQuery || window.Zepto;
3690
3735
 
3691
- var Selectivity = _dereq_(7);
3736
+ var Selectivity = _dereq_(8);
3692
3737
 
3693
3738
  /**
3694
3739
  * SingleSelectivity Constructor.
@@ -3706,21 +3751,25 @@ function SingleSelectivity(options) {
3706
3751
  this._rerenderSelection();
3707
3752
 
3708
3753
  if (!options.positionDropdown) {
3754
+ // dropdowns for single-value inputs should open below the select box,
3755
+ // unless there is not enough space below, in which case the dropdown should be moved up
3756
+ // just enough so it fits in the window, but never so much that it reaches above the top
3709
3757
  this.options.positionDropdown = function($el, $selectEl) {
3710
- var offset = $selectEl.offset(),
3711
- top = offset.top + $selectEl.height();
3758
+ var position = $selectEl.position(),
3759
+ dropdownHeight = $el.height(),
3760
+ selectHeight = $selectEl.height(),
3761
+ top = $selectEl[0].getBoundingClientRect().top,
3762
+ bottom = top + selectHeight + dropdownHeight,
3763
+ deltaUp = 0;
3712
3764
 
3713
3765
  if (typeof window !== 'undefined') {
3714
- var fixedOffset = $selectEl[0].getBoundingClientRect(),
3715
- elHeight = $el.height(),
3716
- windowHeight = $(window).height();
3717
-
3718
- if (fixedOffset.top + elHeight > windowHeight) {
3719
- top = Math.max(windowHeight - elHeight + offset.top - fixedOffset.top, 0);
3720
- }
3766
+ deltaUp = Math.min(Math.max(bottom - $(window).height(), 0), top + selectHeight);
3721
3767
  }
3722
3768
 
3723
- $el.css({ left: offset.left + 'px', top: top + 'px' }).width($selectEl.width());
3769
+ $el.css({
3770
+ left: position.left + 'px',
3771
+ top: (position.top + selectHeight - deltaUp) + 'px'
3772
+ }).width($selectEl.width());
3724
3773
  };
3725
3774
  }
3726
3775
 
@@ -3766,8 +3815,13 @@ var callSuper = Selectivity.inherits(SingleSelectivity, {
3766
3815
 
3767
3816
  callSuper(this, 'close');
3768
3817
 
3818
+ var $input = this.$('.selectivity-single-select-input');
3819
+ if (!this.$searchInput) {
3820
+ this.initSearchInput($input, { noSearch: true });
3821
+ }
3822
+
3769
3823
  if (!options || options.keepFocus !== false) {
3770
- this.$('.selectivity-single-select-input').focus();
3824
+ $input.focus();
3771
3825
  }
3772
3826
 
3773
3827
  this._closing = false;
@@ -3935,11 +3989,11 @@ var callSuper = Selectivity.inherits(SingleSelectivity, {
3935
3989
 
3936
3990
  module.exports = Selectivity.InputTypes.Single = SingleSelectivity;
3937
3991
 
3938
- },{"7":7,"jquery":"jquery"}],15:[function(_dereq_,module,exports){
3992
+ },{"8":8,"jquery":"jquery"}],16:[function(_dereq_,module,exports){
3939
3993
  'use strict';
3940
3994
 
3941
- var Selectivity = _dereq_(7);
3942
- var SelectivityDropdown = _dereq_(9);
3995
+ var Selectivity = _dereq_(8);
3996
+ var SelectivityDropdown = _dereq_(10);
3943
3997
 
3944
3998
  /**
3945
3999
  * Extended dropdown that supports submenus.
@@ -3954,6 +4008,8 @@ function SelectivitySubmenu(options) {
3954
4008
  SelectivityDropdown.call(this, options);
3955
4009
 
3956
4010
  this._closeSubmenuTimeout = 0;
4011
+
4012
+ this._openSubmenuTimeout = 0;
3957
4013
  }
3958
4014
 
3959
4015
  var callSuper = Selectivity.inherits(SelectivitySubmenu, SelectivityDropdown, {
@@ -3980,31 +4036,42 @@ var callSuper = Selectivity.inherits(SelectivitySubmenu, SelectivityDropdown, {
3980
4036
  this.parentMenu.submenu = null;
3981
4037
  this.parentMenu = null;
3982
4038
  }
4039
+
4040
+ clearTimeout(this._closeSubmenuTimeout);
4041
+ clearTimeout(this._openSubmenuTimeout);
3983
4042
  },
3984
4043
 
3985
4044
  /**
3986
4045
  * @inherit
4046
+ *
4047
+ * @param options Optional options object. May contain the following property:
4048
+ * delay - If true, indicates any submenu should not be opened until after some
4049
+ * delay.
3987
4050
  */
3988
- highlight: function(item) {
4051
+ highlight: function(item, options) {
3989
4052
 
3990
- if (this.submenu) {
3991
- if (!this.highlightedResult || this.highlightedResult.id !== item.id) {
3992
- if (this._closeSubmenuTimeout) {
3993
- clearTimeout(this._closeSubmenuTimeout);
3994
- }
4053
+ if (options && options.delay) {
4054
+ callSuper(this, 'highlight', item);
4055
+
4056
+ clearTimeout(this._openSubmenuTimeout);
4057
+ this._openSubmenuTimeout = setTimeout(this._doHighlight.bind(this, item), 300);
4058
+ } else if (this.submenu) {
4059
+ if (this.highlightedResult && this.highlightedResult.id === item.id) {
4060
+ this._doHighlight(item);
4061
+ } else {
4062
+ clearTimeout(this._closeSubmenuTimeout);
3995
4063
  this._closeSubmenuTimeout = setTimeout(
3996
4064
  this._closeSubmenuAndHighlight.bind(this, item), 100
3997
4065
  );
3998
- return;
3999
4066
  }
4000
4067
  } else {
4001
4068
  if (this.parentMenu && this.parentMenu._closeSubmenuTimeout) {
4002
4069
  clearTimeout(this.parentMenu._closeSubmenuTimeout);
4003
4070
  this.parentMenu._closeSubmenuTimeout = 0;
4004
4071
  }
4005
- }
4006
4072
 
4007
- this._doHighlight(item);
4073
+ this._doHighlight(item);
4074
+ }
4008
4075
  },
4009
4076
 
4010
4077
  /**
@@ -4100,11 +4167,11 @@ var callSuper = Selectivity.inherits(SelectivitySubmenu, SelectivityDropdown, {
4100
4167
  this.submenu = new Dropdown({
4101
4168
  parentMenu: this,
4102
4169
  position: item.submenu.positionDropdown || function($el) {
4103
- var offset = $item.offset();
4170
+ var dropdownPosition = $dropdownEl.position();
4104
4171
  var width = $dropdownEl.width();
4105
4172
  $el.css({
4106
- left: offset.left + width + 'px',
4107
- top: offset.top + 'px'
4173
+ left: dropdownPosition.left + width + 'px',
4174
+ top: $item.position().top + dropdownPosition.top + 'px'
4108
4175
  }).width(width);
4109
4176
  },
4110
4177
  restoreOptions: {
@@ -4150,14 +4217,14 @@ Selectivity.findNestedById = function(array, id) {
4150
4217
 
4151
4218
  module.exports = SelectivitySubmenu;
4152
4219
 
4153
- },{"7":7,"9":9}],16:[function(_dereq_,module,exports){
4220
+ },{"10":10,"8":8}],17:[function(_dereq_,module,exports){
4154
4221
  'use strict';
4155
4222
 
4156
- var escape = _dereq_(3);
4223
+ var escape = _dereq_(4);
4157
4224
 
4158
- var Selectivity = _dereq_(7);
4225
+ var Selectivity = _dereq_(8);
4159
4226
 
4160
- _dereq_(12);
4227
+ _dereq_(13);
4161
4228
 
4162
4229
  /**
4163
4230
  * Default set of templates to use with Selectivity.js.
@@ -4454,12 +4521,12 @@ Selectivity.Templates = {
4454
4521
 
4455
4522
  };
4456
4523
 
4457
- },{"12":12,"3":3,"7":7}],17:[function(_dereq_,module,exports){
4524
+ },{"13":13,"4":4,"8":8}],18:[function(_dereq_,module,exports){
4458
4525
  'use strict';
4459
4526
 
4460
4527
  var $ = window.jQuery || window.Zepto;
4461
4528
 
4462
- var Selectivity = _dereq_(7);
4529
+ var Selectivity = _dereq_(8);
4463
4530
 
4464
4531
  function defaultTokenizer(input, selection, createToken, options) {
4465
4532
 
@@ -4521,12 +4588,12 @@ Selectivity.OptionListeners.push(function(selectivity, options) {
4521
4588
  }
4522
4589
  });
4523
4590
 
4524
- },{"7":7,"jquery":"jquery"}],18:[function(_dereq_,module,exports){
4591
+ },{"8":8,"jquery":"jquery"}],19:[function(_dereq_,module,exports){
4525
4592
  'use strict';
4526
4593
 
4527
4594
  var $ = window.jQuery || window.Zepto;
4528
4595
 
4529
- var Selectivity = _dereq_(7);
4596
+ var Selectivity = _dereq_(8);
4530
4597
 
4531
4598
  function replaceSelectElement($el, options) {
4532
4599
 
@@ -4632,5 +4699,5 @@ Selectivity.OptionListeners.push(function(selectivity, options) {
4632
4699
  }
4633
4700
  });
4634
4701
 
4635
- },{"7":7,"jquery":"jquery"}]},{},[1])(1)
4702
+ },{"8":8,"jquery":"jquery"}]},{},[1])(1)
4636
4703
  });
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: selectivity-rails
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.9
4
+ version: 0.1.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Konrad Jurkowski
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2015-05-01 00:00:00.000000000 Z
11
+ date: 2015-05-06 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bundler