mirror of
https://github.com/gantry/gantry5.git
synced 2026-08-19 01:15:04 -05:00
1. Detaching all events, including swipe, when the offcanvas is not meant to be opened. 2. Ensuring to always attach the mutation events when detaching the rest. 3. Code reorganization and cleanup
This commit is contained in:
@@ -55,6 +55,7 @@ var Offcanvas = new prime({
|
||||
constructor: function(options) {
|
||||
this.setOptions(options);
|
||||
|
||||
this.attached = false;
|
||||
this.opening = false;
|
||||
this.moved = false;
|
||||
this.dragging = false;
|
||||
@@ -65,6 +66,9 @@ var Offcanvas = new prime({
|
||||
current: 0
|
||||
};
|
||||
|
||||
this.bodyEl = $('body');
|
||||
this.htmlEl = $('html');
|
||||
|
||||
this.panel = $('#g-page-surround');
|
||||
this.offcanvas = $('#g-offcanvas');
|
||||
|
||||
@@ -80,21 +84,22 @@ var Offcanvas = new prime({
|
||||
|
||||
this.tolerance = typeof this.options.tolerance == 'function' ? this.options.tolerance.call(this, this.options.padding) : this.options.tolerance;
|
||||
|
||||
if (this.options.touch && hasTouchEvents) {
|
||||
this._touchEvents();
|
||||
}
|
||||
|
||||
this.attach();
|
||||
this._checkTogglers();
|
||||
|
||||
return this.attach();
|
||||
return this;
|
||||
},
|
||||
|
||||
attach: function() {
|
||||
var body = $('body');
|
||||
this.attached = true;
|
||||
|
||||
if (this.options.touch && hasTouchEvents) {
|
||||
this.attachTouchEvents();
|
||||
}
|
||||
|
||||
forEach(['toggle', 'open', 'close'], bind(function(mode) {
|
||||
body.delegate('click', '[data-offcanvas-' + mode + ']', this.bound(mode));
|
||||
if (hasTouchEvents) { body.delegate('touchend', '[data-offcanvas-' + mode + ']', this.bound(mode)); }
|
||||
this.bodyEl.delegate('click', '[data-offcanvas-' + mode + ']', this.bound(mode));
|
||||
if (hasTouchEvents) { this.bodyEl.delegate('touchend', '[data-offcanvas-' + mode + ']', this.bound(mode)); }
|
||||
}, this));
|
||||
|
||||
this.attachMutationEvent();
|
||||
@@ -108,12 +113,32 @@ var Offcanvas = new prime({
|
||||
this.offcanvas.on('DOMSubtreeModified', this.bound('_checkTogglers')); // IE8 < has propertychange
|
||||
},
|
||||
|
||||
attachTouchEvents: function() {
|
||||
var msPointerSupported = window.navigator.msPointerEnabled,
|
||||
touch = {
|
||||
start: msPointerSupported ? 'MSPointerDown' : 'touchstart',
|
||||
move: msPointerSupported ? 'MSPointerMove' : 'touchmove',
|
||||
end: msPointerSupported ? 'MSPointerUp' : 'touchend'
|
||||
};
|
||||
|
||||
this._scrollBound = decouple(this.bodyEl, 'scroll', this.bound('_bodyScroll'));
|
||||
this.bodyEl.on(touch.move, this.bound('_bodyMove'));
|
||||
this.panel.on(touch.start, this.bound('_touchStart'));
|
||||
this.panel.on('touchcancel', this.bound('_touchCancel'));
|
||||
this.panel.on(touch.end, this.bound('_touchEnd'));
|
||||
this.panel.on(touch.move, this.bound('_touchMove'));
|
||||
},
|
||||
|
||||
detach: function() {
|
||||
var body = $('body');
|
||||
this.attached = false;
|
||||
|
||||
if (this.options.touch && hasTouchEvents) {
|
||||
this.detachTouchEvents();
|
||||
}
|
||||
|
||||
forEach(['toggle', 'open', 'close'], bind(function(mode) {
|
||||
body.undelegate('click', '[data-offcanvas-' + mode + ']', this.bound(mode));
|
||||
if (hasTouchEvents) { body.undelegate('touchend', '[data-offcanvas-' + mode + ']', this.bound(mode)); }
|
||||
this.bodyEl.undelegate('click', '[data-offcanvas-' + mode + ']', this.bound(mode));
|
||||
if (hasTouchEvents) { this.bodyEl.undelegate('touchend', '[data-offcanvas-' + mode + ']', this.bound(mode)); }
|
||||
}, this));
|
||||
|
||||
this.detachMutationEvent();
|
||||
@@ -127,6 +152,22 @@ var Offcanvas = new prime({
|
||||
this.offcanvas.off('DOMSubtreeModified', this.bound('_checkTogglers'));
|
||||
},
|
||||
|
||||
detachTouchEvents: function() {
|
||||
var msPointerSupported = window.navigator.msPointerEnabled,
|
||||
touch = {
|
||||
start: msPointerSupported ? 'MSPointerDown' : 'touchstart',
|
||||
move: msPointerSupported ? 'MSPointerMove' : 'touchmove',
|
||||
end: msPointerSupported ? 'MSPointerUp' : 'touchend'
|
||||
};
|
||||
|
||||
this.bodyEl[0].removeEventListener('scroll', this._scrollBound);
|
||||
this.bodyEl.off(touch.move, this.bound('_bodyMove'));
|
||||
this.panel.off(touch.start, this.bound('_touchStart'));
|
||||
this.panel.off('touchcancel', this.bound('_touchCancel'));
|
||||
this.panel.off(touch.end, this.bound('_touchEnd'));
|
||||
this.panel.off(touch.move, this.bound('_touchMove'));
|
||||
},
|
||||
|
||||
|
||||
open: function(event) {
|
||||
if (event && event.type.match(/^touch/i)) { event.preventDefault(); }
|
||||
@@ -134,17 +175,14 @@ var Offcanvas = new prime({
|
||||
|
||||
if (this.opened) { return this; }
|
||||
|
||||
var html = $('html'),
|
||||
body = $('body');
|
||||
|
||||
if (!html.hasClass(this.options.openClass)) {
|
||||
html.addClass(this.options.openClass);
|
||||
if (!this.htmlEl.hasClass(this.options.openClass)) {
|
||||
this.htmlEl.addClass(this.options.openClass);
|
||||
}
|
||||
|
||||
this.overlay[0].style.opacity = 1;
|
||||
|
||||
this._setTransition();
|
||||
this._translateXTo((body.hasClass('g-offcanvas-right') ? -1 : 1) * this.options.padding);
|
||||
this._translateXTo((this.bodyEl.hasClass('g-offcanvas-right') ? -1 : 1) * this.options.padding);
|
||||
this.opened = true;
|
||||
|
||||
setTimeout(bind(function() {
|
||||
@@ -165,8 +203,6 @@ var Offcanvas = new prime({
|
||||
if (!this.opened && !this.opening) { return this; }
|
||||
if (this.panel !== element && this.dragging) { return false; }
|
||||
|
||||
var html = $('html');
|
||||
|
||||
this.overlay[0].style.opacity = 0;
|
||||
|
||||
this._setTransition();
|
||||
@@ -176,7 +212,7 @@ var Offcanvas = new prime({
|
||||
setTimeout(bind(function() {
|
||||
var panel = this.panel[0];
|
||||
|
||||
html.removeClass(this.options.openClass);
|
||||
this.htmlEl.removeClass(this.options.openClass);
|
||||
panel.style.transition = panel.style['-webkit-transition'] = '';
|
||||
}, this), this.options.duration);
|
||||
|
||||
@@ -204,99 +240,85 @@ var Offcanvas = new prime({
|
||||
panel.style[prefix.css + 'transform'] = panel.style.transform = 'translate3d(' + x + 'px, 0, 0)';
|
||||
},
|
||||
|
||||
_touchEvents: function() {
|
||||
var msPointerSupported = window.navigator.msPointerEnabled,
|
||||
self = this,
|
||||
html = $('html'),
|
||||
body = $('body'),
|
||||
touch = {
|
||||
start: msPointerSupported ? 'MSPointerDown' : 'touchstart',
|
||||
move: msPointerSupported ? 'MSPointerMove' : 'touchmove',
|
||||
end: msPointerSupported ? 'MSPointerUp' : 'touchend'
|
||||
};
|
||||
_bodyScroll: function() {
|
||||
if (!this.moved) {
|
||||
clearTimeout(scrollTimeout);
|
||||
isScrolling = true;
|
||||
scrollTimeout = setTimeout(function() {
|
||||
isScrolling = false;
|
||||
}, 250);
|
||||
}
|
||||
},
|
||||
|
||||
decouple(body, 'scroll', function() {
|
||||
if (!self.moved) {
|
||||
clearTimeout(scrollTimeout);
|
||||
isScrolling = true;
|
||||
scrollTimeout = setTimeout(function() {
|
||||
isScrolling = false;
|
||||
}, 250);
|
||||
}
|
||||
});
|
||||
_bodyMove: function() {
|
||||
if (this.moved) { event.preventDefault(); }
|
||||
this.dragging = true;
|
||||
},
|
||||
|
||||
body.on(touch.move, function(event) {
|
||||
if (self.moved) { event.preventDefault(); }
|
||||
self.dragging = true;
|
||||
});
|
||||
_touchStart: function(event) {
|
||||
if (!event.touches) { return; }
|
||||
|
||||
this.panel.on(touch.start, function(event) {
|
||||
if (!event.touches) { return; }
|
||||
this.moved = false;
|
||||
this.opening = false;
|
||||
this.dragging = false;
|
||||
this.offsetX.start = event.touches[0].pageX;
|
||||
this.preventOpen = (!this.opened && this.offcanvas[0].clientWidth !== 0);
|
||||
},
|
||||
|
||||
self.moved = false;
|
||||
self.opening = false;
|
||||
self.dragging = false;
|
||||
self.offsetX.start = event.touches[0].pageX;
|
||||
self.preventOpen = (!self.opened && self.offcanvas[0].clientWidth !== 0);
|
||||
});
|
||||
_touchCancel: function() {
|
||||
this.moved = false;
|
||||
this.opening = false;
|
||||
},
|
||||
|
||||
this.panel.on('touchcancel', function() {
|
||||
self.moved = false;
|
||||
self.opening = false;
|
||||
});
|
||||
_touchMove: function(event) {
|
||||
if (isScrolling || this.preventOpen || !event.touches) { return; }
|
||||
|
||||
this.panel.on(touch.end, function(event) {
|
||||
var placement = (this.bodyEl.hasClass('g-offcanvas-right') ? -1 : 1), // 1: left, -1: right
|
||||
place = placement < 0 ? 'right' : 'left',
|
||||
diffX = clamp(event.touches[0].clientX - this.offsetX.start, -this.options.padding, this.options.padding),
|
||||
translateX = this.offsetX.current = diffX,
|
||||
overlayOpacity;
|
||||
|
||||
if (self.moved) {
|
||||
var tolerance = Math.abs(self.offsetX.current) > self.tolerance,
|
||||
placement = body.hasClass('g-offcanvas-right') ? true : false,
|
||||
direction = !placement ? (self.offsetX.current < 0) : (self.offsetX.current > 0);
|
||||
if (Math.abs(translateX) > this.options.padding) { return; }
|
||||
if (Math.abs(diffX) > 0) {
|
||||
this.opening = true;
|
||||
|
||||
self.opening = tolerance ? !direction : direction;
|
||||
self.opened = !self.opening;
|
||||
self[self.opening ? 'open' : 'close'](event, self.panel);
|
||||
// offcanvas on left
|
||||
if (place == 'left' && (this.opened && diffX > 0 || !this.opened && diffX < 0)) { return; }
|
||||
|
||||
// offcanvas on right
|
||||
if (place == 'right' && (this.opened && diffX < 0 || !this.opened && diffX > 0)) { return; }
|
||||
|
||||
if (!this.moved && !this.htmlEl.hasClass(this.options.openClass)) {
|
||||
this.htmlEl.addClass(this.options.openClass);
|
||||
}
|
||||
|
||||
self.moved = false;
|
||||
});
|
||||
|
||||
this.panel.on(touch.move, function(event) {
|
||||
if (isScrolling || self.preventOpen || !event.touches) { return; }
|
||||
|
||||
var placement = (body.hasClass('g-offcanvas-right') ? -1 : 1), // 1: left, -1: right
|
||||
place = placement < 0 ? 'right' : 'left',
|
||||
diffX = clamp(event.touches[0].clientX - self.offsetX.start, -self.options.padding, self.options.padding),
|
||||
translateX = self.offsetX.current = diffX,
|
||||
overlayOpacity;
|
||||
|
||||
if (Math.abs(translateX) > self.options.padding) { return; }
|
||||
if (Math.abs(diffX) > 0) {
|
||||
self.opening = true;
|
||||
|
||||
// offcanvas on left
|
||||
if (place == 'left' && (self.opened && diffX > 0 || !self.opened && diffX < 0)) { return; }
|
||||
|
||||
// offcanvas on right
|
||||
if (place == 'right' && (self.opened && diffX < 0 || !self.opened && diffX > 0)) { return; }
|
||||
|
||||
if (!self.moved && !html.hasClass(self.options.openClass)) {
|
||||
html.addClass(self.options.openClass);
|
||||
}
|
||||
|
||||
if ((place == 'left' && diffX <= 0) || (place == 'right' && diffX >= 0)) {
|
||||
translateX = diffX + (placement * self.options.padding);
|
||||
self.opening = false;
|
||||
}
|
||||
|
||||
overlayOpacity = mapNumber(Math.abs(translateX), 0, self.options.padding, 0, 1);
|
||||
|
||||
self.panel[0].style[prefix.css + 'transform'] = self.panel[0].style.transform = 'translate3d(' + translateX + 'px, 0, 0)';
|
||||
self.overlay[0].style.opacity = overlayOpacity;
|
||||
|
||||
self.moved = true;
|
||||
if ((place == 'left' && diffX <= 0) || (place == 'right' && diffX >= 0)) {
|
||||
translateX = diffX + (placement * this.options.padding);
|
||||
this.opening = false;
|
||||
}
|
||||
|
||||
});
|
||||
overlayOpacity = mapNumber(Math.abs(translateX), 0, this.options.padding, 0, 1);
|
||||
|
||||
this.panel[0].style[prefix.css + 'transform'] = this.panel[0].style.transform = 'translate3d(' + translateX + 'px, 0, 0)';
|
||||
this.overlay[0].style.opacity = overlayOpacity;
|
||||
|
||||
this.moved = true;
|
||||
}
|
||||
},
|
||||
|
||||
_touchEnd: function(event) {
|
||||
if (this.moved) {
|
||||
var tolerance = Math.abs(this.offsetX.current) > this.tolerance,
|
||||
placement = this.bodyEl.hasClass('g-offcanvas-right') ? true : false,
|
||||
direction = !placement ? (this.offsetX.current < 0) : (this.offsetX.current > 0);
|
||||
|
||||
this.opening = tolerance ? !direction : direction;
|
||||
this.opened = !this.opening;
|
||||
this[this.opening ? 'open' : 'close'](event, this.panel);
|
||||
}
|
||||
|
||||
this.moved = false;
|
||||
},
|
||||
|
||||
_checkTogglers: function(mutator) {
|
||||
@@ -313,8 +335,14 @@ var Offcanvas = new prime({
|
||||
if (!togglers || (mutator && ((mutator.target || mutator.srcElement) !== mobileContainer[0]))) { return; }
|
||||
if (this.opened) { this.close(); }
|
||||
|
||||
var check = (blocks && blocks.length == 1) && mobileContainer && !trim(this.offcanvas.text()).length;
|
||||
togglers[check ? 'addClass' : 'removeClass']('g-offcanvas-hide');
|
||||
var shouldCollapse = (blocks && blocks.length == 1) && mobileContainer && !trim(this.offcanvas.text()).length;
|
||||
togglers[shouldCollapse ? 'addClass' : 'removeClass']('g-offcanvas-hide');
|
||||
|
||||
if (!shouldCollapse && !this.attached) { this.attach(); }
|
||||
else if (shouldCollapse && this.attached) {
|
||||
this.detach();
|
||||
this.attachMutationEvent();
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
Reference in New Issue
Block a user