foundation-rails 6.2.4.0 → 6.3.0.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (114) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +2 -2
  3. data/Rakefile +2 -0
  4. data/bower.json +2 -2
  5. data/lib/foundation/rails/version.rb +1 -1
  6. data/lib/generators/foundation/templates/_settings.scss +117 -70
  7. data/lib/generators/foundation/templates/foundation_and_overrides.scss +2 -1
  8. data/vendor/assets/_vendor/normalize-scss/sass/_normalize.scss +3 -0
  9. data/vendor/assets/_vendor/normalize-scss/sass/normalize/_import-now.scss +11 -0
  10. data/vendor/assets/_vendor/normalize-scss/sass/normalize/_normalize-mixin.scss +676 -0
  11. data/vendor/assets/_vendor/normalize-scss/sass/normalize/_variables.scss +36 -0
  12. data/vendor/assets/_vendor/normalize-scss/sass/normalize/_vertical-rhythm.scss +61 -0
  13. data/vendor/assets/_vendor/sassy-lists/stylesheets/functions/_purge.scss +38 -0
  14. data/vendor/assets/_vendor/sassy-lists/stylesheets/functions/_remove.scss +31 -0
  15. data/vendor/assets/_vendor/sassy-lists/stylesheets/functions/_replace.scss +46 -0
  16. data/vendor/assets/_vendor/sassy-lists/stylesheets/functions/_to-list.scss +27 -0
  17. data/vendor/assets/_vendor/sassy-lists/stylesheets/helpers/_missing-dependencies.scss +25 -0
  18. data/vendor/assets/_vendor/sassy-lists/stylesheets/helpers/_true.scss +13 -0
  19. data/vendor/assets/js/foundation.abide.js.es6 +28 -0
  20. data/vendor/assets/js/foundation.accordion.js.es6 +1 -1
  21. data/vendor/assets/js/foundation.accordionMenu.js.es6 +9 -1
  22. data/vendor/assets/js/foundation.core.js.es6 +4 -4
  23. data/vendor/assets/js/foundation.drilldown.js.es6 +128 -14
  24. data/vendor/assets/js/foundation.dropdown.js.es6 +48 -42
  25. data/vendor/assets/js/foundation.dropdownMenu.js.es6 +20 -18
  26. data/vendor/assets/js/foundation.equalizer.js.es6 +12 -6
  27. data/vendor/assets/js/foundation.interchange.js.es6 +3 -2
  28. data/vendor/assets/js/foundation.js.es6 +2 -1
  29. data/vendor/assets/js/foundation.magellan.js.es6 +28 -9
  30. data/vendor/assets/js/foundation.offcanvas.js.es6 +90 -123
  31. data/vendor/assets/js/foundation.orbit.js.es6 +61 -10
  32. data/vendor/assets/js/foundation.responsiveMenu.js.es6 +2 -0
  33. data/vendor/assets/js/foundation.responsiveToggle.js.es6 +52 -12
  34. data/vendor/assets/js/foundation.reveal.js.es6 +48 -48
  35. data/vendor/assets/js/foundation.slider.js.es6 +124 -42
  36. data/vendor/assets/js/foundation.sticky.js.es6 +11 -9
  37. data/vendor/assets/js/foundation.tabs.js.es6 +164 -35
  38. data/vendor/assets/js/foundation.toggler.js.es6 +3 -0
  39. data/vendor/assets/js/foundation.tooltip.js.es6 +20 -10
  40. data/vendor/assets/js/foundation.util.box.js.es6 +2 -2
  41. data/vendor/assets/js/foundation.util.keyboard.js.es6 +37 -0
  42. data/vendor/assets/js/foundation.util.mediaQuery.js.es6 +16 -0
  43. data/vendor/assets/js/foundation.util.motion.js.es6 +7 -1
  44. data/vendor/assets/js/foundation.util.nest.js.es6 +10 -5
  45. data/vendor/assets/js/foundation.util.timerAndImageLoader.js.es6 +6 -4
  46. data/vendor/assets/js/foundation.util.triggers.js.es6 +54 -36
  47. data/vendor/assets/js/foundation.zf.responsiveAccordionTabs.js.es6 +240 -0
  48. data/vendor/assets/scss/_global.scss +25 -450
  49. data/vendor/assets/scss/components/_accordion-menu.scss +8 -4
  50. data/vendor/assets/scss/components/_accordion.scss +43 -22
  51. data/vendor/assets/scss/components/_badge.scss +17 -9
  52. data/vendor/assets/scss/components/_breadcrumbs.scss +7 -5
  53. data/vendor/assets/scss/components/_button-group.scss +54 -6
  54. data/vendor/assets/scss/components/_button.scss +27 -16
  55. data/vendor/assets/scss/components/_callout.scss +3 -2
  56. data/vendor/assets/scss/components/_card.scss +121 -0
  57. data/vendor/assets/scss/components/_close-button.scss +54 -13
  58. data/vendor/assets/scss/components/_drilldown.scss +19 -5
  59. data/vendor/assets/scss/components/_dropdown-menu.scss +23 -18
  60. data/vendor/assets/scss/components/_dropdown.scss +14 -7
  61. data/vendor/assets/scss/components/_flex-video.scss +1 -63
  62. data/vendor/assets/scss/components/_float.scss +1 -1
  63. data/vendor/assets/scss/components/_label.scss +16 -8
  64. data/vendor/assets/scss/components/_media-object.scss +2 -3
  65. data/vendor/assets/scss/components/_menu.scss +68 -33
  66. data/vendor/assets/scss/components/_off-canvas.scss +231 -80
  67. data/vendor/assets/scss/components/_orbit.scss +8 -6
  68. data/vendor/assets/scss/components/_pagination.scss +42 -22
  69. data/vendor/assets/scss/components/_progress-bar.scss +1 -1
  70. data/vendor/assets/scss/components/_responsive-embed.scss +66 -0
  71. data/vendor/assets/scss/components/_reveal.scss +17 -11
  72. data/vendor/assets/scss/components/_slider.scss +6 -1
  73. data/vendor/assets/scss/components/_sticky.scss +3 -3
  74. data/vendor/assets/scss/components/_switch.scss +47 -36
  75. data/vendor/assets/scss/components/_table.scss +83 -23
  76. data/vendor/assets/scss/components/_tabs.scss +54 -23
  77. data/vendor/assets/scss/components/_thumbnail.scss +17 -4
  78. data/vendor/assets/scss/components/_title-bar.scss +5 -6
  79. data/vendor/assets/scss/components/_tooltip.scss +15 -12
  80. data/vendor/assets/scss/components/_top-bar.scss +11 -8
  81. data/vendor/assets/scss/forms/_checkbox.scss +2 -1
  82. data/vendor/assets/scss/forms/_error.scss +10 -6
  83. data/vendor/assets/scss/forms/_fieldset.scss +7 -7
  84. data/vendor/assets/scss/forms/_input-group.scss +17 -11
  85. data/vendor/assets/scss/forms/_label.scss +2 -0
  86. data/vendor/assets/scss/forms/_meter.scss +9 -10
  87. data/vendor/assets/scss/forms/_progress.scss +9 -9
  88. data/vendor/assets/scss/forms/_range.scss +20 -15
  89. data/vendor/assets/scss/forms/_select.scss +26 -8
  90. data/vendor/assets/scss/forms/_text.scss +19 -16
  91. data/vendor/assets/scss/foundation.scss +19 -3
  92. data/vendor/assets/scss/grid/_classes.scss +31 -14
  93. data/vendor/assets/scss/grid/_column.scss +10 -24
  94. data/vendor/assets/scss/grid/_flex-grid.scss +84 -76
  95. data/vendor/assets/scss/grid/_grid.scss +0 -16
  96. data/vendor/assets/scss/grid/_gutter.scss +53 -5
  97. data/vendor/assets/scss/grid/_layout.scss +3 -3
  98. data/vendor/assets/scss/grid/_position.scss +3 -3
  99. data/vendor/assets/scss/grid/_row.scss +24 -19
  100. data/vendor/assets/scss/settings/_settings.scss +117 -70
  101. data/vendor/assets/scss/typography/_base.scss +110 -44
  102. data/vendor/assets/scss/typography/_helpers.scss +1 -0
  103. data/vendor/assets/scss/typography/_print.scss +7 -3
  104. data/vendor/assets/scss/typography/_typography.scss +0 -2
  105. data/vendor/assets/scss/util/_breakpoint.scss +28 -19
  106. data/vendor/assets/scss/util/_color.scss +69 -16
  107. data/vendor/assets/scss/util/_flex.scss +20 -3
  108. data/vendor/assets/scss/util/_math.scss +72 -0
  109. data/vendor/assets/scss/util/_mixins.scss +63 -26
  110. data/vendor/assets/scss/util/_selector.scss +3 -2
  111. data/vendor/assets/scss/util/_unit.scss +61 -4
  112. data/vendor/assets/scss/util/_util.scss +1 -0
  113. data/vendor/assets/scss/util/_value.scss +33 -0
  114. metadata +17 -2
@@ -43,10 +43,20 @@ class Orbit {
43
43
  * @private
44
44
  */
45
45
  _init() {
46
+ // @TODO: consider discussion on PR #9278 about DOM pollution by changeSlide
47
+ this._reset();
48
+
46
49
  this.$wrapper = this.$element.find(`.${this.options.containerClass}`);
47
50
  this.$slides = this.$element.find(`.${this.options.slideClass}`);
51
+
48
52
  var $images = this.$element.find('img'),
49
- initActive = this.$slides.filter('.is-active');
53
+ initActive = this.$slides.filter('.is-active'),
54
+ id = this.$element[0].id || Foundation.GetYoDigits(6, 'orbit');
55
+
56
+ this.$element.attr({
57
+ 'data-resize': id,
58
+ 'id': id
59
+ });
50
60
 
51
61
  if (!initActive.length) {
52
62
  this.$slides.eq(0).addClass('is-active');
@@ -111,9 +121,7 @@ class Orbit {
111
121
  */
112
122
  _prepareForOrbit() {
113
123
  var _this = this;
114
- this._setWrapperHeight(function(max){
115
- _this._setSlideHeight(max);
116
- });
124
+ this._setWrapperHeight();
117
125
  }
118
126
 
119
127
  /**
@@ -123,13 +131,13 @@ class Orbit {
123
131
  * @param {Function} cb - a callback function to fire when complete.
124
132
  */
125
133
  _setWrapperHeight(cb) {//rewrite this to `for` loop
126
- var max = 0, temp, counter = 0;
134
+ var max = 0, temp, counter = 0, _this = this;
127
135
 
128
136
  this.$slides.each(function() {
129
137
  temp = this.getBoundingClientRect().height;
130
138
  $(this).attr('data-slide', counter);
131
139
 
132
- if (counter) {//if not the first slide, set css position and display property
140
+ if (_this.$slides.filter('.is-active')[0] !== _this.$slides.eq(counter)[0]) {//if not the active slide, set css position and display property
133
141
  $(this).css({'position': 'relative', 'display': 'none'});
134
142
  }
135
143
  max = temp > max ? temp : max;
@@ -138,7 +146,7 @@ class Orbit {
138
146
 
139
147
  if (counter === this.$slides.length) {
140
148
  this.$wrapper.css({'height': max}); //only change the wrapper height property once.
141
- cb(max); //fire callback with max height dimension.
149
+ if(cb) {cb(max);} //fire callback with max height dimension.
142
150
  }
143
151
  }
144
152
 
@@ -165,6 +173,10 @@ class Orbit {
165
173
  //**Now using custom event - thanks to:**
166
174
  //** Yohai Ararat of Toronto **
167
175
  //***************************************
176
+ //
177
+ this.$element.off('.resizeme.zf.trigger').on({
178
+ 'resizeme.zf.trigger': this._prepareForOrbit.bind(this)
179
+ })
168
180
  if (this.$slides.length > 1) {
169
181
 
170
182
  if (this.options.swipe) {
@@ -216,7 +228,7 @@ class Orbit {
216
228
  _this.changeSlide(ltr, $slide, idx);
217
229
  });
218
230
  }
219
-
231
+
220
232
  if (this.options.accessible) {
221
233
  this.$wrapper.add(this.$bullets).on('keydown.zf.orbit', function(e) {
222
234
  // handle keyboard event with keyboard util
@@ -238,6 +250,44 @@ class Orbit {
238
250
  }
239
251
  }
240
252
 
253
+ /**
254
+ * Resets Orbit so it can be reinitialized
255
+ */
256
+ _reset() {
257
+ // Don't do anything if there are no slides (first run)
258
+ if (typeof this.$slides == 'undefined') {
259
+ return;
260
+ }
261
+
262
+ if (this.$slides.length > 1) {
263
+ // Remove old events
264
+ this.$element.off('.zf.orbit').find('*').off('.zf.orbit')
265
+
266
+ // Restart timer if autoPlay is enabled
267
+ if (this.options.autoPlay) {
268
+ this.timer.restart();
269
+ }
270
+
271
+ // Reset all sliddes
272
+ this.$slides.each(function(el) {
273
+ $(el).removeClass('is-active is-active is-in')
274
+ .removeAttr('aria-live')
275
+ .hide();
276
+ });
277
+
278
+ // Show the first slide
279
+ this.$slides.first().addClass('is-active').show();
280
+
281
+ // Triggers when the slide has finished animating
282
+ this.$element.trigger('slidechange.zf.orbit', [this.$slides.first()]);
283
+
284
+ // Select first bullet if bullets are present
285
+ if (this.options.bullets) {
286
+ this._updateBullets(0);
287
+ }
288
+ }
289
+ }
290
+
241
291
  /**
242
292
  * Changes the current slide to a new one.
243
293
  * @function
@@ -247,6 +297,7 @@ class Orbit {
247
297
  * @fires Orbit#slidechange
248
298
  */
249
299
  changeSlide(isLTR, chosenSlide, idx) {
300
+ if (!this.$slides) {return; } // Don't freak out if we're in the middle of cleanup
250
301
  var $curSlide = this.$slides.filter('.is-active').eq(0);
251
302
 
252
303
  if (/mui/g.test($curSlide[0].className)) { return false; } //if the slide is currently animating, kick out of the function
@@ -273,13 +324,13 @@ class Orbit {
273
324
  * @event Orbit#beforeslidechange
274
325
  */
275
326
  this.$element.trigger('beforeslidechange.zf.orbit', [$curSlide, $newSlide]);
276
-
327
+
277
328
  if (this.options.bullets) {
278
329
  idx = idx || this.$slides.index($newSlide); //grab index to update bullets
279
330
  this._updateBullets(idx);
280
331
  }
281
332
 
282
- if (this.options.useMUI) {
333
+ if (this.options.useMUI && !this.$element.is(':hidden')) {
283
334
  Foundation.Motion.animateIn(
284
335
  $newSlide.addClass('is-active').css({'position': 'absolute', 'top': 0}),
285
336
  this.options[`animInFrom${dirIn}`],
@@ -62,6 +62,8 @@ class ResponsiveMenu {
62
62
  if (!$.isEmptyObject(this.rules)) {
63
63
  this._checkMediaQueries();
64
64
  }
65
+ // Add data-mutate since children may need it.
66
+ this.$element.attr('data-mutate', (this.$element.attr('data-mutate') || Foundation.GetYoDigits(6, 'responsive-menu')));
65
67
  }
66
68
 
67
69
  /**
@@ -39,6 +39,15 @@ class ResponsiveToggle {
39
39
 
40
40
  this.$targetMenu = $(`#${targetID}`);
41
41
  this.$toggler = this.$element.find('[data-toggle]');
42
+ this.options = $.extend({}, this.options, this.$targetMenu.data());
43
+
44
+ // If they were set, parse the animation classes
45
+ if(this.options.animate) {
46
+ let input = this.options.animate.split(' ');
47
+
48
+ this.animationIn = input[0];
49
+ this.animationOut = input[1] || null;
50
+ }
42
51
 
43
52
  this._update();
44
53
  }
@@ -52,7 +61,7 @@ class ResponsiveToggle {
52
61
  var _this = this;
53
62
 
54
63
  this._updateMqHandler = this._update.bind(this);
55
-
64
+
56
65
  $(window).on('changed.zf.mediaquery', this._updateMqHandler);
57
66
 
58
67
  this.$toggler.on('click.zf.responsiveToggle', this.toggleMenu.bind(this));
@@ -82,24 +91,48 @@ class ResponsiveToggle {
82
91
  * @function
83
92
  * @fires ResponsiveToggle#toggled
84
93
  */
85
- toggleMenu() {
94
+ toggleMenu() {
86
95
  if (!Foundation.MediaQuery.atLeast(this.options.hideFor)) {
87
- this.$targetMenu.toggle(0);
88
-
89
- /**
90
- * Fires when the element attached to the tab bar toggles.
91
- * @event ResponsiveToggle#toggled
92
- */
93
- this.$element.trigger('toggled.zf.responsiveToggle');
96
+ if(this.options.animate) {
97
+ if (this.$targetMenu.is(':hidden')) {
98
+ Foundation.Motion.animateIn(this.$targetMenu, this.animationIn, () => {
99
+ /**
100
+ * Fires when the element attached to the tab bar toggles.
101
+ * @event ResponsiveToggle#toggled
102
+ */
103
+ this.$element.trigger('toggled.zf.responsiveToggle');
104
+ this.$targetMenu.find('[data-mutate]').triggerHandler('mutateme.zf.trigger');
105
+ });
106
+ }
107
+ else {
108
+ Foundation.Motion.animateOut(this.$targetMenu, this.animationOut, () => {
109
+ /**
110
+ * Fires when the element attached to the tab bar toggles.
111
+ * @event ResponsiveToggle#toggled
112
+ */
113
+ this.$element.trigger('toggled.zf.responsiveToggle');
114
+ });
115
+ }
116
+ }
117
+ else {
118
+ this.$targetMenu.toggle(0);
119
+ this.$targetMenu.find('[data-mutate]').trigger('mutateme.zf.trigger');
120
+
121
+ /**
122
+ * Fires when the element attached to the tab bar toggles.
123
+ * @event ResponsiveToggle#toggled
124
+ */
125
+ this.$element.trigger('toggled.zf.responsiveToggle');
126
+ }
94
127
  }
95
128
  };
96
129
 
97
130
  destroy() {
98
131
  this.$element.off('.zf.responsiveToggle');
99
132
  this.$toggler.off('.zf.responsiveToggle');
100
-
133
+
101
134
  $(window).off('changed.zf.mediaquery', this._updateMqHandler);
102
-
135
+
103
136
  Foundation.unregisterPlugin(this);
104
137
  }
105
138
  }
@@ -110,7 +143,14 @@ ResponsiveToggle.defaults = {
110
143
  * @option
111
144
  * @example 'medium'
112
145
  */
113
- hideFor: 'medium'
146
+ hideFor: 'medium',
147
+
148
+ /**
149
+ * To decide if the toggle should be animated or not.
150
+ * @option
151
+ * @example false
152
+ */
153
+ animate: false
114
154
  };
115
155
 
116
156
  // Window exports
@@ -29,8 +29,6 @@ class Reveal {
29
29
  'ENTER': 'open',
30
30
  'SPACE': 'open',
31
31
  'ESCAPE': 'close',
32
- 'TAB': 'tab_forward',
33
- 'SHIFT_TAB': 'tab_backward'
34
32
  });
35
33
  }
36
34
 
@@ -69,7 +67,7 @@ class Reveal {
69
67
  if(this.$overlay) {
70
68
  this.$element.detach().appendTo(this.$overlay);
71
69
  } else {
72
- this.$element.detach().appendTo($('body'));
70
+ this.$element.detach().appendTo($(this.options.appendTo));
73
71
  this.$element.addClass('without-overlay');
74
72
  }
75
73
  this._events();
@@ -82,11 +80,10 @@ class Reveal {
82
80
  * Creates an overlay div to display behind the modal.
83
81
  * @private
84
82
  */
85
- _makeOverlay(id) {
86
- var $overlay = $('<div></div>')
87
- .addClass('reveal-overlay')
88
- .appendTo('body');
89
- return $overlay;
83
+ _makeOverlay() {
84
+ return $('<div></div>')
85
+ .addClass('reveal-overlay')
86
+ .appendTo(this.options.appendTo);
90
87
  }
91
88
 
92
89
  /**
@@ -157,10 +154,10 @@ class Reveal {
157
154
 
158
155
  if (this.options.closeOnClick && this.options.overlay) {
159
156
  this.$overlay.off('.zf.reveal').on('click.zf.reveal', function(e) {
160
- if (e.target === _this.$element[0] ||
161
- $.contains(_this.$element[0], e.target) ||
162
- !$.contains(document, e.target)) {
163
- return;
157
+ if (e.target === _this.$element[0] ||
158
+ $.contains(_this.$element[0], e.target) ||
159
+ !$.contains(document, e.target)) {
160
+ return;
164
161
  }
165
162
  _this.close();
166
163
  });
@@ -232,23 +229,40 @@ class Reveal {
232
229
  */
233
230
  this.$element.trigger('closeme.zf.reveal', this.id);
234
231
  }
232
+
233
+ var _this = this;
234
+
235
+ function addRevealOpenClasses() {
236
+ if (_this.isMobile) {
237
+ if(!_this.originalScrollPos) {
238
+ _this.originalScrollPos = window.pageYOffset;
239
+ }
240
+ $('html, body').addClass('is-reveal-open');
241
+ }
242
+ else {
243
+ $('body').addClass('is-reveal-open');
244
+ }
245
+ }
235
246
  // Motion UI method of reveal
236
247
  if (this.options.animationIn) {
237
- var _this = this;
238
- function afterAnimationFocus(){
248
+ function afterAnimation(){
239
249
  _this.$element
240
250
  .attr({
241
251
  'aria-hidden': false,
242
252
  'tabindex': -1
243
253
  })
244
254
  .focus();
255
+ addRevealOpenClasses();
256
+ Foundation.Keyboard.trapFocus(_this.$element);
245
257
  }
246
258
  if (this.options.overlay) {
247
259
  Foundation.Motion.animateIn(this.$overlay, 'fade-in');
248
260
  }
249
261
  Foundation.Motion.animateIn(this.$element, this.options.animationIn, () => {
250
- this.focusableElements = Foundation.Keyboard.findFocusable(this.$element);
251
- afterAnimationFocus();
262
+ if(this.$element) { // protect against object having been removed
263
+ this.focusableElements = Foundation.Keyboard.findFocusable(this.$element);
264
+ afterAnimation();
265
+ }
252
266
  });
253
267
  }
254
268
  // jQuery method of reveal
@@ -266,6 +280,7 @@ class Reveal {
266
280
  'tabindex': -1
267
281
  })
268
282
  .focus();
283
+ Foundation.Keyboard.trapFocus(this.$element);
269
284
 
270
285
  /**
271
286
  * Fires when the modal has successfully opened.
@@ -273,13 +288,7 @@ class Reveal {
273
288
  */
274
289
  this.$element.trigger('open.zf.reveal');
275
290
 
276
- if (this.isMobile) {
277
- this.originalScrollPos = window.pageYOffset;
278
- $('html, body').addClass('is-reveal-open');
279
- }
280
- else {
281
- $('body').addClass('is-reveal-open');
282
- }
291
+ addRevealOpenClasses();
283
292
 
284
293
  setTimeout(() => {
285
294
  this._extraHandlers();
@@ -292,12 +301,13 @@ class Reveal {
292
301
  */
293
302
  _extraHandlers() {
294
303
  var _this = this;
304
+ if(!this.$element) { return; } // If we're in the middle of cleanup, don't freak out
295
305
  this.focusableElements = Foundation.Keyboard.findFocusable(this.$element);
296
306
 
297
307
  if (!this.options.overlay && this.options.closeOnClick && !this.options.fullScreen) {
298
308
  $('body').on('click.zf.reveal', function(e) {
299
- if (e.target === _this.$element[0] ||
300
- $.contains(_this.$element[0], e.target) ||
309
+ if (e.target === _this.$element[0] ||
310
+ $.contains(_this.$element[0], e.target) ||
301
311
  !$.contains(document, e.target)) { return; }
302
312
  _this.close();
303
313
  });
@@ -321,26 +331,6 @@ class Reveal {
321
331
  var $target = $(this);
322
332
  // handle keyboard event with keyboard util
323
333
  Foundation.Keyboard.handleKey(e, 'Reveal', {
324
- tab_forward: function() {
325
- _this.focusableElements = Foundation.Keyboard.findFocusable(_this.$element);
326
- if (_this.$element.find(':focus').is(_this.focusableElements.eq(-1))) { // left modal downwards, setting focus to first element
327
- _this.focusableElements.eq(0).focus();
328
- return true;
329
- }
330
- if (_this.focusableElements.length === 0) { // no focusable elements inside the modal at all, prevent tabbing in general
331
- return true;
332
- }
333
- },
334
- tab_backward: function() {
335
- _this.focusableElements = Foundation.Keyboard.findFocusable(_this.$element);
336
- if (_this.$element.find(':focus').is(_this.focusableElements.eq(0)) || _this.$element.is(':focus')) { // left modal upwards, setting focus to last element
337
- _this.focusableElements.eq(-1).focus();
338
- return true;
339
- }
340
- if (_this.focusableElements.length === 0) { // no focusable elements inside the modal at all, prevent tabbing in general
341
- return true;
342
- }
343
- },
344
334
  open: function() {
345
335
  if (_this.$element.find(':focus').is(_this.$element.find('[data-close]'))) {
346
336
  setTimeout(function() { // set focus back to anchor if close button has been activated
@@ -422,6 +412,9 @@ class Reveal {
422
412
  $('body').removeClass('is-reveal-open');
423
413
  }
424
414
 
415
+
416
+ Foundation.Keyboard.releaseFocus(_this.$element);
417
+
425
418
  _this.$element.attr('aria-hidden', true);
426
419
 
427
420
  /**
@@ -442,7 +435,7 @@ class Reveal {
442
435
  this.isActive = false;
443
436
  if (_this.options.deepLink) {
444
437
  if (window.history.replaceState) {
445
- window.history.replaceState("", document.title, window.location.pathname);
438
+ window.history.replaceState('', document.title, window.location.href.replace(`#${this.id}`, ''));
446
439
  } else {
447
440
  window.location.hash = '';
448
441
  }
@@ -467,7 +460,7 @@ class Reveal {
467
460
  */
468
461
  destroy() {
469
462
  if (this.options.overlay) {
470
- this.$element.appendTo($('body')); // move $element outside of $overlay to prevent error unregisterPlugin()
463
+ this.$element.appendTo($(this.options.appendTo)); // move $element outside of $overlay to prevent error unregisterPlugin()
471
464
  this.$overlay.hide().off().remove();
472
465
  }
473
466
  this.$element.hide().off();
@@ -562,7 +555,14 @@ Reveal.defaults = {
562
555
  * @option
563
556
  * @example false
564
557
  */
565
- deepLink: false
558
+ deepLink: false,
559
+ /**
560
+ * Allows the modal to append to custom div.
561
+ * @option
562
+ * @example false
563
+ */
564
+ appendTo: "body"
565
+
566
566
  };
567
567
 
568
568
  // Window exports
@@ -13,9 +13,9 @@
13
13
 
14
14
  class Slider {
15
15
  /**
16
- * Creates a new instance of a drilldown menu.
16
+ * Creates a new instance of a slider control.
17
17
  * @class
18
- * @param {jQuery} element - jQuery object to make into an accordion menu.
18
+ * @param {jQuery} element - jQuery object to make into a slider control.
19
19
  * @param {Object} options - Overrides to the default plugin settings.
20
20
  */
21
21
  constructor(element, options) {
@@ -68,8 +68,8 @@ class Slider {
68
68
  this.inputs = $().add(this.$input);
69
69
  this.options.binding = true;
70
70
  }
71
+
71
72
  this._setInitAttr(0);
72
- this._events(this.$handle);
73
73
 
74
74
  if (this.handles[1]) {
75
75
  this.options.doubleSided = true;
@@ -81,18 +81,84 @@ class Slider {
81
81
  }
82
82
  isDbl = true;
83
83
 
84
- this._setHandlePos(this.$handle, this.options.initialStart, true, function() {
85
-
86
- _this._setHandlePos(_this.$handle2, _this.options.initialEnd, true);
87
- });
88
84
  // this.$handle.triggerHandler('click.zf.slider');
89
85
  this._setInitAttr(1);
90
- this._events(this.$handle2);
91
86
  }
92
87
 
93
- if (!isDbl) {
94
- this._setHandlePos(this.$handle, this.options.initialStart, true);
88
+ // Set handle positions
89
+ this.setHandles();
90
+
91
+ this._events();
92
+ }
93
+
94
+ setHandles() {
95
+ if(this.handles[1]) {
96
+ this._setHandlePos(this.$handle, this.inputs.eq(0).val(), true, () => {
97
+ this._setHandlePos(this.$handle2, this.inputs.eq(1).val(), true);
98
+ });
99
+ } else {
100
+ this._setHandlePos(this.$handle, this.inputs.eq(0).val(), true);
101
+ }
102
+ }
103
+
104
+ _reflow() {
105
+ this.setHandles();
106
+ }
107
+ /**
108
+ * @function
109
+ * @private
110
+ * @param {Number} value - floating point (the value) to be transformed using to a relative position on the slider (the inverse of _value)
111
+ */
112
+ _pctOfBar(value) {
113
+ var pctOfBar = percent(value - this.options.start, this.options.end - this.options.start)
114
+
115
+ switch(this.options.positionValueFunction) {
116
+ case "pow":
117
+ pctOfBar = this._logTransform(pctOfBar);
118
+ break;
119
+ case "log":
120
+ pctOfBar = this._powTransform(pctOfBar);
121
+ break;
122
+ }
123
+
124
+ return pctOfBar.toFixed(2)
125
+ }
126
+
127
+ /**
128
+ * @function
129
+ * @private
130
+ * @param {Number} pctOfBar - floating point, the relative position of the slider (typically between 0-1) to be transformed to a value
131
+ */
132
+ _value(pctOfBar) {
133
+ switch(this.options.positionValueFunction) {
134
+ case "pow":
135
+ pctOfBar = this._powTransform(pctOfBar);
136
+ break;
137
+ case "log":
138
+ pctOfBar = this._logTransform(pctOfBar);
139
+ break;
95
140
  }
141
+ var value = (this.options.end - this.options.start) * pctOfBar + this.options.start;
142
+
143
+ return value
144
+ }
145
+
146
+ /**
147
+ * @function
148
+ * @private
149
+ * @param {Number} value - floating point (typically between 0-1) to be transformed using the log function
150
+ */
151
+ _logTransform(value) {
152
+ return baseLog(this.options.nonLinearBase, ((value*(this.options.nonLinearBase-1))+1))
153
+ }
154
+
155
+ /**
156
+ * @function
157
+ * @private
158
+ * @param {Number} value - floating point (typically between 0-1) to be transformed using the power function
159
+ */
160
+ _powTransform(value) {
161
+ return (Math.pow(this.options.nonLinearBase, value) - 1) / (this.options.nonLinearBase - 1)
96
162
  }
97
163
 
98
164
  /**
@@ -142,7 +208,7 @@ class Slider {
142
208
  handleDim = $hndl[0].getBoundingClientRect()[hOrW],
143
209
  elemDim = this.$element[0].getBoundingClientRect()[hOrW],
144
210
  //percentage of bar min/max value based on click or drag point
145
- pctOfBar = percent(location - this.options.start, this.options.end - this.options.start).toFixed(2),
211
+ pctOfBar = this._pctOfBar(location),
146
212
  //number of actual pixels to shift the handle, based on the percentage obtained above
147
213
  pxToMove = (elemDim - handleDim) * pctOfBar,
148
214
  //percentage of bar to shift the handle
@@ -175,7 +241,7 @@ class Slider {
175
241
  var handlePos = parseFloat(this.$handle[0].style[lOrT]);
176
242
  //calculate the new min-height/width for the fill bar. Use isNaN to prevent false positives for numbers <= 0
177
243
  //based on the percentage of movement of the handle being manipulated, less the opposing handle's left/top position, plus the percentage w/h of the handle itself
178
- dim = movement - (isNaN(handlePos) ? this.options.initialStart/((this.options.end-this.options.start)/100) : handlePos) + handlePct;
244
+ dim = movement - (isNaN(handlePos) ? (this.options.initialStart - this.options.start)/((this.options.end-this.options.start)/100) : handlePos) + handlePct;
179
245
  }
180
246
  // assign the min-height/width to our css object
181
247
  css[`min-${hOrW}`] = `${dim}%`;
@@ -193,8 +259,15 @@ class Slider {
193
259
  var moveTime = this.$element.data('dragging') ? 1000/60 : this.options.moveTime;
194
260
 
195
261
  Foundation.Move(moveTime, $hndl, function() {
196
- //adjusting the left/top property of the handle, based on the percentage calculated above
197
- $hndl.css(lOrT, `${movement}%`);
262
+ // adjusting the left/top property of the handle, based on the percentage calculated above
263
+ // if movement isNaN, that is because the slider is hidden and we cannot determine handle width,
264
+ // fall back to next best guess.
265
+ if (isNaN(movement)) {
266
+ $hndl.css(lOrT, `${pctOfBar * 100}%`);
267
+ }
268
+ else {
269
+ $hndl.css(lOrT, `${movement}%`);
270
+ }
198
271
 
199
272
  if (!_this.options.doubleSided) {
200
273
  //if single-handled, a simple method to expand the fill bar
@@ -205,6 +278,7 @@ class Slider {
205
278
  }
206
279
  });
207
280
 
281
+
208
282
  /**
209
283
  * Fires when the value has not been change for a given time.
210
284
  * @event Slider#changed
@@ -222,6 +296,7 @@ class Slider {
222
296
  * @param {Number} idx - index of the current handle/input to use.
223
297
  */
224
298
  _setInitAttr(idx) {
299
+ var initVal = (idx === 0 ? this.options.initialStart : this.options.initialEnd)
225
300
  var id = this.inputs.eq(idx).attr('id') || Foundation.GetYoDigits(6, 'slider');
226
301
  this.inputs.eq(idx).attr({
227
302
  'id': id,
@@ -229,12 +304,13 @@ class Slider {
229
304
  'min': this.options.start,
230
305
  'step': this.options.step
231
306
  });
307
+ this.inputs.eq(idx).val(initVal);
232
308
  this.handles.eq(idx).attr({
233
309
  'role': 'slider',
234
310
  'aria-controls': id,
235
311
  'aria-valuemax': this.options.end,
236
312
  'aria-valuemin': this.options.start,
237
- 'aria-valuenow': idx === 0 ? this.options.initialStart : this.options.initialEnd,
313
+ 'aria-valuenow': initVal,
238
314
  'aria-orientation': this.options.vertical ? 'vertical' : 'horizontal',
239
315
  'tabindex': 0
240
316
  });
@@ -294,7 +370,7 @@ class Slider {
294
370
  }
295
371
  var offsetPct = percent(barXY, barDim);
296
372
 
297
- value = (this.options.end - this.options.start) * offsetPct + this.options.start;
373
+ value = this._value(offsetPct);
298
374
 
299
375
  // turn everything around for RTL, yay math!
300
376
  if (Foundation.rtl() && !this.options.vertical) {value = this.options.end - value;}
@@ -349,9 +425,22 @@ class Slider {
349
425
  * Adds event listeners to the slider elements.
350
426
  * @function
351
427
  * @private
428
+ */
429
+ _events() {
430
+ this._eventsForHandle(this.$handle);
431
+ if(this.handles[1]) {
432
+ this._eventsForHandle(this.$handle2);
433
+ }
434
+ }
435
+
436
+
437
+ /**
438
+ * Adds event listeners a particular handle
439
+ * @function
440
+ * @private
352
441
  * @param {jQuery} $handle - the current handle to apply listeners to.
353
442
  */
354
- _events($handle) {
443
+ _eventsForHandle($handle) {
355
444
  var _this = this,
356
445
  curHandle,
357
446
  timer;
@@ -448,6 +537,8 @@ class Slider {
448
537
  this.inputs.off('.zf.slider');
449
538
  this.$element.off('.zf.slider');
450
539
 
540
+ clearTimeout(this.timeout);
541
+
451
542
  Foundation.unregisterPlugin(this);
452
543
  }
453
544
  }
@@ -556,7 +647,19 @@ Slider.defaults = {
556
647
  * @option
557
648
  * @example 500
558
649
  */
559
- changedDelay: 500
650
+ changedDelay: 500,
651
+ /**
652
+ * Basevalue for non-linear sliders
653
+ * @option
654
+ * @example 5
655
+ */
656
+ nonLinearBase: 5,
657
+ /**
658
+ * Basevalue for non-linear sliders, possible values are: 'linear', 'pow' & 'log'. Pow and Log use the nonLinearBase setting.
659
+ * @option
660
+ * @example 'linear'
661
+ */
662
+ positionValueFunction: 'linear',
560
663
  };
561
664
 
562
665
  function percent(frac, num) {
@@ -565,33 +668,12 @@ function percent(frac, num) {
565
668
  function absPosition($handle, dir, clickPos, param) {
566
669
  return Math.abs(($handle.position()[dir] + ($handle[param]() / 2)) - clickPos);
567
670
  }
671
+ function baseLog(base, value) {
672
+ return Math.log(value)/Math.log(base)
673
+ }
568
674
 
569
675
  // Window exports
570
676
  Foundation.plugin(Slider, 'Slider');
571
677
 
572
678
  }(jQuery);
573
679
 
574
- //*********this is in case we go to static, absolute positions instead of dynamic positioning********
575
- // this.setSteps(function() {
576
- // _this._events();
577
- // var initStart = _this.options.positions[_this.options.initialStart - 1] || null;
578
- // var initEnd = _this.options.initialEnd ? _this.options.position[_this.options.initialEnd - 1] : null;
579
- // if (initStart || initEnd) {
580
- // _this._handleEvent(initStart, initEnd);
581
- // }
582
- // });
583
-
584
- //***********the other part of absolute positions*************
585
- // Slider.prototype.setSteps = function(cb) {
586
- // var posChange = this.$element.outerWidth() / this.options.steps;
587
- // var counter = 0
588
- // while(counter < this.options.steps) {
589
- // if (counter) {
590
- // this.options.positions.push(this.options.positions[counter - 1] + posChange);
591
- // } else {
592
- // this.options.positions.push(posChange);
593
- // }
594
- // counter++;
595
- // }
596
- // cb();
597
- // };