mirror of
https://github.com/Jermolene/TiddlyWiki5
synced 2024-11-19 08:14:50 +00:00
04e91245cb
Now there is now longer a dummy DOM element corresponding to the macro itself. Instead, macros must create a single element child. This allows us to more easily fit Bootstrap's requirements for HTML layout (eg, that problem with links in navbars not being recognised). The refactoring isn't complete, there are still a few bugs to chase down
107 lines
3.6 KiB
JavaScript
107 lines
3.6 KiB
JavaScript
/*\
|
|
title: $:/core/modules/macros/zoomer.js
|
|
type: application/javascript
|
|
module-type: macro
|
|
|
|
Zooming navigator macro
|
|
|
|
\*/
|
|
(function(){
|
|
|
|
/*jslint node: true, browser: true */
|
|
/*global $tw: false */
|
|
"use strict";
|
|
|
|
exports.info = {
|
|
name: "zoomer",
|
|
params: {
|
|
},
|
|
events: ["touchstart","touchmove","touchend"]
|
|
};
|
|
|
|
exports.startZoomer = function(x,y) {
|
|
this.inZoomer = true;
|
|
this.startX = x;
|
|
this.startY = y;
|
|
$tw.utils.addClass(document.body,"in-zoomer");
|
|
};
|
|
|
|
/*
|
|
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
|
|
document.body.style[$tw.browser.transformorigin] = "50% 0";
|
|
// 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)";
|
|
document.body.style[$tw.browser.transform] = transform;
|
|
};
|
|
|
|
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)";
|
|
};
|
|
|
|
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;
|
|
return $tw.Tree.Element("div",{},[]);
|
|
};
|
|
|
|
})();
|