2012-04-30 11:23:03 +00:00
|
|
|
/*\
|
2012-05-03 20:47:16 +00:00
|
|
|
title: $:/core/modules/macros/zoomer.js
|
2012-04-30 11:23:03 +00:00
|
|
|
type: application/javascript
|
|
|
|
module-type: macro
|
|
|
|
|
2012-05-19 17:23:14 +00:00
|
|
|
Zooming navigator macro
|
|
|
|
|
2012-04-30 11:23:03 +00:00
|
|
|
\*/
|
|
|
|
(function(){
|
|
|
|
|
|
|
|
/*jslint node: true, browser: true */
|
2012-05-04 17:49:04 +00:00
|
|
|
/*global $tw: false */
|
2012-04-30 11:23:03 +00:00
|
|
|
"use strict";
|
|
|
|
|
|
|
|
exports.info = {
|
|
|
|
name: "zoomer",
|
|
|
|
params: {
|
2012-06-14 16:15:38 +00:00
|
|
|
}
|
2012-04-30 11:23:03 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
exports.startZoomer = function(x,y) {
|
|
|
|
this.inZoomer = true;
|
|
|
|
this.startX = x;
|
|
|
|
this.startY = y;
|
|
|
|
$tw.utils.addClass(document.body,"in-zoomer");
|
2012-05-04 17:49:04 +00:00
|
|
|
};
|
2012-04-30 11:23:03 +00:00
|
|
|
|
|
|
|
/*
|
|
|
|
Zoom the body element given a touch/mouse position in screen coordinates
|
|
|
|
*/
|
|
|
|
exports.hoverZoomer = function(x,y) {
|
|
|
|
// Put the transform origin at the top in the middle
|
2012-06-07 12:29:16 +00:00
|
|
|
document.body.style[$tw.browser.transformorigin] = "50% 0";
|
2012-04-30 11:23:03 +00:00
|
|
|
// Some shortcuts
|
|
|
|
this.bodyWidth = document.body.offsetWidth;
|
|
|
|
this.bodyHeight = document.body.offsetHeight;
|
|
|
|
this.windowWidth = window.innerWidth;
|
|
|
|
this.windowHeight = window.innerHeight;
|
|
|
|
// Compute the scale factor for fitting the entire page into the window. This is
|
|
|
|
// the scale factor we'll use when the touch is far to the left
|
|
|
|
this.minScale = this.windowHeight / this.bodyHeight;
|
|
|
|
if(this.minScale < 0.1) {
|
|
|
|
// Don't scale to less than 10% of original size
|
|
|
|
this.minScale = 0.1;
|
|
|
|
} else if(this.minScale > 1) {
|
|
|
|
// Nor should we scale up if the body is shorter than the window
|
|
|
|
this.minScale = 1;
|
|
|
|
}
|
|
|
|
// We divide the screen into two horizontal zones divided by the right edge of the body at maximum zoom (ie minimum scale)
|
|
|
|
this.splitPos = this.windowWidth/2 + (this.bodyWidth * this.minScale)/2;
|
|
|
|
// Compute the 0->1 ratio (from right to left) of the position of the touch within the right zone
|
|
|
|
this.xFactor = (this.windowWidth - x) / (this.windowWidth - this.splitPos);
|
|
|
|
if(this.xFactor > 1) {
|
|
|
|
this.xFactor = 1;
|
|
|
|
}
|
|
|
|
// And the 0->1 ratio (from top to bottom) of the position of the touch down the screen
|
|
|
|
this.yFactor = y/this.windowHeight;
|
|
|
|
// Now interpolate the scale
|
|
|
|
this.scale = (this.minScale - 1) * this.xFactor + 1;
|
|
|
|
// Apply the transform. The malarkey with .toFixed() is because otherwise we might get numbers in
|
|
|
|
// exponential notation (such as 5.1e-15) that are illegal in CSS
|
|
|
|
var preTranslateY = window.scrollY * this.xFactor,
|
|
|
|
scale = this.scale,
|
|
|
|
postTranslateY = ((this.windowHeight / this.scale) - this.bodyHeight) * this.yFactor * this.xFactor;
|
|
|
|
var transform = "translateY(" + preTranslateY.toFixed(8) + "px) " +
|
|
|
|
"scale(" + scale.toFixed(8) + ") " +
|
|
|
|
"translateY(" + postTranslateY.toFixed(8) + "px)";
|
2012-06-07 12:29:16 +00:00
|
|
|
document.body.style[$tw.browser.transform] = transform;
|
2012-04-30 11:23:03 +00:00
|
|
|
};
|
|
|
|
|
2012-06-07 12:46:41 +00:00
|
|
|
exports.stopZoomer = function() {
|
|
|
|
var newScrollY = this.yFactor * (this.bodyHeight - this.windowHeight);
|
|
|
|
this.inZoomer = false;
|
|
|
|
window.scrollTo(0,newScrollY);
|
|
|
|
document.body.style[$tw.browser.transform] = "translateY(" + newScrollY * this.xFactor + "px) " +
|
|
|
|
"scale(" + this.scale + ") " +
|
|
|
|
"translateY(" + ((this.windowHeight / this.scale) - this.bodyHeight) * this.yFactor * this.xFactor + "px)";
|
|
|
|
$tw.utils.removeClass(document.body,"in-zoomer");
|
|
|
|
document.body.style[$tw.browser.transform] = "translateY(0) scale(1) translateY(0)";
|
|
|
|
};
|
|
|
|
|
2012-04-30 11:23:03 +00:00
|
|
|
exports.handleEvent = function(event) {
|
|
|
|
switch(event.type) {
|
|
|
|
case "touchstart":
|
|
|
|
this.startZoomer(event.touches[0].clientX,event.touches[0].clientY);
|
|
|
|
this.hoverZoomer(event.touches[0].clientX,event.touches[0].clientY);
|
|
|
|
event.preventDefault();
|
|
|
|
return false;
|
|
|
|
case "touchmove":
|
|
|
|
this.hoverZoomer(event.touches[0].clientX,event.touches[0].clientY);
|
|
|
|
event.preventDefault();
|
|
|
|
return false;
|
|
|
|
case "touchend":
|
|
|
|
this.stopZoomer();
|
|
|
|
event.preventDefault();
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
exports.executeMacro = function() {
|
|
|
|
this.inZoomer = false;
|
2012-06-11 12:05:57 +00:00
|
|
|
var attributes = {
|
2012-06-11 16:36:40 +00:00
|
|
|
style: {
|
|
|
|
"position": "absolute",
|
|
|
|
"right": "0",
|
|
|
|
"top": "0",
|
|
|
|
"min-width": "16px",
|
|
|
|
"height": "100%" // Makes the height the same as the body, since the body is position:relative
|
|
|
|
}
|
|
|
|
};
|
2012-06-11 12:05:57 +00:00
|
|
|
if(this.classes) {
|
|
|
|
attributes["class"] = this.classes.slice(0);
|
|
|
|
}
|
2012-06-14 16:15:38 +00:00
|
|
|
return $tw.Tree.Element("div",attributes,[],{
|
|
|
|
events: ["touchstart","touchmove","touchend"],
|
|
|
|
eventHandler: this
|
|
|
|
});
|
2012-04-30 11:23:03 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
})();
|