diff --git a/bower.json b/bower.json index 411116f..3662147 100644 --- a/bower.json +++ b/bower.json @@ -1,6 +1,6 @@ { "name": "adapt-scrollSnap", - "version": "5.1.1", + "version": "5.1.2", "framework": ">=5.19.2", "displayName" : "ScrollSnap", "extension" : "scrollSnap", diff --git a/js/A11y.js b/js/A11y.js index 757360f..68c689b 100644 --- a/js/A11y.js +++ b/js/A11y.js @@ -15,12 +15,11 @@ const cancellableDebounce = function (original, timeout) { class A11y { - static hideOthers(done) { + static hideOthers() { const currentBlockView = Views.currentBlockView; const otherBlockViews = Views.blocks.filter(view => view !== currentBlockView); otherBlockViews.forEach(view => view.$el.addClass('is-scrollsnap-hidden').attr('aria-hidden', 'true')); currentBlockView.$el.removeClass('is-scrollsnap-hidden').removeAttr('aria-hidden'); - done?.(); } static showAll() { diff --git a/js/Navigation.js b/js/Navigation.js index a7d70f7..2b232a6 100644 --- a/js/Navigation.js +++ b/js/Navigation.js @@ -19,6 +19,20 @@ export default class Navigation extends Backbone.Controller { this._view = null; } + static pause() { + if (!this._view) return; + this._view.model.set({ + _isPaused: true + }); + } + + static play() { + if (!this._view) return; + this._view.model.set({ + _isPaused: false + }); + } + static show() { if (!this._view) return; this._view.model.set({ diff --git a/js/NavigationView.js b/js/NavigationView.js index e6ee73e..add09f0 100644 --- a/js/NavigationView.js +++ b/js/NavigationView.js @@ -26,6 +26,7 @@ export default class NavigationView extends Backbone.View { } changed() { + if (this.model.get('_isPaused')) return; const props = { ...this.model.toJSON() }; @@ -38,16 +39,19 @@ export default class NavigationView extends Backbone.View { } onPreviousClick() { + if (this.model.get('_isPaused')) return; if (this.Snap.scroll({ direction: 'up' })) return; this.Snap.previous(); } onNextClick() { + if (this.model.get('_isPaused')) return; if (this.Snap.scroll({ direction: 'down' })) return; this.Snap.next(); } onLastClick() { + if (this.model.get('_isPaused')) return; this.Snap.first(); } diff --git a/js/Page.js b/js/Page.js index 6e44d83..d905f2c 100644 --- a/js/Page.js +++ b/js/Page.js @@ -14,7 +14,7 @@ export default class Page extends Backbone.Controller { initialize({ controller }) { this._controller = controller; - _.bindAll(this, 'onPageResize'); + this.onPageResize = _.debounce(this.onPageResize.bind(this), 50); } addEvents() { diff --git a/js/Snap.js b/js/Snap.js index 947b0d6..2f4e335 100644 --- a/js/Snap.js +++ b/js/Snap.js @@ -9,6 +9,7 @@ import Classes from './Classes'; import Navigation from './Navigation.js'; import Scroll from './Scroll'; import A11y from './A11y'; +import _ from 'underscore'; export default class Snap extends Backbone.Controller { @@ -63,37 +64,40 @@ export default class Snap extends Backbone.Controller { static toId(id, duration, isForced = false) { if (!State.canSnap) return; if (State.locationId === id && !isForced) return; - if (!isForced) Navigation.hide(); + if (!isForced) Navigation.pause(); // capture previous view before updating `State.currentModel` const $previousView = Views.currentBlockView.$el; if ($previousView) $previousView.removeClass('is-inview'); State.currentModel = Data.findById(id); const $currentView = Views.currentBlockView.$el; - A11y.showAll(); - a11y.focusFirst($currentView, { preventScroll: true, defer: false }); this._preScrollTo(); - const previousModelConfig = Config.getModelConfig(State.previousModel); - const directionType = Models.directionType; - duration = duration ?? Config.getScrollDuration(directionType, previousModelConfig) ?? Config.getScrollDuration(directionType) ?? 400; - const settings = { - duration, - offset: { top: Scroll.offset.top }, - complete: () => { - Classes.updateHtmlClasses(); - State.locationId = id; - State.currentModel.set('_isVisited', true); - State.isAnimating = false; - $currentView.addClass('is-inview'); - if (isForced) return; - Navigation.update(); - Navigation.show(); - A11y.hideOthers(() => a11y.focusFirst($currentView, { preventScroll: true, defer: false })); - Adapt.trigger('scrollsnap:scroll:complete'); - } - }; - if (this.$lastScrollTo) this.$lastScrollTo.stop(); - State.isAnimating = true; - this.$lastScrollTo = $.scrollTo(`.${id}`, settings); + A11y.showAll(); + _.delay(() => { + a11y.focusFirst($currentView, { preventScroll: true, defer: false }); + const previousModelConfig = Config.getModelConfig(State.previousModel); + const directionType = Models.directionType; + duration = duration ?? Config.getScrollDuration(directionType, previousModelConfig) ?? Config.getScrollDuration(directionType) ?? 400; + const settings = { + duration, + offset: { top: Scroll.offset.top }, + complete: () => { + Classes.updateHtmlClasses(); + State.locationId = id; + State.currentModel.set('_isVisited', true); + State.isAnimating = false; + $currentView.addClass('is-inview'); + if (isForced) return; + A11y.hideOthers(); + a11y.focusFirst($currentView, { preventScroll: true, defer: true }); + Navigation.play(); + Navigation.update(); + Adapt.trigger('scrollsnap:scroll:complete'); + } + }; + if (this.$lastScrollTo) this.$lastScrollTo.stop(); + State.isAnimating = true; + this.$lastScrollTo = $.scrollTo(`.${id}`, settings); + }, 100); } static first() {