summaryrefslogtreecommitdiffstats
path: root/assets
diff options
context:
space:
mode:
authorAndy Huang <ath@google.com>2013-03-08 13:50:36 -0800
committerAndy Huang <ath@google.com>2013-03-08 13:50:36 -0800
commit3a398b245930ce60ceb51fc605ab0f20c8df1f62 (patch)
tree5da7a79eb8cce754576d890f3fa986e1af39f835 /assets
parent5ea5a8330532a75c83cbb30993a14ee9b821fa2a (diff)
downloadandroid_packages_apps_UnifiedEmail-3a398b245930ce60ceb51fc605ab0f20c8df1f62.tar.gz
android_packages_apps_UnifiedEmail-3a398b245930ce60ceb51fc605ab0f20c8df1f62.tar.bz2
android_packages_apps_UnifiedEmail-3a398b245930ce60ceb51fc605ab0f20c8df1f62.zip
reverse ineffective HTML transforms, add aggressive <td> transform
Reverse <table> and <td> transform work when the resulting width is unchanged, or significantly unchanged (below a threshold). Switch <table> and <td> transforms to use CSS !important overriding instead of modifying the elements inline. This is easier to reverse. Add another <td> transform to aggressively trigger word wrapping intra- word. This helps break long signatures, but it can render complex promotional email unreadable. I'll have to hide this behind a classifier that prevents this from running on complex messages. Bug: 7400516 Change-Id: Ia17bae2b28eeec9d1cd40d0292380ae5d660586d
Diffstat (limited to 'assets')
-rw-r--r--assets/script.js109
1 files changed, 91 insertions, 18 deletions
diff --git a/assets/script.js b/assets/script.js
index acf219002..c4f3ae6d2 100644
--- a/assets/script.js
+++ b/assets/script.js
@@ -24,6 +24,13 @@ var gImageLoadElements = [];
var gScaleInfo;
/**
+ * Only revert transforms that do an imperfect job of shrinking content if they fail
+ * to shrink by this much. Expressed as a ratio of:
+ * (original width difference : width difference after transforms);
+ */
+TRANSFORM_MINIMUM_EFFECTIVE_RATIO = 0.75;
+
+/**
* Returns the page offset of an element.
*
* @param {Element} element The element to return the page offset for.
@@ -188,51 +195,117 @@ function normalizeElementWidths(elements) {
function mungeTables(el, docWidth, elWidth) {
var nodes;
var i, len;
- var newWidth;
+ var newWidth = elWidth;
var wStr;
- var touched = false;
+ var touched;
+ var actionLog = [];
+ var node;
+ var start;
if (elWidth <= docWidth) {
return;
}
- // first find tables with widths and strip them of widths
- nodes = el.querySelectorAll("table[width]");
+
+ start = Date.now();
+ // Try munging all divs with inline styles where the width
+ // is wider than docWidth, and change it to be a max-width.
+ touched = false;
+ nodes = el.querySelectorAll("div[style]");
for (i = 0, len = nodes.length; i < len; i++) {
- if (nodes[i].hasAttribute("width")) {
- nodes[i].removeAttribute("width");
+ node = nodes[i];
+ wStr = node.style.width;
+ if (wStr && wStr.slice(0, -2) > docWidth) {
+ node.style.width = "";
+ node.style.maxWidth = wStr;
touched = true;
}
}
if (touched) {
newWidth = el.scrollWidth;
+ console.log("ran div-width munger on el=" + el + " oldW=" + elWidth + " newW=" + newWidth
+ + " docW=" + docWidth);
+ if (newWidth <= docWidth) {
+ console.log("munger succeeded, elapsed time=" + (Date.now() - start));
+ return;
+ }
+ }
+
+ // OK, that wasn't enough. Find tables with widths and override their widths.
+ touched = addClassToElements(el.querySelectorAll("table"), shouldMungeTable, "munged",
+ actionLog);
+ if (touched) {
+ newWidth = el.scrollWidth;
console.log("ran table munger on el=" + el + " oldW=" + elWidth + " newW=" + newWidth
+ " docW=" + docWidth);
if (newWidth <= docWidth) {
+ console.log("munger succeeded, elapsed time=" + (Date.now() - start));
return;
}
}
- // OK, that wasn't enough. Try munging all divs with inline styles where the width
- // is wider than docWidth, and change it to be a max-width.
- touched = false;
- nodes = el.querySelectorAll("div[style]");
- for (i = 0, len = nodes.length; i < len; i++) {
- wStr = nodes[i].style.width;
- if (wStr && wStr.slice(0, -2) > docWidth) {
- nodes[i].style.width = "";
- nodes[i].style.maxWidth = wStr;
- touched = true;
+ // OK, that wasn't enough. Try munging all <td> to override any width and nowrap set.
+ touched = addClassToElements(el.querySelectorAll("td"), null /* mungeAll */, "munged",
+ actionLog);
+ if (touched) {
+ newWidth = el.scrollWidth;
+ console.log("ran td munger on el=" + el + " oldW=" + elWidth + " newW=" + newWidth
+ + " docW=" + docWidth);
+ if (newWidth <= docWidth) {
+ console.log("munger succeeded, elapsed time=" + (Date.now() - start));
+ return;
}
}
+
+ // OK, that wasn't enough. Try further munging all <td> to override text wrapping.
+ touched = addClassToElements(el.querySelectorAll("td"), null /* mungeAll */, "munged2",
+ actionLog);
if (touched) {
newWidth = el.scrollWidth;
- console.log("ran div-width munger on el=" + el + " oldW=" + elWidth + " newW=" + newWidth
+ console.log("ran td munger2 on el=" + el + " oldW=" + elWidth + " newW=" + newWidth
+ " docW=" + docWidth);
if (newWidth <= docWidth) {
+ console.log("munger succeeded, elapsed time=" + (Date.now() - start));
return;
}
}
- // TODO: consider reversing changes that didn't help
+ // If the transformations shrank the width significantly enough, leave them in place.
+ // We figure that in those cases, the benefits outweight the risk of rendering artifacts.
+ //
+ // TODO: this is a risky transform that should not be attempted on sufficiently complex mail.
+ // (TBD how to measure that)
+ if ((elWidth - newWidth) / (elWidth - docWidth) > TRANSFORM_MINIMUM_EFFECTIVE_RATIO) {
+ console.log("transform(s) deemed effective enough. elapsed time="
+ + (Date.now() - start));
+ return;
+ }
+
+ // reverse all changes if the width is STILL not narrow enough
+ // (except the width->maxWidth change, which is not particularly destructive)
+ for (i = 0, len = actionLog.length; i < len; i++) {
+ actionLog[i][0].classList.remove(actionLog[i][1]);
+ }
+ if (actionLog.length > 0) {
+ console.log("all mungers failed, changes reversed. elapsed time=" + (Date.now() - start));
+ }
+}
+
+function addClassToElements(nodes, conditionFn, classToAdd, actionLog) {
+ var i, len;
+ var node;
+ var added = false;
+ for (i = 0, len = nodes.length; i < len; i++) {
+ node = nodes[i];
+ if (!conditionFn || conditionFn(node)) {
+ node.classList.add(classToAdd);
+ added = true;
+ actionLog.push([node, classToAdd]);
+ }
+ }
+ return added;
+}
+
+function shouldMungeTable(table) {
+ return table.hasAttribute("width") || table.style.width;
}
function hideAllUnsafeImages() {