mirror of https://github.com/IoTcat/ushio-img.git
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
885 lines
25 KiB
885 lines
25 KiB
// ========================================================================== |
|
// |
|
// Guestures |
|
// Adds touch guestures, handles click and tap events |
|
// |
|
// ========================================================================== |
|
(function(window, document, $) { |
|
"use strict"; |
|
|
|
var requestAFrame = (function() { |
|
return ( |
|
window.requestAnimationFrame || |
|
window.webkitRequestAnimationFrame || |
|
window.mozRequestAnimationFrame || |
|
window.oRequestAnimationFrame || |
|
// if all else fails, use setTimeout |
|
function(callback) { |
|
return window.setTimeout(callback, 1000 / 60); |
|
} |
|
); |
|
})(); |
|
|
|
var cancelAFrame = (function() { |
|
return ( |
|
window.cancelAnimationFrame || |
|
window.webkitCancelAnimationFrame || |
|
window.mozCancelAnimationFrame || |
|
window.oCancelAnimationFrame || |
|
function(id) { |
|
window.clearTimeout(id); |
|
} |
|
); |
|
})(); |
|
|
|
var getPointerXY = function(e) { |
|
var result = []; |
|
|
|
e = e.originalEvent || e || window.e; |
|
e = e.touches && e.touches.length ? e.touches : e.changedTouches && e.changedTouches.length ? e.changedTouches : [e]; |
|
|
|
for (var key in e) { |
|
if (e[key].pageX) { |
|
result.push({ |
|
x: e[key].pageX, |
|
y: e[key].pageY |
|
}); |
|
} else if (e[key].clientX) { |
|
result.push({ |
|
x: e[key].clientX, |
|
y: e[key].clientY |
|
}); |
|
} |
|
} |
|
|
|
return result; |
|
}; |
|
|
|
var distance = function(point2, point1, what) { |
|
if (!point1 || !point2) { |
|
return 0; |
|
} |
|
|
|
if (what === "x") { |
|
return point2.x - point1.x; |
|
} else if (what === "y") { |
|
return point2.y - point1.y; |
|
} |
|
|
|
return Math.sqrt(Math.pow(point2.x - point1.x, 2) + Math.pow(point2.y - point1.y, 2)); |
|
}; |
|
|
|
var isClickable = function($el) { |
|
if ( |
|
$el.is('a,area,button,[role="button"],input,label,select,summary,textarea,video,audio') || |
|
$.isFunction($el.get(0).onclick) || |
|
$el.data("selectable") |
|
) { |
|
return true; |
|
} |
|
|
|
// Check for attributes like data-fancybox-next or data-fancybox-close |
|
for (var i = 0, atts = $el[0].attributes, n = atts.length; i < n; i++) { |
|
if (atts[i].nodeName.substr(0, 14) === "data-fancybox-") { |
|
return true; |
|
} |
|
} |
|
|
|
return false; |
|
}; |
|
|
|
var hasScrollbars = function(el) { |
|
var overflowY = window.getComputedStyle(el)["overflow-y"], |
|
overflowX = window.getComputedStyle(el)["overflow-x"], |
|
vertical = (overflowY === "scroll" || overflowY === "auto") && el.scrollHeight > el.clientHeight, |
|
horizontal = (overflowX === "scroll" || overflowX === "auto") && el.scrollWidth > el.clientWidth; |
|
|
|
return vertical || horizontal; |
|
}; |
|
|
|
var isScrollable = function($el) { |
|
var rez = false; |
|
|
|
while (true) { |
|
rez = hasScrollbars($el.get(0)); |
|
|
|
if (rez) { |
|
break; |
|
} |
|
|
|
$el = $el.parent(); |
|
|
|
if (!$el.length || $el.hasClass("fancybox-stage") || $el.is("body")) { |
|
break; |
|
} |
|
} |
|
|
|
return rez; |
|
}; |
|
|
|
var Guestures = function(instance) { |
|
var self = this; |
|
|
|
self.instance = instance; |
|
|
|
self.$bg = instance.$refs.bg; |
|
self.$stage = instance.$refs.stage; |
|
self.$container = instance.$refs.container; |
|
|
|
self.destroy(); |
|
|
|
self.$container.on("touchstart.fb.touch mousedown.fb.touch", $.proxy(self, "ontouchstart")); |
|
}; |
|
|
|
Guestures.prototype.destroy = function() { |
|
this.$container.off(".fb.touch"); |
|
}; |
|
|
|
Guestures.prototype.ontouchstart = function(e) { |
|
var self = this, |
|
$target = $(e.target), |
|
instance = self.instance, |
|
current = instance.current, |
|
$content = current.$content, |
|
isTouchDevice = e.type == "touchstart"; |
|
|
|
// Do not respond to both (touch and mouse) events |
|
if (isTouchDevice) { |
|
self.$container.off("mousedown.fb.touch"); |
|
} |
|
|
|
// Ignore right click |
|
if (e.originalEvent && e.originalEvent.button == 2) { |
|
return; |
|
} |
|
|
|
// Ignore taping on links, buttons, input elements |
|
if (!$target.length || isClickable($target) || isClickable($target.parent())) { |
|
return; |
|
} |
|
|
|
// Ignore clicks on the scrollbar |
|
if (!$target.is("img") && e.originalEvent.clientX > $target[0].clientWidth + $target.offset().left) { |
|
return; |
|
} |
|
|
|
// Ignore clicks while zooming or closing |
|
if (!current || instance.isAnimating || instance.isClosing) { |
|
e.stopPropagation(); |
|
e.preventDefault(); |
|
|
|
return; |
|
} |
|
|
|
self.realPoints = self.startPoints = getPointerXY(e); |
|
|
|
if (!self.startPoints.length) { |
|
return; |
|
} |
|
|
|
e.stopPropagation(); |
|
|
|
self.startEvent = e; |
|
|
|
self.canTap = true; |
|
self.$target = $target; |
|
self.$content = $content; |
|
self.opts = current.opts.touch; |
|
|
|
self.isPanning = false; |
|
self.isSwiping = false; |
|
self.isZooming = false; |
|
self.isScrolling = false; |
|
|
|
self.startTime = new Date().getTime(); |
|
self.distanceX = self.distanceY = self.distance = 0; |
|
|
|
self.canvasWidth = Math.round(current.$slide[0].clientWidth); |
|
self.canvasHeight = Math.round(current.$slide[0].clientHeight); |
|
|
|
self.contentLastPos = null; |
|
self.contentStartPos = $.fancybox.getTranslate(self.$content) || {top: 0, left: 0}; |
|
self.sliderStartPos = self.sliderLastPos || $.fancybox.getTranslate(current.$slide); |
|
|
|
// Since position will be absolute, but we need to make it relative to the stage |
|
self.stagePos = $.fancybox.getTranslate(instance.$refs.stage); |
|
|
|
self.sliderStartPos.top -= self.stagePos.top; |
|
self.sliderStartPos.left -= self.stagePos.left; |
|
|
|
self.contentStartPos.top -= self.stagePos.top; |
|
self.contentStartPos.left -= self.stagePos.left; |
|
|
|
$(document) |
|
.off(".fb.touch") |
|
.on(isTouchDevice ? "touchend.fb.touch touchcancel.fb.touch" : "mouseup.fb.touch mouseleave.fb.touch", $.proxy(self, "ontouchend")) |
|
.on(isTouchDevice ? "touchmove.fb.touch" : "mousemove.fb.touch", $.proxy(self, "ontouchmove")); |
|
|
|
if ($.fancybox.isMobile) { |
|
document.addEventListener("scroll", self.onscroll, true); |
|
} |
|
|
|
if (!(self.opts || instance.canPan()) || !($target.is(self.$stage) || self.$stage.find($target).length)) { |
|
if ($target.is(".fancybox-image")) { |
|
e.preventDefault(); |
|
} |
|
|
|
return; |
|
} |
|
|
|
if (!($.fancybox.isMobile && (isScrollable($target) || isScrollable($target.parent())))) { |
|
e.preventDefault(); |
|
} |
|
|
|
if (self.startPoints.length === 1 || current.hasError) { |
|
if (self.instance.canPan()) { |
|
$.fancybox.stop(self.$content); |
|
|
|
self.$content.css("transition-duration", ""); |
|
|
|
self.isPanning = true; |
|
} else { |
|
self.isSwiping = true; |
|
} |
|
|
|
self.$container.addClass("fancybox-controls--isGrabbing"); |
|
} |
|
|
|
if (self.startPoints.length === 2 && current.type === "image" && (current.isLoaded || current.$ghost)) { |
|
self.canTap = false; |
|
self.isSwiping = false; |
|
self.isPanning = false; |
|
|
|
self.isZooming = true; |
|
|
|
$.fancybox.stop(self.$content); |
|
|
|
self.$content.css("transition-duration", ""); |
|
|
|
self.centerPointStartX = (self.startPoints[0].x + self.startPoints[1].x) * 0.5 - $(window).scrollLeft(); |
|
self.centerPointStartY = (self.startPoints[0].y + self.startPoints[1].y) * 0.5 - $(window).scrollTop(); |
|
|
|
self.percentageOfImageAtPinchPointX = (self.centerPointStartX - self.contentStartPos.left) / self.contentStartPos.width; |
|
self.percentageOfImageAtPinchPointY = (self.centerPointStartY - self.contentStartPos.top) / self.contentStartPos.height; |
|
|
|
self.startDistanceBetweenFingers = distance(self.startPoints[0], self.startPoints[1]); |
|
} |
|
}; |
|
|
|
Guestures.prototype.onscroll = function(e) { |
|
var self = this; |
|
|
|
self.isScrolling = true; |
|
|
|
document.removeEventListener("scroll", self.onscroll, true); |
|
}; |
|
|
|
Guestures.prototype.ontouchmove = function(e) { |
|
var self = this, |
|
$target = $(e.target); |
|
|
|
// Make sure user has not released over iframe or disabled element |
|
if (e.originalEvent.buttons !== undefined && e.originalEvent.buttons === 0) { |
|
self.ontouchend(e); |
|
return; |
|
} |
|
|
|
if (self.isScrolling || !($target.is(self.$stage) || self.$stage.find($target).length)) { |
|
self.canTap = false; |
|
|
|
return; |
|
} |
|
|
|
self.newPoints = getPointerXY(e); |
|
|
|
if (!(self.opts || self.instance.canPan()) || !self.newPoints.length || !self.newPoints.length) { |
|
return; |
|
} |
|
|
|
if (!(self.isSwiping && self.isSwiping === true)) { |
|
e.preventDefault(); |
|
} |
|
|
|
self.distanceX = distance(self.newPoints[0], self.startPoints[0], "x"); |
|
self.distanceY = distance(self.newPoints[0], self.startPoints[0], "y"); |
|
|
|
self.distance = distance(self.newPoints[0], self.startPoints[0]); |
|
|
|
// Skip false ontouchmove events (Chrome) |
|
if (self.distance > 0) { |
|
if (self.isSwiping) { |
|
self.onSwipe(e); |
|
} else if (self.isPanning) { |
|
self.onPan(); |
|
} else if (self.isZooming) { |
|
self.onZoom(); |
|
} |
|
} |
|
}; |
|
|
|
Guestures.prototype.onSwipe = function(e) { |
|
var self = this, |
|
swiping = self.isSwiping, |
|
left = self.sliderStartPos.left || 0, |
|
angle; |
|
|
|
// If direction is not yet determined |
|
if (swiping === true) { |
|
// We need at least 10px distance to correctly calculate an angle |
|
if (Math.abs(self.distance) > 10) { |
|
self.canTap = false; |
|
|
|
if (self.instance.group.length < 2 && self.opts.vertical) { |
|
self.isSwiping = "y"; |
|
} else if (self.instance.isDragging || self.opts.vertical === false || (self.opts.vertical === "auto" && $(window).width() > 800)) { |
|
self.isSwiping = "x"; |
|
} else { |
|
angle = Math.abs(Math.atan2(self.distanceY, self.distanceX) * 180 / Math.PI); |
|
|
|
self.isSwiping = angle > 45 && angle < 135 ? "y" : "x"; |
|
} |
|
|
|
self.canTap = false; |
|
|
|
if (self.isSwiping === "y" && $.fancybox.isMobile && (isScrollable(self.$target) || isScrollable(self.$target.parent()))) { |
|
self.isScrolling = true; |
|
|
|
return; |
|
} |
|
|
|
self.instance.isDragging = self.isSwiping; |
|
|
|
// Reset points to avoid jumping, because we dropped first swipes to calculate the angle |
|
self.startPoints = self.newPoints; |
|
|
|
$.each(self.instance.slides, function(index, slide) { |
|
$.fancybox.stop(slide.$slide); |
|
|
|
slide.$slide.css("transition-duration", ""); |
|
|
|
slide.inTransition = false; |
|
|
|
if (slide.pos === self.instance.current.pos) { |
|
self.sliderStartPos.left = $.fancybox.getTranslate(slide.$slide).left - $.fancybox.getTranslate(self.instance.$refs.stage).left; |
|
} |
|
}); |
|
|
|
// Stop slideshow |
|
if (self.instance.SlideShow && self.instance.SlideShow.isActive) { |
|
self.instance.SlideShow.stop(); |
|
} |
|
} |
|
|
|
return; |
|
} |
|
|
|
// Sticky edges |
|
if (swiping == "x") { |
|
if ( |
|
self.distanceX > 0 && |
|
(self.instance.group.length < 2 || (self.instance.current.index === 0 && !self.instance.current.opts.loop)) |
|
) { |
|
left = left + Math.pow(self.distanceX, 0.8); |
|
} else if ( |
|
self.distanceX < 0 && |
|
(self.instance.group.length < 2 || |
|
(self.instance.current.index === self.instance.group.length - 1 && !self.instance.current.opts.loop)) |
|
) { |
|
left = left - Math.pow(-self.distanceX, 0.8); |
|
} else { |
|
left = left + self.distanceX; |
|
} |
|
} |
|
|
|
self.sliderLastPos = { |
|
top: swiping == "x" ? 0 : self.sliderStartPos.top + self.distanceY, |
|
left: left |
|
}; |
|
|
|
if (self.requestId) { |
|
cancelAFrame(self.requestId); |
|
|
|
self.requestId = null; |
|
} |
|
|
|
self.requestId = requestAFrame(function() { |
|
if (self.sliderLastPos) { |
|
$.each(self.instance.slides, function(index, slide) { |
|
var pos = slide.pos - self.instance.currPos; |
|
|
|
$.fancybox.setTranslate(slide.$slide, { |
|
top: self.sliderLastPos.top, |
|
left: self.sliderLastPos.left + pos * self.canvasWidth + pos * slide.opts.gutter |
|
}); |
|
}); |
|
|
|
self.$container.addClass("fancybox-is-sliding"); |
|
} |
|
}); |
|
}; |
|
|
|
Guestures.prototype.onPan = function() { |
|
var self = this; |
|
|
|
// Prevent accidental movement (sometimes, when tapping casually, finger can move a bit) |
|
if (distance(self.newPoints[0], self.realPoints[0]) < ($.fancybox.isMobile ? 10 : 5)) { |
|
self.startPoints = self.newPoints; |
|
return; |
|
} |
|
|
|
self.canTap = false; |
|
|
|
self.contentLastPos = self.limitMovement(); |
|
|
|
if (self.requestId) { |
|
cancelAFrame(self.requestId); |
|
|
|
self.requestId = null; |
|
} |
|
|
|
self.requestId = requestAFrame(function() { |
|
$.fancybox.setTranslate(self.$content, self.contentLastPos); |
|
}); |
|
}; |
|
|
|
// Make panning sticky to the edges |
|
Guestures.prototype.limitMovement = function() { |
|
var self = this; |
|
|
|
var canvasWidth = self.canvasWidth; |
|
var canvasHeight = self.canvasHeight; |
|
|
|
var distanceX = self.distanceX; |
|
var distanceY = self.distanceY; |
|
|
|
var contentStartPos = self.contentStartPos; |
|
|
|
var currentOffsetX = contentStartPos.left; |
|
var currentOffsetY = contentStartPos.top; |
|
|
|
var currentWidth = contentStartPos.width; |
|
var currentHeight = contentStartPos.height; |
|
|
|
var minTranslateX, minTranslateY, maxTranslateX, maxTranslateY, newOffsetX, newOffsetY; |
|
|
|
if (currentWidth > canvasWidth) { |
|
newOffsetX = currentOffsetX + distanceX; |
|
} else { |
|
newOffsetX = currentOffsetX; |
|
} |
|
|
|
newOffsetY = currentOffsetY + distanceY; |
|
|
|
// Slow down proportionally to traveled distance |
|
minTranslateX = Math.max(0, canvasWidth * 0.5 - currentWidth * 0.5); |
|
minTranslateY = Math.max(0, canvasHeight * 0.5 - currentHeight * 0.5); |
|
|
|
maxTranslateX = Math.min(canvasWidth - currentWidth, canvasWidth * 0.5 - currentWidth * 0.5); |
|
maxTranslateY = Math.min(canvasHeight - currentHeight, canvasHeight * 0.5 - currentHeight * 0.5); |
|
|
|
// -> |
|
if (distanceX > 0 && newOffsetX > minTranslateX) { |
|
newOffsetX = minTranslateX - 1 + Math.pow(-minTranslateX + currentOffsetX + distanceX, 0.8) || 0; |
|
} |
|
|
|
// <- |
|
if (distanceX < 0 && newOffsetX < maxTranslateX) { |
|
newOffsetX = maxTranslateX + 1 - Math.pow(maxTranslateX - currentOffsetX - distanceX, 0.8) || 0; |
|
} |
|
|
|
// \/ |
|
if (distanceY > 0 && newOffsetY > minTranslateY) { |
|
newOffsetY = minTranslateY - 1 + Math.pow(-minTranslateY + currentOffsetY + distanceY, 0.8) || 0; |
|
} |
|
|
|
// /\ |
|
if (distanceY < 0 && newOffsetY < maxTranslateY) { |
|
newOffsetY = maxTranslateY + 1 - Math.pow(maxTranslateY - currentOffsetY - distanceY, 0.8) || 0; |
|
} |
|
|
|
return { |
|
top: newOffsetY, |
|
left: newOffsetX |
|
}; |
|
}; |
|
|
|
Guestures.prototype.limitPosition = function(newOffsetX, newOffsetY, newWidth, newHeight) { |
|
var self = this; |
|
|
|
var canvasWidth = self.canvasWidth; |
|
var canvasHeight = self.canvasHeight; |
|
|
|
if (newWidth > canvasWidth) { |
|
newOffsetX = newOffsetX > 0 ? 0 : newOffsetX; |
|
newOffsetX = newOffsetX < canvasWidth - newWidth ? canvasWidth - newWidth : newOffsetX; |
|
} else { |
|
// Center horizontally |
|
newOffsetX = Math.max(0, canvasWidth / 2 - newWidth / 2); |
|
} |
|
|
|
if (newHeight > canvasHeight) { |
|
newOffsetY = newOffsetY > 0 ? 0 : newOffsetY; |
|
newOffsetY = newOffsetY < canvasHeight - newHeight ? canvasHeight - newHeight : newOffsetY; |
|
} else { |
|
// Center vertically |
|
newOffsetY = Math.max(0, canvasHeight / 2 - newHeight / 2); |
|
} |
|
|
|
return { |
|
top: newOffsetY, |
|
left: newOffsetX |
|
}; |
|
}; |
|
|
|
Guestures.prototype.onZoom = function() { |
|
var self = this; |
|
|
|
// Calculate current distance between points to get pinch ratio and new width and height |
|
var contentStartPos = self.contentStartPos; |
|
|
|
var currentWidth = contentStartPos.width; |
|
var currentHeight = contentStartPos.height; |
|
|
|
var currentOffsetX = contentStartPos.left; |
|
var currentOffsetY = contentStartPos.top; |
|
|
|
var endDistanceBetweenFingers = distance(self.newPoints[0], self.newPoints[1]); |
|
|
|
var pinchRatio = endDistanceBetweenFingers / self.startDistanceBetweenFingers; |
|
|
|
var newWidth = Math.floor(currentWidth * pinchRatio); |
|
var newHeight = Math.floor(currentHeight * pinchRatio); |
|
|
|
// This is the translation due to pinch-zooming |
|
var translateFromZoomingX = (currentWidth - newWidth) * self.percentageOfImageAtPinchPointX; |
|
var translateFromZoomingY = (currentHeight - newHeight) * self.percentageOfImageAtPinchPointY; |
|
|
|
// Point between the two touches |
|
var centerPointEndX = (self.newPoints[0].x + self.newPoints[1].x) / 2 - $(window).scrollLeft(); |
|
var centerPointEndY = (self.newPoints[0].y + self.newPoints[1].y) / 2 - $(window).scrollTop(); |
|
|
|
// And this is the translation due to translation of the centerpoint |
|
// between the two fingers |
|
var translateFromTranslatingX = centerPointEndX - self.centerPointStartX; |
|
var translateFromTranslatingY = centerPointEndY - self.centerPointStartY; |
|
|
|
// The new offset is the old/current one plus the total translation |
|
var newOffsetX = currentOffsetX + (translateFromZoomingX + translateFromTranslatingX); |
|
var newOffsetY = currentOffsetY + (translateFromZoomingY + translateFromTranslatingY); |
|
|
|
var newPos = { |
|
top: newOffsetY, |
|
left: newOffsetX, |
|
scaleX: pinchRatio, |
|
scaleY: pinchRatio |
|
}; |
|
|
|
self.canTap = false; |
|
|
|
self.newWidth = newWidth; |
|
self.newHeight = newHeight; |
|
|
|
self.contentLastPos = newPos; |
|
|
|
if (self.requestId) { |
|
cancelAFrame(self.requestId); |
|
|
|
self.requestId = null; |
|
} |
|
|
|
self.requestId = requestAFrame(function() { |
|
$.fancybox.setTranslate(self.$content, self.contentLastPos); |
|
}); |
|
}; |
|
|
|
Guestures.prototype.ontouchend = function(e) { |
|
var self = this; |
|
var dMs = Math.max(new Date().getTime() - self.startTime, 1); |
|
|
|
var swiping = self.isSwiping; |
|
var panning = self.isPanning; |
|
var zooming = self.isZooming; |
|
var scrolling = self.isScrolling; |
|
|
|
self.endPoints = getPointerXY(e); |
|
|
|
self.$container.removeClass("fancybox-controls--isGrabbing"); |
|
|
|
$(document).off(".fb.touch"); |
|
|
|
document.removeEventListener("scroll", self.onscroll, true); |
|
|
|
if (self.requestId) { |
|
cancelAFrame(self.requestId); |
|
|
|
self.requestId = null; |
|
} |
|
|
|
self.isSwiping = false; |
|
self.isPanning = false; |
|
self.isZooming = false; |
|
self.isScrolling = false; |
|
|
|
self.instance.isDragging = false; |
|
|
|
if (self.canTap) { |
|
return self.onTap(e); |
|
} |
|
|
|
self.speed = 366; |
|
|
|
// Speed in px/ms |
|
self.velocityX = self.distanceX / dMs * 0.5; |
|
self.velocityY = self.distanceY / dMs * 0.5; |
|
|
|
self.speedX = Math.max(self.speed * 0.5, Math.min(self.speed * 1.5, 1 / Math.abs(self.velocityX) * self.speed)); |
|
|
|
if (panning) { |
|
self.endPanning(); |
|
} else if (zooming) { |
|
self.endZooming(); |
|
} else { |
|
self.endSwiping(swiping, scrolling); |
|
} |
|
|
|
return; |
|
}; |
|
|
|
Guestures.prototype.endSwiping = function(swiping, scrolling) { |
|
var self = this, |
|
ret = false, |
|
len = self.instance.group.length; |
|
|
|
self.sliderLastPos = null; |
|
|
|
// Close if swiped vertically / navigate if horizontally |
|
if (swiping == "y" && !scrolling && Math.abs(self.distanceY) > 50) { |
|
// Continue vertical movement |
|
$.fancybox.animate( |
|
self.instance.current.$slide, |
|
{ |
|
top: self.sliderStartPos.top + self.distanceY + self.velocityY * 150, |
|
opacity: 0 |
|
}, |
|
200 |
|
); |
|
|
|
ret = self.instance.close(true, 200); |
|
} else if (swiping == "x" && self.distanceX > 50 && len > 1) { |
|
ret = self.instance.previous(self.speedX); |
|
} else if (swiping == "x" && self.distanceX < -50 && len > 1) { |
|
ret = self.instance.next(self.speedX); |
|
} |
|
|
|
if (ret === false && (swiping == "x" || swiping == "y")) { |
|
if (scrolling || len < 2) { |
|
self.instance.centerSlide(self.instance.current, 150); |
|
} else { |
|
self.instance.jumpTo(self.instance.current.index); |
|
} |
|
} |
|
|
|
self.$container.removeClass("fancybox-is-sliding"); |
|
}; |
|
|
|
// Limit panning from edges |
|
// ======================== |
|
Guestures.prototype.endPanning = function() { |
|
var self = this; |
|
var newOffsetX, newOffsetY, newPos; |
|
|
|
if (!self.contentLastPos) { |
|
return; |
|
} |
|
|
|
if (self.opts.momentum === false) { |
|
newOffsetX = self.contentLastPos.left; |
|
newOffsetY = self.contentLastPos.top; |
|
} else { |
|
// Continue movement |
|
newOffsetX = self.contentLastPos.left + self.velocityX * self.speed; |
|
newOffsetY = self.contentLastPos.top + self.velocityY * self.speed; |
|
} |
|
|
|
newPos = self.limitPosition(newOffsetX, newOffsetY, self.contentStartPos.width, self.contentStartPos.height); |
|
|
|
newPos.width = self.contentStartPos.width; |
|
newPos.height = self.contentStartPos.height; |
|
|
|
$.fancybox.animate(self.$content, newPos, 330); |
|
}; |
|
|
|
Guestures.prototype.endZooming = function() { |
|
var self = this; |
|
|
|
var current = self.instance.current; |
|
|
|
var newOffsetX, newOffsetY, newPos, reset; |
|
|
|
var newWidth = self.newWidth; |
|
var newHeight = self.newHeight; |
|
|
|
if (!self.contentLastPos) { |
|
return; |
|
} |
|
|
|
newOffsetX = self.contentLastPos.left; |
|
newOffsetY = self.contentLastPos.top; |
|
|
|
reset = { |
|
top: newOffsetY, |
|
left: newOffsetX, |
|
width: newWidth, |
|
height: newHeight, |
|
scaleX: 1, |
|
scaleY: 1 |
|
}; |
|
|
|
// Reset scalex/scaleY values; this helps for perfomance and does not break animation |
|
$.fancybox.setTranslate(self.$content, reset); |
|
|
|
if (newWidth < self.canvasWidth && newHeight < self.canvasHeight) { |
|
self.instance.scaleToFit(150); |
|
} else if (newWidth > current.width || newHeight > current.height) { |
|
self.instance.scaleToActual(self.centerPointStartX, self.centerPointStartY, 150); |
|
} else { |
|
newPos = self.limitPosition(newOffsetX, newOffsetY, newWidth, newHeight); |
|
|
|
// Switch from scale() to width/height or animation will not work correctly |
|
$.fancybox.setTranslate(self.$content, $.fancybox.getTranslate(self.$content)); |
|
|
|
$.fancybox.animate(self.$content, newPos, 150); |
|
} |
|
}; |
|
|
|
Guestures.prototype.onTap = function(e) { |
|
var self = this; |
|
var $target = $(e.target); |
|
|
|
var instance = self.instance; |
|
var current = instance.current; |
|
|
|
var endPoints = (e && getPointerXY(e)) || self.startPoints; |
|
|
|
var tapX = endPoints[0] ? endPoints[0].x - $(window).scrollLeft() - self.stagePos.left : 0; |
|
var tapY = endPoints[0] ? endPoints[0].y - $(window).scrollTop() - self.stagePos.top : 0; |
|
|
|
var where; |
|
|
|
var process = function(prefix) { |
|
var action = current.opts[prefix]; |
|
|
|
if ($.isFunction(action)) { |
|
action = action.apply(instance, [current, e]); |
|
} |
|
|
|
if (!action) { |
|
return; |
|
} |
|
|
|
switch (action) { |
|
case "close": |
|
instance.close(self.startEvent); |
|
|
|
break; |
|
|
|
case "toggleControls": |
|
instance.toggleControls(true); |
|
|
|
break; |
|
|
|
case "next": |
|
instance.next(); |
|
|
|
break; |
|
|
|
case "nextOrClose": |
|
if (instance.group.length > 1) { |
|
instance.next(); |
|
} else { |
|
instance.close(self.startEvent); |
|
} |
|
|
|
break; |
|
|
|
case "zoom": |
|
if (current.type == "image" && (current.isLoaded || current.$ghost)) { |
|
if (instance.canPan()) { |
|
instance.scaleToFit(); |
|
} else if (instance.isScaledDown()) { |
|
instance.scaleToActual(tapX, tapY); |
|
} else if (instance.group.length < 2) { |
|
instance.close(self.startEvent); |
|
} |
|
} |
|
|
|
break; |
|
} |
|
}; |
|
|
|
// Ignore right click |
|
if (e.originalEvent && e.originalEvent.button == 2) { |
|
return; |
|
} |
|
|
|
// Skip if clicked on the scrollbar |
|
if (!$target.is("img") && tapX > $target[0].clientWidth + $target.offset().left) { |
|
return; |
|
} |
|
|
|
// Check where is clicked |
|
if ($target.is(".fancybox-bg,.fancybox-inner,.fancybox-outer,.fancybox-container")) { |
|
where = "Outside"; |
|
} else if ($target.is(".fancybox-slide")) { |
|
where = "Slide"; |
|
} else if ( |
|
instance.current.$content && |
|
instance.current.$content |
|
.find($target) |
|
.addBack() |
|
.filter($target).length |
|
) { |
|
where = "Content"; |
|
} else { |
|
return; |
|
} |
|
|
|
// Check if this is a double tap |
|
if (self.tapped) { |
|
// Stop previously created single tap |
|
clearTimeout(self.tapped); |
|
self.tapped = null; |
|
|
|
// Skip if distance between taps is too big |
|
if (Math.abs(tapX - self.tapX) > 50 || Math.abs(tapY - self.tapY) > 50) { |
|
return this; |
|
} |
|
|
|
// OK, now we assume that this is a double-tap |
|
process("dblclick" + where); |
|
} else { |
|
// Single tap will be processed if user has not clicked second time within 300ms |
|
// or there is no need to wait for double-tap |
|
self.tapX = tapX; |
|
self.tapY = tapY; |
|
|
|
if (current.opts["dblclick" + where] && current.opts["dblclick" + where] !== current.opts["click" + where]) { |
|
self.tapped = setTimeout(function() { |
|
self.tapped = null; |
|
|
|
process("click" + where); |
|
}, 500); |
|
} else { |
|
process("click" + where); |
|
} |
|
} |
|
|
|
return this; |
|
}; |
|
|
|
$(document).on("onActivate.fb", function(e, instance) { |
|
if (instance && !instance.Guestures) { |
|
instance.Guestures = new Guestures(instance); |
|
} |
|
}); |
|
})(window, document, window.jQuery || jQuery);
|
|
|