foundation-rails 5.5.3.2 → 6.1.1.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (169) hide show
  1. checksums.yaml +4 -4
  2. data/LICENSE.txt +1 -1
  3. data/README.md +2 -8
  4. data/Rakefile +23 -0
  5. data/app/views/foundation/rails/styleguide/show.html.erb +2 -5
  6. data/bower.json +2 -2
  7. data/lib/foundation/rails/version.rb +1 -1
  8. data/lib/generators/foundation/install_generator.rb +6 -3
  9. data/lib/generators/foundation/templates/_settings.scss +546 -0
  10. data/lib/generators/foundation/templates/application.html.erb +0 -1
  11. data/lib/generators/foundation/templates/application.html.haml +0 -2
  12. data/lib/generators/foundation/templates/application.html.slim +0 -2
  13. data/lib/generators/foundation/templates/foundation_and_overrides.scss +51 -0
  14. data/vendor/assets/js/foundation.abide.js +418 -0
  15. data/vendor/assets/js/foundation.accordion.js +229 -0
  16. data/vendor/assets/js/foundation.accordionMenu.js +262 -0
  17. data/vendor/assets/js/foundation.core.js +378 -0
  18. data/vendor/assets/js/foundation.drilldown.js +321 -0
  19. data/vendor/assets/js/foundation.dropdown.js +390 -0
  20. data/vendor/assets/js/foundation.dropdownMenu.js +391 -0
  21. data/vendor/assets/js/foundation.equalizer.js +274 -0
  22. data/vendor/assets/js/foundation.interchange.js +184 -0
  23. data/vendor/assets/js/foundation.js +28 -0
  24. data/vendor/assets/js/foundation.magellan.js +212 -0
  25. data/vendor/assets/js/foundation.offcanvas.js +371 -0
  26. data/vendor/assets/js/foundation.orbit.js +419 -0
  27. data/vendor/assets/js/foundation.responsiveMenu.js +145 -0
  28. data/vendor/assets/js/foundation.responsiveToggle.js +106 -0
  29. data/vendor/assets/js/foundation.reveal.js +478 -0
  30. data/vendor/assets/js/foundation.slider.js +484 -0
  31. data/vendor/assets/js/foundation.sticky.js +436 -0
  32. data/vendor/assets/js/foundation.tabs.js +306 -0
  33. data/vendor/assets/js/foundation.toggler.js +147 -0
  34. data/vendor/assets/js/foundation.tooltip.js +429 -0
  35. data/vendor/assets/js/foundation.util.box.js +169 -0
  36. data/vendor/assets/js/foundation.util.keyboard.js +115 -0
  37. data/vendor/assets/js/foundation.util.mediaQuery.js +210 -0
  38. data/vendor/assets/js/foundation.util.motion.js +89 -0
  39. data/vendor/assets/js/foundation.util.nest.js +64 -0
  40. data/vendor/assets/js/foundation.util.timerAndImageLoader.js +78 -0
  41. data/vendor/assets/js/foundation.util.touch.js +339 -0
  42. data/vendor/assets/js/foundation.util.triggers.js +222 -0
  43. data/vendor/assets/scss/_global.scss +626 -0
  44. data/vendor/assets/scss/components/_accordion-menu.scss +32 -0
  45. data/vendor/assets/scss/components/_accordion.scss +113 -0
  46. data/vendor/assets/scss/components/_badge.scss +55 -0
  47. data/vendor/assets/scss/components/_breadcrumbs.scss +94 -0
  48. data/vendor/assets/scss/components/_button-group.scss +130 -0
  49. data/vendor/assets/scss/components/_button.scss +265 -0
  50. data/vendor/assets/scss/components/_callout.scss +105 -0
  51. data/vendor/assets/scss/components/_close-button.scss +61 -0
  52. data/vendor/assets/scss/components/_drilldown.scss +75 -0
  53. data/vendor/assets/scss/components/_dropdown-menu.scss +148 -0
  54. data/vendor/assets/scss/components/_dropdown.scss +64 -0
  55. data/vendor/assets/scss/components/_flex-video.scss +63 -0
  56. data/vendor/assets/scss/components/_float.scss +27 -0
  57. data/vendor/assets/scss/components/_label.scss +56 -0
  58. data/vendor/assets/scss/components/_media-object.scss +74 -0
  59. data/vendor/assets/scss/components/_menu.scss +209 -0
  60. data/vendor/assets/scss/components/_off-canvas.scss +180 -0
  61. data/vendor/assets/scss/components/_orbit.scss +193 -0
  62. data/vendor/assets/scss/components/_pagination.scss +158 -0
  63. data/vendor/assets/scss/components/_progress-bar.scss +83 -0
  64. data/vendor/assets/scss/components/_reveal.scss +156 -0
  65. data/vendor/assets/scss/components/_slider.scss +158 -0
  66. data/vendor/assets/scss/components/_sticky.scss +38 -0
  67. data/vendor/assets/scss/components/_switch.scss +232 -0
  68. data/vendor/assets/scss/components/_table.scss +213 -0
  69. data/vendor/assets/scss/components/_tabs.scss +170 -0
  70. data/vendor/assets/scss/components/_thumbnail.scss +54 -0
  71. data/vendor/assets/scss/components/_title-bar.scss +68 -0
  72. data/vendor/assets/scss/components/_tooltip.scss +100 -0
  73. data/vendor/assets/scss/components/_top-bar.scss +89 -0
  74. data/vendor/assets/scss/components/_visibility.scss +131 -0
  75. data/vendor/assets/scss/forms/_checkbox.scss +36 -0
  76. data/vendor/assets/scss/forms/_error.scss +82 -0
  77. data/vendor/assets/scss/forms/_fieldset.scss +53 -0
  78. data/vendor/assets/scss/forms/_forms.scss +32 -0
  79. data/vendor/assets/scss/forms/_help-text.scss +30 -0
  80. data/vendor/assets/scss/forms/_input-group.scss +91 -0
  81. data/vendor/assets/scss/forms/_label.scss +48 -0
  82. data/vendor/assets/scss/forms/_select.scss +63 -0
  83. data/vendor/assets/scss/forms/_text.scss +154 -0
  84. data/vendor/assets/scss/foundation.scss +91 -0
  85. data/vendor/assets/scss/grid/_classes.scss +153 -0
  86. data/vendor/assets/scss/grid/_column.scss +124 -0
  87. data/vendor/assets/scss/grid/_flex-grid.scss +281 -0
  88. data/vendor/assets/scss/grid/_grid.scss +48 -0
  89. data/vendor/assets/scss/grid/_gutter.scss +34 -0
  90. data/vendor/assets/scss/grid/_layout.scss +33 -0
  91. data/vendor/assets/scss/grid/_position.scss +72 -0
  92. data/vendor/assets/scss/grid/_row.scss +97 -0
  93. data/vendor/assets/scss/grid/_size.scss +24 -0
  94. data/vendor/assets/scss/settings/_settings.scss +547 -0
  95. data/vendor/assets/scss/typography/_alignment.scss +22 -0
  96. data/vendor/assets/scss/typography/_base.scss +439 -0
  97. data/vendor/assets/scss/typography/_helpers.scss +77 -0
  98. data/vendor/assets/scss/typography/_print.scss +73 -0
  99. data/vendor/assets/scss/typography/_typography.scss +28 -0
  100. data/vendor/assets/scss/util/_breakpoint.scss +266 -0
  101. data/vendor/assets/scss/util/_color.scss +41 -0
  102. data/vendor/assets/scss/util/_mixins.scss +223 -0
  103. data/vendor/assets/scss/util/_selector.scss +40 -0
  104. data/vendor/assets/scss/util/_unit.scss +90 -0
  105. data/vendor/assets/scss/util/_util.scss +15 -0
  106. data/vendor/assets/scss/util/_value.scss +126 -0
  107. metadata +97 -64
  108. data/update-gem.sh +0 -20
  109. data/vendor/assets/javascripts/foundation.js +0 -17
  110. data/vendor/assets/javascripts/foundation/foundation.abide.js +0 -426
  111. data/vendor/assets/javascripts/foundation/foundation.accordion.js +0 -125
  112. data/vendor/assets/javascripts/foundation/foundation.alert.js +0 -43
  113. data/vendor/assets/javascripts/foundation/foundation.clearing.js +0 -586
  114. data/vendor/assets/javascripts/foundation/foundation.dropdown.js +0 -468
  115. data/vendor/assets/javascripts/foundation/foundation.equalizer.js +0 -104
  116. data/vendor/assets/javascripts/foundation/foundation.interchange.js +0 -360
  117. data/vendor/assets/javascripts/foundation/foundation.joyride.js +0 -935
  118. data/vendor/assets/javascripts/foundation/foundation.js +0 -732
  119. data/vendor/assets/javascripts/foundation/foundation.magellan.js +0 -214
  120. data/vendor/assets/javascripts/foundation/foundation.offcanvas.js +0 -225
  121. data/vendor/assets/javascripts/foundation/foundation.orbit.js +0 -476
  122. data/vendor/assets/javascripts/foundation/foundation.reveal.js +0 -522
  123. data/vendor/assets/javascripts/foundation/foundation.slider.js +0 -296
  124. data/vendor/assets/javascripts/foundation/foundation.tab.js +0 -247
  125. data/vendor/assets/javascripts/foundation/foundation.tooltip.js +0 -348
  126. data/vendor/assets/javascripts/foundation/foundation.topbar.js +0 -458
  127. data/vendor/assets/javascripts/vendor/modernizr.js +0 -1406
  128. data/vendor/assets/stylesheets/foundation.scss +0 -42
  129. data/vendor/assets/stylesheets/foundation/_functions.scss +0 -156
  130. data/vendor/assets/stylesheets/foundation/_settings.scss +0 -1489
  131. data/vendor/assets/stylesheets/foundation/components/_accordion.scss +0 -161
  132. data/vendor/assets/stylesheets/foundation/components/_alert-boxes.scss +0 -128
  133. data/vendor/assets/stylesheets/foundation/components/_block-grid.scss +0 -133
  134. data/vendor/assets/stylesheets/foundation/components/_breadcrumbs.scss +0 -132
  135. data/vendor/assets/stylesheets/foundation/components/_button-groups.scss +0 -208
  136. data/vendor/assets/stylesheets/foundation/components/_buttons.scss +0 -261
  137. data/vendor/assets/stylesheets/foundation/components/_clearing.scss +0 -260
  138. data/vendor/assets/stylesheets/foundation/components/_dropdown-buttons.scss +0 -130
  139. data/vendor/assets/stylesheets/foundation/components/_dropdown.scss +0 -269
  140. data/vendor/assets/stylesheets/foundation/components/_flex-video.scss +0 -51
  141. data/vendor/assets/stylesheets/foundation/components/_forms.scss +0 -607
  142. data/vendor/assets/stylesheets/foundation/components/_global.scss +0 -566
  143. data/vendor/assets/stylesheets/foundation/components/_grid.scss +0 -292
  144. data/vendor/assets/stylesheets/foundation/components/_icon-bar.scss +0 -460
  145. data/vendor/assets/stylesheets/foundation/components/_inline-lists.scss +0 -58
  146. data/vendor/assets/stylesheets/foundation/components/_joyride.scss +0 -220
  147. data/vendor/assets/stylesheets/foundation/components/_keystrokes.scss +0 -60
  148. data/vendor/assets/stylesheets/foundation/components/_labels.scss +0 -106
  149. data/vendor/assets/stylesheets/foundation/components/_magellan.scss +0 -34
  150. data/vendor/assets/stylesheets/foundation/components/_offcanvas.scss +0 -606
  151. data/vendor/assets/stylesheets/foundation/components/_orbit.scss +0 -388
  152. data/vendor/assets/stylesheets/foundation/components/_pagination.scss +0 -163
  153. data/vendor/assets/stylesheets/foundation/components/_panels.scss +0 -107
  154. data/vendor/assets/stylesheets/foundation/components/_pricing-tables.scss +0 -150
  155. data/vendor/assets/stylesheets/foundation/components/_progress-bars.scss +0 -85
  156. data/vendor/assets/stylesheets/foundation/components/_range-slider.scss +0 -177
  157. data/vendor/assets/stylesheets/foundation/components/_reveal.scss +0 -212
  158. data/vendor/assets/stylesheets/foundation/components/_side-nav.scss +0 -120
  159. data/vendor/assets/stylesheets/foundation/components/_split-buttons.scss +0 -203
  160. data/vendor/assets/stylesheets/foundation/components/_sub-nav.scss +0 -125
  161. data/vendor/assets/stylesheets/foundation/components/_switches.scss +0 -241
  162. data/vendor/assets/stylesheets/foundation/components/_tables.scss +0 -135
  163. data/vendor/assets/stylesheets/foundation/components/_tabs.scss +0 -142
  164. data/vendor/assets/stylesheets/foundation/components/_thumbs.scss +0 -66
  165. data/vendor/assets/stylesheets/foundation/components/_tooltips.scss +0 -142
  166. data/vendor/assets/stylesheets/foundation/components/_top-bar.scss +0 -745
  167. data/vendor/assets/stylesheets/foundation/components/_type.scss +0 -525
  168. data/vendor/assets/stylesheets/foundation/components/_visibility.scss +0 -425
  169. data/vendor/assets/stylesheets/normalize.scss +0 -424
@@ -0,0 +1,436 @@
1
+ /**
2
+ * Sticky module.
3
+ * @module foundation.sticky
4
+ * @requires foundation.util.triggers
5
+ * @requires foundation.util.mediaQuery
6
+ */
7
+ !function($, Foundation){
8
+ 'use strict';
9
+
10
+ /**
11
+ * Creates a new instance of a sticky thing.
12
+ * @class
13
+ * @param {jQuery} element - jQuery object to make sticky.
14
+ * @param {Object} options - options object passed when creating the element programmatically.
15
+ */
16
+ function Sticky(element, options){
17
+ this.$element = element;
18
+ this.options = $.extend({}, Sticky.defaults, this.$element.data(), options);
19
+
20
+ this._init();
21
+
22
+ Foundation.registerPlugin(this, 'Sticky');
23
+ }
24
+ Sticky.defaults = {
25
+ /**
26
+ * Customizable container template. Add your own classes for styling and sizing.
27
+ * @option
28
+ * @example '<div data-sticky-container class="small-6 columns"></div>'
29
+ */
30
+ container: '<div data-sticky-container></div>',
31
+ /**
32
+ * Location in the view the element sticks to.
33
+ * @option
34
+ * @example 'top'
35
+ */
36
+ stickTo: 'top',
37
+ /**
38
+ * If anchored to a single element, the id of that element.
39
+ * @option
40
+ * @example 'exampleId'
41
+ */
42
+ anchor: '',
43
+ /**
44
+ * If using more than one element as anchor points, the id of the top anchor.
45
+ * @option
46
+ * @example 'exampleId:top'
47
+ */
48
+ topAnchor: '',
49
+ /**
50
+ * If using more than one element as anchor points, the id of the bottom anchor.
51
+ * @option
52
+ * @example 'exampleId:bottom'
53
+ */
54
+ btmAnchor: '',
55
+ /**
56
+ * Margin, in `em`'s to apply to the top of the element when it becomes sticky.
57
+ * @option
58
+ * @example 1
59
+ */
60
+ marginTop: 1,
61
+ /**
62
+ * Margin, in `em`'s to apply to the bottom of the element when it becomes sticky.
63
+ * @option
64
+ * @example 1
65
+ */
66
+ marginBottom: 1,
67
+ /**
68
+ * Breakpoint string that is the minimum screen size an element should become sticky.
69
+ * @option
70
+ * @example 'medium'
71
+ */
72
+ stickyOn: 'medium',
73
+ /**
74
+ * Class applied to sticky element, and removed on destruction. Foundation defaults to `sticky`.
75
+ * @option
76
+ * @example 'sticky'
77
+ */
78
+ stickyClass: 'sticky',
79
+ /**
80
+ * Class applied to sticky container. Foundation defaults to `sticky-container`.
81
+ * @option
82
+ * @example 'sticky-container'
83
+ */
84
+ containerClass: 'sticky-container',
85
+ /**
86
+ * Number of scroll events between the plugin's recalculating sticky points. Setting it to `0` will cause it to recalc every scroll event, setting it to `-1` will prevent recalc on scroll.
87
+ * @option
88
+ * @example 50
89
+ */
90
+ checkEvery: -1
91
+ };
92
+
93
+ /**
94
+ * Initializes the sticky element by adding classes, getting/setting dimensions, breakpoints and attributes
95
+ * @function
96
+ * @private
97
+ */
98
+ Sticky.prototype._init = function(){
99
+ var $parent = this.$element.parent('[data-sticky-container]'),
100
+ id = this.$element[0].id || Foundation.GetYoDigits(6, 'sticky'),
101
+ _this = this;
102
+
103
+ if(!$parent.length){
104
+ this.wasWrapped = true;
105
+ }
106
+ this.$container = $parent.length ? $parent : $(this.options.container).wrapInner(this.$element);
107
+ this.$container.addClass(this.options.containerClass);
108
+
109
+
110
+ this.$element.addClass(this.options.stickyClass)
111
+ .attr({'data-resize': id});
112
+
113
+ this.scrollCount = this.options.checkEvery;
114
+ this.isStuck = false;
115
+
116
+ if(this.options.anchor !== ''){
117
+ this.$anchor = $('#' + this.options.anchor);
118
+ }else{
119
+ this._parsePoints();
120
+ }
121
+
122
+ this._setSizes(function(){
123
+ _this._calc(false);
124
+ });
125
+ this._events(id.split('-').reverse().join('-'));
126
+ };
127
+ /**
128
+ * If using multiple elements as anchors, calculates the top and bottom pixel values the sticky thing should stick and unstick on.
129
+ * @function
130
+ * @private
131
+ */
132
+ Sticky.prototype._parsePoints = function(){
133
+ var top = this.options.topAnchor,
134
+ btm = this.options.btmAnchor,
135
+ pts = [top, btm],
136
+ breaks = {};
137
+ if(top && btm){
138
+
139
+ for(var i = 0, len = pts.length; i < len && pts[i]; i++){
140
+ var pt;
141
+ if(typeof pts[i] === 'number'){
142
+ pt = pts[i];
143
+ }else{
144
+ var place = pts[i].split(':'),
145
+ anchor = $('#' + place[0]);
146
+
147
+ pt = anchor.offset().top;
148
+ if(place[1] && place[1].toLowerCase() === 'bottom'){
149
+ pt += anchor[0].getBoundingClientRect().height;
150
+ }
151
+ }
152
+ breaks[i] = pt;
153
+ }
154
+ }else{
155
+ breaks = {0: 1, 1: document.documentElement.scrollHeight};
156
+ }
157
+
158
+ this.points = breaks;
159
+ return;
160
+ };
161
+
162
+ /**
163
+ * Adds event handlers for the scrolling element.
164
+ * @private
165
+ * @param {String} id - psuedo-random id for unique scroll event listener.
166
+ */
167
+ Sticky.prototype._events = function(id){
168
+ var _this = this,
169
+ scrollListener = this.scrollListener = 'scroll.zf.' + id;
170
+ if(this.isOn){ return; }
171
+ if(this.canStick){
172
+ this.isOn = true;
173
+ $(window).off(scrollListener)
174
+ .on(scrollListener, function(e){
175
+ if(_this.scrollCount === 0){
176
+ _this.scrollCount = _this.options.checkEvery;
177
+ _this._setSizes(function(){
178
+ _this._calc(false, window.pageYOffset);
179
+ });
180
+ }else{
181
+ _this.scrollCount--;
182
+ _this._calc(false, window.pageYOffset);
183
+ }
184
+ });
185
+ }
186
+
187
+ this.$element.off('resizeme.zf.trigger')
188
+ .on('resizeme.zf.trigger', function(e, el){
189
+ _this._setSizes(function(){
190
+ _this._calc(false);
191
+ if(_this.canStick){
192
+ if(!_this.isOn){
193
+ _this._events(id);
194
+ }
195
+ }else if(_this.isOn){
196
+ _this._pauseListeners(scrollListener);
197
+ }
198
+ });
199
+ });
200
+ };
201
+
202
+ /**
203
+ * Removes event handlers for scroll and change events on anchor.
204
+ * @fires Sticky#pause
205
+ * @param {String} scrollListener - unique, namespaced scroll listener attached to `window`
206
+ */
207
+ Sticky.prototype._pauseListeners = function(scrollListener){
208
+ this.isOn = false;
209
+ $(window).off(scrollListener);
210
+
211
+ /**
212
+ * Fires when the plugin is paused due to resize event shrinking the view.
213
+ * @event Sticky#pause
214
+ * @private
215
+ */
216
+ this.$element.trigger('pause.zf.sticky');
217
+ };
218
+
219
+ /**
220
+ * Called on every `scroll` event and on `_init`
221
+ * fires functions based on booleans and cached values
222
+ * @param {Boolean} checkSizes - true if plugin should recalculate sizes and breakpoints.
223
+ * @param {Number} scroll - current scroll position passed from scroll event cb function. If not passed, defaults to `window.pageYOffset`.
224
+ */
225
+ Sticky.prototype._calc = function(checkSizes, scroll){
226
+ if(checkSizes){ this._setSizes(); }
227
+
228
+ if(!this.canStick){
229
+ if(this.isStuck){
230
+ this._removeSticky(true);
231
+ }
232
+ return false;
233
+ }
234
+
235
+ if(!scroll){ scroll = window.pageYOffset; }
236
+
237
+ if(scroll >= this.topPoint){
238
+ if(scroll <= this.bottomPoint){
239
+ if(!this.isStuck){
240
+ this._setSticky();
241
+ }
242
+ }else{
243
+ if(this.isStuck){
244
+ this._removeSticky(false);
245
+ }
246
+ }
247
+ }else{
248
+ if(this.isStuck){
249
+ this._removeSticky(true);
250
+ }
251
+ }
252
+ };
253
+ /**
254
+ * Causes the $element to become stuck.
255
+ * Adds `position: fixed;`, and helper classes.
256
+ * @fires Sticky#stuckto
257
+ * @function
258
+ * @private
259
+ */
260
+ Sticky.prototype._setSticky = function(){
261
+ var stickTo = this.options.stickTo,
262
+ mrgn = stickTo === 'top' ? 'marginTop' : 'marginBottom',
263
+ notStuckTo = stickTo === 'top' ? 'bottom' : 'top',
264
+ css = {};
265
+
266
+ css[mrgn] = this.options[mrgn] + 'em';
267
+ css[stickTo] = 0;
268
+ css[notStuckTo] = 'auto';
269
+ css['left'] = this.$container.offset().left + parseInt(window.getComputedStyle(this.$container[0])["padding-left"], 10);
270
+ this.isStuck = true;
271
+ this.$element.removeClass('is-anchored is-at-' + notStuckTo)
272
+ .addClass('is-stuck is-at-' + stickTo)
273
+ .css(css)
274
+ /**
275
+ * Fires when the $element has become `position: fixed;`
276
+ * Namespaced to `top` or `bottom`.
277
+ * @event Sticky#stuckto
278
+ */
279
+ .trigger('sticky.zf.stuckto:' + stickTo);
280
+ };
281
+
282
+ /**
283
+ * Causes the $element to become unstuck.
284
+ * Removes `position: fixed;`, and helper classes.
285
+ * Adds other helper classes.
286
+ * @param {Boolean} isTop - tells the function if the $element should anchor to the top or bottom of its $anchor element.
287
+ * @fires Sticky#unstuckfrom
288
+ * @private
289
+ */
290
+ Sticky.prototype._removeSticky = function(isTop){
291
+ var stickTo = this.options.stickTo,
292
+ stickToTop = stickTo === 'top',
293
+ css = {},
294
+ anchorPt = (this.points ? this.points[1] - this.points[0] : this.anchorHeight) - this.elemHeight,
295
+ mrgn = stickToTop ? 'marginTop' : 'marginBottom',
296
+ notStuckTo = stickToTop ? 'bottom' : 'top',
297
+ topOrBottom = isTop ? 'top' : 'bottom';
298
+
299
+ css[mrgn] = 0;
300
+
301
+ if((isTop && !stickToTop) || (stickToTop && !isTop)){
302
+ css[stickTo] = anchorPt;
303
+ css[notStuckTo] = 0;
304
+ }else{
305
+ css[stickTo] = 0;
306
+ css[notStuckTo] = anchorPt;
307
+ }
308
+
309
+ css['left'] = '';
310
+ this.isStuck = false;
311
+ this.$element.removeClass('is-stuck is-at-' + stickTo)
312
+ .addClass('is-anchored is-at-' + topOrBottom)
313
+ .css(css)
314
+ /**
315
+ * Fires when the $element has become anchored.
316
+ * Namespaced to `top` or `bottom`.
317
+ * @event Sticky#unstuckfrom
318
+ */
319
+ .trigger('sticky.zf.unstuckfrom:' + topOrBottom);
320
+ };
321
+
322
+ /**
323
+ * Sets the $element and $container sizes for plugin.
324
+ * Calls `_setBreakPoints`.
325
+ * @param {Function} cb - optional callback function to fire on completion of `_setBreakPoints`.
326
+ * @private
327
+ */
328
+ Sticky.prototype._setSizes = function(cb){
329
+ this.canStick = Foundation.MediaQuery.atLeast(this.options.stickyOn);
330
+ if(!this.canStick){ cb(); }
331
+ var _this = this,
332
+ newElemWidth = this.$container[0].getBoundingClientRect().width,
333
+ comp = window.getComputedStyle(this.$container[0]),
334
+ pdng = parseInt(comp['padding-right'], 10);
335
+
336
+ if(this.$anchor && this.$anchor.length){
337
+ this.anchorHeight = this.$anchor[0].getBoundingClientRect().height;
338
+ }else{
339
+ this._parsePoints();
340
+ }
341
+
342
+ this.$element.css({
343
+ 'max-width': newElemWidth - pdng + 'px'
344
+ });
345
+
346
+ var newContainerHeight = this.$element[0].getBoundingClientRect().height || this.containerHeight;
347
+ this.containerHeight = newContainerHeight;
348
+ this.$container.css({
349
+ height: newContainerHeight
350
+ });
351
+ this.elemHeight = newContainerHeight;
352
+
353
+ if (this.isStuck) {
354
+ this.$element.css({"left":this.$container.offset().left + parseInt(comp['padding-left'], 10)});
355
+ }
356
+
357
+ this._setBreakPoints(newContainerHeight, function(){
358
+ if(cb){ cb(); }
359
+ });
360
+
361
+ };
362
+ /**
363
+ * Sets the upper and lower breakpoints for the element to become sticky/unsticky.
364
+ * @param {Number} elemHeight - px value for sticky.$element height, calculated by `_setSizes`.
365
+ * @param {Function} cb - optional callback function to be called on completion.
366
+ * @private
367
+ */
368
+ Sticky.prototype._setBreakPoints = function(elemHeight, cb){
369
+ if(!this.canStick){
370
+ if(cb){ cb(); }
371
+ else{ return false; }
372
+ }
373
+ var mTop = emCalc(this.options.marginTop),
374
+ mBtm = emCalc(this.options.marginBottom),
375
+ topPoint = this.points ? this.points[0] : this.$anchor.offset().top,
376
+ bottomPoint = this.points ? this.points[1] : topPoint + this.anchorHeight,
377
+ // topPoint = this.$anchor.offset().top || this.points[0],
378
+ // bottomPoint = topPoint + this.anchorHeight || this.points[1],
379
+ winHeight = window.innerHeight;
380
+
381
+ if(this.options.stickTo === 'top'){
382
+ topPoint -= mTop;
383
+ bottomPoint -= (elemHeight + mTop);
384
+ }else if(this.options.stickTo === 'bottom'){
385
+ topPoint -= (winHeight - (elemHeight + mBtm));
386
+ bottomPoint -= (winHeight - mBtm);
387
+ }else{
388
+ //this would be the stickTo: both option... tricky
389
+ }
390
+
391
+ this.topPoint = topPoint;
392
+ this.bottomPoint = bottomPoint;
393
+
394
+ if(cb){ cb(); }
395
+ };
396
+
397
+ /**
398
+ * Destroys the current sticky element.
399
+ * Resets the element to the top position first.
400
+ * Removes event listeners, JS-added css properties and classes, and unwraps the $element if the JS added the $container.
401
+ * @function
402
+ */
403
+ Sticky.prototype.destroy = function(){
404
+ this._removeSticky(true);
405
+
406
+ this.$element.removeClass(this.options.stickyClass + ' is-anchored is-at-top')
407
+ .css({
408
+ height: '',
409
+ top: '',
410
+ bottom: '',
411
+ 'max-width': ''
412
+ })
413
+ .off('resizeme.zf.trigger');
414
+
415
+ this.$anchor.off('change.zf.sticky');
416
+ $(window).off(this.scrollListener);
417
+
418
+ if(this.wasWrapped){
419
+ this.$element.unwrap();
420
+ }else{
421
+ this.$container.removeClass(this.options.containerClass)
422
+ .css({
423
+ height: ''
424
+ });
425
+ }
426
+ Foundation.unregisterPlugin(this);
427
+ };
428
+ /**
429
+ * Helper function to calculate em values
430
+ * @param Number {em} - number of em's to calculate into pixels
431
+ */
432
+ function emCalc(em){
433
+ return parseInt(window.getComputedStyle(document.body, null).fontSize, 10) * em;
434
+ }
435
+ Foundation.plugin(Sticky, 'Sticky');
436
+ }(jQuery, window.Foundation);
@@ -0,0 +1,306 @@
1
+ /**
2
+ * Tabs module.
3
+ * @module foundation.tabs
4
+ * @requires foundation.util.keyboard
5
+ * @requires foundation.util.timerAndImageLoader if tabs contain images
6
+ */
7
+ !function($, Foundation) {
8
+ 'use strict';
9
+
10
+ /**
11
+ * Creates a new instance of tabs.
12
+ * @class
13
+ * @fires Tabs#init
14
+ * @param {jQuery} element - jQuery object to make into tabs.
15
+ * @param {Object} options - Overrides to the default plugin settings.
16
+ */
17
+ function Tabs(element, options){
18
+ this.$element = element;
19
+ this.options = $.extend({}, Tabs.defaults, this.$element.data(), options);
20
+
21
+ this._init();
22
+ Foundation.registerPlugin(this, 'Tabs');
23
+ Foundation.Keyboard.register('Tabs', {
24
+ 'ENTER': 'open',
25
+ 'SPACE': 'open',
26
+ 'ARROW_RIGHT': 'next',
27
+ 'ARROW_UP': 'previous',
28
+ 'ARROW_DOWN': 'next',
29
+ 'ARROW_LEFT': 'previous'
30
+ // 'TAB': 'next',
31
+ // 'SHIFT_TAB': 'previous'
32
+ });
33
+ }
34
+
35
+ Tabs.defaults = {
36
+ // /**
37
+ // * Allows the JS to alter the url of the window. Not yet implemented.
38
+ // */
39
+ // deepLinking: false,
40
+ // /**
41
+ // * If deepLinking is enabled, allows the window to scroll to content if window is loaded with a hash including a tab-pane id
42
+ // */
43
+ // scrollToContent: false,
44
+ /**
45
+ * Allows the window to scroll to content of active pane on load if set to true.
46
+ * @option
47
+ * @example false
48
+ */
49
+ autoFocus: false,
50
+ /**
51
+ * Allows keyboard input to 'wrap' around the tab links.
52
+ * @option
53
+ * @example true
54
+ */
55
+ wrapOnKeys: true,
56
+ /**
57
+ * Allows the tab content panes to match heights if set to true.
58
+ * @option
59
+ * @example false
60
+ */
61
+ matchHeight: false,
62
+ /**
63
+ * Class applied to `li`'s in tab link list.
64
+ * @option
65
+ * @example 'tabs-title'
66
+ */
67
+ linkClass: 'tabs-title',
68
+ // contentClass: 'tabs-content',
69
+ /**
70
+ * Class applied to the content containers.
71
+ * @option
72
+ * @example 'tabs-panel'
73
+ */
74
+ panelClass: 'tabs-panel'
75
+ };
76
+
77
+ /**
78
+ * Initializes the tabs by showing and focusing (if autoFocus=true) the preset active tab.
79
+ * @private
80
+ */
81
+ Tabs.prototype._init = function(){
82
+ var _this = this;
83
+
84
+ this.$tabTitles = this.$element.find('.' + this.options.linkClass);
85
+ this.$tabContent = $('[data-tabs-content="' + this.$element[0].id + '"]');
86
+
87
+ this.$tabTitles.each(function(){
88
+ var $elem = $(this),
89
+ $link = $elem.find('a'),
90
+ isActive = $elem.hasClass('is-active'),
91
+ hash = $link.attr('href').slice(1),
92
+ linkId = hash + '-label',
93
+ $tabContent = $(hash);
94
+
95
+ $elem.attr({'role': 'presentation'});
96
+
97
+ $link.attr({
98
+ 'role': 'tab',
99
+ 'aria-controls': hash,
100
+ 'aria-selected': isActive,
101
+ 'id': linkId
102
+ });
103
+
104
+ $tabContent.attr({
105
+ 'role': 'tabpanel',
106
+ 'aria-hidden': !isActive,
107
+ 'aria-labelledby': linkId
108
+ });
109
+
110
+ if(isActive && _this.options.autoFocus){
111
+ $link.focus();
112
+ }
113
+ });
114
+ if(this.options.matchHeight){
115
+ var $images = this.$tabContent.find('img');
116
+ if($images.length){
117
+ Foundation.onImagesLoaded($images, this._setHeight.bind(this));
118
+ }else{
119
+ this._setHeight();
120
+ }
121
+ }
122
+ this._events();
123
+ };
124
+ /**
125
+ * Adds event handlers for items within the tabs.
126
+ * @private
127
+ */
128
+ Tabs.prototype._events = function(){
129
+ this._addKeyHandler();
130
+ this._addClickHandler();
131
+ if(this.options.matchHeight){
132
+ $(window).on('changed.zf.mediaquery', this._setHeight.bind(this));
133
+ }
134
+ };
135
+
136
+ /**
137
+ * Adds click handlers for items within the tabs.
138
+ * @private
139
+ */
140
+ Tabs.prototype._addClickHandler = function(){
141
+ var _this = this;
142
+ this.$element.off('click.zf.tabs')
143
+ .on('click.zf.tabs', '.' + this.options.linkClass, function(e){
144
+ e.preventDefault();
145
+ e.stopPropagation();
146
+ if($(this).hasClass('is-active')){
147
+ return;
148
+ }
149
+ _this._handleTabChange($(this));
150
+ });
151
+ };
152
+
153
+ /**
154
+ * Adds keyboard event handlers for items within the tabs.
155
+ * @private
156
+ */
157
+ Tabs.prototype._addKeyHandler = function(){
158
+ var _this = this;
159
+ var $firstTab = _this.$element.find('li:first-of-type');
160
+ var $lastTab = _this.$element.find('li:last-of-type');
161
+
162
+ this.$tabTitles.off('keydown.zf.tabs').on('keydown.zf.tabs', function(e){
163
+ if(e.which === 9) return;
164
+ e.stopPropagation();
165
+ e.preventDefault();
166
+
167
+ var $element = $(this),
168
+ $elements = $element.parent('ul').children('li'),
169
+ $prevElement,
170
+ $nextElement;
171
+
172
+ $elements.each(function(i) {
173
+ if ($(this).is($element)) {
174
+ if (_this.options.wrapOnKeys) {
175
+ $prevElement = i === 0 ? $elements.last() : $elements.eq(i-1);
176
+ $nextElement = i === $elements.length -1 ? $elements.first() : $elements.eq(i+1);
177
+ } else {
178
+ $prevElement = $elements.eq(Math.max(0, i-1));
179
+ $nextElement = $elements.eq(Math.min(i+1, $elements.length-1));
180
+ }
181
+ return;
182
+ }
183
+ });
184
+
185
+ // handle keyboard event with keyboard util
186
+ Foundation.Keyboard.handleKey(e, 'Tabs', {
187
+ open: function() {
188
+ $element.find('[role="tab"]').focus();
189
+ _this._handleTabChange($element);
190
+ },
191
+ previous: function() {
192
+ $prevElement.find('[role="tab"]').focus();
193
+ _this._handleTabChange($prevElement);
194
+ },
195
+ next: function() {
196
+ $nextElement.find('[role="tab"]').focus();
197
+ _this._handleTabChange($nextElement);
198
+ }
199
+ });
200
+ });
201
+ };
202
+
203
+
204
+ /**
205
+ * Opens the tab `$targetContent` defined by `$target`.
206
+ * @param {jQuery} $target - Tab to open.
207
+ * @fires Tabs#change
208
+ * @function
209
+ */
210
+ Tabs.prototype._handleTabChange = function($target){
211
+ var $tabLink = $target.find('[role="tab"]'),
212
+ hash = $tabLink.attr('href'),
213
+ $targetContent = $(hash),
214
+
215
+ $oldTab = this.$element.find('.' + this.options.linkClass + '.is-active')
216
+ .removeClass('is-active').find('[role="tab"]')
217
+ .attr({'aria-selected': 'false'}).attr('href');
218
+
219
+ $($oldTab).removeClass('is-active').attr({'aria-hidden': 'true'});
220
+
221
+ $target.addClass('is-active');
222
+
223
+ $tabLink.attr({'aria-selected': 'true'});
224
+
225
+ $targetContent
226
+ .addClass('is-active')
227
+ .attr({'aria-hidden': 'false'});
228
+
229
+ /**
230
+ * Fires when the plugin has successfully changed tabs.
231
+ * @event Tabs#change
232
+ */
233
+ this.$element.trigger('change.zf.tabs', [$target]);
234
+ // Foundation.reflow(this.$element, 'tabs');
235
+ };
236
+
237
+ /**
238
+ * Public method for selecting a content pane to display.
239
+ * @param {jQuery | String} elem - jQuery object or string of the id of the pane to display.
240
+ * @function
241
+ */
242
+ Tabs.prototype.selectTab = function(elem){
243
+ var idStr;
244
+ if(typeof elem === 'object'){
245
+ idStr = elem[0].id;
246
+ }else{
247
+ idStr = elem;
248
+ }
249
+
250
+ if(idStr.indexOf('#') < 0){
251
+ idStr = '#' + idStr;
252
+ }
253
+ var $target = this.$tabTitles.find('[href="' + idStr + '"]').parent('.' + this.options.linkClass);
254
+
255
+ this._handleTabChange($target);
256
+ };
257
+ /**
258
+ * Sets the height of each panel to the height of the tallest panel.
259
+ * If enabled in options, gets called on media query change.
260
+ * If loading content via external source, can be called directly or with _reflow.
261
+ * @function
262
+ * @private
263
+ */
264
+ Tabs.prototype._setHeight = function(){
265
+ var max = 0;
266
+ this.$tabContent.find('.' + this.options.panelClass)
267
+ .css('height', '')
268
+ .each(function(){
269
+ var panel = $(this),
270
+ isActive = panel.hasClass('is-active');
271
+
272
+ if(!isActive){
273
+ panel.css({'visibility': 'hidden', 'display': 'block'});
274
+ }
275
+ var temp = this.getBoundingClientRect().height;
276
+
277
+ if(!isActive){
278
+ panel.css({'visibility': '', 'display': ''});
279
+ }
280
+
281
+ max = temp > max ? temp : max;
282
+ })
283
+ .css('height', max + 'px');
284
+ };
285
+
286
+ /**
287
+ * Destroys an instance of an tabs.
288
+ * @fires Tabs#destroyed
289
+ */
290
+ Tabs.prototype.destroy = function() {
291
+ this.$element.find('.' + this.options.linkClass)
292
+ .off('.zf.tabs').hide().end()
293
+ .find('.' + this.options.panelClass)
294
+ .hide();
295
+ if(this.options.matchHeight){
296
+ $(window).off('changed.zf.mediaquery');
297
+ }
298
+ Foundation.unregisterPlugin(this);
299
+ };
300
+
301
+ Foundation.plugin(Tabs, 'Tabs');
302
+
303
+ function checkClass($elem){
304
+ return $elem.hasClass('is-active');
305
+ }
306
+ }(jQuery, window.Foundation);