1f70fc4052b72a850bbb9be585d0f5a4877ee9448Andy Huang/* 2f70fc4052b72a850bbb9be585d0f5a4877ee9448Andy Huang * Copyright (C) 2012 Google Inc. 3f70fc4052b72a850bbb9be585d0f5a4877ee9448Andy Huang * Licensed to The Android Open Source Project. 4f70fc4052b72a850bbb9be585d0f5a4877ee9448Andy Huang * 5f70fc4052b72a850bbb9be585d0f5a4877ee9448Andy Huang * Licensed under the Apache License, Version 2.0 (the "License"); 6f70fc4052b72a850bbb9be585d0f5a4877ee9448Andy Huang * you may not use this file except in compliance with the License. 7f70fc4052b72a850bbb9be585d0f5a4877ee9448Andy Huang * You may obtain a copy of the License at 8f70fc4052b72a850bbb9be585d0f5a4877ee9448Andy Huang * 9f70fc4052b72a850bbb9be585d0f5a4877ee9448Andy Huang * http://www.apache.org/licenses/LICENSE-2.0 10f70fc4052b72a850bbb9be585d0f5a4877ee9448Andy Huang * 11f70fc4052b72a850bbb9be585d0f5a4877ee9448Andy Huang * Unless required by applicable law or agreed to in writing, software 12f70fc4052b72a850bbb9be585d0f5a4877ee9448Andy Huang * distributed under the License is distributed on an "AS IS" BASIS, 13f70fc4052b72a850bbb9be585d0f5a4877ee9448Andy Huang * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14f70fc4052b72a850bbb9be585d0f5a4877ee9448Andy Huang * See the License for the specific language governing permissions and 15f70fc4052b72a850bbb9be585d0f5a4877ee9448Andy Huang * limitations under the License. 16f70fc4052b72a850bbb9be585d0f5a4877ee9448Andy Huang */ 17f70fc4052b72a850bbb9be585d0f5a4877ee9448Andy Huang 183233bff8ae08a56543c9f5abf1bc6ab38f0574ceAndy Huangvar BLOCKED_SRC_ATTR = "blocked-src"; 19f70fc4052b72a850bbb9be585d0f5a4877ee9448Andy Huang 2063b3c6725d60386f564ab53e3ba6495f0c158d9bAndy Huang// the set of Elements currently scheduled for processing in handleAllImageLoads 2163b3c6725d60386f564ab53e3ba6495f0c158d9bAndy Huang// this is an Array, but we treat it like a Set and only insert unique items 2263b3c6725d60386f564ab53e3ba6495f0c158d9bAndy Huangvar gImageLoadElements = []; 2363b3c6725d60386f564ab53e3ba6495f0c158d9bAndy Huang 2402f9d18a54072db8d86c524f9c09e508092ddd7cAndy Huangvar gScaleInfo; 2502f9d18a54072db8d86c524f9c09e508092ddd7cAndy Huang 26f70fc4052b72a850bbb9be585d0f5a4877ee9448Andy Huang/** 273a398b245930ce60ceb51fc605ab0f20c8df1f62Andy Huang * Only revert transforms that do an imperfect job of shrinking content if they fail 283a398b245930ce60ceb51fc605ab0f20c8df1f62Andy Huang * to shrink by this much. Expressed as a ratio of: 293a398b245930ce60ceb51fc605ab0f20c8df1f62Andy Huang * (original width difference : width difference after transforms); 303a398b245930ce60ceb51fc605ab0f20c8df1f62Andy Huang */ 3104e53a2e6e71615ddcee39eeb0014a4cd4baf956Andy Huangvar TRANSFORM_MINIMUM_EFFECTIVE_RATIO = 0.7; 3204e53a2e6e71615ddcee39eeb0014a4cd4baf956Andy Huang 3304e53a2e6e71615ddcee39eeb0014a4cd4baf956Andy Huang// Don't ship with this on. 3404e53a2e6e71615ddcee39eeb0014a4cd4baf956Andy Huangvar DEBUG_DISPLAY_TRANSFORMS = false; 353a398b245930ce60ceb51fc605ab0f20c8df1f62Andy Huang 3605c70c88e6b421bedce134799a0ea928dbf44cd5Andy Huangvar gTransformText = {}; 3705c70c88e6b421bedce134799a0ea928dbf44cd5Andy Huang 383a398b245930ce60ceb51fc605ab0f20c8df1f62Andy Huang/** 39f70fc4052b72a850bbb9be585d0f5a4877ee9448Andy Huang * Returns the page offset of an element. 40f70fc4052b72a850bbb9be585d0f5a4877ee9448Andy Huang * 41f70fc4052b72a850bbb9be585d0f5a4877ee9448Andy Huang * @param {Element} element The element to return the page offset for. 42f70fc4052b72a850bbb9be585d0f5a4877ee9448Andy Huang * @return {left: number, top: number} A tuple including a left and top value representing 43f70fc4052b72a850bbb9be585d0f5a4877ee9448Andy Huang * the page offset of the element. 44f70fc4052b72a850bbb9be585d0f5a4877ee9448Andy Huang */ 45f70fc4052b72a850bbb9be585d0f5a4877ee9448Andy Huangfunction getTotalOffset(el) { 46f70fc4052b72a850bbb9be585d0f5a4877ee9448Andy Huang var result = { 47f70fc4052b72a850bbb9be585d0f5a4877ee9448Andy Huang left: 0, 48f70fc4052b72a850bbb9be585d0f5a4877ee9448Andy Huang top: 0 49f70fc4052b72a850bbb9be585d0f5a4877ee9448Andy Huang }; 50f70fc4052b72a850bbb9be585d0f5a4877ee9448Andy Huang var parent = el; 51f70fc4052b72a850bbb9be585d0f5a4877ee9448Andy Huang 52f70fc4052b72a850bbb9be585d0f5a4877ee9448Andy Huang while (parent) { 53f70fc4052b72a850bbb9be585d0f5a4877ee9448Andy Huang result.left += parent.offsetLeft; 54f70fc4052b72a850bbb9be585d0f5a4877ee9448Andy Huang result.top += parent.offsetTop; 55f70fc4052b72a850bbb9be585d0f5a4877ee9448Andy Huang parent = parent.offsetParent; 56f70fc4052b72a850bbb9be585d0f5a4877ee9448Andy Huang } 57f70fc4052b72a850bbb9be585d0f5a4877ee9448Andy Huang 58f70fc4052b72a850bbb9be585d0f5a4877ee9448Andy Huang return result; 59f70fc4052b72a850bbb9be585d0f5a4877ee9448Andy Huang} 60f70fc4052b72a850bbb9be585d0f5a4877ee9448Andy Huang 61ffc725fe4b4fa1024feb22b1d1f76c24febadcdbAndy Huang/** 62ffc725fe4b4fa1024feb22b1d1f76c24febadcdbAndy Huang * Walks up the DOM starting at a given element, and returns an element that has the 63ffc725fe4b4fa1024feb22b1d1f76c24febadcdbAndy Huang * specified class name or null. 64ffc725fe4b4fa1024feb22b1d1f76c24febadcdbAndy Huang */ 65ffc725fe4b4fa1024feb22b1d1f76c24febadcdbAndy Huangfunction up(el, className) { 66ffc725fe4b4fa1024feb22b1d1f76c24febadcdbAndy Huang var parent = el; 67ffc725fe4b4fa1024feb22b1d1f76c24febadcdbAndy Huang while (parent) { 68ffc725fe4b4fa1024feb22b1d1f76c24febadcdbAndy Huang if (parent.classList && parent.classList.contains(className)) { 69ffc725fe4b4fa1024feb22b1d1f76c24febadcdbAndy Huang break; 70ffc725fe4b4fa1024feb22b1d1f76c24febadcdbAndy Huang } 71ffc725fe4b4fa1024feb22b1d1f76c24febadcdbAndy Huang parent = parent.parentNode; 72ffc725fe4b4fa1024feb22b1d1f76c24febadcdbAndy Huang } 73ffc725fe4b4fa1024feb22b1d1f76c24febadcdbAndy Huang return parent || null; 74ffc725fe4b4fa1024feb22b1d1f76c24febadcdbAndy Huang} 75ffc725fe4b4fa1024feb22b1d1f76c24febadcdbAndy Huang 7602f9d18a54072db8d86c524f9c09e508092ddd7cAndy Huangfunction getCachedValue(div, property, attrName) { 7702f9d18a54072db8d86c524f9c09e508092ddd7cAndy Huang var value; 7802f9d18a54072db8d86c524f9c09e508092ddd7cAndy Huang if (div.hasAttribute(attrName)) { 7902f9d18a54072db8d86c524f9c09e508092ddd7cAndy Huang value = div.getAttribute(attrName); 8002f9d18a54072db8d86c524f9c09e508092ddd7cAndy Huang } else { 8102f9d18a54072db8d86c524f9c09e508092ddd7cAndy Huang value = div[property]; 8202f9d18a54072db8d86c524f9c09e508092ddd7cAndy Huang div.setAttribute(attrName, value); 8302f9d18a54072db8d86c524f9c09e508092ddd7cAndy Huang } 8402f9d18a54072db8d86c524f9c09e508092ddd7cAndy Huang return value; 8502f9d18a54072db8d86c524f9c09e508092ddd7cAndy Huang} 8602f9d18a54072db8d86c524f9c09e508092ddd7cAndy Huang 87df0d91c5fa064e93b647fd62fe2446791664003fAndy Huangfunction onToggleClick(e) { 88df0d91c5fa064e93b647fd62fe2446791664003fAndy Huang toggleQuotedText(e.target); 89df0d91c5fa064e93b647fd62fe2446791664003fAndy Huang measurePositions(); 90df0d91c5fa064e93b647fd62fe2446791664003fAndy Huang} 91df0d91c5fa064e93b647fd62fe2446791664003fAndy Huang 92df0d91c5fa064e93b647fd62fe2446791664003fAndy Huangfunction toggleQuotedText(toggleElement) { 93f70fc4052b72a850bbb9be585d0f5a4877ee9448Andy Huang var elidedTextElement = toggleElement.nextSibling; 94f70fc4052b72a850bbb9be585d0f5a4877ee9448Andy Huang var isHidden = getComputedStyle(elidedTextElement).display == 'none'; 95f70fc4052b72a850bbb9be585d0f5a4877ee9448Andy Huang toggleElement.innerHTML = isHidden ? MSG_HIDE_ELIDED : MSG_SHOW_ELIDED; 96f70fc4052b72a850bbb9be585d0f5a4877ee9448Andy Huang elidedTextElement.style.display = isHidden ? 'block' : 'none'; 97ffc725fe4b4fa1024feb22b1d1f76c24febadcdbAndy Huang 98ffc725fe4b4fa1024feb22b1d1f76c24febadcdbAndy Huang // Revealing the elided text should normalize it to fit-width to prevent 99ffc725fe4b4fa1024feb22b1d1f76c24febadcdbAndy Huang // this message from blowing out the conversation width. 100ffc725fe4b4fa1024feb22b1d1f76c24febadcdbAndy Huang if (isHidden) { 101ffc725fe4b4fa1024feb22b1d1f76c24febadcdbAndy Huang normalizeElementWidths([elidedTextElement]); 102ffc725fe4b4fa1024feb22b1d1f76c24febadcdbAndy Huang } 103f70fc4052b72a850bbb9be585d0f5a4877ee9448Andy Huang} 104f70fc4052b72a850bbb9be585d0f5a4877ee9448Andy Huang 105014ea4c15d147794789b9c5bf4e243fa08781ad9Andy Huangfunction collapseAllQuotedText() { 106df0d91c5fa064e93b647fd62fe2446791664003fAndy Huang processQuotedText(document.documentElement, false /* showElided */); 107014ea4c15d147794789b9c5bf4e243fa08781ad9Andy Huang} 108014ea4c15d147794789b9c5bf4e243fa08781ad9Andy Huang 109df0d91c5fa064e93b647fd62fe2446791664003fAndy Huangfunction processQuotedText(elt, showElided) { 110f70fc4052b72a850bbb9be585d0f5a4877ee9448Andy Huang var i; 111014ea4c15d147794789b9c5bf4e243fa08781ad9Andy Huang var elements = elt.getElementsByClassName("elided-text"); 112f70fc4052b72a850bbb9be585d0f5a4877ee9448Andy Huang var elidedElement, toggleElement; 113f70fc4052b72a850bbb9be585d0f5a4877ee9448Andy Huang for (i = 0; i < elements.length; i++) { 114f70fc4052b72a850bbb9be585d0f5a4877ee9448Andy Huang elidedElement = elements[i]; 115f70fc4052b72a850bbb9be585d0f5a4877ee9448Andy Huang toggleElement = document.createElement("div"); 11682119afe5d596c69109ad9ce80e025dbec9ca4d1Andy Huang toggleElement.className = "mail-elided-text"; 117f70fc4052b72a850bbb9be585d0f5a4877ee9448Andy Huang toggleElement.innerHTML = MSG_SHOW_ELIDED; 1187c421434986c14be09bedebf54caf7b65b327111Andrew Sapperstein toggleElement.setAttribute("dir", "auto"); 119df0d91c5fa064e93b647fd62fe2446791664003fAndy Huang toggleElement.onclick = onToggleClick; 120df0d91c5fa064e93b647fd62fe2446791664003fAndy Huang elidedElement.style.display = 'none'; 121f70fc4052b72a850bbb9be585d0f5a4877ee9448Andy Huang elidedElement.parentNode.insertBefore(toggleElement, elidedElement); 122df0d91c5fa064e93b647fd62fe2446791664003fAndy Huang if (showElided) { 123df0d91c5fa064e93b647fd62fe2446791664003fAndy Huang toggleQuotedText(toggleElement); 124df0d91c5fa064e93b647fd62fe2446791664003fAndy Huang } 125f70fc4052b72a850bbb9be585d0f5a4877ee9448Andy Huang } 126f70fc4052b72a850bbb9be585d0f5a4877ee9448Andy Huang} 127f70fc4052b72a850bbb9be585d0f5a4877ee9448Andy Huang 1284cfe22a8b0fe9fb98df9c82303bacc5c1a79f19bAndy Huangfunction isConversationEmpty(bodyDivs) { 1294cfe22a8b0fe9fb98df9c82303bacc5c1a79f19bAndy Huang var i, len; 1304cfe22a8b0fe9fb98df9c82303bacc5c1a79f19bAndy Huang var msgBody; 1314cfe22a8b0fe9fb98df9c82303bacc5c1a79f19bAndy Huang var text; 1324cfe22a8b0fe9fb98df9c82303bacc5c1a79f19bAndy Huang 1334cfe22a8b0fe9fb98df9c82303bacc5c1a79f19bAndy Huang // Check if given divs are empty (in appearance), and disable zoom if so. 1344cfe22a8b0fe9fb98df9c82303bacc5c1a79f19bAndy Huang for (i = 0, len = bodyDivs.length; i < len; i++) { 1354cfe22a8b0fe9fb98df9c82303bacc5c1a79f19bAndy Huang msgBody = bodyDivs[i]; 1364cfe22a8b0fe9fb98df9c82303bacc5c1a79f19bAndy Huang // use 'textContent' to exclude markup when determining whether bodies are empty 1374cfe22a8b0fe9fb98df9c82303bacc5c1a79f19bAndy Huang // (fall back to more expensive 'innerText' if 'textContent' isn't implemented) 1384cfe22a8b0fe9fb98df9c82303bacc5c1a79f19bAndy Huang text = msgBody.textContent || msgBody.innerText; 1394cfe22a8b0fe9fb98df9c82303bacc5c1a79f19bAndy Huang if (text.trim().length > 0) { 1404cfe22a8b0fe9fb98df9c82303bacc5c1a79f19bAndy Huang return false; 1414cfe22a8b0fe9fb98df9c82303bacc5c1a79f19bAndy Huang } 1424cfe22a8b0fe9fb98df9c82303bacc5c1a79f19bAndy Huang } 1434cfe22a8b0fe9fb98df9c82303bacc5c1a79f19bAndy Huang return true; 1444cfe22a8b0fe9fb98df9c82303bacc5c1a79f19bAndy Huang} 1454cfe22a8b0fe9fb98df9c82303bacc5c1a79f19bAndy Huang 146ffc725fe4b4fa1024feb22b1d1f76c24febadcdbAndy Huangfunction normalizeAllMessageWidths() { 1474cfe22a8b0fe9fb98df9c82303bacc5c1a79f19bAndy Huang var expandedBodyDivs; 1484cfe22a8b0fe9fb98df9c82303bacc5c1a79f19bAndy Huang var metaViewport; 1494cfe22a8b0fe9fb98df9c82303bacc5c1a79f19bAndy Huang var contentValues; 1504cfe22a8b0fe9fb98df9c82303bacc5c1a79f19bAndy Huang var isEmpty; 1514cfe22a8b0fe9fb98df9c82303bacc5c1a79f19bAndy Huang 1524cfe22a8b0fe9fb98df9c82303bacc5c1a79f19bAndy Huang expandedBodyDivs = document.querySelectorAll(".expanded > .mail-message-content"); 1534cfe22a8b0fe9fb98df9c82303bacc5c1a79f19bAndy Huang 1544cfe22a8b0fe9fb98df9c82303bacc5c1a79f19bAndy Huang isEmpty = isConversationEmpty(expandedBodyDivs); 1554cfe22a8b0fe9fb98df9c82303bacc5c1a79f19bAndy Huang 1564cfe22a8b0fe9fb98df9c82303bacc5c1a79f19bAndy Huang normalizeElementWidths(expandedBodyDivs); 1574cfe22a8b0fe9fb98df9c82303bacc5c1a79f19bAndy Huang 1584cfe22a8b0fe9fb98df9c82303bacc5c1a79f19bAndy Huang // assemble a working <meta> viewport "content" value from the base value in the 1594cfe22a8b0fe9fb98df9c82303bacc5c1a79f19bAndy Huang // document, plus any dynamically determined options 1604cfe22a8b0fe9fb98df9c82303bacc5c1a79f19bAndy Huang metaViewport = document.getElementById("meta-viewport"); 1614cfe22a8b0fe9fb98df9c82303bacc5c1a79f19bAndy Huang contentValues = [metaViewport.getAttribute("content")]; 1624cfe22a8b0fe9fb98df9c82303bacc5c1a79f19bAndy Huang if (isEmpty) { 1634cfe22a8b0fe9fb98df9c82303bacc5c1a79f19bAndy Huang contentValues.push(metaViewport.getAttribute("data-zoom-off")); 1644cfe22a8b0fe9fb98df9c82303bacc5c1a79f19bAndy Huang } else { 1654cfe22a8b0fe9fb98df9c82303bacc5c1a79f19bAndy Huang contentValues.push(metaViewport.getAttribute("data-zoom-on")); 1664cfe22a8b0fe9fb98df9c82303bacc5c1a79f19bAndy Huang } 1674cfe22a8b0fe9fb98df9c82303bacc5c1a79f19bAndy Huang metaViewport.setAttribute("content", contentValues.join(",")); 168ffc725fe4b4fa1024feb22b1d1f76c24febadcdbAndy Huang} 169ffc725fe4b4fa1024feb22b1d1f76c24febadcdbAndy Huang 170ffc725fe4b4fa1024feb22b1d1f76c24febadcdbAndy Huang/* 171ffc725fe4b4fa1024feb22b1d1f76c24febadcdbAndy Huang * Normalizes the width of all elements supplied to the document body's overall width. 172ffc725fe4b4fa1024feb22b1d1f76c24febadcdbAndy Huang * Narrower elements are zoomed in, and wider elements are zoomed out. 173ffc725fe4b4fa1024feb22b1d1f76c24febadcdbAndy Huang * This method is idempotent. 174ffc725fe4b4fa1024feb22b1d1f76c24febadcdbAndy Huang */ 175ffc725fe4b4fa1024feb22b1d1f76c24febadcdbAndy Huangfunction normalizeElementWidths(elements) { 176f70fc4052b72a850bbb9be585d0f5a4877ee9448Andy Huang var i; 177ffc725fe4b4fa1024feb22b1d1f76c24febadcdbAndy Huang var el; 178adbf3e8cadb66666f307352b72537fbac57b916fAndy Huang var documentWidth; 1794dc732387454eef3ee6d89f9fa393630eb6213f9Andy Huang var goalWidth; 1804dc732387454eef3ee6d89f9fa393630eb6213f9Andy Huang var origWidth; 181ffc725fe4b4fa1024feb22b1d1f76c24febadcdbAndy Huang var newZoom, oldZoom; 1824dc732387454eef3ee6d89f9fa393630eb6213f9Andy Huang var outerZoom; 1834dc732387454eef3ee6d89f9fa393630eb6213f9Andy Huang var outerDiv; 184256b35c0a8287f48c28e0d1ba3fae65790063295Andy Huang 185adbf3e8cadb66666f307352b72537fbac57b916fAndy Huang documentWidth = document.body.offsetWidth; 1862160d53e6ae0bfb797569d616e735e46c21522ffAndy Huang goalWidth = WEBVIEW_WIDTH; 187adbf3e8cadb66666f307352b72537fbac57b916fAndy Huang 188f70fc4052b72a850bbb9be585d0f5a4877ee9448Andy Huang for (i = 0; i < elements.length; i++) { 189ffc725fe4b4fa1024feb22b1d1f76c24febadcdbAndy Huang el = elements[i]; 190ffc725fe4b4fa1024feb22b1d1f76c24febadcdbAndy Huang oldZoom = el.style.zoom; 191ffc725fe4b4fa1024feb22b1d1f76c24febadcdbAndy Huang // reset any existing normalization 192ffc725fe4b4fa1024feb22b1d1f76c24febadcdbAndy Huang if (oldZoom) { 193ffc725fe4b4fa1024feb22b1d1f76c24febadcdbAndy Huang el.style.zoom = 1; 194ffc725fe4b4fa1024feb22b1d1f76c24febadcdbAndy Huang } 1954dc732387454eef3ee6d89f9fa393630eb6213f9Andy Huang origWidth = el.style.width; 1964dc732387454eef3ee6d89f9fa393630eb6213f9Andy Huang el.style.width = goalWidth + "px"; 1974dc732387454eef3ee6d89f9fa393630eb6213f9Andy Huang transformContent(el, goalWidth, el.scrollWidth); 1985ea5a8330532a75c83cbb30993a14ee9b821fa2aAndy Huang newZoom = documentWidth / el.scrollWidth; 1995ea5a8330532a75c83cbb30993a14ee9b821fa2aAndy Huang if (NORMALIZE_MESSAGE_WIDTHS) { 2004dc732387454eef3ee6d89f9fa393630eb6213f9Andy Huang if (el.classList.contains("mail-message-content")) { 2014dc732387454eef3ee6d89f9fa393630eb6213f9Andy Huang outerZoom = 1; 2024dc732387454eef3ee6d89f9fa393630eb6213f9Andy Huang } else { 2034dc732387454eef3ee6d89f9fa393630eb6213f9Andy Huang outerDiv = up(el, "mail-message-content"); 2044dc732387454eef3ee6d89f9fa393630eb6213f9Andy Huang outerZoom = outerDiv ? outerDiv.style.zoom : 1; 2054dc732387454eef3ee6d89f9fa393630eb6213f9Andy Huang } 2064dc732387454eef3ee6d89f9fa393630eb6213f9Andy Huang el.style.zoom = newZoom / outerZoom; 2075ea5a8330532a75c83cbb30993a14ee9b821fa2aAndy Huang } 2084dc732387454eef3ee6d89f9fa393630eb6213f9Andy Huang el.style.width = origWidth; 2095ea5a8330532a75c83cbb30993a14ee9b821fa2aAndy Huang } 2105ea5a8330532a75c83cbb30993a14ee9b821fa2aAndy Huang} 2115ea5a8330532a75c83cbb30993a14ee9b821fa2aAndy Huang 2120180f27c0998623b702274048b49cd4bec536cf1Andy Huangfunction transformContent(el, docWidth, elWidth) { 2135ea5a8330532a75c83cbb30993a14ee9b821fa2aAndy Huang var nodes; 2145ea5a8330532a75c83cbb30993a14ee9b821fa2aAndy Huang var i, len; 2150180f27c0998623b702274048b49cd4bec536cf1Andy Huang var index; 2163a398b245930ce60ceb51fc605ab0f20c8df1f62Andy Huang var newWidth = elWidth; 2175ea5a8330532a75c83cbb30993a14ee9b821fa2aAndy Huang var wStr; 2183a398b245930ce60ceb51fc605ab0f20c8df1f62Andy Huang var touched; 2190180f27c0998623b702274048b49cd4bec536cf1Andy Huang // the format of entries in this array is: 2200180f27c0998623b702274048b49cd4bec536cf1Andy Huang // entry := [ undoFunction, undoFunctionThis, undoFunctionParamArray ] 2213a398b245930ce60ceb51fc605ab0f20c8df1f62Andy Huang var actionLog = []; 2223a398b245930ce60ceb51fc605ab0f20c8df1f62Andy Huang var node; 22305c70c88e6b421bedce134799a0ea928dbf44cd5Andy Huang var done = false; 22405c70c88e6b421bedce134799a0ea928dbf44cd5Andy Huang var msgId; 22505c70c88e6b421bedce134799a0ea928dbf44cd5Andy Huang var transformText; 22605c70c88e6b421bedce134799a0ea928dbf44cd5Andy Huang var existingText; 22705c70c88e6b421bedce134799a0ea928dbf44cd5Andy Huang var textElement; 2283a398b245930ce60ceb51fc605ab0f20c8df1f62Andy Huang var start; 2290ecc58252046c81b575e23db909b1687beb871b4Andy Huang var beforeWidth; 2300ecc58252046c81b575e23db909b1687beb871b4Andy Huang var tmpActionLog = []; 2315ea5a8330532a75c83cbb30993a14ee9b821fa2aAndy Huang if (elWidth <= docWidth) { 2325ea5a8330532a75c83cbb30993a14ee9b821fa2aAndy Huang return; 2335ea5a8330532a75c83cbb30993a14ee9b821fa2aAndy Huang } 2343a398b245930ce60ceb51fc605ab0f20c8df1f62Andy Huang 2353a398b245930ce60ceb51fc605ab0f20c8df1f62Andy Huang start = Date.now(); 23605c70c88e6b421bedce134799a0ea928dbf44cd5Andy Huang 23705c70c88e6b421bedce134799a0ea928dbf44cd5Andy Huang if (el.parentElement.classList.contains("mail-message")) { 23805c70c88e6b421bedce134799a0ea928dbf44cd5Andy Huang msgId = el.parentElement.id; 23905c70c88e6b421bedce134799a0ea928dbf44cd5Andy Huang transformText = "[origW=" + elWidth + "/" + docWidth; 24005c70c88e6b421bedce134799a0ea928dbf44cd5Andy Huang } 24105c70c88e6b421bedce134799a0ea928dbf44cd5Andy Huang 24233578eaf140b8eeb5dad6e0c015b2e204054a86bAndy Huang // Try munging all divs or textareas with inline styles where the width 2433a398b245930ce60ceb51fc605ab0f20c8df1f62Andy Huang // is wider than docWidth, and change it to be a max-width. 2443a398b245930ce60ceb51fc605ab0f20c8df1f62Andy Huang touched = false; 24533578eaf140b8eeb5dad6e0c015b2e204054a86bAndy Huang nodes = ENABLE_MUNGE_TABLES ? el.querySelectorAll("div[style], textarea[style]") : []; 24633578eaf140b8eeb5dad6e0c015b2e204054a86bAndy Huang touched = transformBlockElements(nodes, docWidth, actionLog); 2475ea5a8330532a75c83cbb30993a14ee9b821fa2aAndy Huang if (touched) { 2485ea5a8330532a75c83cbb30993a14ee9b821fa2aAndy Huang newWidth = el.scrollWidth; 2493a398b245930ce60ceb51fc605ab0f20c8df1f62Andy Huang console.log("ran div-width munger on el=" + el + " oldW=" + elWidth + " newW=" + newWidth 2503a398b245930ce60ceb51fc605ab0f20c8df1f62Andy Huang + " docW=" + docWidth); 25105c70c88e6b421bedce134799a0ea928dbf44cd5Andy Huang if (msgId) { 25205c70c88e6b421bedce134799a0ea928dbf44cd5Andy Huang transformText += " DIV:newW=" + newWidth; 25305c70c88e6b421bedce134799a0ea928dbf44cd5Andy Huang } 2543a398b245930ce60ceb51fc605ab0f20c8df1f62Andy Huang if (newWidth <= docWidth) { 25505c70c88e6b421bedce134799a0ea928dbf44cd5Andy Huang done = true; 2563a398b245930ce60ceb51fc605ab0f20c8df1f62Andy Huang } 2573a398b245930ce60ceb51fc605ab0f20c8df1f62Andy Huang } 2583a398b245930ce60ceb51fc605ab0f20c8df1f62Andy Huang 25905c70c88e6b421bedce134799a0ea928dbf44cd5Andy Huang if (!done) { 26005c70c88e6b421bedce134799a0ea928dbf44cd5Andy Huang // OK, that wasn't enough. Find images with widths and override their widths. 26105c70c88e6b421bedce134799a0ea928dbf44cd5Andy Huang nodes = ENABLE_MUNGE_IMAGES ? el.querySelectorAll("img") : []; 26205c70c88e6b421bedce134799a0ea928dbf44cd5Andy Huang touched = transformImages(nodes, docWidth, actionLog); 26305c70c88e6b421bedce134799a0ea928dbf44cd5Andy Huang if (touched) { 26405c70c88e6b421bedce134799a0ea928dbf44cd5Andy Huang newWidth = el.scrollWidth; 26505c70c88e6b421bedce134799a0ea928dbf44cd5Andy Huang console.log("ran img munger on el=" + el + " oldW=" + elWidth + " newW=" + newWidth 26605c70c88e6b421bedce134799a0ea928dbf44cd5Andy Huang + " docW=" + docWidth); 26705c70c88e6b421bedce134799a0ea928dbf44cd5Andy Huang if (msgId) { 26805c70c88e6b421bedce134799a0ea928dbf44cd5Andy Huang transformText += " IMG:newW=" + newWidth; 26905c70c88e6b421bedce134799a0ea928dbf44cd5Andy Huang } 27005c70c88e6b421bedce134799a0ea928dbf44cd5Andy Huang if (newWidth <= docWidth) { 27105c70c88e6b421bedce134799a0ea928dbf44cd5Andy Huang done = true; 27205c70c88e6b421bedce134799a0ea928dbf44cd5Andy Huang } 2730180f27c0998623b702274048b49cd4bec536cf1Andy Huang } 2740180f27c0998623b702274048b49cd4bec536cf1Andy Huang } 2750180f27c0998623b702274048b49cd4bec536cf1Andy Huang 27605c70c88e6b421bedce134799a0ea928dbf44cd5Andy Huang if (!done) { 27705c70c88e6b421bedce134799a0ea928dbf44cd5Andy Huang // OK, that wasn't enough. Find tables with widths and override their widths. 278543e709c976ce954a072020ba6f75d12f41b1fbaAndy Huang // Also ensure that any use of 'table-layout: fixed' is negated, since using 279543e709c976ce954a072020ba6f75d12f41b1fbaAndy Huang // that with 'width: auto' causes erratic table width. 28005c70c88e6b421bedce134799a0ea928dbf44cd5Andy Huang nodes = ENABLE_MUNGE_TABLES ? el.querySelectorAll("table") : []; 28105c70c88e6b421bedce134799a0ea928dbf44cd5Andy Huang touched = addClassToElements(nodes, shouldMungeTable, "munged", 28205c70c88e6b421bedce134799a0ea928dbf44cd5Andy Huang actionLog); 28305c70c88e6b421bedce134799a0ea928dbf44cd5Andy Huang if (touched) { 28405c70c88e6b421bedce134799a0ea928dbf44cd5Andy Huang newWidth = el.scrollWidth; 28505c70c88e6b421bedce134799a0ea928dbf44cd5Andy Huang console.log("ran table munger on el=" + el + " oldW=" + elWidth + " newW=" + newWidth 28605c70c88e6b421bedce134799a0ea928dbf44cd5Andy Huang + " docW=" + docWidth); 28705c70c88e6b421bedce134799a0ea928dbf44cd5Andy Huang if (msgId) { 28805c70c88e6b421bedce134799a0ea928dbf44cd5Andy Huang transformText += " TABLE:newW=" + newWidth; 28905c70c88e6b421bedce134799a0ea928dbf44cd5Andy Huang } 29005c70c88e6b421bedce134799a0ea928dbf44cd5Andy Huang if (newWidth <= docWidth) { 29105c70c88e6b421bedce134799a0ea928dbf44cd5Andy Huang done = true; 29205c70c88e6b421bedce134799a0ea928dbf44cd5Andy Huang } 2935ea5a8330532a75c83cbb30993a14ee9b821fa2aAndy Huang } 294f70fc4052b72a850bbb9be585d0f5a4877ee9448Andy Huang } 2955ea5a8330532a75c83cbb30993a14ee9b821fa2aAndy Huang 29605c70c88e6b421bedce134799a0ea928dbf44cd5Andy Huang if (!done) { 29705c70c88e6b421bedce134799a0ea928dbf44cd5Andy Huang // OK, that wasn't enough. Try munging all <td> to override any width and nowrap set. 2980ecc58252046c81b575e23db909b1687beb871b4Andy Huang beforeWidth = newWidth; 29905c70c88e6b421bedce134799a0ea928dbf44cd5Andy Huang nodes = ENABLE_MUNGE_TABLES ? el.querySelectorAll("td") : []; 30005c70c88e6b421bedce134799a0ea928dbf44cd5Andy Huang touched = addClassToElements(nodes, null /* mungeAll */, "munged", 3010ecc58252046c81b575e23db909b1687beb871b4Andy Huang tmpActionLog); 30205c70c88e6b421bedce134799a0ea928dbf44cd5Andy Huang if (touched) { 30305c70c88e6b421bedce134799a0ea928dbf44cd5Andy Huang newWidth = el.scrollWidth; 30405c70c88e6b421bedce134799a0ea928dbf44cd5Andy Huang console.log("ran td munger on el=" + el + " oldW=" + elWidth + " newW=" + newWidth 30505c70c88e6b421bedce134799a0ea928dbf44cd5Andy Huang + " docW=" + docWidth); 30605c70c88e6b421bedce134799a0ea928dbf44cd5Andy Huang if (msgId) { 30705c70c88e6b421bedce134799a0ea928dbf44cd5Andy Huang transformText += " TD:newW=" + newWidth; 30805c70c88e6b421bedce134799a0ea928dbf44cd5Andy Huang } 30905c70c88e6b421bedce134799a0ea928dbf44cd5Andy Huang if (newWidth <= docWidth) { 31005c70c88e6b421bedce134799a0ea928dbf44cd5Andy Huang done = true; 3110ecc58252046c81b575e23db909b1687beb871b4Andy Huang } else if (newWidth == beforeWidth) { 3120ecc58252046c81b575e23db909b1687beb871b4Andy Huang // this transform did not improve things, and it is somewhat risky. 3130ecc58252046c81b575e23db909b1687beb871b4Andy Huang // back it out, since it's the last transform and we gained nothing. 3140ecc58252046c81b575e23db909b1687beb871b4Andy Huang undoActions(tmpActionLog); 3150ecc58252046c81b575e23db909b1687beb871b4Andy Huang } else { 3160ecc58252046c81b575e23db909b1687beb871b4Andy Huang // the transform WAS effective (although not 100%) 3170ecc58252046c81b575e23db909b1687beb871b4Andy Huang // copy the temporary action log entries over as normal 3180ecc58252046c81b575e23db909b1687beb871b4Andy Huang for (i = 0, len = tmpActionLog.length; i < len; i++) { 3190ecc58252046c81b575e23db909b1687beb871b4Andy Huang actionLog.push(tmpActionLog[i]); 3200ecc58252046c81b575e23db909b1687beb871b4Andy Huang } 32105c70c88e6b421bedce134799a0ea928dbf44cd5Andy Huang } 3225ea5a8330532a75c83cbb30993a14ee9b821fa2aAndy Huang } 3235ea5a8330532a75c83cbb30993a14ee9b821fa2aAndy Huang } 3243a398b245930ce60ceb51fc605ab0f20c8df1f62Andy Huang 3253a398b245930ce60ceb51fc605ab0f20c8df1f62Andy Huang // If the transformations shrank the width significantly enough, leave them in place. 3263a398b245930ce60ceb51fc605ab0f20c8df1f62Andy Huang // We figure that in those cases, the benefits outweight the risk of rendering artifacts. 32705c70c88e6b421bedce134799a0ea928dbf44cd5Andy Huang if (!done && (elWidth - newWidth) / (elWidth - docWidth) > 32805c70c88e6b421bedce134799a0ea928dbf44cd5Andy Huang TRANSFORM_MINIMUM_EFFECTIVE_RATIO) { 32905c70c88e6b421bedce134799a0ea928dbf44cd5Andy Huang console.log("transform(s) deemed effective enough"); 33005c70c88e6b421bedce134799a0ea928dbf44cd5Andy Huang done = true; 33105c70c88e6b421bedce134799a0ea928dbf44cd5Andy Huang } 33205c70c88e6b421bedce134799a0ea928dbf44cd5Andy Huang 33305c70c88e6b421bedce134799a0ea928dbf44cd5Andy Huang if (done) { 33405c70c88e6b421bedce134799a0ea928dbf44cd5Andy Huang if (msgId) { 33505c70c88e6b421bedce134799a0ea928dbf44cd5Andy Huang transformText += "]"; 33605c70c88e6b421bedce134799a0ea928dbf44cd5Andy Huang existingText = gTransformText[msgId]; 33705c70c88e6b421bedce134799a0ea928dbf44cd5Andy Huang if (!existingText) { 33805c70c88e6b421bedce134799a0ea928dbf44cd5Andy Huang transformText = "Message transforms: " + transformText; 33905c70c88e6b421bedce134799a0ea928dbf44cd5Andy Huang } else { 34005c70c88e6b421bedce134799a0ea928dbf44cd5Andy Huang transformText = existingText + " " + transformText; 34105c70c88e6b421bedce134799a0ea928dbf44cd5Andy Huang } 34205c70c88e6b421bedce134799a0ea928dbf44cd5Andy Huang gTransformText[msgId] = transformText; 34305c70c88e6b421bedce134799a0ea928dbf44cd5Andy Huang window.mail.onMessageTransform(msgId, transformText); 34404e53a2e6e71615ddcee39eeb0014a4cd4baf956Andy Huang if (DEBUG_DISPLAY_TRANSFORMS) { 34504e53a2e6e71615ddcee39eeb0014a4cd4baf956Andy Huang textElement = el.firstChild; 34604e53a2e6e71615ddcee39eeb0014a4cd4baf956Andy Huang if (!textElement.classList || !textElement.classList.contains("transform-text")) { 34704e53a2e6e71615ddcee39eeb0014a4cd4baf956Andy Huang textElement = document.createElement("div"); 34804e53a2e6e71615ddcee39eeb0014a4cd4baf956Andy Huang textElement.classList.add("transform-text"); 34904e53a2e6e71615ddcee39eeb0014a4cd4baf956Andy Huang textElement.style.fontSize = "10px"; 35004e53a2e6e71615ddcee39eeb0014a4cd4baf956Andy Huang textElement.style.color = "#ccc"; 35104e53a2e6e71615ddcee39eeb0014a4cd4baf956Andy Huang el.insertBefore(textElement, el.firstChild); 35204e53a2e6e71615ddcee39eeb0014a4cd4baf956Andy Huang } 35304e53a2e6e71615ddcee39eeb0014a4cd4baf956Andy Huang textElement.innerHTML = transformText + "<br>"; 35405c70c88e6b421bedce134799a0ea928dbf44cd5Andy Huang } 35505c70c88e6b421bedce134799a0ea928dbf44cd5Andy Huang } 35605c70c88e6b421bedce134799a0ea928dbf44cd5Andy Huang console.log("munger(s) succeeded, elapsed time=" + (Date.now() - start)); 3573a398b245930ce60ceb51fc605ab0f20c8df1f62Andy Huang return; 3583a398b245930ce60ceb51fc605ab0f20c8df1f62Andy Huang } 3593a398b245930ce60ceb51fc605ab0f20c8df1f62Andy Huang 3603a398b245930ce60ceb51fc605ab0f20c8df1f62Andy Huang // reverse all changes if the width is STILL not narrow enough 3613a398b245930ce60ceb51fc605ab0f20c8df1f62Andy Huang // (except the width->maxWidth change, which is not particularly destructive) 3620ecc58252046c81b575e23db909b1687beb871b4Andy Huang undoActions(actionLog); 3633a398b245930ce60ceb51fc605ab0f20c8df1f62Andy Huang if (actionLog.length > 0) { 3643a398b245930ce60ceb51fc605ab0f20c8df1f62Andy Huang console.log("all mungers failed, changes reversed. elapsed time=" + (Date.now() - start)); 3653a398b245930ce60ceb51fc605ab0f20c8df1f62Andy Huang } 3663a398b245930ce60ceb51fc605ab0f20c8df1f62Andy Huang} 3673a398b245930ce60ceb51fc605ab0f20c8df1f62Andy Huang 3680ecc58252046c81b575e23db909b1687beb871b4Andy Huangfunction undoActions(actionLog) { 3690ecc58252046c81b575e23db909b1687beb871b4Andy Huang for (i = 0, len = actionLog.length; i < len; i++) { 3700ecc58252046c81b575e23db909b1687beb871b4Andy Huang actionLog[i][0].apply(actionLog[i][1], actionLog[i][2]); 3710ecc58252046c81b575e23db909b1687beb871b4Andy Huang } 3720ecc58252046c81b575e23db909b1687beb871b4Andy Huang} 3730ecc58252046c81b575e23db909b1687beb871b4Andy Huang 3743a398b245930ce60ceb51fc605ab0f20c8df1f62Andy Huangfunction addClassToElements(nodes, conditionFn, classToAdd, actionLog) { 3753a398b245930ce60ceb51fc605ab0f20c8df1f62Andy Huang var i, len; 3763a398b245930ce60ceb51fc605ab0f20c8df1f62Andy Huang var node; 3773a398b245930ce60ceb51fc605ab0f20c8df1f62Andy Huang var added = false; 3783a398b245930ce60ceb51fc605ab0f20c8df1f62Andy Huang for (i = 0, len = nodes.length; i < len; i++) { 3793a398b245930ce60ceb51fc605ab0f20c8df1f62Andy Huang node = nodes[i]; 3803a398b245930ce60ceb51fc605ab0f20c8df1f62Andy Huang if (!conditionFn || conditionFn(node)) { 3814821bbb4aeaf4393e45575e0e43c7086521039adAndy Huang if (node.classList.contains(classToAdd)) { 3824821bbb4aeaf4393e45575e0e43c7086521039adAndy Huang continue; 3834821bbb4aeaf4393e45575e0e43c7086521039adAndy Huang } 3843a398b245930ce60ceb51fc605ab0f20c8df1f62Andy Huang node.classList.add(classToAdd); 3853a398b245930ce60ceb51fc605ab0f20c8df1f62Andy Huang added = true; 3860180f27c0998623b702274048b49cd4bec536cf1Andy Huang actionLog.push([node.classList.remove, node.classList, [classToAdd]]); 3873a398b245930ce60ceb51fc605ab0f20c8df1f62Andy Huang } 3883a398b245930ce60ceb51fc605ab0f20c8df1f62Andy Huang } 3893a398b245930ce60ceb51fc605ab0f20c8df1f62Andy Huang return added; 3903a398b245930ce60ceb51fc605ab0f20c8df1f62Andy Huang} 3913a398b245930ce60ceb51fc605ab0f20c8df1f62Andy Huang 39233578eaf140b8eeb5dad6e0c015b2e204054a86bAndy Huangfunction transformBlockElements(nodes, docWidth, actionLog) { 39333578eaf140b8eeb5dad6e0c015b2e204054a86bAndy Huang var i, len; 39433578eaf140b8eeb5dad6e0c015b2e204054a86bAndy Huang var node; 39533578eaf140b8eeb5dad6e0c015b2e204054a86bAndy Huang var wStr; 39633578eaf140b8eeb5dad6e0c015b2e204054a86bAndy Huang var index; 39733578eaf140b8eeb5dad6e0c015b2e204054a86bAndy Huang var touched = false; 39833578eaf140b8eeb5dad6e0c015b2e204054a86bAndy Huang 39933578eaf140b8eeb5dad6e0c015b2e204054a86bAndy Huang for (i = 0, len = nodes.length; i < len; i++) { 40033578eaf140b8eeb5dad6e0c015b2e204054a86bAndy Huang node = nodes[i]; 40133578eaf140b8eeb5dad6e0c015b2e204054a86bAndy Huang wStr = node.style.width || node.style.minWidth; 40233578eaf140b8eeb5dad6e0c015b2e204054a86bAndy Huang index = wStr ? wStr.indexOf("px") : -1; 40333578eaf140b8eeb5dad6e0c015b2e204054a86bAndy Huang if (index >= 0 && wStr.slice(0, index) > docWidth) { 40433578eaf140b8eeb5dad6e0c015b2e204054a86bAndy Huang saveStyleProperty(node, "width", actionLog); 40533578eaf140b8eeb5dad6e0c015b2e204054a86bAndy Huang saveStyleProperty(node, "minWidth", actionLog); 40633578eaf140b8eeb5dad6e0c015b2e204054a86bAndy Huang saveStyleProperty(node, "maxWidth", actionLog); 40733578eaf140b8eeb5dad6e0c015b2e204054a86bAndy Huang node.style.width = "100%"; 40833578eaf140b8eeb5dad6e0c015b2e204054a86bAndy Huang node.style.minWidth = ""; 40933578eaf140b8eeb5dad6e0c015b2e204054a86bAndy Huang node.style.maxWidth = wStr; 41033578eaf140b8eeb5dad6e0c015b2e204054a86bAndy Huang touched = true; 41133578eaf140b8eeb5dad6e0c015b2e204054a86bAndy Huang } 41233578eaf140b8eeb5dad6e0c015b2e204054a86bAndy Huang } 41333578eaf140b8eeb5dad6e0c015b2e204054a86bAndy Huang return touched; 41433578eaf140b8eeb5dad6e0c015b2e204054a86bAndy Huang} 41533578eaf140b8eeb5dad6e0c015b2e204054a86bAndy Huang 4160180f27c0998623b702274048b49cd4bec536cf1Andy Huangfunction transformImages(nodes, docWidth, actionLog) { 4170180f27c0998623b702274048b49cd4bec536cf1Andy Huang var i, len; 4180180f27c0998623b702274048b49cd4bec536cf1Andy Huang var node; 4190180f27c0998623b702274048b49cd4bec536cf1Andy Huang var w, h; 4200180f27c0998623b702274048b49cd4bec536cf1Andy Huang var touched = false; 4210180f27c0998623b702274048b49cd4bec536cf1Andy Huang 4220180f27c0998623b702274048b49cd4bec536cf1Andy Huang for (i = 0, len = nodes.length; i < len; i++) { 4230180f27c0998623b702274048b49cd4bec536cf1Andy Huang node = nodes[i]; 4240180f27c0998623b702274048b49cd4bec536cf1Andy Huang w = node.offsetWidth; 4250180f27c0998623b702274048b49cd4bec536cf1Andy Huang h = node.offsetHeight; 4260180f27c0998623b702274048b49cd4bec536cf1Andy Huang // shrink w/h proportionally if the img is wider than available width 4270180f27c0998623b702274048b49cd4bec536cf1Andy Huang if (w > docWidth) { 42833578eaf140b8eeb5dad6e0c015b2e204054a86bAndy Huang saveStyleProperty(node, "maxWidth", actionLog); 42933578eaf140b8eeb5dad6e0c015b2e204054a86bAndy Huang saveStyleProperty(node, "width", actionLog); 43033578eaf140b8eeb5dad6e0c015b2e204054a86bAndy Huang saveStyleProperty(node, "height", actionLog); 4310180f27c0998623b702274048b49cd4bec536cf1Andy Huang node.style.maxWidth = docWidth + "px"; 4320180f27c0998623b702274048b49cd4bec536cf1Andy Huang node.style.width = "100%"; 4330180f27c0998623b702274048b49cd4bec536cf1Andy Huang node.style.height = "auto"; 4340180f27c0998623b702274048b49cd4bec536cf1Andy Huang touched = true; 4350180f27c0998623b702274048b49cd4bec536cf1Andy Huang } 4360180f27c0998623b702274048b49cd4bec536cf1Andy Huang } 4370180f27c0998623b702274048b49cd4bec536cf1Andy Huang return touched; 4380180f27c0998623b702274048b49cd4bec536cf1Andy Huang} 4390180f27c0998623b702274048b49cd4bec536cf1Andy Huang 44033578eaf140b8eeb5dad6e0c015b2e204054a86bAndy Huangfunction saveStyleProperty(node, property, actionLog) { 44133578eaf140b8eeb5dad6e0c015b2e204054a86bAndy Huang var savedName = "data-" + property; 44233578eaf140b8eeb5dad6e0c015b2e204054a86bAndy Huang node.setAttribute(savedName, node.style[property]); 44333578eaf140b8eeb5dad6e0c015b2e204054a86bAndy Huang actionLog.push([undoSetProperty, node, [property, savedName]]); 44433578eaf140b8eeb5dad6e0c015b2e204054a86bAndy Huang} 44533578eaf140b8eeb5dad6e0c015b2e204054a86bAndy Huang 4460180f27c0998623b702274048b49cd4bec536cf1Andy Huangfunction undoSetProperty(property, savedProperty) { 4470180f27c0998623b702274048b49cd4bec536cf1Andy Huang this.style[property] = savedProperty ? this.getAttribute(savedProperty) : ""; 4480180f27c0998623b702274048b49cd4bec536cf1Andy Huang} 4490180f27c0998623b702274048b49cd4bec536cf1Andy Huang 4503a398b245930ce60ceb51fc605ab0f20c8df1f62Andy Huangfunction shouldMungeTable(table) { 4513a398b245930ce60ceb51fc605ab0f20c8df1f62Andy Huang return table.hasAttribute("width") || table.style.width; 452f70fc4052b72a850bbb9be585d0f5a4877ee9448Andy Huang} 453f70fc4052b72a850bbb9be585d0f5a4877ee9448Andy Huang 454f500db85dd13394dd6bdcfa38824b2ca6ada77e8Andy Huangfunction hideAllUnsafeImages() { 455f500db85dd13394dd6bdcfa38824b2ca6ada77e8Andy Huang hideUnsafeImages(document.getElementsByClassName("mail-message-content")); 456f500db85dd13394dd6bdcfa38824b2ca6ada77e8Andy Huang} 457f500db85dd13394dd6bdcfa38824b2ca6ada77e8Andy Huang 458f500db85dd13394dd6bdcfa38824b2ca6ada77e8Andy Huangfunction hideUnsafeImages(msgContentDivs) { 459f500db85dd13394dd6bdcfa38824b2ca6ada77e8Andy Huang var i, msgContentCount; 4603233bff8ae08a56543c9f5abf1bc6ab38f0574ceAndy Huang var j, imgCount; 461f500db85dd13394dd6bdcfa38824b2ca6ada77e8Andy Huang var msgContentDiv, image; 4623233bff8ae08a56543c9f5abf1bc6ab38f0574ceAndy Huang var images; 4633233bff8ae08a56543c9f5abf1bc6ab38f0574ceAndy Huang var showImages; 4648ec43e877a9c1925514f066655984e21fbd255e8Andrew Sapperstein var k = 0; 4658ec43e877a9c1925514f066655984e21fbd255e8Andrew Sapperstein var urls = new Array(); 4668ec43e877a9c1925514f066655984e21fbd255e8Andrew Sapperstein var messageIds = new Array(); 467f500db85dd13394dd6bdcfa38824b2ca6ada77e8Andy Huang for (i = 0, msgContentCount = msgContentDivs.length; i < msgContentCount; i++) { 468f500db85dd13394dd6bdcfa38824b2ca6ada77e8Andy Huang msgContentDiv = msgContentDivs[i]; 469f500db85dd13394dd6bdcfa38824b2ca6ada77e8Andy Huang showImages = msgContentDiv.classList.contains("mail-show-images"); 4703233bff8ae08a56543c9f5abf1bc6ab38f0574ceAndy Huang 471f500db85dd13394dd6bdcfa38824b2ca6ada77e8Andy Huang images = msgContentDiv.getElementsByTagName("img"); 4723233bff8ae08a56543c9f5abf1bc6ab38f0574ceAndy Huang for (j = 0, imgCount = images.length; j < imgCount; j++) { 4733233bff8ae08a56543c9f5abf1bc6ab38f0574ceAndy Huang image = images[j]; 4748ec43e877a9c1925514f066655984e21fbd255e8Andrew Sapperstein var src = rewriteRelativeImageSrc(image); 4758ec43e877a9c1925514f066655984e21fbd255e8Andrew Sapperstein if (src) { 4768ec43e877a9c1925514f066655984e21fbd255e8Andrew Sapperstein urls[k] = src; 4778ec43e877a9c1925514f066655984e21fbd255e8Andrew Sapperstein messageIds[k] = msgContentDiv.parentNode.id; 4788ec43e877a9c1925514f066655984e21fbd255e8Andrew Sapperstein k++; 4798ec43e877a9c1925514f066655984e21fbd255e8Andrew Sapperstein } 4803233bff8ae08a56543c9f5abf1bc6ab38f0574ceAndy Huang attachImageLoadListener(image); 4813233bff8ae08a56543c9f5abf1bc6ab38f0574ceAndy Huang // TODO: handle inline image attachments for all supported protocols 4823233bff8ae08a56543c9f5abf1bc6ab38f0574ceAndy Huang if (!showImages) { 4833233bff8ae08a56543c9f5abf1bc6ab38f0574ceAndy Huang blockImage(image); 4843233bff8ae08a56543c9f5abf1bc6ab38f0574ceAndy Huang } 4853233bff8ae08a56543c9f5abf1bc6ab38f0574ceAndy Huang } 4863233bff8ae08a56543c9f5abf1bc6ab38f0574ceAndy Huang } 4878ec43e877a9c1925514f066655984e21fbd255e8Andrew Sapperstein 4888ec43e877a9c1925514f066655984e21fbd255e8Andrew Sapperstein window.mail.onInlineAttachmentsParsed(urls, messageIds); 4893233bff8ae08a56543c9f5abf1bc6ab38f0574ceAndy Huang} 4903233bff8ae08a56543c9f5abf1bc6ab38f0574ceAndy Huang 49141dca185f7683b36bdafd9520c0648c897a95834Paul Westbrook/** 4928ec43e877a9c1925514f066655984e21fbd255e8Andrew Sapperstein * Changes relative paths to absolute path by pre-pending the account uri. 49341dca185f7683b36bdafd9520c0648c897a95834Paul Westbrook * @param {Element} imgElement Image for which the src path will be updated. 4948ec43e877a9c1925514f066655984e21fbd255e8Andrew Sapperstein * @returns the rewritten image src string or null if the imgElement was not rewritten. 49541dca185f7683b36bdafd9520c0648c897a95834Paul Westbrook */ 49641dca185f7683b36bdafd9520c0648c897a95834Paul Westbrookfunction rewriteRelativeImageSrc(imgElement) { 49741dca185f7683b36bdafd9520c0648c897a95834Paul Westbrook var src = imgElement.src; 498cebcc64fbd69618ff89f9fac0bfe9b9e7d7ce104Paul Westbrook 499cebcc64fbd69618ff89f9fac0bfe9b9e7d7ce104Paul Westbrook // DOC_BASE_URI will always be a unique x-thread:// uri for this particular conversation 500cebcc64fbd69618ff89f9fac0bfe9b9e7d7ce104Paul Westbrook if (src.indexOf(DOC_BASE_URI) == 0 && (DOC_BASE_URI != CONVERSATION_BASE_URI)) { 501cebcc64fbd69618ff89f9fac0bfe9b9e7d7ce104Paul Westbrook // The conversation specifies a different base uri than the document 502cebcc64fbd69618ff89f9fac0bfe9b9e7d7ce104Paul Westbrook src = CONVERSATION_BASE_URI + src.substring(DOC_BASE_URI.length); 503cebcc64fbd69618ff89f9fac0bfe9b9e7d7ce104Paul Westbrook imgElement.src = src; 5048ec43e877a9c1925514f066655984e21fbd255e8Andrew Sapperstein return src; 50541dca185f7683b36bdafd9520c0648c897a95834Paul Westbrook } 5068ec43e877a9c1925514f066655984e21fbd255e8Andrew Sapperstein 5078ec43e877a9c1925514f066655984e21fbd255e8Andrew Sapperstein return null; 50841dca185f7683b36bdafd9520c0648c897a95834Paul Westbrook}; 50941dca185f7683b36bdafd9520c0648c897a95834Paul Westbrook 51041dca185f7683b36bdafd9520c0648c897a95834Paul Westbrook 5113233bff8ae08a56543c9f5abf1bc6ab38f0574ceAndy Huangfunction attachImageLoadListener(imageElement) { 5123233bff8ae08a56543c9f5abf1bc6ab38f0574ceAndy Huang // Reset the src attribute to the empty string because onload will only fire if the src 5133233bff8ae08a56543c9f5abf1bc6ab38f0574ceAndy Huang // attribute is set after the onload listener. 5143233bff8ae08a56543c9f5abf1bc6ab38f0574ceAndy Huang var originalSrc = imageElement.src; 5153233bff8ae08a56543c9f5abf1bc6ab38f0574ceAndy Huang imageElement.src = ''; 516ffc725fe4b4fa1024feb22b1d1f76c24febadcdbAndy Huang imageElement.onload = imageOnLoad; 5173233bff8ae08a56543c9f5abf1bc6ab38f0574ceAndy Huang imageElement.src = originalSrc; 5183233bff8ae08a56543c9f5abf1bc6ab38f0574ceAndy Huang} 5193233bff8ae08a56543c9f5abf1bc6ab38f0574ceAndy Huang 52063b3c6725d60386f564ab53e3ba6495f0c158d9bAndy Huang/** 52163b3c6725d60386f564ab53e3ba6495f0c158d9bAndy Huang * Handle an onload event for an <img> tag. 52263b3c6725d60386f564ab53e3ba6495f0c158d9bAndy Huang * The image could be within an elided-text block, or at the top level of a message. 52363b3c6725d60386f564ab53e3ba6495f0c158d9bAndy Huang * When a new image loads, its new bounds may affect message or elided-text geometry, 52463b3c6725d60386f564ab53e3ba6495f0c158d9bAndy Huang * so we need to inspect and adjust the enclosing element's zoom level where necessary. 52563b3c6725d60386f564ab53e3ba6495f0c158d9bAndy Huang * 52663b3c6725d60386f564ab53e3ba6495f0c158d9bAndy Huang * Because this method can be called really often, and zoom-level adjustment is slow, 52763b3c6725d60386f564ab53e3ba6495f0c158d9bAndy Huang * we collect the elements to be processed and do them all later in a single deferred pass. 52863b3c6725d60386f564ab53e3ba6495f0c158d9bAndy Huang */ 529ffc725fe4b4fa1024feb22b1d1f76c24febadcdbAndy Huangfunction imageOnLoad(e) { 530ffc725fe4b4fa1024feb22b1d1f76c24febadcdbAndy Huang // normalize the quoted text parent if we're in a quoted text block, or else 531ffc725fe4b4fa1024feb22b1d1f76c24febadcdbAndy Huang // normalize the parent message content element 532ffc725fe4b4fa1024feb22b1d1f76c24febadcdbAndy Huang var parent = up(e.target, "elided-text") || up(e.target, "mail-message-content"); 53363b3c6725d60386f564ab53e3ba6495f0c158d9bAndy Huang if (!parent) { 53463b3c6725d60386f564ab53e3ba6495f0c158d9bAndy Huang // sanity check. shouldn't really happen. 53563b3c6725d60386f564ab53e3ba6495f0c158d9bAndy Huang return; 53663b3c6725d60386f564ab53e3ba6495f0c158d9bAndy Huang } 53763b3c6725d60386f564ab53e3ba6495f0c158d9bAndy Huang 53863b3c6725d60386f564ab53e3ba6495f0c158d9bAndy Huang // if there was no previous work, schedule a new deferred job 53963b3c6725d60386f564ab53e3ba6495f0c158d9bAndy Huang if (gImageLoadElements.length == 0) { 54063b3c6725d60386f564ab53e3ba6495f0c158d9bAndy Huang window.setTimeout(handleAllImageOnLoads, 0); 54163b3c6725d60386f564ab53e3ba6495f0c158d9bAndy Huang } 54263b3c6725d60386f564ab53e3ba6495f0c158d9bAndy Huang 54363b3c6725d60386f564ab53e3ba6495f0c158d9bAndy Huang // enqueue the work if it wasn't already enqueued 54463b3c6725d60386f564ab53e3ba6495f0c158d9bAndy Huang if (gImageLoadElements.indexOf(parent) == -1) { 54563b3c6725d60386f564ab53e3ba6495f0c158d9bAndy Huang gImageLoadElements.push(parent); 546ffc725fe4b4fa1024feb22b1d1f76c24febadcdbAndy Huang } 54763b3c6725d60386f564ab53e3ba6495f0c158d9bAndy Huang} 54863b3c6725d60386f564ab53e3ba6495f0c158d9bAndy Huang 54963b3c6725d60386f564ab53e3ba6495f0c158d9bAndy Huang// handle all deferred work from image onload events 55063b3c6725d60386f564ab53e3ba6495f0c158d9bAndy Huangfunction handleAllImageOnLoads() { 55163b3c6725d60386f564ab53e3ba6495f0c158d9bAndy Huang normalizeElementWidths(gImageLoadElements); 552ffc725fe4b4fa1024feb22b1d1f76c24febadcdbAndy Huang measurePositions(); 55363b3c6725d60386f564ab53e3ba6495f0c158d9bAndy Huang // clear the queue so the next onload event starts a new job 55463b3c6725d60386f564ab53e3ba6495f0c158d9bAndy Huang gImageLoadElements = []; 555ffc725fe4b4fa1024feb22b1d1f76c24febadcdbAndy Huang} 556ffc725fe4b4fa1024feb22b1d1f76c24febadcdbAndy Huang 5573233bff8ae08a56543c9f5abf1bc6ab38f0574ceAndy Huangfunction blockImage(imageElement) { 5583233bff8ae08a56543c9f5abf1bc6ab38f0574ceAndy Huang var src = imageElement.src; 55941dca185f7683b36bdafd9520c0648c897a95834Paul Westbrook if (src.indexOf("http://") == 0 || src.indexOf("https://") == 0 || 56041dca185f7683b36bdafd9520c0648c897a95834Paul Westbrook src.indexOf("content://") == 0) { 5613233bff8ae08a56543c9f5abf1bc6ab38f0574ceAndy Huang imageElement.setAttribute(BLOCKED_SRC_ATTR, src); 5623233bff8ae08a56543c9f5abf1bc6ab38f0574ceAndy Huang imageElement.src = "data:"; 5633233bff8ae08a56543c9f5abf1bc6ab38f0574ceAndy Huang } 5643233bff8ae08a56543c9f5abf1bc6ab38f0574ceAndy Huang} 5653233bff8ae08a56543c9f5abf1bc6ab38f0574ceAndy Huang 56623014705ca9872cd5004a1aa76e83ae260165ecaAndy Huangfunction setWideViewport() { 56723014705ca9872cd5004a1aa76e83ae260165ecaAndy Huang var metaViewport = document.getElementById('meta-viewport'); 56823014705ca9872cd5004a1aa76e83ae260165ecaAndy Huang metaViewport.setAttribute('content', 'width=' + WIDE_VIEWPORT_WIDTH); 56923014705ca9872cd5004a1aa76e83ae260165ecaAndy Huang} 57023014705ca9872cd5004a1aa76e83ae260165ecaAndy Huang 571e964eeec3a088b3f4c29b68d41f99e43a321ac52Andy Huangfunction restoreScrollPosition() { 572e964eeec3a088b3f4c29b68d41f99e43a321ac52Andy Huang var scrollYPercent = window.mail.getScrollYPercent(); 573e964eeec3a088b3f4c29b68d41f99e43a321ac52Andy Huang if (scrollYPercent && document.body.offsetHeight > window.innerHeight) { 574e964eeec3a088b3f4c29b68d41f99e43a321ac52Andy Huang document.body.scrollTop = Math.floor(scrollYPercent * document.body.offsetHeight); 575e964eeec3a088b3f4c29b68d41f99e43a321ac52Andy Huang } 576e964eeec3a088b3f4c29b68d41f99e43a321ac52Andy Huang} 577e964eeec3a088b3f4c29b68d41f99e43a321ac52Andy Huang 578bffc312614505b923f0054fde20d015bd21112cfAndy Huangfunction onContentReady(event) { 579575e82b628dca4a67dd25b883c504ce9109a345aAndrew Sapperstein // hack for b/1333356 580575e82b628dca4a67dd25b883c504ce9109a345aAndrew Sapperstein if (RUNNING_KITKAT_OR_LATER) { 581575e82b628dca4a67dd25b883c504ce9109a345aAndrew Sapperstein restoreScrollPosition(); 582575e82b628dca4a67dd25b883c504ce9109a345aAndrew Sapperstein } 583bffc312614505b923f0054fde20d015bd21112cfAndy Huang window.mail.onContentReady(); 584bffc312614505b923f0054fde20d015bd21112cfAndy Huang} 585bffc312614505b923f0054fde20d015bd21112cfAndy Huang 586bffc312614505b923f0054fde20d015bd21112cfAndy Huangfunction setupContentReady() { 587bffc312614505b923f0054fde20d015bd21112cfAndy Huang var signalDiv; 588bffc312614505b923f0054fde20d015bd21112cfAndy Huang 589bffc312614505b923f0054fde20d015bd21112cfAndy Huang // PAGE READINESS SIGNAL FOR JELLYBEAN AND NEWER 590bffc312614505b923f0054fde20d015bd21112cfAndy Huang // Notify the app on 'webkitAnimationStart' of a simple dummy element with a simple no-op 591bffc312614505b923f0054fde20d015bd21112cfAndy Huang // animation that immediately runs on page load. The app uses this as a signal that the 592bffc312614505b923f0054fde20d015bd21112cfAndy Huang // content is loaded and ready to draw, since WebView delays firing this event until the 593bffc312614505b923f0054fde20d015bd21112cfAndy Huang // layers are composited and everything is ready to draw. 594bffc312614505b923f0054fde20d015bd21112cfAndy Huang // 595bffc312614505b923f0054fde20d015bd21112cfAndy Huang // This code is conditionally enabled on JB+ by setting the ENABLE_CONTENT_READY flag. 596bffc312614505b923f0054fde20d015bd21112cfAndy Huang if (ENABLE_CONTENT_READY) { 597bffc312614505b923f0054fde20d015bd21112cfAndy Huang signalDiv = document.getElementById("initial-load-signal"); 598bffc312614505b923f0054fde20d015bd21112cfAndy Huang signalDiv.addEventListener("webkitAnimationStart", onContentReady, false); 599bffc312614505b923f0054fde20d015bd21112cfAndy Huang } 600bffc312614505b923f0054fde20d015bd21112cfAndy Huang} 601bffc312614505b923f0054fde20d015bd21112cfAndy Huang 60223014705ca9872cd5004a1aa76e83ae260165ecaAndy Huang// BEGIN Java->JavaScript handlers 603f70fc4052b72a850bbb9be585d0f5a4877ee9448Andy Huangfunction measurePositions() { 604adbf3e8cadb66666f307352b72537fbac57b916fAndy Huang var overlayTops, overlayBottoms; 605f70fc4052b72a850bbb9be585d0f5a4877ee9448Andy Huang var i; 606f70fc4052b72a850bbb9be585d0f5a4877ee9448Andy Huang var len; 607f70fc4052b72a850bbb9be585d0f5a4877ee9448Andy Huang 608adbf3e8cadb66666f307352b72537fbac57b916fAndy Huang var expandedBody, headerSpacer; 609adbf3e8cadb66666f307352b72537fbac57b916fAndy Huang var prevBodyBottom = 0; 610adbf3e8cadb66666f307352b72537fbac57b916fAndy Huang var expandedBodyDivs = document.querySelectorAll(".expanded > .mail-message-content"); 611adbf3e8cadb66666f307352b72537fbac57b916fAndy Huang 612adbf3e8cadb66666f307352b72537fbac57b916fAndy Huang // N.B. offsetTop and offsetHeight of an element with the "zoom:" style applied cannot be 613adbf3e8cadb66666f307352b72537fbac57b916fAndy Huang // trusted. 614f70fc4052b72a850bbb9be585d0f5a4877ee9448Andy Huang 615adbf3e8cadb66666f307352b72537fbac57b916fAndy Huang overlayTops = new Array(expandedBodyDivs.length + 1); 616adbf3e8cadb66666f307352b72537fbac57b916fAndy Huang overlayBottoms = new Array(expandedBodyDivs.length + 1); 617adbf3e8cadb66666f307352b72537fbac57b916fAndy Huang for (i = 0, len = expandedBodyDivs.length; i < len; i++) { 618adbf3e8cadb66666f307352b72537fbac57b916fAndy Huang expandedBody = expandedBodyDivs[i]; 619adbf3e8cadb66666f307352b72537fbac57b916fAndy Huang headerSpacer = expandedBody.previousElementSibling; 620f70fc4052b72a850bbb9be585d0f5a4877ee9448Andy Huang // addJavascriptInterface handler only supports string arrays 62173bac140429627ef9111438d2358958d5d58638bAndrew Sapperstein overlayTops[i] = prevBodyBottom; 62273bac140429627ef9111438d2358958d5d58638bAndrew Sapperstein overlayBottoms[i] = (getTotalOffset(headerSpacer).top + headerSpacer.offsetHeight); 623adbf3e8cadb66666f307352b72537fbac57b916fAndy Huang prevBodyBottom = getTotalOffset(expandedBody.nextElementSibling).top; 624f70fc4052b72a850bbb9be585d0f5a4877ee9448Andy Huang } 625adbf3e8cadb66666f307352b72537fbac57b916fAndy Huang // add an extra one to mark the top/bottom of the last message footer spacer 62673bac140429627ef9111438d2358958d5d58638bAndrew Sapperstein overlayTops[i] = prevBodyBottom; 62773bac140429627ef9111438d2358958d5d58638bAndrew Sapperstein overlayBottoms[i] = document.documentElement.scrollHeight; 628e4e1c49e550171ae44e94910d6b030e866436607Andrew Sapperstein 629adbf3e8cadb66666f307352b72537fbac57b916fAndy Huang window.mail.onWebContentGeometryChange(overlayTops, overlayBottoms); 630f70fc4052b72a850bbb9be585d0f5a4877ee9448Andy Huang} 631f70fc4052b72a850bbb9be585d0f5a4877ee9448Andy Huang 632eb9a4bdc53269ee05fe11870b9ebf03f18196585Scott Kennedyfunction unblockImages(messageDomIds) { 633eb9a4bdc53269ee05fe11870b9ebf03f18196585Scott Kennedy var i, j, images, imgCount, image, blockedSrc; 634eb9a4bdc53269ee05fe11870b9ebf03f18196585Scott Kennedy for (j = 0, len = messageDomIds.length; j < len; j++) { 635eb9a4bdc53269ee05fe11870b9ebf03f18196585Scott Kennedy var messageDomId = messageDomIds[j]; 636eb9a4bdc53269ee05fe11870b9ebf03f18196585Scott Kennedy var msg = document.getElementById(messageDomId); 637eb9a4bdc53269ee05fe11870b9ebf03f18196585Scott Kennedy if (!msg) { 638eb9a4bdc53269ee05fe11870b9ebf03f18196585Scott Kennedy console.log("can't unblock, no matching message for id: " + messageDomId); 639eb9a4bdc53269ee05fe11870b9ebf03f18196585Scott Kennedy continue; 640eb9a4bdc53269ee05fe11870b9ebf03f18196585Scott Kennedy } 641eb9a4bdc53269ee05fe11870b9ebf03f18196585Scott Kennedy images = msg.getElementsByTagName("img"); 642eb9a4bdc53269ee05fe11870b9ebf03f18196585Scott Kennedy for (i = 0, imgCount = images.length; i < imgCount; i++) { 643eb9a4bdc53269ee05fe11870b9ebf03f18196585Scott Kennedy image = images[i]; 644eb9a4bdc53269ee05fe11870b9ebf03f18196585Scott Kennedy blockedSrc = image.getAttribute(BLOCKED_SRC_ATTR); 645eb9a4bdc53269ee05fe11870b9ebf03f18196585Scott Kennedy if (blockedSrc) { 646eb9a4bdc53269ee05fe11870b9ebf03f18196585Scott Kennedy image.src = blockedSrc; 647eb9a4bdc53269ee05fe11870b9ebf03f18196585Scott Kennedy image.removeAttribute(BLOCKED_SRC_ATTR); 648eb9a4bdc53269ee05fe11870b9ebf03f18196585Scott Kennedy } 6493233bff8ae08a56543c9f5abf1bc6ab38f0574ceAndy Huang } 6503233bff8ae08a56543c9f5abf1bc6ab38f0574ceAndy Huang } 6513233bff8ae08a56543c9f5abf1bc6ab38f0574ceAndy Huang} 652c7543579c6a97c0ae3341578332f56d4d226f34cAndy Huang 653ab2d998506c83e82ddae25b6ba1419414e1e8122Mark Weifunction setConversationHeaderSpacerHeight(spacerHeight) { 654ab2d998506c83e82ddae25b6ba1419414e1e8122Mark Wei var spacer = document.getElementById("conversation-header"); 655ab2d998506c83e82ddae25b6ba1419414e1e8122Mark Wei if (!spacer) { 656ab2d998506c83e82ddae25b6ba1419414e1e8122Mark Wei console.log("can't set spacer for conversation header"); 657ab2d998506c83e82ddae25b6ba1419414e1e8122Mark Wei return; 658ab2d998506c83e82ddae25b6ba1419414e1e8122Mark Wei } 659ab2d998506c83e82ddae25b6ba1419414e1e8122Mark Wei spacer.style.height = spacerHeight + "px"; 660ab2d998506c83e82ddae25b6ba1419414e1e8122Mark Wei measurePositions(); 661ab2d998506c83e82ddae25b6ba1419414e1e8122Mark Wei} 662ab2d998506c83e82ddae25b6ba1419414e1e8122Mark Wei 663735a22a197215ec4787ad9f3cbaf465cce54f4d0Andrew Sappersteinfunction setConversationFooterSpacerHeight(spacerHeight) { 664735a22a197215ec4787ad9f3cbaf465cce54f4d0Andrew Sapperstein var spacer = document.getElementById("conversation-footer"); 665735a22a197215ec4787ad9f3cbaf465cce54f4d0Andrew Sapperstein if (!spacer) { 666735a22a197215ec4787ad9f3cbaf465cce54f4d0Andrew Sapperstein console.log("can't set spacer for conversation footer"); 667735a22a197215ec4787ad9f3cbaf465cce54f4d0Andrew Sapperstein return; 668735a22a197215ec4787ad9f3cbaf465cce54f4d0Andrew Sapperstein } 669735a22a197215ec4787ad9f3cbaf465cce54f4d0Andrew Sapperstein spacer.style.height = spacerHeight + "px"; 670735a22a197215ec4787ad9f3cbaf465cce54f4d0Andrew Sapperstein measurePositions(); 671735a22a197215ec4787ad9f3cbaf465cce54f4d0Andrew Sapperstein} 672735a22a197215ec4787ad9f3cbaf465cce54f4d0Andrew Sapperstein 673c7543579c6a97c0ae3341578332f56d4d226f34cAndy Huangfunction setMessageHeaderSpacerHeight(messageDomId, spacerHeight) { 674c7543579c6a97c0ae3341578332f56d4d226f34cAndy Huang var spacer = document.querySelector("#" + messageDomId + " > .mail-message-header"); 675381c322eb30c39f63a2bb82812d63262eb3c1c1cAndrew Sapperstein setSpacerHeight(spacer, spacerHeight); 676381c322eb30c39f63a2bb82812d63262eb3c1c1cAndrew Sapperstein} 677381c322eb30c39f63a2bb82812d63262eb3c1c1cAndrew Sapperstein 678381c322eb30c39f63a2bb82812d63262eb3c1c1cAndrew Sappersteinfunction setSpacerHeight(spacer, spacerHeight) { 679c7543579c6a97c0ae3341578332f56d4d226f34cAndy Huang if (!spacer) { 680c7543579c6a97c0ae3341578332f56d4d226f34cAndy Huang console.log("can't set spacer for message with id: " + messageDomId); 681c7543579c6a97c0ae3341578332f56d4d226f34cAndy Huang return; 682c7543579c6a97c0ae3341578332f56d4d226f34cAndy Huang } 683c7543579c6a97c0ae3341578332f56d4d226f34cAndy Huang spacer.style.height = spacerHeight + "px"; 684c7543579c6a97c0ae3341578332f56d4d226f34cAndy Huang measurePositions(); 685c7543579c6a97c0ae3341578332f56d4d226f34cAndy Huang} 686c7543579c6a97c0ae3341578332f56d4d226f34cAndy Huang 68759ccec3db4710f2aea6a4a9a30160ad19331367dAndrew Sappersteinfunction setMessageBodyVisible(messageDomId, isVisible, spacerHeight) { 688c7543579c6a97c0ae3341578332f56d4d226f34cAndy Huang var i, len; 689c7543579c6a97c0ae3341578332f56d4d226f34cAndy Huang var visibility = isVisible ? "block" : "none"; 690c7543579c6a97c0ae3341578332f56d4d226f34cAndy Huang var messageDiv = document.querySelector("#" + messageDomId); 691c7543579c6a97c0ae3341578332f56d4d226f34cAndy Huang var collapsibleDivs = document.querySelectorAll("#" + messageDomId + " > .collapsible"); 692c7543579c6a97c0ae3341578332f56d4d226f34cAndy Huang if (!messageDiv || collapsibleDivs.length == 0) { 693c7543579c6a97c0ae3341578332f56d4d226f34cAndy Huang console.log("can't set body visibility for message with id: " + messageDomId); 694c7543579c6a97c0ae3341578332f56d4d226f34cAndy Huang return; 695c7543579c6a97c0ae3341578332f56d4d226f34cAndy Huang } 696cee3c90574b48ccaa0f8b9f9341383c231ed41d2Andrew Sapperstein 697c7543579c6a97c0ae3341578332f56d4d226f34cAndy Huang messageDiv.classList.toggle("expanded"); 698c7543579c6a97c0ae3341578332f56d4d226f34cAndy Huang for (i = 0, len = collapsibleDivs.length; i < len; i++) { 699c7543579c6a97c0ae3341578332f56d4d226f34cAndy Huang collapsibleDivs[i].style.display = visibility; 700c7543579c6a97c0ae3341578332f56d4d226f34cAndy Huang } 701ffc725fe4b4fa1024feb22b1d1f76c24febadcdbAndy Huang 702ffc725fe4b4fa1024feb22b1d1f76c24febadcdbAndy Huang // revealing new content should trigger width normalization, since the initial render 703ffc725fe4b4fa1024feb22b1d1f76c24febadcdbAndy Huang // skips collapsed and super-collapsed messages 704ffc725fe4b4fa1024feb22b1d1f76c24febadcdbAndy Huang if (isVisible) { 705ffc725fe4b4fa1024feb22b1d1f76c24febadcdbAndy Huang normalizeElementWidths(messageDiv.getElementsByClassName("mail-message-content")); 706ffc725fe4b4fa1024feb22b1d1f76c24febadcdbAndy Huang } 707ffc725fe4b4fa1024feb22b1d1f76c24febadcdbAndy Huang 708c7543579c6a97c0ae3341578332f56d4d226f34cAndy Huang setMessageHeaderSpacerHeight(messageDomId, spacerHeight); 709c7543579c6a97c0ae3341578332f56d4d226f34cAndy Huang} 71046dfba6160b55a582b344328067e3dafeb881dd9Andy Huang 71146dfba6160b55a582b344328067e3dafeb881dd9Andy Huangfunction replaceSuperCollapsedBlock(startIndex) { 712f500db85dd13394dd6bdcfa38824b2ca6ada77e8Andy Huang var parent, block, msg; 71346dfba6160b55a582b344328067e3dafeb881dd9Andy Huang 71446dfba6160b55a582b344328067e3dafeb881dd9Andy Huang block = document.querySelector(".mail-super-collapsed-block[index='" + startIndex + "']"); 71546dfba6160b55a582b344328067e3dafeb881dd9Andy Huang if (!block) { 71646dfba6160b55a582b344328067e3dafeb881dd9Andy Huang console.log("can't expand super collapsed block at index: " + startIndex); 71746dfba6160b55a582b344328067e3dafeb881dd9Andy Huang return; 71846dfba6160b55a582b344328067e3dafeb881dd9Andy Huang } 71946dfba6160b55a582b344328067e3dafeb881dd9Andy Huang parent = block.parentNode; 72046dfba6160b55a582b344328067e3dafeb881dd9Andy Huang block.innerHTML = window.mail.getTempMessageBodies(); 72146dfba6160b55a582b344328067e3dafeb881dd9Andy Huang 722f500db85dd13394dd6bdcfa38824b2ca6ada77e8Andy Huang // process the new block contents in one go before we pluck them out of the common ancestor 723f500db85dd13394dd6bdcfa38824b2ca6ada77e8Andy Huang processQuotedText(block, false /* showElided */); 724f500db85dd13394dd6bdcfa38824b2ca6ada77e8Andy Huang hideUnsafeImages(block.getElementsByClassName("mail-message-content")); 725f500db85dd13394dd6bdcfa38824b2ca6ada77e8Andy Huang 726f500db85dd13394dd6bdcfa38824b2ca6ada77e8Andy Huang msg = block.firstChild; 727f500db85dd13394dd6bdcfa38824b2ca6ada77e8Andy Huang while (msg) { 728f500db85dd13394dd6bdcfa38824b2ca6ada77e8Andy Huang parent.insertBefore(msg, block); 729f500db85dd13394dd6bdcfa38824b2ca6ada77e8Andy Huang msg = block.firstChild; 73046dfba6160b55a582b344328067e3dafeb881dd9Andy Huang } 73146dfba6160b55a582b344328067e3dafeb881dd9Andy Huang parent.removeChild(block); 73246dfba6160b55a582b344328067e3dafeb881dd9Andy Huang measurePositions(); 73346dfba6160b55a582b344328067e3dafeb881dd9Andy Huang} 7343bcf180f8104bc27319086a9a6ece5a3c2917c37mindyp 735986776bbd046c9569a4abb67501819bee61e7194Andy Huangfunction processNewMessageBody(msgContentDiv) { 736986776bbd046c9569a4abb67501819bee61e7194Andy Huang processQuotedText(msgContentDiv, true /* showElided */); 737986776bbd046c9569a4abb67501819bee61e7194Andy Huang hideUnsafeImages([msgContentDiv]); 738986776bbd046c9569a4abb67501819bee61e7194Andy Huang if (up(msgContentDiv, "mail-message").classList.contains("expanded")) { 739986776bbd046c9569a4abb67501819bee61e7194Andy Huang normalizeElementWidths([msgContentDiv]); 740986776bbd046c9569a4abb67501819bee61e7194Andy Huang } 741986776bbd046c9569a4abb67501819bee61e7194Andy Huang} 742986776bbd046c9569a4abb67501819bee61e7194Andy Huang 743014ea4c15d147794789b9c5bf4e243fa08781ad9Andy Huangfunction replaceMessageBodies(messageIds) { 744014ea4c15d147794789b9c5bf4e243fa08781ad9Andy Huang var i; 745014ea4c15d147794789b9c5bf4e243fa08781ad9Andy Huang var id; 746014ea4c15d147794789b9c5bf4e243fa08781ad9Andy Huang var msgContentDiv; 747014ea4c15d147794789b9c5bf4e243fa08781ad9Andy Huang 748014ea4c15d147794789b9c5bf4e243fa08781ad9Andy Huang for (i = 0, len = messageIds.length; i < len; i++) { 749014ea4c15d147794789b9c5bf4e243fa08781ad9Andy Huang id = messageIds[i]; 750014ea4c15d147794789b9c5bf4e243fa08781ad9Andy Huang msgContentDiv = document.querySelector("#" + id + " > .mail-message-content"); 751014ea4c15d147794789b9c5bf4e243fa08781ad9Andy Huang msgContentDiv.innerHTML = window.mail.getMessageBody(id); 752986776bbd046c9569a4abb67501819bee61e7194Andy Huang processNewMessageBody(msgContentDiv); 753014ea4c15d147794789b9c5bf4e243fa08781ad9Andy Huang } 75491d782abc8015bd651fb5d0252b4d1ef369ec57bAndy Huang measurePositions(); 755014ea4c15d147794789b9c5bf4e243fa08781ad9Andy Huang} 756014ea4c15d147794789b9c5bf4e243fa08781ad9Andy Huang 75706c0362f59437f3ea2b5832272fb66158bb4b8c0Andy Huang// handle the special case of adding a single new message at the end of a conversation 75806c0362f59437f3ea2b5832272fb66158bb4b8c0Andy Huangfunction appendMessageHtml() { 75906c0362f59437f3ea2b5832272fb66158bb4b8c0Andy Huang var msg = document.createElement("div"); 76006c0362f59437f3ea2b5832272fb66158bb4b8c0Andy Huang msg.innerHTML = window.mail.getTempMessageBodies(); 7611f082231c4a51eb3be37df6d2a0024634dfe4a9bAndrew Sapperstein var body = msg.children[0]; // toss the outer div, it was just to render innerHTML into 762e2a30e19a9fff0e4368c4ec36280a3fcd4ca03e2Andrew Sapperstein document.body.insertBefore(body, document.getElementById("conversation-footer")); 763986776bbd046c9569a4abb67501819bee61e7194Andy Huang processNewMessageBody(body.querySelector(".mail-message-content")); 76491d782abc8015bd651fb5d0252b4d1ef369ec57bAndy Huang measurePositions(); 76506c0362f59437f3ea2b5832272fb66158bb4b8c0Andy Huang} 76606c0362f59437f3ea2b5832272fb66158bb4b8c0Andy Huang 7673233bff8ae08a56543c9f5abf1bc6ab38f0574ceAndy Huang// END Java->JavaScript handlers 7683233bff8ae08a56543c9f5abf1bc6ab38f0574ceAndy Huang 7694cfe22a8b0fe9fb98df9c82303bacc5c1a79f19bAndy Huang// Do this first to ensure that the readiness signal comes through, 7704cfe22a8b0fe9fb98df9c82303bacc5c1a79f19bAndy Huang// even if a stray exception later occurs. 7714cfe22a8b0fe9fb98df9c82303bacc5c1a79f19bAndy HuangsetupContentReady(); 7724cfe22a8b0fe9fb98df9c82303bacc5c1a79f19bAndy Huang 773014ea4c15d147794789b9c5bf4e243fa08781ad9Andy HuangcollapseAllQuotedText(); 774f500db85dd13394dd6bdcfa38824b2ca6ada77e8Andy HuanghideAllUnsafeImages(); 775ffc725fe4b4fa1024feb22b1d1f76c24febadcdbAndy HuangnormalizeAllMessageWidths(); 77623014705ca9872cd5004a1aa76e83ae260165ecaAndy Huang//setWideViewport(); 777575e82b628dca4a67dd25b883c504ce9109a345aAndrew Sapperstein// hack for b/1333356 778575e82b628dca4a67dd25b883c504ce9109a345aAndrew Sappersteinif (!RUNNING_KITKAT_OR_LATER) { 779575e82b628dca4a67dd25b883c504ce9109a345aAndrew Sapperstein restoreScrollPosition(); 780575e82b628dca4a67dd25b883c504ce9109a345aAndrew Sapperstein} 781f70fc4052b72a850bbb9be585d0f5a4877ee9448Andy HuangmeasurePositions(); 782f70fc4052b72a850bbb9be585d0f5a4877ee9448Andy Huang 783