foundation-rails 6.3.1.0 → 6.4.1.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (139) hide show
  1. checksums.yaml +4 -4
  2. data/bower.json +3 -3
  3. data/lib/foundation/rails/version.rb +1 -1
  4. data/lib/generators/foundation/install_generator.rb +1 -1
  5. data/lib/generators/foundation/templates/_settings.scss +291 -48
  6. data/vendor/assets/js/entries/foundation-plugins.js +25 -0
  7. data/vendor/assets/js/entries/foundation.js +101 -0
  8. data/vendor/assets/js/entries/plugins/foundation.abide.js +4 -0
  9. data/vendor/assets/js/entries/plugins/foundation.accordion.js +4 -0
  10. data/vendor/assets/js/entries/plugins/foundation.accordionMenu.js +5 -0
  11. data/vendor/assets/js/entries/plugins/foundation.core.js +21 -0
  12. data/vendor/assets/js/entries/plugins/foundation.drilldown.js +4 -0
  13. data/vendor/assets/js/entries/plugins/foundation.dropdown.js +5 -0
  14. data/vendor/assets/js/entries/plugins/foundation.dropdownMenu.js +4 -0
  15. data/vendor/assets/js/entries/plugins/foundation.equalizer.js +4 -0
  16. data/vendor/assets/js/entries/plugins/foundation.interchange.js +4 -0
  17. data/vendor/assets/js/entries/plugins/foundation.magellan.js +4 -0
  18. data/vendor/assets/js/entries/plugins/foundation.offcanvas.js +4 -0
  19. data/vendor/assets/js/entries/plugins/foundation.orbit.js +5 -0
  20. data/vendor/assets/js/entries/plugins/foundation.responsiveAccordionTabs.js +5 -0
  21. data/vendor/assets/js/entries/plugins/foundation.responsiveMenu.js +5 -0
  22. data/vendor/assets/js/entries/plugins/foundation.responsiveToggle.js +5 -0
  23. data/vendor/assets/js/entries/plugins/foundation.reveal.js +4 -0
  24. data/vendor/assets/js/entries/plugins/foundation.slider.js +5 -0
  25. data/vendor/assets/js/entries/plugins/foundation.smoothScroll.js +5 -0
  26. data/vendor/assets/js/entries/plugins/foundation.sticky.js +5 -0
  27. data/vendor/assets/js/entries/plugins/foundation.tabs.js +5 -0
  28. data/vendor/assets/js/entries/plugins/foundation.toggler.js +5 -0
  29. data/vendor/assets/js/entries/plugins/foundation.tooltip.js +4 -0
  30. data/vendor/assets/js/entries/plugins/foundation.util.box.js +4 -0
  31. data/vendor/assets/js/entries/plugins/foundation.util.imageLoader.js +5 -0
  32. data/vendor/assets/js/entries/plugins/foundation.util.keyboard.js +4 -0
  33. data/vendor/assets/js/entries/plugins/foundation.util.mediaQuery.js +4 -0
  34. data/vendor/assets/js/entries/plugins/foundation.util.motion.js +5 -0
  35. data/vendor/assets/js/entries/plugins/foundation.util.nest.js +5 -0
  36. data/vendor/assets/js/entries/plugins/foundation.util.timer.js +5 -0
  37. data/vendor/assets/js/entries/plugins/foundation.util.touch.js +7 -0
  38. data/vendor/assets/js/entries/plugins/foundation.util.triggers.js +5 -0
  39. data/vendor/assets/js/foundation.abide.js.es6 +18 -15
  40. data/vendor/assets/js/foundation.accordion.js.es6 +37 -23
  41. data/vendor/assets/js/foundation.accordionMenu.js.es6 +96 -51
  42. data/vendor/assets/js/foundation.core.js.es6 +46 -87
  43. data/vendor/assets/js/foundation.drilldown.js.es6 +47 -29
  44. data/vendor/assets/js/foundation.dropdown.js.es6 +84 -122
  45. data/vendor/assets/js/foundation.dropdownMenu.js.es6 +44 -28
  46. data/vendor/assets/js/foundation.equalizer.js.es6 +18 -17
  47. data/vendor/assets/js/foundation.interchange.js.es6 +26 -19
  48. data/vendor/assets/js/foundation.js.es6 +8 -3
  49. data/vendor/assets/js/foundation.magellan.js.es6 +36 -30
  50. data/vendor/assets/js/foundation.offcanvas.js.es6 +148 -36
  51. data/vendor/assets/js/foundation.orbit.js.es6 +26 -18
  52. data/vendor/assets/js/foundation.plugin.js.es6 +54 -0
  53. data/vendor/assets/js/foundation.positionable.js.es6 +206 -0
  54. data/vendor/assets/js/{foundation.zf.responsiveAccordionTabs.js.es6 → foundation.responsiveAccordionTabs.js.es6} +33 -30
  55. data/vendor/assets/js/foundation.responsiveMenu.js.es6 +37 -29
  56. data/vendor/assets/js/foundation.responsiveToggle.js.es6 +17 -16
  57. data/vendor/assets/js/foundation.reveal.js.es6 +61 -79
  58. data/vendor/assets/js/foundation.slider.js.es6 +33 -18
  59. data/vendor/assets/js/foundation.smoothScroll.js.es6 +135 -0
  60. data/vendor/assets/js/foundation.sticky.js.es6 +25 -17
  61. data/vendor/assets/js/foundation.tabs.js.es6 +35 -27
  62. data/vendor/assets/js/foundation.toggler.js.es6 +15 -13
  63. data/vendor/assets/js/foundation.tooltip.js.es6 +100 -108
  64. data/vendor/assets/js/foundation.util.box.js.es6 +114 -78
  65. data/vendor/assets/js/foundation.util.core.js.es6 +52 -0
  66. data/vendor/assets/js/foundation.util.imageLoader.js.es6 +45 -0
  67. data/vendor/assets/js/foundation.util.keyboard.js.es6 +41 -31
  68. data/vendor/assets/js/foundation.util.mediaQuery.js.es6 +59 -55
  69. data/vendor/assets/js/foundation.util.motion.js.es6 +4 -5
  70. data/vendor/assets/js/foundation.util.nest.js.es6 +9 -23
  71. data/vendor/assets/js/{foundation.util.timerAndImageLoader.js.es6 → foundation.util.timer.js.es6} +2 -42
  72. data/vendor/assets/js/foundation.util.touch.js.es6 +91 -294
  73. data/vendor/assets/js/foundation.util.triggers.js.es6 +199 -141
  74. data/vendor/assets/scss/_global.scss +29 -1
  75. data/vendor/assets/scss/components/_accordion-menu.scss +148 -13
  76. data/vendor/assets/scss/components/_accordion.scss +5 -0
  77. data/vendor/assets/scss/components/_breadcrumbs.scss +26 -9
  78. data/vendor/assets/scss/components/_button-group.scss +4 -4
  79. data/vendor/assets/scss/components/_button.scss +59 -12
  80. data/vendor/assets/scss/components/_card.scss +10 -2
  81. data/vendor/assets/scss/components/_drilldown.scss +90 -41
  82. data/vendor/assets/scss/components/_dropdown-menu.scss +52 -6
  83. data/vendor/assets/scss/components/_dropdown.scss +8 -1
  84. data/vendor/assets/scss/components/_flex.scss +85 -2
  85. data/vendor/assets/scss/components/_menu.scss +267 -162
  86. data/vendor/assets/scss/components/_off-canvas.scss +159 -45
  87. data/vendor/assets/scss/components/_pagination.scss +1 -1
  88. data/vendor/assets/scss/components/_reveal.scss +13 -11
  89. data/vendor/assets/scss/components/_slider.scss +0 -1
  90. data/vendor/assets/scss/components/_sticky.scss +1 -0
  91. data/vendor/assets/scss/components/_table.scss +7 -6
  92. data/vendor/assets/scss/components/_tabs.scss +1 -1
  93. data/vendor/assets/scss/components/_title-bar.scss +1 -1
  94. data/vendor/assets/scss/components/_tooltip.scss +74 -21
  95. data/vendor/assets/scss/components/_top-bar.scss +2 -0
  96. data/vendor/assets/scss/forms/_fieldset.scss +0 -1
  97. data/vendor/assets/scss/forms/_meter.scss +7 -1
  98. data/vendor/assets/scss/forms/_select.scss +4 -3
  99. data/vendor/assets/scss/forms/_text.scss +11 -2
  100. data/vendor/assets/scss/foundation.scss +17 -3
  101. data/vendor/assets/scss/grid/_flex-grid.scss +3 -52
  102. data/vendor/assets/scss/prototype/_arrow.scss +36 -0
  103. data/vendor/assets/scss/prototype/_border-box.scss +35 -0
  104. data/vendor/assets/scss/prototype/_border-none.scss +35 -0
  105. data/vendor/assets/scss/prototype/_bordered.scss +54 -0
  106. data/vendor/assets/scss/prototype/_box.scss +23 -0
  107. data/vendor/assets/scss/prototype/_display.scss +50 -0
  108. data/vendor/assets/scss/prototype/_font-styling.scss +95 -0
  109. data/vendor/assets/scss/prototype/_list-style-type.scss +95 -0
  110. data/vendor/assets/scss/prototype/_overflow.scss +72 -0
  111. data/vendor/assets/scss/prototype/_position.scss +114 -0
  112. data/vendor/assets/scss/prototype/_prototype.scss +91 -0
  113. data/vendor/assets/scss/prototype/_relation.scss +157 -0
  114. data/vendor/assets/scss/prototype/_rotate.scss +31 -0
  115. data/vendor/assets/scss/prototype/_rounded.scss +54 -0
  116. data/vendor/assets/scss/prototype/_separator.scss +96 -0
  117. data/vendor/assets/scss/prototype/_shadow.scss +43 -0
  118. data/vendor/assets/scss/prototype/_sizing.scss +73 -0
  119. data/vendor/assets/scss/prototype/_spacing.scss +204 -0
  120. data/vendor/assets/scss/prototype/_text-decoration.scss +48 -0
  121. data/vendor/assets/scss/prototype/_text-transformation.scss +48 -0
  122. data/vendor/assets/scss/prototype/_text-utilities.scss +88 -0
  123. data/vendor/assets/scss/prototype/_typescale.scss +20 -0
  124. data/vendor/assets/scss/settings/_settings.scss +291 -48
  125. data/vendor/assets/scss/typography/_base.scss +2 -2
  126. data/vendor/assets/scss/typography/_helpers.scss +6 -4
  127. data/vendor/assets/scss/util/_breakpoint.scss +60 -1
  128. data/vendor/assets/scss/util/_color.scss +8 -5
  129. data/vendor/assets/scss/util/_mixins.scss +45 -5
  130. data/vendor/assets/scss/xy-grid/_cell.scss +179 -0
  131. data/vendor/assets/scss/xy-grid/_classes.scss +455 -0
  132. data/vendor/assets/scss/xy-grid/_collapse.scss +54 -0
  133. data/vendor/assets/scss/xy-grid/_frame.scss +54 -0
  134. data/vendor/assets/scss/xy-grid/_grid.scss +56 -0
  135. data/vendor/assets/scss/xy-grid/_gutters.scss +45 -0
  136. data/vendor/assets/scss/xy-grid/_layout.scss +33 -0
  137. data/vendor/assets/scss/xy-grid/_position.scss +28 -0
  138. data/vendor/assets/scss/xy-grid/_xy-grid.scss +52 -0
  139. metadata +73 -4
@@ -1,29 +1,33 @@
1
1
  'use strict';
2
2
 
3
- !function($) {
3
+ import $ from 'jquery';
4
+ import { MediaQuery } from './foundation.util.mediaQuery';
5
+ import { onImagesLoaded } from './foundation.util.imageLoader';
6
+ import { GetYoDigits } from './foundation.util.core';
7
+ import { Plugin } from './foundation.plugin';
4
8
 
5
9
  /**
6
10
  * Equalizer module.
7
11
  * @module foundation.equalizer
8
12
  * @requires foundation.util.mediaQuery
9
- * @requires foundation.util.timerAndImageLoader if equalizer contains images
13
+ * @requires foundation.util.imageLoader if equalizer contains images
10
14
  */
11
15
 
12
- class Equalizer {
16
+ class Equalizer extends Plugin {
13
17
  /**
14
18
  * Creates a new instance of Equalizer.
15
19
  * @class
20
+ * @name Equalizer
16
21
  * @fires Equalizer#init
17
22
  * @param {Object} element - jQuery object to add the trigger to.
18
23
  * @param {Object} options - Overrides to the default plugin settings.
19
24
  */
20
- constructor(element, options){
25
+ _setup(element, options){
21
26
  this.$element = element;
22
27
  this.options = $.extend({}, Equalizer.defaults, this.$element.data(), options);
28
+ this.className = 'Equalizer'; // ie9 back compat
23
29
 
24
30
  this._init();
25
-
26
- Foundation.registerPlugin(this, 'Equalizer');
27
31
  }
28
32
 
29
33
  /**
@@ -34,9 +38,11 @@ class Equalizer {
34
38
  var eqId = this.$element.attr('data-equalizer') || '';
35
39
  var $watched = this.$element.find(`[data-equalizer-watch="${eqId}"]`);
36
40
 
41
+ MediaQuery._init();
42
+
37
43
  this.$watched = $watched.length ? $watched : this.$element.find('[data-equalizer-watch]');
38
- this.$element.attr('data-resize', (eqId || Foundation.GetYoDigits(6, 'eq')));
39
- this.$element.attr('data-mutate', (eqId || Foundation.GetYoDigits(6, 'eq')));
44
+ this.$element.attr('data-resize', (eqId || GetYoDigits(6, 'eq')));
45
+ this.$element.attr('data-mutate', (eqId || GetYoDigits(6, 'eq')));
40
46
 
41
47
  this.hasNested = this.$element.find('[data-equalizer]').length > 0;
42
48
  this.isNested = this.$element.parentsUntil(document.body, '[data-equalizer]').length > 0;
@@ -56,7 +62,7 @@ class Equalizer {
56
62
  }
57
63
  if((tooSmall !== undefined && tooSmall === false) || tooSmall === undefined){
58
64
  if(imgs.length){
59
- Foundation.onImagesLoaded(imgs, this._reflow.bind(this));
65
+ onImagesLoaded(imgs, this._reflow.bind(this));
60
66
  }else{
61
67
  this._reflow();
62
68
  }
@@ -113,7 +119,7 @@ class Equalizer {
113
119
  * @private
114
120
  */
115
121
  _checkMQ() {
116
- var tooSmall = !Foundation.MediaQuery.is(this.options.equalizeOn);
122
+ var tooSmall = !MediaQuery.is(this.options.equalizeOn);
117
123
  if(tooSmall){
118
124
  if(this.isOn){
119
125
  this._pauseEvents();
@@ -276,11 +282,9 @@ class Equalizer {
276
282
  * Destroys an instance of Equalizer.
277
283
  * @function
278
284
  */
279
- destroy() {
285
+ _destroy() {
280
286
  this._pauseEvents();
281
287
  this.$watched.css('height', 'auto');
282
-
283
- Foundation.unregisterPlugin(this);
284
288
  }
285
289
  }
286
290
 
@@ -311,7 +315,4 @@ Equalizer.defaults = {
311
315
  equalizeOn: ''
312
316
  };
313
317
 
314
- // Window exports
315
- Foundation.plugin(Equalizer, 'Equalizer');
316
-
317
- }(jQuery);
318
+ export {Equalizer};
@@ -1,32 +1,35 @@
1
1
  'use strict';
2
2
 
3
- !function($) {
3
+ import $ from 'jquery';
4
+ import { MediaQuery } from './foundation.util.mediaQuery';
5
+ import { Plugin } from './foundation.plugin';
6
+ import { GetYoDigits } from './foundation.util.core';
7
+
4
8
 
5
9
  /**
6
10
  * Interchange module.
7
11
  * @module foundation.interchange
8
12
  * @requires foundation.util.mediaQuery
9
- * @requires foundation.util.timerAndImageLoader
10
13
  */
11
14
 
12
- class Interchange {
15
+ class Interchange extends Plugin {
13
16
  /**
14
17
  * Creates a new instance of Interchange.
15
18
  * @class
19
+ * @name Interchange
16
20
  * @fires Interchange#init
17
21
  * @param {Object} element - jQuery object to add the trigger to.
18
22
  * @param {Object} options - Overrides to the default plugin settings.
19
23
  */
20
- constructor(element, options) {
24
+ _setup(element, options) {
21
25
  this.$element = element;
22
26
  this.options = $.extend({}, Interchange.defaults, options);
23
27
  this.rules = [];
24
28
  this.currentPath = '';
29
+ this.className = 'Interchange'; // ie9 back compat
25
30
 
26
31
  this._init();
27
32
  this._events();
28
-
29
- Foundation.registerPlugin(this, 'Interchange');
30
33
  }
31
34
 
32
35
  /**
@@ -35,6 +38,14 @@ class Interchange {
35
38
  * @private
36
39
  */
37
40
  _init() {
41
+ MediaQuery._init();
42
+
43
+ var id = this.$element[0].id || GetYoDigits(6, 'interchange');
44
+ this.$element.attr({
45
+ 'data-resize': id,
46
+ 'id': id
47
+ });
48
+
38
49
  this._addBreakpoints();
39
50
  this._generateRules();
40
51
  this._reflow();
@@ -46,9 +57,7 @@ class Interchange {
46
57
  * @private
47
58
  */
48
59
  _events() {
49
- $(window).on('resize.zf.interchange', Foundation.util.throttle(() => {
50
- this._reflow();
51
- }, 50));
60
+ this.$element.off('resizeme.zf.trigger').on('resizeme.zf.trigger', () => this._reflow());
52
61
  }
53
62
 
54
63
  /**
@@ -80,9 +89,9 @@ class Interchange {
80
89
  * @private
81
90
  */
82
91
  _addBreakpoints() {
83
- for (var i in Foundation.MediaQuery.queries) {
84
- if (Foundation.MediaQuery.queries.hasOwnProperty(i)) {
85
- var query = Foundation.MediaQuery.queries[i];
92
+ for (var i in MediaQuery.queries) {
93
+ if (MediaQuery.queries.hasOwnProperty(i)) {
94
+ var query = MediaQuery.queries[i];
86
95
  Interchange.SPECIAL_QUERIES[query.name] = query.value;
87
96
  }
88
97
  }
@@ -105,7 +114,7 @@ class Interchange {
105
114
  else {
106
115
  rules = this.$element.data('interchange');
107
116
  }
108
-
117
+
109
118
  rules = typeof rules === 'string' ? rules.match(/\[.*?\]/g) : rules;
110
119
 
111
120
  for (var i in rules) {
@@ -149,6 +158,7 @@ class Interchange {
149
158
  }
150
159
  // Replacing background images
151
160
  else if (path.match(/\.(gif|jpg|jpeg|png|svg|tiff)([?#].*)?/i)) {
161
+ path = path.replace(/\(/g, '%28').replace(/\)/g, '%29');
152
162
  this.$element.css({ 'background-image': 'url('+path+')' })
153
163
  .trigger(trigger);
154
164
  }
@@ -173,8 +183,8 @@ class Interchange {
173
183
  * Destroys an instance of interchange.
174
184
  * @function
175
185
  */
176
- destroy() {
177
- //TODO this.
186
+ _destroy() {
187
+ this.$element.off('resizeme.zf.trigger')
178
188
  }
179
189
  }
180
190
 
@@ -197,7 +207,4 @@ Interchange.SPECIAL_QUERIES = {
197
207
  'retina': 'only screen and (-webkit-min-device-pixel-ratio: 2), only screen and (min--moz-device-pixel-ratio: 2), only screen and (-o-min-device-pixel-ratio: 2/1), only screen and (min-device-pixel-ratio: 2), only screen and (min-resolution: 192dpi), only screen and (min-resolution: 2dppx)'
198
208
  };
199
209
 
200
- // Window exports
201
- Foundation.plugin(Interchange, 'Interchange');
202
-
203
- }(jQuery);
210
+ export {Interchange};
@@ -10,20 +10,25 @@
10
10
  //= require foundation.magellan.js
11
11
  //= require foundation.offcanvas.js
12
12
  //= require foundation.orbit.js
13
+ //= require foundation.plugin.js
14
+ //= require foundation.positionable.js
15
+ //= require foundation.responsiveAccordionTabs.js
13
16
  //= require foundation.responsiveMenu.js
14
17
  //= require foundation.responsiveToggle.js
15
18
  //= require foundation.reveal.js
16
19
  //= require foundation.slider.js
20
+ //= require foundation.smoothScroll.js
17
21
  //= require foundation.sticky.js
18
22
  //= require foundation.tabs.js
19
23
  //= require foundation.toggler.js
20
24
  //= require foundation.tooltip.js
21
25
  //= require foundation.util.box.js
26
+ //= require foundation.util.core.js
27
+ //= require foundation.util.imageLoader.js
22
28
  //= require foundation.util.keyboard.js
23
29
  //= require foundation.util.mediaQuery.js
24
30
  //= require foundation.util.motion.js
25
31
  //= require foundation.util.nest.js
26
- //= require foundation.util.timerAndImageLoader.js
32
+ //= require foundation.util.timer.js
27
33
  //= require foundation.util.touch.js
28
- //= require foundation.util.triggers.js
29
- //= require foundation.zf.responsiveAccordionTabs.js
34
+ //= require foundation.util.triggers.js
@@ -1,28 +1,33 @@
1
1
  'use strict';
2
2
 
3
- !function($) {
3
+
4
+ import $ from 'jquery';
5
+ import { GetYoDigits } from './foundation.util.core';
6
+ import { Plugin } from './foundation.plugin';
7
+ import { SmoothScroll } from './foundation.smoothScroll';
4
8
 
5
9
  /**
6
10
  * Magellan module.
7
11
  * @module foundation.magellan
12
+ * @requires foundation.smoothScroll
8
13
  */
9
14
 
10
- class Magellan {
15
+ class Magellan extends Plugin {
11
16
  /**
12
17
  * Creates a new instance of Magellan.
13
18
  * @class
19
+ * @name Magellan
14
20
  * @fires Magellan#init
15
21
  * @param {Object} element - jQuery object to add the trigger to.
16
22
  * @param {Object} options - Overrides to the default plugin settings.
17
23
  */
18
- constructor(element, options) {
24
+ _setup(element, options) {
19
25
  this.$element = element;
20
26
  this.options = $.extend({}, Magellan.defaults, this.$element.data(), options);
27
+ this.className = 'Magellan'; // ie9 back compat
21
28
 
22
29
  this._init();
23
30
  this.calcPoints();
24
-
25
- Foundation.registerPlugin(this, 'Magellan');
26
31
  }
27
32
 
28
33
  /**
@@ -30,7 +35,7 @@ class Magellan {
30
35
  * @private
31
36
  */
32
37
  _init() {
33
- var id = this.$element[0].id || Foundation.GetYoDigits(6, 'magellan');
38
+ var id = this.$element[0].id || GetYoDigits(6, 'magellan');
34
39
  var _this = this;
35
40
  this.$targets = $('[data-magellan-target]');
36
41
  this.$links = this.$element.find('a');
@@ -96,11 +101,14 @@ class Magellan {
96
101
  var arrival = this.getAttribute('href');
97
102
  _this.scrollToLoc(arrival);
98
103
  });
99
- $(window).on('popstate', function(e) {
104
+
105
+ this._deepLinkScroll = function(e) {
100
106
  if(_this.options.deepLinking) {
101
107
  _this.scrollToLoc(window.location.hash);
102
108
  }
103
- });
109
+ };
110
+
111
+ $(window).on('popstate', this._deepLinkScroll);
104
112
  }
105
113
 
106
114
  /**
@@ -109,18 +117,20 @@ class Magellan {
109
117
  * @function
110
118
  */
111
119
  scrollToLoc(loc) {
112
- // Do nothing if target does not exist to prevent errors
113
- if (!$(loc).length) {return false;}
114
120
  this._inTransition = true;
115
- var _this = this,
116
- scrollPos = Math.round($(loc).offset().top - this.options.threshold / 2 - this.options.barOffset);
117
-
118
- $('html, body').stop(true).animate(
119
- { scrollTop: scrollPos },
120
- this.options.animationDuration,
121
- this.options.animationEasing,
122
- function() {_this._inTransition = false; _this._updateActive()}
123
- );
121
+ var _this = this;
122
+
123
+ var options = {
124
+ animationEasing: this.options.animationEasing,
125
+ animationDuration: this.options.animationDuration,
126
+ threshold: this.options.threshold,
127
+ offset: this.options.offset
128
+ };
129
+
130
+ SmoothScroll.scrollToLoc(loc, options, function() {
131
+ _this._inTransition = false;
132
+ _this._updateActive();
133
+ })
124
134
  }
125
135
 
126
136
  /**
@@ -149,7 +159,7 @@ class Magellan {
149
159
  var isDown = this.scrollPos < winPos,
150
160
  _this = this,
151
161
  curVisible = this.points.filter(function(p, i){
152
- return isDown ? p - _this.options.barOffset <= winPos : p - _this.options.barOffset - _this.options.threshold <= winPos;
162
+ return isDown ? p - _this.options.offset <= winPos : p - _this.options.offset - _this.options.threshold <= winPos;
153
163
  });
154
164
  curIdx = curVisible.length ? curVisible.length - 1 : 0;
155
165
  }
@@ -183,7 +193,7 @@ class Magellan {
183
193
  * Destroys an instance of Magellan and resets the url of the window.
184
194
  * @function
185
195
  */
186
- destroy() {
196
+ _destroy() {
187
197
  this.$element.off('.zf.trigger .zf.magellan')
188
198
  .find(`.${this.options.activeClass}`).removeClass(this.options.activeClass);
189
199
 
@@ -191,8 +201,7 @@ class Magellan {
191
201
  var hash = this.$active[0].getAttribute('href');
192
202
  window.location.hash.replace(hash, '');
193
203
  }
194
-
195
- Foundation.unregisterPlugin(this);
204
+ $(window).off('popstate', this._deepLinkScroll);
196
205
  }
197
206
  }
198
207
 
@@ -226,9 +235,9 @@ Magellan.defaults = {
226
235
  * Class applied to the active locations link on the magellan container.
227
236
  * @option
228
237
  * @type {string}
229
- * @default 'active'
238
+ * @default 'is-active'
230
239
  */
231
- activeClass: 'active',
240
+ activeClass: 'is-active',
232
241
  /**
233
242
  * Allows the script to manipulate the url of the current page, and if supported, alter the history.
234
243
  * @option
@@ -242,10 +251,7 @@ Magellan.defaults = {
242
251
  * @type {number}
243
252
  * @default 0
244
253
  */
245
- barOffset: 0
254
+ offset: 0
246
255
  }
247
256
 
248
- // Window exports
249
- Foundation.plugin(Magellan, 'Magellan');
250
-
251
- }(jQuery);
257
+ export {Magellan};
@@ -1,6 +1,12 @@
1
1
  'use strict';
2
2
 
3
- !function($) {
3
+ import $ from 'jquery';
4
+ import { Keyboard } from './foundation.util.keyboard';
5
+ import { MediaQuery } from './foundation.util.mediaQuery';
6
+ import { transitionend } from './foundation.util.core';
7
+ import { Plugin } from './foundation.plugin';
8
+
9
+ import { Triggers } from './foundation.util.triggers';
4
10
 
5
11
  /**
6
12
  * OffCanvas module.
@@ -8,28 +14,45 @@
8
14
  * @requires foundation.util.keyboard
9
15
  * @requires foundation.util.mediaQuery
10
16
  * @requires foundation.util.triggers
11
- * @requires foundation.util.motion
12
17
  */
13
18
 
14
- class OffCanvas {
19
+ class OffCanvas extends Plugin {
15
20
  /**
16
21
  * Creates a new instance of an off-canvas wrapper.
17
22
  * @class
23
+ * @name OffCanvas
18
24
  * @fires OffCanvas#init
19
25
  * @param {Object} element - jQuery object to initialize.
20
26
  * @param {Object} options - Overrides to the default plugin settings.
21
27
  */
22
- constructor(element, options) {
28
+ _setup(element, options) {
29
+ this.className = 'OffCanvas'; // ie9 back compat
23
30
  this.$element = element;
24
31
  this.options = $.extend({}, OffCanvas.defaults, this.$element.data(), options);
32
+ this.contentClasses = { base: [], reveal: [] };
25
33
  this.$lastTrigger = $();
26
34
  this.$triggers = $();
35
+ this.position = 'left';
36
+ this.$content = $();
37
+ this.nested = !!(this.options.nested);
38
+
39
+ // Defines the CSS transition/position classes of the off-canvas content container.
40
+ $(['push', 'overlap']).each((index, val) => {
41
+ this.contentClasses.base.push('has-transition-'+val);
42
+ });
43
+ $(['left', 'right', 'top', 'bottom']).each((index, val) => {
44
+ this.contentClasses.base.push('has-position-'+val);
45
+ this.contentClasses.reveal.push('has-reveal-'+val);
46
+ });
47
+
48
+ // Triggers init is idempotent, just need to make sure it is initialized
49
+ Triggers.init($);
50
+ MediaQuery._init();
27
51
 
28
52
  this._init();
29
53
  this._events();
30
54
 
31
- Foundation.registerPlugin(this, 'OffCanvas')
32
- Foundation.Keyboard.register('OffCanvas', {
55
+ Keyboard.register('OffCanvas', {
33
56
  'ESCAPE': 'close'
34
57
  });
35
58
 
@@ -45,7 +68,33 @@ class OffCanvas {
45
68
 
46
69
  this.$element.attr('aria-hidden', 'true');
47
70
 
48
- this.$element.addClass(`is-transition-${this.options.transition}`);
71
+ // Find off-canvas content, either by ID (if specified), by siblings or by closest selector (fallback)
72
+ if (this.options.contentId) {
73
+ this.$content = $('#'+this.options.contentId);
74
+ } else if (this.$element.siblings('[data-off-canvas-content]').length) {
75
+ this.$content = this.$element.siblings('[data-off-canvas-content]').first();
76
+ } else {
77
+ this.$content = this.$element.closest('[data-off-canvas-content]').first();
78
+ }
79
+
80
+ if (!this.options.contentId) {
81
+ // Assume that the off-canvas element is nested if it isn't a sibling of the content
82
+ this.nested = this.$element.siblings('[data-off-canvas-content]').length === 0;
83
+
84
+ } else if (this.options.contentId && this.options.nested === null) {
85
+ // Warning if using content ID without setting the nested option
86
+ // Once the element is nested it is required to work properly in this case
87
+ console.warn('Remember to use the nested option if using the content ID option!');
88
+ }
89
+
90
+ if (this.nested === true) {
91
+ // Force transition overlap if nested
92
+ this.options.transition = 'overlap';
93
+ // Remove appropriate classes if already assigned in markup
94
+ this.$element.removeClass('is-transition-push');
95
+ }
96
+
97
+ this.$element.addClass(`is-transition-${this.options.transition} is-closed`);
49
98
 
50
99
  // Find triggers that affect this element and add aria-expanded to them
51
100
  this.$triggers = $(document)
@@ -53,6 +102,9 @@ class OffCanvas {
53
102
  .attr('aria-expanded', 'false')
54
103
  .attr('aria-controls', id);
55
104
 
105
+ // Get position by checking for related CSS class
106
+ this.position = this.$element.is('.position-left, .position-top, .position-right, .position-bottom') ? this.$element.attr('class').match(/position\-(left|top|right|bottom)/)[1] : this.position;
107
+
56
108
  // Add an overlay over the content if necessary
57
109
  if (this.options.contentOverlay === true) {
58
110
  var overlay = document.createElement('div');
@@ -60,9 +112,9 @@ class OffCanvas {
60
112
  overlay.setAttribute('class', 'js-off-canvas-overlay ' + overlayPosition);
61
113
  this.$overlay = $(overlay);
62
114
  if(overlayPosition === 'is-overlay-fixed') {
63
- $('body').append(this.$overlay);
115
+ $(this.$overlay).insertAfter(this.$element);
64
116
  } else {
65
- this.$element.siblings('[data-off-canvas-content]').append(this.$overlay);
117
+ this.$content.append(this.$overlay);
66
118
  }
67
119
  }
68
120
 
@@ -72,9 +124,13 @@ class OffCanvas {
72
124
  this.options.revealOn = this.options.revealOn || this.$element[0].className.match(/(reveal-for-medium|reveal-for-large)/g)[0].split('-')[2];
73
125
  this._setMQChecker();
74
126
  }
75
- if (!this.options.transitionTime === true) {
76
- this.options.transitionTime = parseFloat(window.getComputedStyle($('[data-off-canvas]')[0]).transitionDuration) * 1000;
127
+
128
+ if (this.options.transitionTime) {
129
+ this.$element.css('transition-duration', this.options.transitionTime);
77
130
  }
131
+
132
+ // Initally remove all transition/position CSS classes from off-canvas content container.
133
+ this._removeContentClasses();
78
134
  }
79
135
 
80
136
  /**
@@ -91,7 +147,7 @@ class OffCanvas {
91
147
  });
92
148
 
93
149
  if (this.options.closeOnClick === true) {
94
- var $target = this.options.contentOverlay ? this.$overlay : $('[data-off-canvas-content]');
150
+ var $target = this.options.contentOverlay ? this.$overlay : this.$content;
95
151
  $target.on({'click.zf.offcanvas': this.close.bind(this)});
96
152
  }
97
153
  }
@@ -104,31 +160,56 @@ class OffCanvas {
104
160
  var _this = this;
105
161
 
106
162
  $(window).on('changed.zf.mediaquery', function() {
107
- if (Foundation.MediaQuery.atLeast(_this.options.revealOn)) {
163
+ if (MediaQuery.atLeast(_this.options.revealOn)) {
108
164
  _this.reveal(true);
109
165
  } else {
110
166
  _this.reveal(false);
111
167
  }
112
168
  }).one('load.zf.offcanvas', function() {
113
- if (Foundation.MediaQuery.atLeast(_this.options.revealOn)) {
169
+ if (MediaQuery.atLeast(_this.options.revealOn)) {
114
170
  _this.reveal(true);
115
171
  }
116
172
  });
117
173
  }
118
174
 
175
+ /**
176
+ * Removes the CSS transition/position classes of the off-canvas content container.
177
+ * Removing the classes is important when another off-canvas gets opened that uses the same content container.
178
+ * @private
179
+ */
180
+ _removeContentClasses(hasReveal) {
181
+ this.$content.removeClass(this.contentClasses.base.join(' '));
182
+ if (hasReveal === true) {
183
+ this.$content.removeClass(this.contentClasses.reveal.join(' '));
184
+ }
185
+ }
186
+
187
+ /**
188
+ * Adds the CSS transition/position classes of the off-canvas content container, based on the opening off-canvas element.
189
+ * Beforehand any transition/position class gets removed.
190
+ * @param {Boolean} hasReveal - true if related off-canvas element is revealed.
191
+ * @private
192
+ */
193
+ _addContentClasses(hasReveal) {
194
+ this._removeContentClasses();
195
+ this.$content.addClass(`has-transition-${this.options.transition} has-position-${this.position}`);
196
+ if (hasReveal === true) {
197
+ this.$content.addClass(`has-reveal-${this.position}`);
198
+ }
199
+ }
200
+
119
201
  /**
120
202
  * Handles the revealing/hiding the off-canvas at breakpoints, not the same as open.
121
203
  * @param {Boolean} isRevealed - true if element should be revealed.
122
204
  * @function
123
205
  */
124
206
  reveal(isRevealed) {
125
- var $closer = this.$element.find('[data-close]');
126
207
  if (isRevealed) {
127
208
  this.close();
128
209
  this.isRevealed = true;
129
210
  this.$element.attr('aria-hidden', 'false');
130
211
  this.$element.off('open.zf.trigger toggle.zf.trigger');
131
- if ($closer.length) { $closer.hide(); }
212
+ this.$element.removeClass('is-closed');
132
213
  } else {
133
214
  this.isRevealed = false;
134
215
  this.$element.attr('aria-hidden', 'true');
@@ -136,10 +217,9 @@ class OffCanvas {
136
217
  'open.zf.trigger': this.open.bind(this),
137
218
  'toggle.zf.trigger': this.toggle.bind(this)
138
219
  });
139
- if ($closer.length) {
140
- $closer.show();
141
- }
220
+ this.$element.addClass('is-closed');
142
221
  }
222
+ this._addContentClasses(isRevealed);
143
223
  }
144
224
 
145
225
  /**
@@ -205,16 +285,24 @@ class OffCanvas {
205
285
  window.scrollTo(0,document.body.scrollHeight);
206
286
  }
207
287
 
288
+ if (this.options.transitionTime && this.options.transition !== 'overlap') {
289
+ this.$element.siblings('[data-off-canvas-content]').css('transition-duration', this.options.transitionTime);
290
+ } else {
291
+ this.$element.siblings('[data-off-canvas-content]').css('transition-duration', '');
292
+ }
293
+
208
294
  /**
209
295
  * Fires when the off-canvas menu opens.
210
296
  * @event OffCanvas#opened
211
297
  */
212
- _this.$element.addClass('is-open')
298
+ this.$element.addClass('is-open').removeClass('is-closed');
213
299
 
214
300
  this.$triggers.attr('aria-expanded', 'true');
215
301
  this.$element.attr('aria-hidden', 'false')
216
302
  .trigger('opened.zf.offcanvas');
217
303
 
304
+ this.$content.addClass('is-open-' + this.position);
305
+
218
306
  // If `contentScroll` is set to false, add class and disable scrolling on touch devices.
219
307
  if (this.options.contentScroll === false) {
220
308
  $('body').addClass('is-off-canvas-open').on('touchmove', this._stopScrolling);
@@ -231,7 +319,10 @@ class OffCanvas {
231
319
  }
232
320
 
233
321
  if (this.options.autoFocus === true) {
234
- this.$element.one(Foundation.transitionend(this.$element), function() {
322
+ this.$element.one(transitionend(this.$element), function() {
323
+ if (!_this.$element.hasClass('is-open')) {
324
+ return; // exit if prematurely closed
325
+ }
235
326
  var canvasFocus = _this.$element.find('[data-autofocus]');
236
327
  if (canvasFocus.length) {
237
328
  canvasFocus.eq(0).focus();
@@ -242,9 +333,11 @@ class OffCanvas {
242
333
  }
243
334
 
244
335
  if (this.options.trapFocus === true) {
245
- this.$element.siblings('[data-off-canvas-content]').attr('tabindex', '-1');
246
- Foundation.Keyboard.trapFocus(this.$element);
336
+ this.$content.attr('tabindex', '-1');
337
+ Keyboard.trapFocus(this.$element);
247
338
  }
339
+
340
+ this._addContentClasses();
248
341
  }
249
342
 
250
343
  /**
@@ -258,7 +351,7 @@ class OffCanvas {
258
351
 
259
352
  var _this = this;
260
353
 
261
- _this.$element.removeClass('is-open');
354
+ this.$element.removeClass('is-open');
262
355
 
263
356
  this.$element.attr('aria-hidden', 'true')
264
357
  /**
@@ -267,6 +360,8 @@ class OffCanvas {
267
360
  */
268
361
  .trigger('closed.zf.offcanvas');
269
362
 
363
+ this.$content.removeClass('is-open-left is-open-top is-open-right is-open-bottom');
364
+
270
365
  // If `contentScroll` is set to false, remove class and re-enable scrolling on touch devices.
271
366
  if (this.options.contentScroll === false) {
272
367
  $('body').removeClass('is-off-canvas-open').off('touchmove', this._stopScrolling);
@@ -285,9 +380,15 @@ class OffCanvas {
285
380
  this.$triggers.attr('aria-expanded', 'false');
286
381
 
287
382
  if (this.options.trapFocus === true) {
288
- this.$element.siblings('[data-off-canvas-content]').removeAttr('tabindex');
289
- Foundation.Keyboard.releaseFocus(this.$element);
383
+ this.$content.removeAttr('tabindex');
384
+ Keyboard.releaseFocus(this.$element);
290
385
  }
386
+
387
+ // Listen to transitionEnd and add class when done.
388
+ this.$element.one(transitionend(this.$element), function(e) {
389
+ _this.$element.addClass('is-closed');
390
+ _this._removeContentClasses();
391
+ });
291
392
  }
292
393
 
293
394
  /**
@@ -311,7 +412,7 @@ class OffCanvas {
311
412
  * @private
312
413
  */
313
414
  _handleKeyboard(e) {
314
- Foundation.Keyboard.handleKey(e, 'OffCanvas', {
415
+ Keyboard.handleKey(e, 'OffCanvas', {
315
416
  close: () => {
316
417
  this.close();
317
418
  this.$lastTrigger.focus();
@@ -328,12 +429,10 @@ class OffCanvas {
328
429
  * Destroys the offcanvas plugin.
329
430
  * @function
330
431
  */
331
- destroy() {
432
+ _destroy() {
332
433
  this.close();
333
434
  this.$element.off('.zf.trigger .zf.offcanvas');
334
435
  this.$overlay.off('.zf.offcanvas');
335
-
336
- Foundation.unregisterPlugin(this);
337
436
  }
338
437
  }
339
438
 
@@ -354,6 +453,22 @@ OffCanvas.defaults = {
354
453
  */
355
454
  contentOverlay: true,
356
455
 
456
+ /**
457
+ * Target an off-canvas content container by ID that may be placed anywhere. If null the closest content container will be taken.
458
+ * @option
459
+ * @type {?string}
460
+ * @default null
461
+ */
462
+ contentId: null,
463
+
464
+ /**
465
+ * Define the off-canvas element is nested in an off-canvas content. This is required when using the contentId option for a nested element.
466
+ * @option
467
+ * @type {boolean}
468
+ * @default null
469
+ */
470
+ nested: null,
471
+
357
472
  /**
358
473
  * Enable/disable scrolling of the main content when an off canvas panel is open.
359
474
  * @option
@@ -366,9 +481,9 @@ OffCanvas.defaults = {
366
481
  * Amount of time in ms the open and close transition requires. If none selected, pulls from body style.
367
482
  * @option
368
483
  * @type {number}
369
- * @default 0
484
+ * @default null
370
485
  */
371
- transitionTime: 0,
486
+ transitionTime: null,
372
487
 
373
488
  /**
374
489
  * Type of transition for the offcanvas menu. Options are 'push', 'detached' or 'slide'.
@@ -428,7 +543,4 @@ OffCanvas.defaults = {
428
543
  trapFocus: false
429
544
  }
430
545
 
431
- // Window exports
432
- Foundation.plugin(OffCanvas, 'OffCanvas');
433
-
434
- }(jQuery);
546
+ export {OffCanvas};