@materializecss/materialize 1.2.1 → 1.2.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.
package/js/dropdown.js CHANGED
@@ -562,7 +562,7 @@
562
562
 
563
563
  // Container here will be closest ancestor with overflow: hidden
564
564
  let closestOverflowParent = getClosestAncestor(this.dropdownEl, (ancestor) => {
565
- return $(ancestor).css('overflow') !== 'visible';
565
+ return !$(ancestor).is('html,body') && $(ancestor).css('overflow') !== 'visible';
566
566
  });
567
567
  // Fallback
568
568
  if (!closestOverflowParent) {
package/js/global.js CHANGED
@@ -24,7 +24,7 @@ if (typeof define === 'function' && define.amd) {
24
24
  exports.default = M;
25
25
  }
26
26
 
27
- M.version = '1.2.1';
27
+ M.version = '1.2.2';
28
28
 
29
29
  M.keys = {
30
30
  TAB: 9,
package/js/slider.js CHANGED
@@ -5,7 +5,10 @@
5
5
  indicators: true,
6
6
  height: 400,
7
7
  duration: 500,
8
- interval: 6000
8
+ interval: 6000,
9
+ pauseOnFocus: true,
10
+ pauseOnHover: true,
11
+ indicatorLabelFunc: null // Function which will generate a label for the indicators (ARIA)
9
12
  };
10
13
 
11
14
  /**
@@ -31,9 +34,19 @@
31
34
  * @prop {Number} [height=400] - height of slider
32
35
  * @prop {Number} [duration=500] - Length in ms of slide transition
33
36
  * @prop {Number} [interval=6000] - Length in ms of slide interval
37
+ * @prop {Boolean} [pauseOnFocus=true] - Pauses transition when slider receives keyboard focus
38
+ * @prop {Boolean} [pauseOnHover=true] - Pauses transition while mouse hovers the slider
39
+ * @prop {Function} [indicatorLabelFunc=null] - Function used to generate ARIA label to indicators (for accessibility purposes).
34
40
  */
35
41
  this.options = $.extend({}, Slider.defaults, options);
36
42
 
43
+ // init props
44
+ this.interval = null;
45
+ this.eventPause = false;
46
+ this._hovered = false;
47
+ this._focused = false;
48
+ this._focusCurrent = false;
49
+
37
50
  // setup
38
51
  this.$slider = this.$el.find('.slides');
39
52
  this.$slides = this.$slider.children('li');
@@ -49,6 +62,13 @@
49
62
 
50
63
  this._setSliderHeight();
51
64
 
65
+ // Sets element id if it does not have one
66
+ if (this.$slider.attr('id')) this._sliderId = this.$slider.attr('id');
67
+ else {
68
+ this._sliderId = 'slider-' + M.guid();
69
+ this.$slider.attr('id', this._sliderId);
70
+ }
71
+
52
72
  // Set initial positions of captions
53
73
  this.$slides.find('.caption').each((el) => {
54
74
  this._animateCaptionIn(el, 0);
@@ -63,12 +83,18 @@
63
83
  $(el).attr('src', placeholderBase64);
64
84
  }
65
85
  });
86
+ this.$slides.each((el) => {
87
+ // Sets slide as focusable by code
88
+ if (!el.hasAttribute('tabindex')) el.setAttribute('tabindex', -1);
89
+ // Removes initial visibility from "inactive" slides
90
+ el.style.visibility = 'hidden';
91
+ });
66
92
 
67
93
  this._setupIndicators();
68
94
 
69
95
  // Show active slide
70
96
  if (this.$active) {
71
- this.$active.css('display', 'block');
97
+ this.$active.css('display', 'block').css('visibility', 'visible');
72
98
  } else {
73
99
  this.$slides.first().addClass('active');
74
100
  anim({
@@ -77,13 +103,14 @@
77
103
  duration: this.options.duration,
78
104
  easing: 'easeOutQuad'
79
105
  });
106
+ this.$slides.first().css('visibility', 'visible');
80
107
 
81
108
  this.activeIndex = 0;
82
109
  this.$active = this.$slides.eq(this.activeIndex);
83
110
 
84
111
  // Update indicators
85
112
  if (this.options.indicators) {
86
- this.$indicators.eq(this.activeIndex).addClass('active');
113
+ this.$indicators.eq(this.activeIndex).children().first().addClass('active');
87
114
  }
88
115
  }
89
116
 
@@ -137,11 +164,22 @@
137
164
  _setupEventHandlers() {
138
165
  this._handleIntervalBound = this._handleInterval.bind(this);
139
166
  this._handleIndicatorClickBound = this._handleIndicatorClick.bind(this);
167
+ this._handleAutoPauseFocusBound = this._handleAutoPauseFocus.bind(this);
168
+ this._handleAutoStartFocusBound = this._handleAutoStartFocus.bind(this);
169
+ this._handleAutoPauseHoverBound = this._handleAutoPauseHover.bind(this);
170
+ this._handleAutoStartHoverBound = this._handleAutoStartHover.bind(this);
171
+
172
+ if (this.options.pauseOnFocus) {
173
+ this.el.addEventListener('focusin', this._handleAutoPauseFocusBound);
174
+ this.el.addEventListener('focusout', this._handleAutoStartFocusBound);
175
+ }
176
+ if (this.options.pauseOnHover) {
177
+ this.el.addEventListener('mouseenter', this._handleAutoPauseHoverBound);
178
+ this.el.addEventListener('mouseleave', this._handleAutoStartHoverBound);
179
+ }
140
180
 
141
181
  if (this.options.indicators) {
142
- this.$indicators.each((el) => {
143
- el.addEventListener('click', this._handleIndicatorClickBound);
144
- });
182
+ this.$indicators.children().on('click', this._handleIndicatorClickBound);
145
183
  }
146
184
  }
147
185
 
@@ -149,10 +187,16 @@
149
187
  * Remove Event Handlers
150
188
  */
151
189
  _removeEventHandlers() {
190
+ if (this.options.pauseOnFocus) {
191
+ this.el.removeEventListener('focusin', this._handleAutoPauseFocusBound);
192
+ this.el.removeEventListener('focusout', this._handleAutoStartFocusBound);
193
+ }
194
+ if (this.options.pauseOnHover) {
195
+ this.el.removeEventListener('mouseenter', this._handleAutoPauseHoverBound);
196
+ this.el.removeEventListener('mouseleave', this._handleAutoStartHoverBound);
197
+ }
152
198
  if (this.options.indicators) {
153
- this.$indicators.each((el) => {
154
- el.removeEventListener('click', this._handleIndicatorClickBound);
155
- });
199
+ this.$indicators.children().off('click', this._handleIndicatorClickBound);
156
200
  }
157
201
  }
158
202
 
@@ -161,10 +205,51 @@
161
205
  * @param {Event} e
162
206
  */
163
207
  _handleIndicatorClick(e) {
164
- let currIndex = $(e.target).index();
208
+ let currIndex = $(e.target).parent().index();
209
+ this._focusCurrent = true;
165
210
  this.set(currIndex);
166
211
  }
167
212
 
213
+ /**
214
+ * Mouse enter event handler
215
+ */
216
+ _handleAutoPauseHover() {
217
+ this._hovered = true;
218
+ if (this.interval != null) {
219
+ this._pause(true);
220
+ }
221
+ }
222
+
223
+ /**
224
+ * Focus in event handler
225
+ */
226
+ _handleAutoPauseFocus() {
227
+ this._focused = true;
228
+ if (this.interval != null) {
229
+ this._pause(true);
230
+ }
231
+ }
232
+
233
+ /**
234
+ * Mouse enter event handler
235
+ */
236
+ _handleAutoStartHover() {
237
+ this._hovered = false;
238
+ if (!(this.options.pauseOnFocus && this._focused) && this.eventPause) {
239
+ this.start();
240
+ }
241
+ }
242
+
243
+ /**
244
+ * Focus out leave event handler
245
+ */
246
+ _handleAutoStartFocus() {
247
+ this._focused = false;
248
+ if (!(this.options.pauseOnHover && this._hovered) && this.eventPause) {
249
+ this.start();
250
+ }
251
+ }
252
+
168
253
  /**
169
254
  * Handle Interval
170
255
  */
@@ -223,8 +308,13 @@
223
308
  _setupIndicators() {
224
309
  if (this.options.indicators) {
225
310
  this.$indicators = $('<ul class="indicators"></ul>');
226
- this.$slides.each((el, index) => {
227
- let $indicator = $('<li class="indicator-item"></li>');
311
+ this.$slides.each((el, i) => {
312
+ let label = this.options.indicatorLabelFunc
313
+ ? this.options.indicatorLabelFunc.call(this, i + 1, i === 0)
314
+ : `${i + 1}`;
315
+ let $indicator = $(`<li class="indicator-item">
316
+ <button type="button" class="indicator-item-btn" aria-label="${label}" aria-controls="${this._sliderId}"></button>
317
+ </li>`);
228
318
  this.$indicators.append($indicator[0]);
229
319
  });
230
320
  this.$el.append(this.$indicators[0]);
@@ -253,6 +343,8 @@
253
343
  this.$active = this.$slides.eq(this.activeIndex);
254
344
  let $caption = this.$active.find('.caption');
255
345
  this.$active.removeClass('active');
346
+ // Enables every slide
347
+ this.$slides.css('visibility', 'visible');
256
348
 
257
349
  anim({
258
350
  targets: this.$active[0],
@@ -269,6 +361,8 @@
269
361
  duration: 0,
270
362
  easing: 'easeOutQuad'
271
363
  });
364
+ // Disables invisible slides (for assistive technologies)
365
+ el.style.visibility = 'hidden';
272
366
  });
273
367
  }
274
368
  });
@@ -277,8 +371,34 @@
277
371
 
278
372
  // Update indicators
279
373
  if (this.options.indicators) {
280
- this.$indicators.eq(this.activeIndex).removeClass('active');
281
- this.$indicators.eq(index).addClass('active');
374
+ let activeIndicator = this.$indicators
375
+ .eq(this.activeIndex)
376
+ .children()
377
+ .first();
378
+ let nextIndicator = this.$indicators
379
+ .eq(index)
380
+ .children()
381
+ .first();
382
+ activeIndicator.removeClass('active');
383
+ nextIndicator.addClass('active');
384
+ if (typeof this.options.indicatorLabelFunc === "function"){
385
+ activeIndicator.attr(
386
+ 'aria-label',
387
+ this.options.indicatorLabelFunc.call(
388
+ this,
389
+ this.$indicators.eq(this.activeIndex).index(),
390
+ false
391
+ )
392
+ );
393
+ nextIndicator.attr(
394
+ 'aria-label',
395
+ this.options.indicatorLabelFunc.call(
396
+ this,
397
+ this.$indicators.eq(index).index(),
398
+ true
399
+ )
400
+ );
401
+ }
282
402
  }
283
403
 
284
404
  anim({
@@ -299,18 +419,35 @@
299
419
  });
300
420
 
301
421
  this.$slides.eq(index).addClass('active');
422
+ if (this._focusCurrent) {
423
+ this.$slides.eq(index)[0].focus();
424
+ this._focusCurrent = false;
425
+ }
302
426
  this.activeIndex = index;
303
427
 
304
- // Reset interval
305
- this.start();
428
+ // Reset interval, if allowed. This check prevents autostart
429
+ // when slider is paused, since it can be changed though indicators.
430
+ if (this.interval != null) {
431
+ this.start();
432
+ }
306
433
  }
307
434
  }
308
435
 
436
+ /**
437
+ * "Protected" function which pauses current interval
438
+ * @param {boolean} fromEvent Specifies if request came from event
439
+ */
440
+ _pause(fromEvent) {
441
+ clearInterval(this.interval);
442
+ this.eventPause = fromEvent;
443
+ this.interval = null;
444
+ }
445
+
309
446
  /**
310
447
  * Pause slider interval
311
448
  */
312
449
  pause() {
313
- clearInterval(this.interval);
450
+ this._pause(false);
314
451
  }
315
452
 
316
453
  /**
@@ -322,6 +459,7 @@
322
459
  this._handleIntervalBound,
323
460
  this.options.duration + this.options.interval
324
461
  );
462
+ this.eventPause = false;
325
463
  }
326
464
 
327
465
  /**
package/package.json CHANGED
@@ -3,7 +3,7 @@
3
3
  "description": "Builds Materialize distribution packages",
4
4
  "author": "Alvin Wang, Alan Chang",
5
5
  "homepage": "https://materializecss.github.io/materialize/",
6
- "version": "1.2.1",
6
+ "version": "1.2.2",
7
7
  "main": "dist/js/materialize.js",
8
8
  "style": "dist/css/materialize.css",
9
9
  "sass": "sass/materialize.scss",
@@ -74,18 +74,27 @@
74
74
  .indicator-item {
75
75
  display: inline-block;
76
76
  position: relative;
77
- cursor: pointer;
78
77
  height: 16px;
79
78
  width: 16px;
80
79
  margin: 0 12px;
80
+ }
81
+
82
+ .indicator-item-btn {
83
+ &.active {
84
+ background-color: $slider-indicator-color;
85
+ }
86
+ position: absolute;
87
+ top: 0;
88
+ left: 0;
89
+ cursor: pointer;
81
90
  background-color: $slider-bg-color-light;
82
91
 
83
92
  transition: background-color .3s;
84
93
  border-radius: 50%;
94
+ border-width: 0;
85
95
 
86
- &.active {
87
- background-color: $slider-indicator-color;
88
- }
96
+ width: 100%;
97
+ height: 100%;
89
98
  }
90
99
  }
91
100