summaryrefslogtreecommitdiffstats
path: root/assets
diff options
context:
space:
mode:
authorAndy Huang <ath@google.com>2012-11-28 22:38:02 -0800
committerAndy Huang <ath@google.com>2012-12-12 16:55:14 -0800
commit02f9d18a54072db8d86c524f9c09e508092ddd7c (patch)
tree712e1b78fefd0e2d9afcc38b791315591fba78ae /assets
parent0886b2910872b17f6cb6716ee4e92fba3c69d873 (diff)
downloadandroid_packages_apps_UnifiedEmail-02f9d18a54072db8d86c524f9c09e508092ddd7c.tar.gz
android_packages_apps_UnifiedEmail-02f9d18a54072db8d86c524f9c09e508092ddd7c.tar.bz2
android_packages_apps_UnifiedEmail-02f9d18a54072db8d86c524f9c09e508092ddd7c.zip
per-message zoom using JavaScript + CSS 3D transforms
When Auto-fit is off, disable built-in WebView zooming, which is only capable of zooming an entire document (the entire conversation). Use ScaleGestureDetector to trigger a CSS 3D transform to zoom in/out just a single message div. During the gesture, the elements above and below the message being scaled are untouched. This is ugly. TODO: they should either move away (tricky) or at least fade out. When the gesture is complete, to avoid leaving overlapping elements, we force-scale the height and reset the transform origin to the top left. TODO: auto-scroll to the correct place to counteract this perceived jump. Double-tap is not yet implemented. We'll have to do it ourselves. Bug: 7478834 Change-Id: I114e4977304c7060d499d116cc75bc0488967448
Diffstat (limited to 'assets')
-rw-r--r--assets/script.js120
1 files changed, 120 insertions, 0 deletions
diff --git a/assets/script.js b/assets/script.js
index 4a015786f..6ea24e819 100644
--- a/assets/script.js
+++ b/assets/script.js
@@ -21,6 +21,8 @@ var BLOCKED_SRC_ATTR = "blocked-src";
// this is an Array, but we treat it like a Set and only insert unique items
var gImageLoadElements = [];
+var gScaleInfo;
+
/**
* Returns the page offset of an element.
*
@@ -59,6 +61,17 @@ function up(el, className) {
return parent || null;
}
+function getCachedValue(div, property, attrName) {
+ var value;
+ if (div.hasAttribute(attrName)) {
+ value = div.getAttribute(attrName);
+ } else {
+ value = div[property];
+ div.setAttribute(attrName, value);
+ }
+ return value;
+}
+
function onToggleClick(e) {
toggleQuotedText(e.target);
measurePositions();
@@ -448,6 +461,113 @@ function appendMessageHtml() {
measurePositions();
}
+function onScaleBegin(screenX, screenY) {
+// console.log("JS got scaleBegin x/y=" + screenX + "/" + screenY);
+ var focusX = screenX + document.body.scrollLeft;
+ var focusY = screenY + document.body.scrollTop;
+ var i, len;
+ var msgDivs = document.getElementsByClassName("mail-message");
+ var msgDiv, msgBodyDiv;
+ var msgTop, msgDivTop, nextMsgTop;
+ var initialH;
+ var initialScale;
+ var scaledOriginX, scaledOriginY;
+ var translateX, translateY;
+ var origin;
+
+ gScaleInfo = undefined;
+
+ for (i = 0, len = msgDivs.length; i < len; i++) {
+ msgDiv = msgDivs[i];
+ msgTop = nextMsgTop ? nextMsgTop : getTotalOffset(msgDiv).top;
+ nextMsgTop = (i < len-1) ? getTotalOffset(msgDivs[i+1]).top : document.body.offsetHeight;
+ if (focusY >= msgTop && focusY < nextMsgTop) {
+ msgBodyDiv = msgDiv.children[1];
+ initialScale = msgBodyDiv.getAttribute("data-initial-scale") || 1.0;
+
+ msgDivTop = getTotalOffset(msgBodyDiv).top;
+
+ scaledOriginX = focusX;// / initialScale;
+ scaledOriginY = (focusY - msgDivTop);// / initialScale;
+
+ translateX = scaledOriginX * (initialScale - 1.0) / initialScale;
+ translateY = scaledOriginY * (initialScale - 1.0) / initialScale;
+
+ gScaleInfo = {
+ div: msgBodyDiv,
+ divTop: msgDivTop,
+ initialScale: initialScale,
+ initialX: focusX,
+ initialY: focusY,
+ translateX: translateX,
+ translateY: translateY,
+ initialH: getCachedValue(msgBodyDiv, "offsetHeight", "data-initial-height"),
+ minScale: Math.min(document.body.offsetWidth / msgBodyDiv.scrollWidth, 1.0),
+ currScale: initialScale
+ };
+
+ origin = scaledOriginX + "px " + scaledOriginY + "px";
+ msgBodyDiv.classList.add("zooming-focused");
+ msgBodyDiv.style.webkitTransformOrigin = origin;
+ msgBodyDiv.style.webkitTransform = "scale3d(" + initialScale + "," + initialScale
+ + ",1) translate3d(" + translateX + "px," + translateY + "px,0)";
+// console.log("scaleBegin, h=" + gScaleInfo.initialH + " origin='" + origin + "'");
+ break;
+ }
+ }
+}
+
+function onScaleEnd(screenX, screenY) {
+ var msgBodyDiv;
+ var scale;
+ var h;
+ if (!gScaleInfo) {
+ return;
+ }
+
+// console.log("JS got scaleEnd x/y=" + screenX + "/" + screenY);
+ msgBodyDiv = gScaleInfo.div;
+ scale = gScaleInfo.currScale;
+ msgBodyDiv.style.webkitTransformOrigin = "0 0";
+ // clear any translate
+ msgBodyDiv.style.webkitTransform = "scale3d(" + scale + "," + scale + ",1)";
+ // switching to a 2D transform here re-renders the fonts more clearly, but introduces
+ // texture upload lag to any subsequent scale operation
+ //msgBodyDiv.style.webkitTransform = "scale(" + gScaleInfo.currScale + ")";
+ h = gScaleInfo.initialH * scale;
+// console.log("onScaleEnd set h=" + h);
+ msgBodyDiv.style.height = h + "px";
+ msgBodyDiv.classList.remove("zooming-focused");
+ msgBodyDiv.setAttribute("data-initial-scale", scale);
+}
+
+function onScale(relativeScale, screenX, screenY) {
+ var focusX, focusY;
+ var scale;
+ var translateX, translateY;
+ var transform;
+
+ if (!gScaleInfo) {
+ return;
+ }
+ focusX = screenX + document.body.scrollLeft;
+ focusY = screenY + document.body.scrollTop;
+
+ scale = Math.max(gScaleInfo.initialScale * relativeScale, gScaleInfo.minScale);
+ if (scale > 4.0) {
+ scale = 4.0;
+ }
+ gScaleInfo.currScale = scale;
+ translateX = focusX - gScaleInfo.initialX;
+ translateY = focusY - gScaleInfo.initialY;
+ transform = "translate3d(" + translateX + "px," + translateY + "px,0) scale3d("
+ + scale + "," + scale + ",1) translate3d(" + gScaleInfo.translateX + "px,"
+ + gScaleInfo.translateY + "px,0)";
+ gScaleInfo.div.style.webkitTransform = transform;
+// console.log("JS got scale=" + relativeScale + " x/y=" + screenX + "/" + screenY
+// + " transform='" + transform + "'");
+}
+
// END Java->JavaScript handlers
// Do this first to ensure that the readiness signal comes through,