activeadmin_materialize_theme 0.1.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (94) hide show
  1. checksums.yaml +7 -0
  2. data/MIT-LICENSE +20 -0
  3. data/README.md +26 -0
  4. data/Rakefile +34 -0
  5. data/app/assets/config/activeadmin_materialize_theme_manifest.js +1 -0
  6. data/app/assets/javascripts/activeadmin_materialize_theme.js +65 -0
  7. data/app/assets/javascripts/materialize/anime.min.js +34 -0
  8. data/app/assets/javascripts/materialize/autocomplete.js +450 -0
  9. data/app/assets/javascripts/materialize/bin/materialize.js +12374 -0
  10. data/app/assets/javascripts/materialize/bin/materialize.min.js +6 -0
  11. data/app/assets/javascripts/materialize/buttons.js +354 -0
  12. data/app/assets/javascripts/materialize/cards.js +40 -0
  13. data/app/assets/javascripts/materialize/carousel.js +717 -0
  14. data/app/assets/javascripts/materialize/cash.js +960 -0
  15. data/app/assets/javascripts/materialize/characterCounter.js +136 -0
  16. data/app/assets/javascripts/materialize/chips.js +481 -0
  17. data/app/assets/javascripts/materialize/collapsible.js +275 -0
  18. data/app/assets/javascripts/materialize/component.js +44 -0
  19. data/app/assets/javascripts/materialize/datepicker.js +975 -0
  20. data/app/assets/javascripts/materialize/dropdown.js +617 -0
  21. data/app/assets/javascripts/materialize/forms.js +275 -0
  22. data/app/assets/javascripts/materialize/global.js +427 -0
  23. data/app/assets/javascripts/materialize/materialbox.js +453 -0
  24. data/app/assets/javascripts/materialize/modal.js +382 -0
  25. data/app/assets/javascripts/materialize/parallax.js +138 -0
  26. data/app/assets/javascripts/materialize/pushpin.js +145 -0
  27. data/app/assets/javascripts/materialize/range.js +263 -0
  28. data/app/assets/javascripts/materialize/scrollspy.js +295 -0
  29. data/app/assets/javascripts/materialize/select.js +432 -0
  30. data/app/assets/javascripts/materialize/sidenav.js +580 -0
  31. data/app/assets/javascripts/materialize/slider.js +359 -0
  32. data/app/assets/javascripts/materialize/tabs.js +402 -0
  33. data/app/assets/javascripts/materialize/tapTarget.js +314 -0
  34. data/app/assets/javascripts/materialize/timepicker.js +647 -0
  35. data/app/assets/javascripts/materialize/toasts.js +310 -0
  36. data/app/assets/javascripts/materialize/tooltip.js +303 -0
  37. data/app/assets/javascripts/materialize/waves.js +335 -0
  38. data/app/assets/stylesheets/activeadmin_materialize_theme/base.scss +107 -0
  39. data/app/assets/stylesheets/activeadmin_materialize_theme/components/footer.scss +18 -0
  40. data/app/assets/stylesheets/activeadmin_materialize_theme/components/form.scss +140 -0
  41. data/app/assets/stylesheets/activeadmin_materialize_theme/components/header.scss +61 -0
  42. data/app/assets/stylesheets/activeadmin_materialize_theme/components/layout_index.scss +83 -0
  43. data/app/assets/stylesheets/activeadmin_materialize_theme/components/layout_show.scss +56 -0
  44. data/app/assets/stylesheets/activeadmin_materialize_theme/components/sidebar.scss +37 -0
  45. data/app/assets/stylesheets/activeadmin_materialize_theme/components/title_bar.scss +43 -0
  46. data/app/assets/stylesheets/activeadmin_materialize_theme/materialize/LICENSE +21 -0
  47. data/app/assets/stylesheets/activeadmin_materialize_theme/materialize/README.md +91 -0
  48. data/app/assets/stylesheets/activeadmin_materialize_theme/materialize/components/_badges.scss +55 -0
  49. data/app/assets/stylesheets/activeadmin_materialize_theme/materialize/components/_buttons.scss +322 -0
  50. data/app/assets/stylesheets/activeadmin_materialize_theme/materialize/components/_cards.scss +195 -0
  51. data/app/assets/stylesheets/activeadmin_materialize_theme/materialize/components/_carousel.scss +90 -0
  52. data/app/assets/stylesheets/activeadmin_materialize_theme/materialize/components/_chips.scss +90 -0
  53. data/app/assets/stylesheets/activeadmin_materialize_theme/materialize/components/_collapsible.scss +91 -0
  54. data/app/assets/stylesheets/activeadmin_materialize_theme/materialize/components/_color-classes.scss +32 -0
  55. data/app/assets/stylesheets/activeadmin_materialize_theme/materialize/components/_color-variables.scss +370 -0
  56. data/app/assets/stylesheets/activeadmin_materialize_theme/materialize/components/_datepicker.scss +191 -0
  57. data/app/assets/stylesheets/activeadmin_materialize_theme/materialize/components/_dropdown.scss +85 -0
  58. data/app/assets/stylesheets/activeadmin_materialize_theme/materialize/components/_global.scss +769 -0
  59. data/app/assets/stylesheets/activeadmin_materialize_theme/materialize/components/_grid.scss +156 -0
  60. data/app/assets/stylesheets/activeadmin_materialize_theme/materialize/components/_icons-material-design.scss +5 -0
  61. data/app/assets/stylesheets/activeadmin_materialize_theme/materialize/components/_materialbox.scss +43 -0
  62. data/app/assets/stylesheets/activeadmin_materialize_theme/materialize/components/_modal.scss +94 -0
  63. data/app/assets/stylesheets/activeadmin_materialize_theme/materialize/components/_navbar.scss +208 -0
  64. data/app/assets/stylesheets/activeadmin_materialize_theme/materialize/components/_normalize.scss +447 -0
  65. data/app/assets/stylesheets/activeadmin_materialize_theme/materialize/components/_preloader.scss +334 -0
  66. data/app/assets/stylesheets/activeadmin_materialize_theme/materialize/components/_pulse.scss +34 -0
  67. data/app/assets/stylesheets/activeadmin_materialize_theme/materialize/components/_sidenav.scss +216 -0
  68. data/app/assets/stylesheets/activeadmin_materialize_theme/materialize/components/_slider.scss +92 -0
  69. data/app/assets/stylesheets/activeadmin_materialize_theme/materialize/components/_table_of_contents.scss +33 -0
  70. data/app/assets/stylesheets/activeadmin_materialize_theme/materialize/components/_tabs.scss +99 -0
  71. data/app/assets/stylesheets/activeadmin_materialize_theme/materialize/components/_tapTarget.scss +103 -0
  72. data/app/assets/stylesheets/activeadmin_materialize_theme/materialize/components/_timepicker.scss +183 -0
  73. data/app/assets/stylesheets/activeadmin_materialize_theme/materialize/components/_toast.scss +58 -0
  74. data/app/assets/stylesheets/activeadmin_materialize_theme/materialize/components/_tooltip.scss +32 -0
  75. data/app/assets/stylesheets/activeadmin_materialize_theme/materialize/components/_transitions.scss +13 -0
  76. data/app/assets/stylesheets/activeadmin_materialize_theme/materialize/components/_typography.scss +60 -0
  77. data/app/assets/stylesheets/activeadmin_materialize_theme/materialize/components/_variables.scss +349 -0
  78. data/app/assets/stylesheets/activeadmin_materialize_theme/materialize/components/_waves.scss +114 -0
  79. data/app/assets/stylesheets/activeadmin_materialize_theme/materialize/components/forms/_checkboxes.scss +200 -0
  80. data/app/assets/stylesheets/activeadmin_materialize_theme/materialize/components/forms/_file-input.scss +44 -0
  81. data/app/assets/stylesheets/activeadmin_materialize_theme/materialize/components/forms/_forms.scss +22 -0
  82. data/app/assets/stylesheets/activeadmin_materialize_theme/materialize/components/forms/_input-fields.scss +354 -0
  83. data/app/assets/stylesheets/activeadmin_materialize_theme/materialize/components/forms/_radio-buttons.scss +115 -0
  84. data/app/assets/stylesheets/activeadmin_materialize_theme/materialize/components/forms/_range.scss +161 -0
  85. data/app/assets/stylesheets/activeadmin_materialize_theme/materialize/components/forms/_select.scss +180 -0
  86. data/app/assets/stylesheets/activeadmin_materialize_theme/materialize/components/forms/_switches.scss +89 -0
  87. data/app/assets/stylesheets/activeadmin_materialize_theme/materialize/materialize.scss +41 -0
  88. data/app/assets/stylesheets/activeadmin_materialize_theme/normalize.css +349 -0
  89. data/app/assets/stylesheets/activeadmin_materialize_theme/theme.scss +13 -0
  90. data/app/assets/stylesheets/activeadmin_materialize_theme/variables.scss +14 -0
  91. data/lib/activeadmin_materialize_theme.rb +6 -0
  92. data/lib/activeadmin_materialize_theme/engine.rb +7 -0
  93. data/lib/activeadmin_materialize_theme/version.rb +5 -0
  94. metadata +149 -0
@@ -0,0 +1,359 @@
1
+ (function($, anim) {
2
+ 'use strict';
3
+
4
+ let _defaults = {
5
+ indicators: true,
6
+ height: 400,
7
+ duration: 500,
8
+ interval: 6000
9
+ };
10
+
11
+ /**
12
+ * @class
13
+ *
14
+ */
15
+ class Slider extends Component {
16
+ /**
17
+ * Construct Slider instance and set up overlay
18
+ * @constructor
19
+ * @param {Element} el
20
+ * @param {Object} options
21
+ */
22
+ constructor(el, options) {
23
+ super(Slider, el, options);
24
+
25
+ this.el.M_Slider = this;
26
+
27
+ /**
28
+ * Options for the modal
29
+ * @member Slider#options
30
+ * @prop {Boolean} [indicators=true] - Show indicators
31
+ * @prop {Number} [height=400] - height of slider
32
+ * @prop {Number} [duration=500] - Length in ms of slide transition
33
+ * @prop {Number} [interval=6000] - Length in ms of slide interval
34
+ */
35
+ this.options = $.extend({}, Slider.defaults, options);
36
+
37
+ // setup
38
+ this.$slider = this.$el.find('.slides');
39
+ this.$slides = this.$slider.children('li');
40
+ this.activeIndex = this.$slides
41
+ .filter(function(item) {
42
+ return $(item).hasClass('active');
43
+ })
44
+ .first()
45
+ .index();
46
+ if (this.activeIndex != -1) {
47
+ this.$active = this.$slides.eq(this.activeIndex);
48
+ }
49
+
50
+ this._setSliderHeight();
51
+
52
+ // Set initial positions of captions
53
+ this.$slides.find('.caption').each((el) => {
54
+ this._animateCaptionIn(el, 0);
55
+ });
56
+
57
+ // Move img src into background-image
58
+ this.$slides.find('img').each((el) => {
59
+ let placeholderBase64 =
60
+ 'data:image/gif;base64,R0lGODlhAQABAIABAP///wAAACH5BAEKAAEALAAAAAABAAEAAAICTAEAOw==';
61
+ if ($(el).attr('src') !== placeholderBase64) {
62
+ $(el).css('background-image', 'url("' + $(el).attr('src') + '")');
63
+ $(el).attr('src', placeholderBase64);
64
+ }
65
+ });
66
+
67
+ this._setupIndicators();
68
+
69
+ // Show active slide
70
+ if (this.$active) {
71
+ this.$active.css('display', 'block');
72
+ } else {
73
+ this.$slides.first().addClass('active');
74
+ anim({
75
+ targets: this.$slides.first()[0],
76
+ opacity: 1,
77
+ duration: this.options.duration,
78
+ easing: 'easeOutQuad'
79
+ });
80
+
81
+ this.activeIndex = 0;
82
+ this.$active = this.$slides.eq(this.activeIndex);
83
+
84
+ // Update indicators
85
+ if (this.options.indicators) {
86
+ this.$indicators.eq(this.activeIndex).addClass('active');
87
+ }
88
+ }
89
+
90
+ // Adjust height to current slide
91
+ this.$active.find('img').each((el) => {
92
+ anim({
93
+ targets: this.$active.find('.caption')[0],
94
+ opacity: 1,
95
+ translateX: 0,
96
+ translateY: 0,
97
+ duration: this.options.duration,
98
+ easing: 'easeOutQuad'
99
+ });
100
+ });
101
+
102
+ this._setupEventHandlers();
103
+
104
+ // auto scroll
105
+ this.start();
106
+ }
107
+
108
+ static get defaults() {
109
+ return _defaults;
110
+ }
111
+
112
+ static init(els, options) {
113
+ return super.init(this, els, options);
114
+ }
115
+
116
+ /**
117
+ * Get Instance
118
+ */
119
+ static getInstance(el) {
120
+ let domElem = !!el.jquery ? el[0] : el;
121
+ return domElem.M_Slider;
122
+ }
123
+
124
+ /**
125
+ * Teardown component
126
+ */
127
+ destroy() {
128
+ this.pause();
129
+ this._removeIndicators();
130
+ this._removeEventHandlers();
131
+ this.el.M_Slider = undefined;
132
+ }
133
+
134
+ /**
135
+ * Setup Event Handlers
136
+ */
137
+ _setupEventHandlers() {
138
+ this._handleIntervalBound = this._handleInterval.bind(this);
139
+ this._handleIndicatorClickBound = this._handleIndicatorClick.bind(this);
140
+
141
+ if (this.options.indicators) {
142
+ this.$indicators.each((el) => {
143
+ el.addEventListener('click', this._handleIndicatorClickBound);
144
+ });
145
+ }
146
+ }
147
+
148
+ /**
149
+ * Remove Event Handlers
150
+ */
151
+ _removeEventHandlers() {
152
+ if (this.options.indicators) {
153
+ this.$indicators.each((el) => {
154
+ el.removeEventListener('click', this._handleIndicatorClickBound);
155
+ });
156
+ }
157
+ }
158
+
159
+ /**
160
+ * Handle indicator click
161
+ * @param {Event} e
162
+ */
163
+ _handleIndicatorClick(e) {
164
+ let currIndex = $(e.target).index();
165
+ this.set(currIndex);
166
+ }
167
+
168
+ /**
169
+ * Handle Interval
170
+ */
171
+ _handleInterval() {
172
+ let newActiveIndex = this.$slider.find('.active').index();
173
+ if (this.$slides.length === newActiveIndex + 1) newActiveIndex = 0;
174
+ // loop to start
175
+ else newActiveIndex += 1;
176
+
177
+ this.set(newActiveIndex);
178
+ }
179
+
180
+ /**
181
+ * Animate in caption
182
+ * @param {Element} caption
183
+ * @param {Number} duration
184
+ */
185
+ _animateCaptionIn(caption, duration) {
186
+ let animOptions = {
187
+ targets: caption,
188
+ opacity: 0,
189
+ duration: duration,
190
+ easing: 'easeOutQuad'
191
+ };
192
+
193
+ if ($(caption).hasClass('center-align')) {
194
+ animOptions.translateY = -100;
195
+ } else if ($(caption).hasClass('right-align')) {
196
+ animOptions.translateX = 100;
197
+ } else if ($(caption).hasClass('left-align')) {
198
+ animOptions.translateX = -100;
199
+ }
200
+
201
+ anim(animOptions);
202
+ }
203
+
204
+ /**
205
+ * Set height of slider
206
+ */
207
+ _setSliderHeight() {
208
+ // If fullscreen, do nothing
209
+ if (!this.$el.hasClass('fullscreen')) {
210
+ if (this.options.indicators) {
211
+ // Add height if indicators are present
212
+ this.$el.css('height', this.options.height + 40 + 'px');
213
+ } else {
214
+ this.$el.css('height', this.options.height + 'px');
215
+ }
216
+ this.$slider.css('height', this.options.height + 'px');
217
+ }
218
+ }
219
+
220
+ /**
221
+ * Setup indicators
222
+ */
223
+ _setupIndicators() {
224
+ if (this.options.indicators) {
225
+ this.$indicators = $('<ul class="indicators"></ul>');
226
+ this.$slides.each((el, index) => {
227
+ let $indicator = $('<li class="indicator-item"></li>');
228
+ this.$indicators.append($indicator[0]);
229
+ });
230
+ this.$el.append(this.$indicators[0]);
231
+ this.$indicators = this.$indicators.children('li.indicator-item');
232
+ }
233
+ }
234
+
235
+ /**
236
+ * Remove indicators
237
+ */
238
+ _removeIndicators() {
239
+ this.$el.find('ul.indicators').remove();
240
+ }
241
+
242
+ /**
243
+ * Cycle to nth item
244
+ * @param {Number} index
245
+ */
246
+ set(index) {
247
+ // Wrap around indices.
248
+ if (index >= this.$slides.length) index = 0;
249
+ else if (index < 0) index = this.$slides.length - 1;
250
+
251
+ // Only do if index changes
252
+ if (this.activeIndex != index) {
253
+ this.$active = this.$slides.eq(this.activeIndex);
254
+ let $caption = this.$active.find('.caption');
255
+ this.$active.removeClass('active');
256
+
257
+ anim({
258
+ targets: this.$active[0],
259
+ opacity: 0,
260
+ duration: this.options.duration,
261
+ easing: 'easeOutQuad',
262
+ complete: () => {
263
+ this.$slides.not('.active').each((el) => {
264
+ anim({
265
+ targets: el,
266
+ opacity: 0,
267
+ translateX: 0,
268
+ translateY: 0,
269
+ duration: 0,
270
+ easing: 'easeOutQuad'
271
+ });
272
+ });
273
+ }
274
+ });
275
+
276
+ this._animateCaptionIn($caption[0], this.options.duration);
277
+
278
+ // Update indicators
279
+ if (this.options.indicators) {
280
+ this.$indicators.eq(this.activeIndex).removeClass('active');
281
+ this.$indicators.eq(index).addClass('active');
282
+ }
283
+
284
+ anim({
285
+ targets: this.$slides.eq(index)[0],
286
+ opacity: 1,
287
+ duration: this.options.duration,
288
+ easing: 'easeOutQuad'
289
+ });
290
+
291
+ anim({
292
+ targets: this.$slides.eq(index).find('.caption')[0],
293
+ opacity: 1,
294
+ translateX: 0,
295
+ translateY: 0,
296
+ duration: this.options.duration,
297
+ delay: this.options.duration,
298
+ easing: 'easeOutQuad'
299
+ });
300
+
301
+ this.$slides.eq(index).addClass('active');
302
+ this.activeIndex = index;
303
+
304
+ // Reset interval
305
+ this.start();
306
+ }
307
+ }
308
+
309
+ /**
310
+ * Pause slider interval
311
+ */
312
+ pause() {
313
+ clearInterval(this.interval);
314
+ }
315
+
316
+ /**
317
+ * Start slider interval
318
+ */
319
+ start() {
320
+ clearInterval(this.interval);
321
+ this.interval = setInterval(
322
+ this._handleIntervalBound,
323
+ this.options.duration + this.options.interval
324
+ );
325
+ }
326
+
327
+ /**
328
+ * Move to next slide
329
+ */
330
+ next() {
331
+ let newIndex = this.activeIndex + 1;
332
+
333
+ // Wrap around indices.
334
+ if (newIndex >= this.$slides.length) newIndex = 0;
335
+ else if (newIndex < 0) newIndex = this.$slides.length - 1;
336
+
337
+ this.set(newIndex);
338
+ }
339
+
340
+ /**
341
+ * Move to previous slide
342
+ */
343
+ prev() {
344
+ let newIndex = this.activeIndex - 1;
345
+
346
+ // Wrap around indices.
347
+ if (newIndex >= this.$slides.length) newIndex = 0;
348
+ else if (newIndex < 0) newIndex = this.$slides.length - 1;
349
+
350
+ this.set(newIndex);
351
+ }
352
+ }
353
+
354
+ M.Slider = Slider;
355
+
356
+ if (M.jQueryLoaded) {
357
+ M.initializeJqueryWrapper(Slider, 'slider', 'M_Slider');
358
+ }
359
+ })(cash, M.anime);
@@ -0,0 +1,402 @@
1
+ (function($, anim) {
2
+ 'use strict';
3
+
4
+ let _defaults = {
5
+ duration: 300,
6
+ onShow: null,
7
+ swipeable: false,
8
+ responsiveThreshold: Infinity // breakpoint for swipeable
9
+ };
10
+
11
+ /**
12
+ * @class
13
+ *
14
+ */
15
+ class Tabs extends Component {
16
+ /**
17
+ * Construct Tabs instance
18
+ * @constructor
19
+ * @param {Element} el
20
+ * @param {Object} options
21
+ */
22
+ constructor(el, options) {
23
+ super(Tabs, el, options);
24
+
25
+ this.el.M_Tabs = this;
26
+
27
+ /**
28
+ * Options for the Tabs
29
+ * @member Tabs#options
30
+ * @prop {Number} duration
31
+ * @prop {Function} onShow
32
+ * @prop {Boolean} swipeable
33
+ * @prop {Number} responsiveThreshold
34
+ */
35
+ this.options = $.extend({}, Tabs.defaults, options);
36
+
37
+ // Setup
38
+ this.$tabLinks = this.$el.children('li.tab').children('a');
39
+ this.index = 0;
40
+ this._setupActiveTabLink();
41
+
42
+ // Setup tabs content
43
+ if (this.options.swipeable) {
44
+ this._setupSwipeableTabs();
45
+ } else {
46
+ this._setupNormalTabs();
47
+ }
48
+
49
+ // Setup tabs indicator after content to ensure accurate widths
50
+ this._setTabsAndTabWidth();
51
+ this._createIndicator();
52
+
53
+ this._setupEventHandlers();
54
+ }
55
+
56
+ static get defaults() {
57
+ return _defaults;
58
+ }
59
+
60
+ static init(els, options) {
61
+ return super.init(this, els, options);
62
+ }
63
+
64
+ /**
65
+ * Get Instance
66
+ */
67
+ static getInstance(el) {
68
+ let domElem = !!el.jquery ? el[0] : el;
69
+ return domElem.M_Tabs;
70
+ }
71
+
72
+ /**
73
+ * Teardown component
74
+ */
75
+ destroy() {
76
+ this._removeEventHandlers();
77
+ this._indicator.parentNode.removeChild(this._indicator);
78
+
79
+ if (this.options.swipeable) {
80
+ this._teardownSwipeableTabs();
81
+ } else {
82
+ this._teardownNormalTabs();
83
+ }
84
+
85
+ this.$el[0].M_Tabs = undefined;
86
+ }
87
+
88
+ /**
89
+ * Setup Event Handlers
90
+ */
91
+ _setupEventHandlers() {
92
+ this._handleWindowResizeBound = this._handleWindowResize.bind(this);
93
+ window.addEventListener('resize', this._handleWindowResizeBound);
94
+
95
+ this._handleTabClickBound = this._handleTabClick.bind(this);
96
+ this.el.addEventListener('click', this._handleTabClickBound);
97
+ }
98
+
99
+ /**
100
+ * Remove Event Handlers
101
+ */
102
+ _removeEventHandlers() {
103
+ window.removeEventListener('resize', this._handleWindowResizeBound);
104
+ this.el.removeEventListener('click', this._handleTabClickBound);
105
+ }
106
+
107
+ /**
108
+ * Handle window Resize
109
+ */
110
+ _handleWindowResize() {
111
+ this._setTabsAndTabWidth();
112
+
113
+ if (this.tabWidth !== 0 && this.tabsWidth !== 0) {
114
+ this._indicator.style.left = this._calcLeftPos(this.$activeTabLink) + 'px';
115
+ this._indicator.style.right = this._calcRightPos(this.$activeTabLink) + 'px';
116
+ }
117
+ }
118
+
119
+ /**
120
+ * Handle tab click
121
+ * @param {Event} e
122
+ */
123
+ _handleTabClick(e) {
124
+ let tab = $(e.target).closest('li.tab');
125
+ let tabLink = $(e.target).closest('a');
126
+
127
+ // Handle click on tab link only
128
+ if (!tabLink.length || !tabLink.parent().hasClass('tab')) {
129
+ return;
130
+ }
131
+
132
+ if (tab.hasClass('disabled')) {
133
+ e.preventDefault();
134
+ return;
135
+ }
136
+
137
+ // Act as regular link if target attribute is specified.
138
+ if (!!tabLink.attr('target')) {
139
+ return;
140
+ }
141
+
142
+ // Make the old tab inactive.
143
+ this.$activeTabLink.removeClass('active');
144
+ let $oldContent = this.$content;
145
+
146
+ // Update the variables with the new link and content
147
+ this.$activeTabLink = tabLink;
148
+ this.$content = $(M.escapeHash(tabLink[0].hash));
149
+ this.$tabLinks = this.$el.children('li.tab').children('a');
150
+
151
+ // Make the tab active.
152
+ this.$activeTabLink.addClass('active');
153
+ let prevIndex = this.index;
154
+ this.index = Math.max(this.$tabLinks.index(tabLink), 0);
155
+
156
+ // Swap content
157
+ if (this.options.swipeable) {
158
+ if (this._tabsCarousel) {
159
+ this._tabsCarousel.set(this.index, () => {
160
+ if (typeof this.options.onShow === 'function') {
161
+ this.options.onShow.call(this, this.$content[0]);
162
+ }
163
+ });
164
+ }
165
+ } else {
166
+ if (this.$content.length) {
167
+ this.$content[0].style.display = 'block';
168
+ this.$content.addClass('active');
169
+ if (typeof this.options.onShow === 'function') {
170
+ this.options.onShow.call(this, this.$content[0]);
171
+ }
172
+
173
+ if ($oldContent.length && !$oldContent.is(this.$content)) {
174
+ $oldContent[0].style.display = 'none';
175
+ $oldContent.removeClass('active');
176
+ }
177
+ }
178
+ }
179
+
180
+ // Update widths after content is swapped (scrollbar bugfix)
181
+ this._setTabsAndTabWidth();
182
+
183
+ // Update indicator
184
+ this._animateIndicator(prevIndex);
185
+
186
+ // Prevent the anchor's default click action
187
+ e.preventDefault();
188
+ }
189
+
190
+ /**
191
+ * Generate elements for tab indicator.
192
+ */
193
+ _createIndicator() {
194
+ let indicator = document.createElement('li');
195
+ indicator.classList.add('indicator');
196
+
197
+ this.el.appendChild(indicator);
198
+ this._indicator = indicator;
199
+
200
+ setTimeout(() => {
201
+ this._indicator.style.left = this._calcLeftPos(this.$activeTabLink) + 'px';
202
+ this._indicator.style.right = this._calcRightPos(this.$activeTabLink) + 'px';
203
+ }, 0);
204
+ }
205
+
206
+ /**
207
+ * Setup first active tab link.
208
+ */
209
+ _setupActiveTabLink() {
210
+ // If the location.hash matches one of the links, use that as the active tab.
211
+ this.$activeTabLink = $(this.$tabLinks.filter('[href="' + location.hash + '"]'));
212
+
213
+ // If no match is found, use the first link or any with class 'active' as the initial active tab.
214
+ if (this.$activeTabLink.length === 0) {
215
+ this.$activeTabLink = this.$el
216
+ .children('li.tab')
217
+ .children('a.active')
218
+ .first();
219
+ }
220
+ if (this.$activeTabLink.length === 0) {
221
+ this.$activeTabLink = this.$el
222
+ .children('li.tab')
223
+ .children('a')
224
+ .first();
225
+ }
226
+
227
+ this.$tabLinks.removeClass('active');
228
+ this.$activeTabLink[0].classList.add('active');
229
+
230
+ this.index = Math.max(this.$tabLinks.index(this.$activeTabLink), 0);
231
+
232
+ if (this.$activeTabLink.length) {
233
+ this.$content = $(M.escapeHash(this.$activeTabLink[0].hash));
234
+ this.$content.addClass('active');
235
+ }
236
+ }
237
+
238
+ /**
239
+ * Setup swipeable tabs
240
+ */
241
+ _setupSwipeableTabs() {
242
+ // Change swipeable according to responsive threshold
243
+ if (window.innerWidth > this.options.responsiveThreshold) {
244
+ this.options.swipeable = false;
245
+ }
246
+
247
+ let $tabsContent = $();
248
+ this.$tabLinks.each((link) => {
249
+ let $currContent = $(M.escapeHash(link.hash));
250
+ $currContent.addClass('carousel-item');
251
+ $tabsContent = $tabsContent.add($currContent);
252
+ });
253
+
254
+ let $tabsWrapper = $('<div class="tabs-content carousel carousel-slider"></div>');
255
+ $tabsContent.first().before($tabsWrapper);
256
+ $tabsWrapper.append($tabsContent);
257
+ $tabsContent[0].style.display = '';
258
+
259
+ // Keep active tab index to set initial carousel slide
260
+ let activeTabIndex = this.$activeTabLink.closest('.tab').index();
261
+
262
+ this._tabsCarousel = M.Carousel.init($tabsWrapper[0], {
263
+ fullWidth: true,
264
+ noWrap: true,
265
+ onCycleTo: (item) => {
266
+ let prevIndex = this.index;
267
+ this.index = $(item).index();
268
+ this.$activeTabLink.removeClass('active');
269
+ this.$activeTabLink = this.$tabLinks.eq(this.index);
270
+ this.$activeTabLink.addClass('active');
271
+ this._animateIndicator(prevIndex);
272
+ if (typeof this.options.onShow === 'function') {
273
+ this.options.onShow.call(this, this.$content[0]);
274
+ }
275
+ }
276
+ });
277
+
278
+ // Set initial carousel slide to active tab
279
+ this._tabsCarousel.set(activeTabIndex);
280
+ }
281
+
282
+ /**
283
+ * Teardown normal tabs.
284
+ */
285
+ _teardownSwipeableTabs() {
286
+ let $tabsWrapper = this._tabsCarousel.$el;
287
+ this._tabsCarousel.destroy();
288
+
289
+ // Unwrap
290
+ $tabsWrapper.after($tabsWrapper.children());
291
+ $tabsWrapper.remove();
292
+ }
293
+
294
+ /**
295
+ * Setup normal tabs.
296
+ */
297
+ _setupNormalTabs() {
298
+ // Hide Tabs Content
299
+ this.$tabLinks.not(this.$activeTabLink).each((link) => {
300
+ if (!!link.hash) {
301
+ let $currContent = $(M.escapeHash(link.hash));
302
+ if ($currContent.length) {
303
+ $currContent[0].style.display = 'none';
304
+ }
305
+ }
306
+ });
307
+ }
308
+
309
+ /**
310
+ * Teardown normal tabs.
311
+ */
312
+ _teardownNormalTabs() {
313
+ // show Tabs Content
314
+ this.$tabLinks.each((link) => {
315
+ if (!!link.hash) {
316
+ let $currContent = $(M.escapeHash(link.hash));
317
+ if ($currContent.length) {
318
+ $currContent[0].style.display = '';
319
+ }
320
+ }
321
+ });
322
+ }
323
+
324
+ /**
325
+ * set tabs and tab width
326
+ */
327
+ _setTabsAndTabWidth() {
328
+ this.tabsWidth = this.$el.width();
329
+ this.tabWidth = Math.max(this.tabsWidth, this.el.scrollWidth) / this.$tabLinks.length;
330
+ }
331
+
332
+ /**
333
+ * Finds right attribute for indicator based on active tab.
334
+ * @param {cash} el
335
+ */
336
+ _calcRightPos(el) {
337
+ return Math.ceil(this.tabsWidth - el.position().left - el[0].getBoundingClientRect().width);
338
+ }
339
+
340
+ /**
341
+ * Finds left attribute for indicator based on active tab.
342
+ * @param {cash} el
343
+ */
344
+ _calcLeftPos(el) {
345
+ return Math.floor(el.position().left);
346
+ }
347
+
348
+ updateTabIndicator() {
349
+ this._setTabsAndTabWidth();
350
+ this._animateIndicator(this.index);
351
+ }
352
+
353
+ /**
354
+ * Animates Indicator to active tab.
355
+ * @param {Number} prevIndex
356
+ */
357
+ _animateIndicator(prevIndex) {
358
+ let leftDelay = 0,
359
+ rightDelay = 0;
360
+
361
+ if (this.index - prevIndex >= 0) {
362
+ leftDelay = 90;
363
+ } else {
364
+ rightDelay = 90;
365
+ }
366
+
367
+ // Animate
368
+ let animOptions = {
369
+ targets: this._indicator,
370
+ left: {
371
+ value: this._calcLeftPos(this.$activeTabLink),
372
+ delay: leftDelay
373
+ },
374
+ right: {
375
+ value: this._calcRightPos(this.$activeTabLink),
376
+ delay: rightDelay
377
+ },
378
+ duration: this.options.duration,
379
+ easing: 'easeOutQuad'
380
+ };
381
+ anim.remove(this._indicator);
382
+ anim(animOptions);
383
+ }
384
+
385
+ /**
386
+ * Select tab.
387
+ * @param {String} tabId
388
+ */
389
+ select(tabId) {
390
+ let tab = this.$tabLinks.filter('[href="#' + tabId + '"]');
391
+ if (tab.length) {
392
+ tab.trigger('click');
393
+ }
394
+ }
395
+ }
396
+
397
+ M.Tabs = Tabs;
398
+
399
+ if (M.jQueryLoaded) {
400
+ M.initializeJqueryWrapper(Tabs, 'tabs', 'M_Tabs');
401
+ }
402
+ })(cash, M.anime);