script.js revision 986776bbd046c9569a4abb67501819bee61e7194
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; 118df0d91c5fa064e93b647fd62fe2446791664003fAndy Huang toggleElement.onclick = onToggleClick; 119df0d91c5fa064e93b647fd62fe2446791664003fAndy Huang elidedElement.style.display = 'none'; 120f70fc4052b72a850bbb9be585d0f5a4877ee9448Andy Huang elidedElement.parentNode.insertBefore(toggleElement, elidedElement); 121df0d91c5fa064e93b647fd62fe2446791664003fAndy Huang if (showElided) { 122df0d91c5fa064e93b647fd62fe2446791664003fAndy Huang toggleQuotedText(toggleElement); 123df0d91c5fa064e93b647fd62fe2446791664003fAndy Huang } 124f70fc4052b72a850bbb9be585d0f5a4877ee9448Andy Huang } 125f70fc4052b72a850bbb9be585d0f5a4877ee9448Andy Huang} 126f70fc4052b72a850bbb9be585d0f5a4877ee9448Andy Huang 1274cfe22a8b0fe9fb98df9c82303bacc5c1a79f19bAndy Huangfunction isConversationEmpty(bodyDivs) { 1284cfe22a8b0fe9fb98df9c82303bacc5c1a79f19bAndy Huang var i, len; 1294cfe22a8b0fe9fb98df9c82303bacc5c1a79f19bAndy Huang var msgBody; 1304cfe22a8b0fe9fb98df9c82303bacc5c1a79f19bAndy Huang var text; 1314cfe22a8b0fe9fb98df9c82303bacc5c1a79f19bAndy Huang 1324cfe22a8b0fe9fb98df9c82303bacc5c1a79f19bAndy Huang // Check if given divs are empty (in appearance), and disable zoom if so. 1334cfe22a8b0fe9fb98df9c82303bacc5c1a79f19bAndy Huang for (i = 0, len = bodyDivs.length; i < len; i++) { 1344cfe22a8b0fe9fb98df9c82303bacc5c1a79f19bAndy Huang msgBody = bodyDivs[i]; 1354cfe22a8b0fe9fb98df9c82303bacc5c1a79f19bAndy Huang // use 'textContent' to exclude markup when determining whether bodies are empty 1364cfe22a8b0fe9fb98df9c82303bacc5c1a79f19bAndy Huang // (fall back to more expensive 'innerText' if 'textContent' isn't implemented) 1374cfe22a8b0fe9fb98df9c82303bacc5c1a79f19bAndy Huang text = msgBody.textContent || msgBody.innerText; 1384cfe22a8b0fe9fb98df9c82303bacc5c1a79f19bAndy Huang if (text.trim().length > 0) { 1394cfe22a8b0fe9fb98df9c82303bacc5c1a79f19bAndy Huang return false; 1404cfe22a8b0fe9fb98df9c82303bacc5c1a79f19bAndy Huang } 1414cfe22a8b0fe9fb98df9c82303bacc5c1a79f19bAndy Huang } 1424cfe22a8b0fe9fb98df9c82303bacc5c1a79f19bAndy Huang return true; 1434cfe22a8b0fe9fb98df9c82303bacc5c1a79f19bAndy Huang} 1444cfe22a8b0fe9fb98df9c82303bacc5c1a79f19bAndy Huang 145ffc725fe4b4fa1024feb22b1d1f76c24febadcdbAndy Huangfunction normalizeAllMessageWidths() { 1464cfe22a8b0fe9fb98df9c82303bacc5c1a79f19bAndy Huang var expandedBodyDivs; 1474cfe22a8b0fe9fb98df9c82303bacc5c1a79f19bAndy Huang var metaViewport; 1484cfe22a8b0fe9fb98df9c82303bacc5c1a79f19bAndy Huang var contentValues; 1494cfe22a8b0fe9fb98df9c82303bacc5c1a79f19bAndy Huang var isEmpty; 1504cfe22a8b0fe9fb98df9c82303bacc5c1a79f19bAndy Huang 1514cfe22a8b0fe9fb98df9c82303bacc5c1a79f19bAndy Huang expandedBodyDivs = document.querySelectorAll(".expanded > .mail-message-content"); 1524cfe22a8b0fe9fb98df9c82303bacc5c1a79f19bAndy Huang 1534cfe22a8b0fe9fb98df9c82303bacc5c1a79f19bAndy Huang isEmpty = isConversationEmpty(expandedBodyDivs); 1544cfe22a8b0fe9fb98df9c82303bacc5c1a79f19bAndy Huang 1554cfe22a8b0fe9fb98df9c82303bacc5c1a79f19bAndy Huang normalizeElementWidths(expandedBodyDivs); 1564cfe22a8b0fe9fb98df9c82303bacc5c1a79f19bAndy Huang 1574cfe22a8b0fe9fb98df9c82303bacc5c1a79f19bAndy Huang // assemble a working <meta> viewport "content" value from the base value in the 1584cfe22a8b0fe9fb98df9c82303bacc5c1a79f19bAndy Huang // document, plus any dynamically determined options 1594cfe22a8b0fe9fb98df9c82303bacc5c1a79f19bAndy Huang metaViewport = document.getElementById("meta-viewport"); 1604cfe22a8b0fe9fb98df9c82303bacc5c1a79f19bAndy Huang contentValues = [metaViewport.getAttribute("content")]; 1614cfe22a8b0fe9fb98df9c82303bacc5c1a79f19bAndy Huang if (isEmpty) { 1624cfe22a8b0fe9fb98df9c82303bacc5c1a79f19bAndy Huang contentValues.push(metaViewport.getAttribute("data-zoom-off")); 1634cfe22a8b0fe9fb98df9c82303bacc5c1a79f19bAndy Huang } else { 1644cfe22a8b0fe9fb98df9c82303bacc5c1a79f19bAndy Huang contentValues.push(metaViewport.getAttribute("data-zoom-on")); 1654cfe22a8b0fe9fb98df9c82303bacc5c1a79f19bAndy Huang } 1664cfe22a8b0fe9fb98df9c82303bacc5c1a79f19bAndy Huang metaViewport.setAttribute("content", contentValues.join(",")); 167ffc725fe4b4fa1024feb22b1d1f76c24febadcdbAndy Huang} 168ffc725fe4b4fa1024feb22b1d1f76c24febadcdbAndy Huang 169ffc725fe4b4fa1024feb22b1d1f76c24febadcdbAndy Huang/* 170ffc725fe4b4fa1024feb22b1d1f76c24febadcdbAndy Huang * Normalizes the width of all elements supplied to the document body's overall width. 171ffc725fe4b4fa1024feb22b1d1f76c24febadcdbAndy Huang * Narrower elements are zoomed in, and wider elements are zoomed out. 172ffc725fe4b4fa1024feb22b1d1f76c24febadcdbAndy Huang * This method is idempotent. 173ffc725fe4b4fa1024feb22b1d1f76c24febadcdbAndy Huang */ 174ffc725fe4b4fa1024feb22b1d1f76c24febadcdbAndy Huangfunction normalizeElementWidths(elements) { 175f70fc4052b72a850bbb9be585d0f5a4877ee9448Andy Huang var i; 176ffc725fe4b4fa1024feb22b1d1f76c24febadcdbAndy Huang var el; 177adbf3e8cadb66666f307352b72537fbac57b916fAndy Huang var documentWidth; 1784dc732387454eef3ee6d89f9fa393630eb6213f9Andy Huang var goalWidth; 1794dc732387454eef3ee6d89f9fa393630eb6213f9Andy Huang var origWidth; 180ffc725fe4b4fa1024feb22b1d1f76c24febadcdbAndy Huang var newZoom, oldZoom; 1814dc732387454eef3ee6d89f9fa393630eb6213f9Andy Huang var outerZoom; 1824dc732387454eef3ee6d89f9fa393630eb6213f9Andy Huang var outerDiv; 183256b35c0a8287f48c28e0d1ba3fae65790063295Andy Huang 184adbf3e8cadb66666f307352b72537fbac57b916fAndy Huang documentWidth = document.body.offsetWidth; 1852160d53e6ae0bfb797569d616e735e46c21522ffAndy Huang goalWidth = WEBVIEW_WIDTH; 186adbf3e8cadb66666f307352b72537fbac57b916fAndy Huang 187f70fc4052b72a850bbb9be585d0f5a4877ee9448Andy Huang for (i = 0; i < elements.length; i++) { 188ffc725fe4b4fa1024feb22b1d1f76c24febadcdbAndy Huang el = elements[i]; 189ffc725fe4b4fa1024feb22b1d1f76c24febadcdbAndy Huang oldZoom = el.style.zoom; 190ffc725fe4b4fa1024feb22b1d1f76c24febadcdbAndy Huang // reset any existing normalization 191ffc725fe4b4fa1024feb22b1d1f76c24febadcdbAndy Huang if (oldZoom) { 192ffc725fe4b4fa1024feb22b1d1f76c24febadcdbAndy Huang el.style.zoom = 1; 193ffc725fe4b4fa1024feb22b1d1f76c24febadcdbAndy Huang } 1944dc732387454eef3ee6d89f9fa393630eb6213f9Andy Huang origWidth = el.style.width; 1954dc732387454eef3ee6d89f9fa393630eb6213f9Andy Huang el.style.width = goalWidth + "px"; 1964dc732387454eef3ee6d89f9fa393630eb6213f9Andy Huang transformContent(el, goalWidth, el.scrollWidth); 1975ea5a8330532a75c83cbb30993a14ee9b821fa2aAndy Huang newZoom = documentWidth / el.scrollWidth; 1985ea5a8330532a75c83cbb30993a14ee9b821fa2aAndy Huang if (NORMALIZE_MESSAGE_WIDTHS) { 1994dc732387454eef3ee6d89f9fa393630eb6213f9Andy Huang if (el.classList.contains("mail-message-content")) { 2004dc732387454eef3ee6d89f9fa393630eb6213f9Andy Huang outerZoom = 1; 2014dc732387454eef3ee6d89f9fa393630eb6213f9Andy Huang } else { 2024dc732387454eef3ee6d89f9fa393630eb6213f9Andy Huang outerDiv = up(el, "mail-message-content"); 2034dc732387454eef3ee6d89f9fa393630eb6213f9Andy Huang outerZoom = outerDiv ? outerDiv.style.zoom : 1; 2044dc732387454eef3ee6d89f9fa393630eb6213f9Andy Huang } 2054dc732387454eef3ee6d89f9fa393630eb6213f9Andy Huang el.style.zoom = newZoom / outerZoom; 2065ea5a8330532a75c83cbb30993a14ee9b821fa2aAndy Huang } 2074dc732387454eef3ee6d89f9fa393630eb6213f9Andy Huang el.style.width = origWidth; 2085ea5a8330532a75c83cbb30993a14ee9b821fa2aAndy Huang } 2095ea5a8330532a75c83cbb30993a14ee9b821fa2aAndy Huang} 2105ea5a8330532a75c83cbb30993a14ee9b821fa2aAndy Huang 2110180f27c0998623b702274048b49cd4bec536cf1Andy Huangfunction transformContent(el, docWidth, elWidth) { 2125ea5a8330532a75c83cbb30993a14ee9b821fa2aAndy Huang var nodes; 2135ea5a8330532a75c83cbb30993a14ee9b821fa2aAndy Huang var i, len; 2140180f27c0998623b702274048b49cd4bec536cf1Andy Huang var index; 2153a398b245930ce60ceb51fc605ab0f20c8df1f62Andy Huang var newWidth = elWidth; 2165ea5a8330532a75c83cbb30993a14ee9b821fa2aAndy Huang var wStr; 2173a398b245930ce60ceb51fc605ab0f20c8df1f62Andy Huang var touched; 2180180f27c0998623b702274048b49cd4bec536cf1Andy Huang // the format of entries in this array is: 2190180f27c0998623b702274048b49cd4bec536cf1Andy Huang // entry := [ undoFunction, undoFunctionThis, undoFunctionParamArray ] 2203a398b245930ce60ceb51fc605ab0f20c8df1f62Andy Huang var actionLog = []; 2213a398b245930ce60ceb51fc605ab0f20c8df1f62Andy Huang var node; 22205c70c88e6b421bedce134799a0ea928dbf44cd5Andy Huang var done = false; 22305c70c88e6b421bedce134799a0ea928dbf44cd5Andy Huang var msgId; 22405c70c88e6b421bedce134799a0ea928dbf44cd5Andy Huang var transformText; 22505c70c88e6b421bedce134799a0ea928dbf44cd5Andy Huang var existingText; 22605c70c88e6b421bedce134799a0ea928dbf44cd5Andy Huang var textElement; 2273a398b245930ce60ceb51fc605ab0f20c8df1f62Andy Huang var start; 2280ecc58252046c81b575e23db909b1687beb871b4Andy Huang var beforeWidth; 2290ecc58252046c81b575e23db909b1687beb871b4Andy Huang var tmpActionLog = []; 2305ea5a8330532a75c83cbb30993a14ee9b821fa2aAndy Huang if (elWidth <= docWidth) { 2315ea5a8330532a75c83cbb30993a14ee9b821fa2aAndy Huang return; 2325ea5a8330532a75c83cbb30993a14ee9b821fa2aAndy Huang } 2333a398b245930ce60ceb51fc605ab0f20c8df1f62Andy Huang 2343a398b245930ce60ceb51fc605ab0f20c8df1f62Andy Huang start = Date.now(); 23505c70c88e6b421bedce134799a0ea928dbf44cd5Andy Huang 23605c70c88e6b421bedce134799a0ea928dbf44cd5Andy Huang if (el.parentElement.classList.contains("mail-message")) { 23705c70c88e6b421bedce134799a0ea928dbf44cd5Andy Huang msgId = el.parentElement.id; 23805c70c88e6b421bedce134799a0ea928dbf44cd5Andy Huang transformText = "[origW=" + elWidth + "/" + docWidth; 23905c70c88e6b421bedce134799a0ea928dbf44cd5Andy Huang } 24005c70c88e6b421bedce134799a0ea928dbf44cd5Andy Huang 24133578eaf140b8eeb5dad6e0c015b2e204054a86bAndy Huang // Try munging all divs or textareas with inline styles where the width 2423a398b245930ce60ceb51fc605ab0f20c8df1f62Andy Huang // is wider than docWidth, and change it to be a max-width. 2433a398b245930ce60ceb51fc605ab0f20c8df1f62Andy Huang touched = false; 24433578eaf140b8eeb5dad6e0c015b2e204054a86bAndy Huang nodes = ENABLE_MUNGE_TABLES ? el.querySelectorAll("div[style], textarea[style]") : []; 24533578eaf140b8eeb5dad6e0c015b2e204054a86bAndy Huang touched = transformBlockElements(nodes, docWidth, actionLog); 2465ea5a8330532a75c83cbb30993a14ee9b821fa2aAndy Huang if (touched) { 2475ea5a8330532a75c83cbb30993a14ee9b821fa2aAndy Huang newWidth = el.scrollWidth; 2483a398b245930ce60ceb51fc605ab0f20c8df1f62Andy Huang console.log("ran div-width munger on el=" + el + " oldW=" + elWidth + " newW=" + newWidth 2493a398b245930ce60ceb51fc605ab0f20c8df1f62Andy Huang + " docW=" + docWidth); 25005c70c88e6b421bedce134799a0ea928dbf44cd5Andy Huang if (msgId) { 25105c70c88e6b421bedce134799a0ea928dbf44cd5Andy Huang transformText += " DIV:newW=" + newWidth; 25205c70c88e6b421bedce134799a0ea928dbf44cd5Andy Huang } 2533a398b245930ce60ceb51fc605ab0f20c8df1f62Andy Huang if (newWidth <= docWidth) { 25405c70c88e6b421bedce134799a0ea928dbf44cd5Andy Huang done = true; 2553a398b245930ce60ceb51fc605ab0f20c8df1f62Andy Huang } 2563a398b245930ce60ceb51fc605ab0f20c8df1f62Andy Huang } 2573a398b245930ce60ceb51fc605ab0f20c8df1f62Andy Huang 25805c70c88e6b421bedce134799a0ea928dbf44cd5Andy Huang if (!done) { 25905c70c88e6b421bedce134799a0ea928dbf44cd5Andy Huang // OK, that wasn't enough. Find images with widths and override their widths. 26005c70c88e6b421bedce134799a0ea928dbf44cd5Andy Huang nodes = ENABLE_MUNGE_IMAGES ? el.querySelectorAll("img") : []; 26105c70c88e6b421bedce134799a0ea928dbf44cd5Andy Huang touched = transformImages(nodes, docWidth, actionLog); 26205c70c88e6b421bedce134799a0ea928dbf44cd5Andy Huang if (touched) { 26305c70c88e6b421bedce134799a0ea928dbf44cd5Andy Huang newWidth = el.scrollWidth; 26405c70c88e6b421bedce134799a0ea928dbf44cd5Andy Huang console.log("ran img munger on el=" + el + " oldW=" + elWidth + " newW=" + newWidth 26505c70c88e6b421bedce134799a0ea928dbf44cd5Andy Huang + " docW=" + docWidth); 26605c70c88e6b421bedce134799a0ea928dbf44cd5Andy Huang if (msgId) { 26705c70c88e6b421bedce134799a0ea928dbf44cd5Andy Huang transformText += " IMG:newW=" + newWidth; 26805c70c88e6b421bedce134799a0ea928dbf44cd5Andy Huang } 26905c70c88e6b421bedce134799a0ea928dbf44cd5Andy Huang if (newWidth <= docWidth) { 27005c70c88e6b421bedce134799a0ea928dbf44cd5Andy Huang done = true; 27105c70c88e6b421bedce134799a0ea928dbf44cd5Andy Huang } 2720180f27c0998623b702274048b49cd4bec536cf1Andy Huang } 2730180f27c0998623b702274048b49cd4bec536cf1Andy Huang } 2740180f27c0998623b702274048b49cd4bec536cf1Andy Huang 27505c70c88e6b421bedce134799a0ea928dbf44cd5Andy Huang if (!done) { 27605c70c88e6b421bedce134799a0ea928dbf44cd5Andy Huang // OK, that wasn't enough. Find tables with widths and override their widths. 277543e709c976ce954a072020ba6f75d12f41b1fbaAndy Huang // Also ensure that any use of 'table-layout: fixed' is negated, since using 278543e709c976ce954a072020ba6f75d12f41b1fbaAndy Huang // that with 'width: auto' causes erratic table width. 27905c70c88e6b421bedce134799a0ea928dbf44cd5Andy Huang nodes = ENABLE_MUNGE_TABLES ? el.querySelectorAll("table") : []; 28005c70c88e6b421bedce134799a0ea928dbf44cd5Andy Huang touched = addClassToElements(nodes, shouldMungeTable, "munged", 28105c70c88e6b421bedce134799a0ea928dbf44cd5Andy Huang actionLog); 28205c70c88e6b421bedce134799a0ea928dbf44cd5Andy Huang if (touched) { 28305c70c88e6b421bedce134799a0ea928dbf44cd5Andy Huang newWidth = el.scrollWidth; 28405c70c88e6b421bedce134799a0ea928dbf44cd5Andy Huang console.log("ran table munger on el=" + el + " oldW=" + elWidth + " newW=" + newWidth 28505c70c88e6b421bedce134799a0ea928dbf44cd5Andy Huang + " docW=" + docWidth); 28605c70c88e6b421bedce134799a0ea928dbf44cd5Andy Huang if (msgId) { 28705c70c88e6b421bedce134799a0ea928dbf44cd5Andy Huang transformText += " TABLE:newW=" + newWidth; 28805c70c88e6b421bedce134799a0ea928dbf44cd5Andy Huang } 28905c70c88e6b421bedce134799a0ea928dbf44cd5Andy Huang if (newWidth <= docWidth) { 29005c70c88e6b421bedce134799a0ea928dbf44cd5Andy Huang done = true; 29105c70c88e6b421bedce134799a0ea928dbf44cd5Andy Huang } 2925ea5a8330532a75c83cbb30993a14ee9b821fa2aAndy Huang } 293f70fc4052b72a850bbb9be585d0f5a4877ee9448Andy Huang } 2945ea5a8330532a75c83cbb30993a14ee9b821fa2aAndy Huang 29505c70c88e6b421bedce134799a0ea928dbf44cd5Andy Huang if (!done) { 29605c70c88e6b421bedce134799a0ea928dbf44cd5Andy Huang // OK, that wasn't enough. Try munging all <td> to override any width and nowrap set. 2970ecc58252046c81b575e23db909b1687beb871b4Andy Huang beforeWidth = newWidth; 29805c70c88e6b421bedce134799a0ea928dbf44cd5Andy Huang nodes = ENABLE_MUNGE_TABLES ? el.querySelectorAll("td") : []; 29905c70c88e6b421bedce134799a0ea928dbf44cd5Andy Huang touched = addClassToElements(nodes, null /* mungeAll */, "munged", 3000ecc58252046c81b575e23db909b1687beb871b4Andy Huang tmpActionLog); 30105c70c88e6b421bedce134799a0ea928dbf44cd5Andy Huang if (touched) { 30205c70c88e6b421bedce134799a0ea928dbf44cd5Andy Huang newWidth = el.scrollWidth; 30305c70c88e6b421bedce134799a0ea928dbf44cd5Andy Huang console.log("ran td munger on el=" + el + " oldW=" + elWidth + " newW=" + newWidth 30405c70c88e6b421bedce134799a0ea928dbf44cd5Andy Huang + " docW=" + docWidth); 30505c70c88e6b421bedce134799a0ea928dbf44cd5Andy Huang if (msgId) { 30605c70c88e6b421bedce134799a0ea928dbf44cd5Andy Huang transformText += " TD:newW=" + newWidth; 30705c70c88e6b421bedce134799a0ea928dbf44cd5Andy Huang } 30805c70c88e6b421bedce134799a0ea928dbf44cd5Andy Huang if (newWidth <= docWidth) { 30905c70c88e6b421bedce134799a0ea928dbf44cd5Andy Huang done = true; 3100ecc58252046c81b575e23db909b1687beb871b4Andy Huang } else if (newWidth == beforeWidth) { 3110ecc58252046c81b575e23db909b1687beb871b4Andy Huang // this transform did not improve things, and it is somewhat risky. 3120ecc58252046c81b575e23db909b1687beb871b4Andy Huang // back it out, since it's the last transform and we gained nothing. 3130ecc58252046c81b575e23db909b1687beb871b4Andy Huang undoActions(tmpActionLog); 3140ecc58252046c81b575e23db909b1687beb871b4Andy Huang } else { 3150ecc58252046c81b575e23db909b1687beb871b4Andy Huang // the transform WAS effective (although not 100%) 3160ecc58252046c81b575e23db909b1687beb871b4Andy Huang // copy the temporary action log entries over as normal 3170ecc58252046c81b575e23db909b1687beb871b4Andy Huang for (i = 0, len = tmpActionLog.length; i < len; i++) { 3180ecc58252046c81b575e23db909b1687beb871b4Andy Huang actionLog.push(tmpActionLog[i]); 3190ecc58252046c81b575e23db909b1687beb871b4Andy Huang } 32005c70c88e6b421bedce134799a0ea928dbf44cd5Andy Huang } 3215ea5a8330532a75c83cbb30993a14ee9b821fa2aAndy Huang } 3225ea5a8330532a75c83cbb30993a14ee9b821fa2aAndy Huang } 3233a398b245930ce60ceb51fc605ab0f20c8df1f62Andy Huang 3243a398b245930ce60ceb51fc605ab0f20c8df1f62Andy Huang // If the transformations shrank the width significantly enough, leave them in place. 3253a398b245930ce60ceb51fc605ab0f20c8df1f62Andy Huang // We figure that in those cases, the benefits outweight the risk of rendering artifacts. 32605c70c88e6b421bedce134799a0ea928dbf44cd5Andy Huang if (!done && (elWidth - newWidth) / (elWidth - docWidth) > 32705c70c88e6b421bedce134799a0ea928dbf44cd5Andy Huang TRANSFORM_MINIMUM_EFFECTIVE_RATIO) { 32805c70c88e6b421bedce134799a0ea928dbf44cd5Andy Huang console.log("transform(s) deemed effective enough"); 32905c70c88e6b421bedce134799a0ea928dbf44cd5Andy Huang done = true; 33005c70c88e6b421bedce134799a0ea928dbf44cd5Andy Huang } 33105c70c88e6b421bedce134799a0ea928dbf44cd5Andy Huang 33205c70c88e6b421bedce134799a0ea928dbf44cd5Andy Huang if (done) { 33305c70c88e6b421bedce134799a0ea928dbf44cd5Andy Huang if (msgId) { 33405c70c88e6b421bedce134799a0ea928dbf44cd5Andy Huang transformText += "]"; 33505c70c88e6b421bedce134799a0ea928dbf44cd5Andy Huang existingText = gTransformText[msgId]; 33605c70c88e6b421bedce134799a0ea928dbf44cd5Andy Huang if (!existingText) { 33705c70c88e6b421bedce134799a0ea928dbf44cd5Andy Huang transformText = "Message transforms: " + transformText; 33805c70c88e6b421bedce134799a0ea928dbf44cd5Andy Huang } else { 33905c70c88e6b421bedce134799a0ea928dbf44cd5Andy Huang transformText = existingText + " " + transformText; 34005c70c88e6b421bedce134799a0ea928dbf44cd5Andy Huang } 34105c70c88e6b421bedce134799a0ea928dbf44cd5Andy Huang gTransformText[msgId] = transformText; 34205c70c88e6b421bedce134799a0ea928dbf44cd5Andy Huang window.mail.onMessageTransform(msgId, transformText); 34304e53a2e6e71615ddcee39eeb0014a4cd4baf956Andy Huang if (DEBUG_DISPLAY_TRANSFORMS) { 34404e53a2e6e71615ddcee39eeb0014a4cd4baf956Andy Huang textElement = el.firstChild; 34504e53a2e6e71615ddcee39eeb0014a4cd4baf956Andy Huang if (!textElement.classList || !textElement.classList.contains("transform-text")) { 34604e53a2e6e71615ddcee39eeb0014a4cd4baf956Andy Huang textElement = document.createElement("div"); 34704e53a2e6e71615ddcee39eeb0014a4cd4baf956Andy Huang textElement.classList.add("transform-text"); 34804e53a2e6e71615ddcee39eeb0014a4cd4baf956Andy Huang textElement.style.fontSize = "10px"; 34904e53a2e6e71615ddcee39eeb0014a4cd4baf956Andy Huang textElement.style.color = "#ccc"; 35004e53a2e6e71615ddcee39eeb0014a4cd4baf956Andy Huang el.insertBefore(textElement, el.firstChild); 35104e53a2e6e71615ddcee39eeb0014a4cd4baf956Andy Huang } 35204e53a2e6e71615ddcee39eeb0014a4cd4baf956Andy Huang textElement.innerHTML = transformText + "<br>"; 35305c70c88e6b421bedce134799a0ea928dbf44cd5Andy Huang } 35405c70c88e6b421bedce134799a0ea928dbf44cd5Andy Huang } 35505c70c88e6b421bedce134799a0ea928dbf44cd5Andy Huang console.log("munger(s) succeeded, elapsed time=" + (Date.now() - start)); 3563a398b245930ce60ceb51fc605ab0f20c8df1f62Andy Huang return; 3573a398b245930ce60ceb51fc605ab0f20c8df1f62Andy Huang } 3583a398b245930ce60ceb51fc605ab0f20c8df1f62Andy Huang 3593a398b245930ce60ceb51fc605ab0f20c8df1f62Andy Huang // reverse all changes if the width is STILL not narrow enough 3603a398b245930ce60ceb51fc605ab0f20c8df1f62Andy Huang // (except the width->maxWidth change, which is not particularly destructive) 3610ecc58252046c81b575e23db909b1687beb871b4Andy Huang undoActions(actionLog); 3623a398b245930ce60ceb51fc605ab0f20c8df1f62Andy Huang if (actionLog.length > 0) { 3633a398b245930ce60ceb51fc605ab0f20c8df1f62Andy Huang console.log("all mungers failed, changes reversed. elapsed time=" + (Date.now() - start)); 3643a398b245930ce60ceb51fc605ab0f20c8df1f62Andy Huang } 3653a398b245930ce60ceb51fc605ab0f20c8df1f62Andy Huang} 3663a398b245930ce60ceb51fc605ab0f20c8df1f62Andy Huang 3670ecc58252046c81b575e23db909b1687beb871b4Andy Huangfunction undoActions(actionLog) { 3680ecc58252046c81b575e23db909b1687beb871b4Andy Huang for (i = 0, len = actionLog.length; i < len; i++) { 3690ecc58252046c81b575e23db909b1687beb871b4Andy Huang actionLog[i][0].apply(actionLog[i][1], actionLog[i][2]); 3700ecc58252046c81b575e23db909b1687beb871b4Andy Huang } 3710ecc58252046c81b575e23db909b1687beb871b4Andy Huang} 3720ecc58252046c81b575e23db909b1687beb871b4Andy Huang 3733a398b245930ce60ceb51fc605ab0f20c8df1f62Andy Huangfunction addClassToElements(nodes, conditionFn, classToAdd, actionLog) { 3743a398b245930ce60ceb51fc605ab0f20c8df1f62Andy Huang var i, len; 3753a398b245930ce60ceb51fc605ab0f20c8df1f62Andy Huang var node; 3763a398b245930ce60ceb51fc605ab0f20c8df1f62Andy Huang var added = false; 3773a398b245930ce60ceb51fc605ab0f20c8df1f62Andy Huang for (i = 0, len = nodes.length; i < len; i++) { 3783a398b245930ce60ceb51fc605ab0f20c8df1f62Andy Huang node = nodes[i]; 3793a398b245930ce60ceb51fc605ab0f20c8df1f62Andy Huang if (!conditionFn || conditionFn(node)) { 3804821bbb4aeaf4393e45575e0e43c7086521039adAndy Huang if (node.classList.contains(classToAdd)) { 3814821bbb4aeaf4393e45575e0e43c7086521039adAndy Huang continue; 3824821bbb4aeaf4393e45575e0e43c7086521039adAndy Huang } 3833a398b245930ce60ceb51fc605ab0f20c8df1f62Andy Huang node.classList.add(classToAdd); 3843a398b245930ce60ceb51fc605ab0f20c8df1f62Andy Huang added = true; 3850180f27c0998623b702274048b49cd4bec536cf1Andy Huang actionLog.push([node.classList.remove, node.classList, [classToAdd]]); 3863a398b245930ce60ceb51fc605ab0f20c8df1f62Andy Huang } 3873a398b245930ce60ceb51fc605ab0f20c8df1f62Andy Huang } 3883a398b245930ce60ceb51fc605ab0f20c8df1f62Andy Huang return added; 3893a398b245930ce60ceb51fc605ab0f20c8df1f62Andy Huang} 3903a398b245930ce60ceb51fc605ab0f20c8df1f62Andy Huang 39133578eaf140b8eeb5dad6e0c015b2e204054a86bAndy Huangfunction transformBlockElements(nodes, docWidth, actionLog) { 39233578eaf140b8eeb5dad6e0c015b2e204054a86bAndy Huang var i, len; 39333578eaf140b8eeb5dad6e0c015b2e204054a86bAndy Huang var node; 39433578eaf140b8eeb5dad6e0c015b2e204054a86bAndy Huang var wStr; 39533578eaf140b8eeb5dad6e0c015b2e204054a86bAndy Huang var index; 39633578eaf140b8eeb5dad6e0c015b2e204054a86bAndy Huang var touched = false; 39733578eaf140b8eeb5dad6e0c015b2e204054a86bAndy Huang 39833578eaf140b8eeb5dad6e0c015b2e204054a86bAndy Huang for (i = 0, len = nodes.length; i < len; i++) { 39933578eaf140b8eeb5dad6e0c015b2e204054a86bAndy Huang node = nodes[i]; 40033578eaf140b8eeb5dad6e0c015b2e204054a86bAndy Huang wStr = node.style.width || node.style.minWidth; 40133578eaf140b8eeb5dad6e0c015b2e204054a86bAndy Huang index = wStr ? wStr.indexOf("px") : -1; 40233578eaf140b8eeb5dad6e0c015b2e204054a86bAndy Huang if (index >= 0 && wStr.slice(0, index) > docWidth) { 40333578eaf140b8eeb5dad6e0c015b2e204054a86bAndy Huang saveStyleProperty(node, "width", actionLog); 40433578eaf140b8eeb5dad6e0c015b2e204054a86bAndy Huang saveStyleProperty(node, "minWidth", actionLog); 40533578eaf140b8eeb5dad6e0c015b2e204054a86bAndy Huang saveStyleProperty(node, "maxWidth", actionLog); 40633578eaf140b8eeb5dad6e0c015b2e204054a86bAndy Huang node.style.width = "100%"; 40733578eaf140b8eeb5dad6e0c015b2e204054a86bAndy Huang node.style.minWidth = ""; 40833578eaf140b8eeb5dad6e0c015b2e204054a86bAndy Huang node.style.maxWidth = wStr; 40933578eaf140b8eeb5dad6e0c015b2e204054a86bAndy Huang touched = true; 41033578eaf140b8eeb5dad6e0c015b2e204054a86bAndy Huang } 41133578eaf140b8eeb5dad6e0c015b2e204054a86bAndy Huang } 41233578eaf140b8eeb5dad6e0c015b2e204054a86bAndy Huang return touched; 41333578eaf140b8eeb5dad6e0c015b2e204054a86bAndy Huang} 41433578eaf140b8eeb5dad6e0c015b2e204054a86bAndy Huang 4150180f27c0998623b702274048b49cd4bec536cf1Andy Huangfunction transformImages(nodes, docWidth, actionLog) { 4160180f27c0998623b702274048b49cd4bec536cf1Andy Huang var i, len; 4170180f27c0998623b702274048b49cd4bec536cf1Andy Huang var node; 4180180f27c0998623b702274048b49cd4bec536cf1Andy Huang var w, h; 4190180f27c0998623b702274048b49cd4bec536cf1Andy Huang var touched = false; 4200180f27c0998623b702274048b49cd4bec536cf1Andy Huang 4210180f27c0998623b702274048b49cd4bec536cf1Andy Huang for (i = 0, len = nodes.length; i < len; i++) { 4220180f27c0998623b702274048b49cd4bec536cf1Andy Huang node = nodes[i]; 4230180f27c0998623b702274048b49cd4bec536cf1Andy Huang w = node.offsetWidth; 4240180f27c0998623b702274048b49cd4bec536cf1Andy Huang h = node.offsetHeight; 4250180f27c0998623b702274048b49cd4bec536cf1Andy Huang // shrink w/h proportionally if the img is wider than available width 4260180f27c0998623b702274048b49cd4bec536cf1Andy Huang if (w > docWidth) { 42733578eaf140b8eeb5dad6e0c015b2e204054a86bAndy Huang saveStyleProperty(node, "maxWidth", actionLog); 42833578eaf140b8eeb5dad6e0c015b2e204054a86bAndy Huang saveStyleProperty(node, "width", actionLog); 42933578eaf140b8eeb5dad6e0c015b2e204054a86bAndy Huang saveStyleProperty(node, "height", actionLog); 4300180f27c0998623b702274048b49cd4bec536cf1Andy Huang node.style.maxWidth = docWidth + "px"; 4310180f27c0998623b702274048b49cd4bec536cf1Andy Huang node.style.width = "100%"; 4320180f27c0998623b702274048b49cd4bec536cf1Andy Huang node.style.height = "auto"; 4330180f27c0998623b702274048b49cd4bec536cf1Andy Huang touched = true; 4340180f27c0998623b702274048b49cd4bec536cf1Andy Huang } 4350180f27c0998623b702274048b49cd4bec536cf1Andy Huang } 4360180f27c0998623b702274048b49cd4bec536cf1Andy Huang return touched; 4370180f27c0998623b702274048b49cd4bec536cf1Andy Huang} 4380180f27c0998623b702274048b49cd4bec536cf1Andy Huang 43933578eaf140b8eeb5dad6e0c015b2e204054a86bAndy Huangfunction saveStyleProperty(node, property, actionLog) { 44033578eaf140b8eeb5dad6e0c015b2e204054a86bAndy Huang var savedName = "data-" + property; 44133578eaf140b8eeb5dad6e0c015b2e204054a86bAndy Huang node.setAttribute(savedName, node.style[property]); 44233578eaf140b8eeb5dad6e0c015b2e204054a86bAndy Huang actionLog.push([undoSetProperty, node, [property, savedName]]); 44333578eaf140b8eeb5dad6e0c015b2e204054a86bAndy Huang} 44433578eaf140b8eeb5dad6e0c015b2e204054a86bAndy Huang 4450180f27c0998623b702274048b49cd4bec536cf1Andy Huangfunction undoSetProperty(property, savedProperty) { 4460180f27c0998623b702274048b49cd4bec536cf1Andy Huang this.style[property] = savedProperty ? this.getAttribute(savedProperty) : ""; 4470180f27c0998623b702274048b49cd4bec536cf1Andy Huang} 4480180f27c0998623b702274048b49cd4bec536cf1Andy Huang 4493a398b245930ce60ceb51fc605ab0f20c8df1f62Andy Huangfunction shouldMungeTable(table) { 4503a398b245930ce60ceb51fc605ab0f20c8df1f62Andy Huang return table.hasAttribute("width") || table.style.width; 451f70fc4052b72a850bbb9be585d0f5a4877ee9448Andy Huang} 452f70fc4052b72a850bbb9be585d0f5a4877ee9448Andy Huang 453f500db85dd13394dd6bdcfa38824b2ca6ada77e8Andy Huangfunction hideAllUnsafeImages() { 454f500db85dd13394dd6bdcfa38824b2ca6ada77e8Andy Huang hideUnsafeImages(document.getElementsByClassName("mail-message-content")); 455f500db85dd13394dd6bdcfa38824b2ca6ada77e8Andy Huang} 456f500db85dd13394dd6bdcfa38824b2ca6ada77e8Andy Huang 457f500db85dd13394dd6bdcfa38824b2ca6ada77e8Andy Huangfunction hideUnsafeImages(msgContentDivs) { 458f500db85dd13394dd6bdcfa38824b2ca6ada77e8Andy Huang var i, msgContentCount; 4593233bff8ae08a56543c9f5abf1bc6ab38f0574ceAndy Huang var j, imgCount; 460f500db85dd13394dd6bdcfa38824b2ca6ada77e8Andy Huang var msgContentDiv, image; 4613233bff8ae08a56543c9f5abf1bc6ab38f0574ceAndy Huang var images; 4623233bff8ae08a56543c9f5abf1bc6ab38f0574ceAndy Huang var showImages; 4638ec43e877a9c1925514f066655984e21fbd255e8Andrew Sapperstein var k = 0; 4648ec43e877a9c1925514f066655984e21fbd255e8Andrew Sapperstein var urls = new Array(); 4658ec43e877a9c1925514f066655984e21fbd255e8Andrew Sapperstein var messageIds = new Array(); 466f500db85dd13394dd6bdcfa38824b2ca6ada77e8Andy Huang for (i = 0, msgContentCount = msgContentDivs.length; i < msgContentCount; i++) { 467f500db85dd13394dd6bdcfa38824b2ca6ada77e8Andy Huang msgContentDiv = msgContentDivs[i]; 468f500db85dd13394dd6bdcfa38824b2ca6ada77e8Andy Huang showImages = msgContentDiv.classList.contains("mail-show-images"); 4693233bff8ae08a56543c9f5abf1bc6ab38f0574ceAndy Huang 470f500db85dd13394dd6bdcfa38824b2ca6ada77e8Andy Huang images = msgContentDiv.getElementsByTagName("img"); 4713233bff8ae08a56543c9f5abf1bc6ab38f0574ceAndy Huang for (j = 0, imgCount = images.length; j < imgCount; j++) { 4723233bff8ae08a56543c9f5abf1bc6ab38f0574ceAndy Huang image = images[j]; 4738ec43e877a9c1925514f066655984e21fbd255e8Andrew Sapperstein var src = rewriteRelativeImageSrc(image); 4748ec43e877a9c1925514f066655984e21fbd255e8Andrew Sapperstein if (src) { 4758ec43e877a9c1925514f066655984e21fbd255e8Andrew Sapperstein urls[k] = src; 4768ec43e877a9c1925514f066655984e21fbd255e8Andrew Sapperstein messageIds[k] = msgContentDiv.parentNode.id; 4778ec43e877a9c1925514f066655984e21fbd255e8Andrew Sapperstein k++; 4788ec43e877a9c1925514f066655984e21fbd255e8Andrew Sapperstein } 4793233bff8ae08a56543c9f5abf1bc6ab38f0574ceAndy Huang attachImageLoadListener(image); 4803233bff8ae08a56543c9f5abf1bc6ab38f0574ceAndy Huang // TODO: handle inline image attachments for all supported protocols 4813233bff8ae08a56543c9f5abf1bc6ab38f0574ceAndy Huang if (!showImages) { 4823233bff8ae08a56543c9f5abf1bc6ab38f0574ceAndy Huang blockImage(image); 4833233bff8ae08a56543c9f5abf1bc6ab38f0574ceAndy Huang } 4843233bff8ae08a56543c9f5abf1bc6ab38f0574ceAndy Huang } 4853233bff8ae08a56543c9f5abf1bc6ab38f0574ceAndy Huang } 4868ec43e877a9c1925514f066655984e21fbd255e8Andrew Sapperstein 4878ec43e877a9c1925514f066655984e21fbd255e8Andrew Sapperstein window.mail.onInlineAttachmentsParsed(urls, messageIds); 4883233bff8ae08a56543c9f5abf1bc6ab38f0574ceAndy Huang} 4893233bff8ae08a56543c9f5abf1bc6ab38f0574ceAndy Huang 49041dca185f7683b36bdafd9520c0648c897a95834Paul Westbrook/** 4918ec43e877a9c1925514f066655984e21fbd255e8Andrew Sapperstein * Changes relative paths to absolute path by pre-pending the account uri. 49241dca185f7683b36bdafd9520c0648c897a95834Paul Westbrook * @param {Element} imgElement Image for which the src path will be updated. 4938ec43e877a9c1925514f066655984e21fbd255e8Andrew Sapperstein * @returns the rewritten image src string or null if the imgElement was not rewritten. 49441dca185f7683b36bdafd9520c0648c897a95834Paul Westbrook */ 49541dca185f7683b36bdafd9520c0648c897a95834Paul Westbrookfunction rewriteRelativeImageSrc(imgElement) { 49641dca185f7683b36bdafd9520c0648c897a95834Paul Westbrook var src = imgElement.src; 497cebcc64fbd69618ff89f9fac0bfe9b9e7d7ce104Paul Westbrook 498cebcc64fbd69618ff89f9fac0bfe9b9e7d7ce104Paul Westbrook // DOC_BASE_URI will always be a unique x-thread:// uri for this particular conversation 499cebcc64fbd69618ff89f9fac0bfe9b9e7d7ce104Paul Westbrook if (src.indexOf(DOC_BASE_URI) == 0 && (DOC_BASE_URI != CONVERSATION_BASE_URI)) { 500cebcc64fbd69618ff89f9fac0bfe9b9e7d7ce104Paul Westbrook // The conversation specifies a different base uri than the document 501cebcc64fbd69618ff89f9fac0bfe9b9e7d7ce104Paul Westbrook src = CONVERSATION_BASE_URI + src.substring(DOC_BASE_URI.length); 502cebcc64fbd69618ff89f9fac0bfe9b9e7d7ce104Paul Westbrook imgElement.src = src; 5038ec43e877a9c1925514f066655984e21fbd255e8Andrew Sapperstein return src; 50441dca185f7683b36bdafd9520c0648c897a95834Paul Westbrook } 5058ec43e877a9c1925514f066655984e21fbd255e8Andrew Sapperstein 5068ec43e877a9c1925514f066655984e21fbd255e8Andrew Sapperstein return null; 50741dca185f7683b36bdafd9520c0648c897a95834Paul Westbrook}; 50841dca185f7683b36bdafd9520c0648c897a95834Paul Westbrook 50941dca185f7683b36bdafd9520c0648c897a95834Paul Westbrook 5103233bff8ae08a56543c9f5abf1bc6ab38f0574ceAndy Huangfunction attachImageLoadListener(imageElement) { 5113233bff8ae08a56543c9f5abf1bc6ab38f0574ceAndy Huang // Reset the src attribute to the empty string because onload will only fire if the src 5123233bff8ae08a56543c9f5abf1bc6ab38f0574ceAndy Huang // attribute is set after the onload listener. 5133233bff8ae08a56543c9f5abf1bc6ab38f0574ceAndy Huang var originalSrc = imageElement.src; 5143233bff8ae08a56543c9f5abf1bc6ab38f0574ceAndy Huang imageElement.src = ''; 515ffc725fe4b4fa1024feb22b1d1f76c24febadcdbAndy Huang imageElement.onload = imageOnLoad; 5163233bff8ae08a56543c9f5abf1bc6ab38f0574ceAndy Huang imageElement.src = originalSrc; 5173233bff8ae08a56543c9f5abf1bc6ab38f0574ceAndy Huang} 5183233bff8ae08a56543c9f5abf1bc6ab38f0574ceAndy Huang 51963b3c6725d60386f564ab53e3ba6495f0c158d9bAndy Huang/** 52063b3c6725d60386f564ab53e3ba6495f0c158d9bAndy Huang * Handle an onload event for an <img> tag. 52163b3c6725d60386f564ab53e3ba6495f0c158d9bAndy Huang * The image could be within an elided-text block, or at the top level of a message. 52263b3c6725d60386f564ab53e3ba6495f0c158d9bAndy Huang * When a new image loads, its new bounds may affect message or elided-text geometry, 52363b3c6725d60386f564ab53e3ba6495f0c158d9bAndy Huang * so we need to inspect and adjust the enclosing element's zoom level where necessary. 52463b3c6725d60386f564ab53e3ba6495f0c158d9bAndy Huang * 52563b3c6725d60386f564ab53e3ba6495f0c158d9bAndy Huang * Because this method can be called really often, and zoom-level adjustment is slow, 52663b3c6725d60386f564ab53e3ba6495f0c158d9bAndy Huang * we collect the elements to be processed and do them all later in a single deferred pass. 52763b3c6725d60386f564ab53e3ba6495f0c158d9bAndy Huang */ 528ffc725fe4b4fa1024feb22b1d1f76c24febadcdbAndy Huangfunction imageOnLoad(e) { 529ffc725fe4b4fa1024feb22b1d1f76c24febadcdbAndy Huang // normalize the quoted text parent if we're in a quoted text block, or else 530ffc725fe4b4fa1024feb22b1d1f76c24febadcdbAndy Huang // normalize the parent message content element 531ffc725fe4b4fa1024feb22b1d1f76c24febadcdbAndy Huang var parent = up(e.target, "elided-text") || up(e.target, "mail-message-content"); 53263b3c6725d60386f564ab53e3ba6495f0c158d9bAndy Huang if (!parent) { 53363b3c6725d60386f564ab53e3ba6495f0c158d9bAndy Huang // sanity check. shouldn't really happen. 53463b3c6725d60386f564ab53e3ba6495f0c158d9bAndy Huang return; 53563b3c6725d60386f564ab53e3ba6495f0c158d9bAndy Huang } 53663b3c6725d60386f564ab53e3ba6495f0c158d9bAndy Huang 53763b3c6725d60386f564ab53e3ba6495f0c158d9bAndy Huang // if there was no previous work, schedule a new deferred job 53863b3c6725d60386f564ab53e3ba6495f0c158d9bAndy Huang if (gImageLoadElements.length == 0) { 53963b3c6725d60386f564ab53e3ba6495f0c158d9bAndy Huang window.setTimeout(handleAllImageOnLoads, 0); 54063b3c6725d60386f564ab53e3ba6495f0c158d9bAndy Huang } 54163b3c6725d60386f564ab53e3ba6495f0c158d9bAndy Huang 54263b3c6725d60386f564ab53e3ba6495f0c158d9bAndy Huang // enqueue the work if it wasn't already enqueued 54363b3c6725d60386f564ab53e3ba6495f0c158d9bAndy Huang if (gImageLoadElements.indexOf(parent) == -1) { 54463b3c6725d60386f564ab53e3ba6495f0c158d9bAndy Huang gImageLoadElements.push(parent); 545ffc725fe4b4fa1024feb22b1d1f76c24febadcdbAndy Huang } 54663b3c6725d60386f564ab53e3ba6495f0c158d9bAndy Huang} 54763b3c6725d60386f564ab53e3ba6495f0c158d9bAndy Huang 54863b3c6725d60386f564ab53e3ba6495f0c158d9bAndy Huang// handle all deferred work from image onload events 54963b3c6725d60386f564ab53e3ba6495f0c158d9bAndy Huangfunction handleAllImageOnLoads() { 55063b3c6725d60386f564ab53e3ba6495f0c158d9bAndy Huang normalizeElementWidths(gImageLoadElements); 551ffc725fe4b4fa1024feb22b1d1f76c24febadcdbAndy Huang measurePositions(); 55263b3c6725d60386f564ab53e3ba6495f0c158d9bAndy Huang // clear the queue so the next onload event starts a new job 55363b3c6725d60386f564ab53e3ba6495f0c158d9bAndy Huang gImageLoadElements = []; 554ffc725fe4b4fa1024feb22b1d1f76c24febadcdbAndy Huang} 555ffc725fe4b4fa1024feb22b1d1f76c24febadcdbAndy Huang 5563233bff8ae08a56543c9f5abf1bc6ab38f0574ceAndy Huangfunction blockImage(imageElement) { 5573233bff8ae08a56543c9f5abf1bc6ab38f0574ceAndy Huang var src = imageElement.src; 55841dca185f7683b36bdafd9520c0648c897a95834Paul Westbrook if (src.indexOf("http://") == 0 || src.indexOf("https://") == 0 || 55941dca185f7683b36bdafd9520c0648c897a95834Paul Westbrook src.indexOf("content://") == 0) { 5603233bff8ae08a56543c9f5abf1bc6ab38f0574ceAndy Huang imageElement.setAttribute(BLOCKED_SRC_ATTR, src); 5613233bff8ae08a56543c9f5abf1bc6ab38f0574ceAndy Huang imageElement.src = "data:"; 5623233bff8ae08a56543c9f5abf1bc6ab38f0574ceAndy Huang } 5633233bff8ae08a56543c9f5abf1bc6ab38f0574ceAndy Huang} 5643233bff8ae08a56543c9f5abf1bc6ab38f0574ceAndy Huang 56523014705ca9872cd5004a1aa76e83ae260165ecaAndy Huangfunction setWideViewport() { 56623014705ca9872cd5004a1aa76e83ae260165ecaAndy Huang var metaViewport = document.getElementById('meta-viewport'); 56723014705ca9872cd5004a1aa76e83ae260165ecaAndy Huang metaViewport.setAttribute('content', 'width=' + WIDE_VIEWPORT_WIDTH); 56823014705ca9872cd5004a1aa76e83ae260165ecaAndy Huang} 56923014705ca9872cd5004a1aa76e83ae260165ecaAndy Huang 570e964eeec3a088b3f4c29b68d41f99e43a321ac52Andy Huangfunction restoreScrollPosition() { 571e964eeec3a088b3f4c29b68d41f99e43a321ac52Andy Huang var scrollYPercent = window.mail.getScrollYPercent(); 572e964eeec3a088b3f4c29b68d41f99e43a321ac52Andy Huang if (scrollYPercent && document.body.offsetHeight > window.innerHeight) { 573e964eeec3a088b3f4c29b68d41f99e43a321ac52Andy Huang document.body.scrollTop = Math.floor(scrollYPercent * document.body.offsetHeight); 574e964eeec3a088b3f4c29b68d41f99e43a321ac52Andy Huang } 575e964eeec3a088b3f4c29b68d41f99e43a321ac52Andy Huang} 576e964eeec3a088b3f4c29b68d41f99e43a321ac52Andy Huang 577bffc312614505b923f0054fde20d015bd21112cfAndy Huangfunction onContentReady(event) { 578bffc312614505b923f0054fde20d015bd21112cfAndy Huang window.mail.onContentReady(); 579bffc312614505b923f0054fde20d015bd21112cfAndy Huang} 580bffc312614505b923f0054fde20d015bd21112cfAndy Huang 581bffc312614505b923f0054fde20d015bd21112cfAndy Huangfunction setupContentReady() { 582bffc312614505b923f0054fde20d015bd21112cfAndy Huang var signalDiv; 583bffc312614505b923f0054fde20d015bd21112cfAndy Huang 584bffc312614505b923f0054fde20d015bd21112cfAndy Huang // PAGE READINESS SIGNAL FOR JELLYBEAN AND NEWER 585bffc312614505b923f0054fde20d015bd21112cfAndy Huang // Notify the app on 'webkitAnimationStart' of a simple dummy element with a simple no-op 586bffc312614505b923f0054fde20d015bd21112cfAndy Huang // animation that immediately runs on page load. The app uses this as a signal that the 587bffc312614505b923f0054fde20d015bd21112cfAndy Huang // content is loaded and ready to draw, since WebView delays firing this event until the 588bffc312614505b923f0054fde20d015bd21112cfAndy Huang // layers are composited and everything is ready to draw. 589bffc312614505b923f0054fde20d015bd21112cfAndy Huang // 590bffc312614505b923f0054fde20d015bd21112cfAndy Huang // This code is conditionally enabled on JB+ by setting the ENABLE_CONTENT_READY flag. 591bffc312614505b923f0054fde20d015bd21112cfAndy Huang if (ENABLE_CONTENT_READY) { 592bffc312614505b923f0054fde20d015bd21112cfAndy Huang signalDiv = document.getElementById("initial-load-signal"); 593bffc312614505b923f0054fde20d015bd21112cfAndy Huang signalDiv.addEventListener("webkitAnimationStart", onContentReady, false); 594bffc312614505b923f0054fde20d015bd21112cfAndy Huang } 595bffc312614505b923f0054fde20d015bd21112cfAndy Huang} 596bffc312614505b923f0054fde20d015bd21112cfAndy Huang 59723014705ca9872cd5004a1aa76e83ae260165ecaAndy Huang// BEGIN Java->JavaScript handlers 598f70fc4052b72a850bbb9be585d0f5a4877ee9448Andy Huangfunction measurePositions() { 599adbf3e8cadb66666f307352b72537fbac57b916fAndy Huang var overlayTops, overlayBottoms; 600f70fc4052b72a850bbb9be585d0f5a4877ee9448Andy Huang var i; 601f70fc4052b72a850bbb9be585d0f5a4877ee9448Andy Huang var len; 602f70fc4052b72a850bbb9be585d0f5a4877ee9448Andy Huang 603adbf3e8cadb66666f307352b72537fbac57b916fAndy Huang var expandedBody, headerSpacer; 604adbf3e8cadb66666f307352b72537fbac57b916fAndy Huang var prevBodyBottom = 0; 605adbf3e8cadb66666f307352b72537fbac57b916fAndy Huang var expandedBodyDivs = document.querySelectorAll(".expanded > .mail-message-content"); 606adbf3e8cadb66666f307352b72537fbac57b916fAndy Huang 607adbf3e8cadb66666f307352b72537fbac57b916fAndy Huang // N.B. offsetTop and offsetHeight of an element with the "zoom:" style applied cannot be 608adbf3e8cadb66666f307352b72537fbac57b916fAndy Huang // trusted. 609f70fc4052b72a850bbb9be585d0f5a4877ee9448Andy Huang 610adbf3e8cadb66666f307352b72537fbac57b916fAndy Huang overlayTops = new Array(expandedBodyDivs.length + 1); 611adbf3e8cadb66666f307352b72537fbac57b916fAndy Huang overlayBottoms = new Array(expandedBodyDivs.length + 1); 612adbf3e8cadb66666f307352b72537fbac57b916fAndy Huang for (i = 0, len = expandedBodyDivs.length; i < len; i++) { 613adbf3e8cadb66666f307352b72537fbac57b916fAndy Huang expandedBody = expandedBodyDivs[i]; 614adbf3e8cadb66666f307352b72537fbac57b916fAndy Huang headerSpacer = expandedBody.previousElementSibling; 615f70fc4052b72a850bbb9be585d0f5a4877ee9448Andy Huang // addJavascriptInterface handler only supports string arrays 616adbf3e8cadb66666f307352b72537fbac57b916fAndy Huang overlayTops[i] = "" + prevBodyBottom; 617adbf3e8cadb66666f307352b72537fbac57b916fAndy Huang overlayBottoms[i] = "" + (getTotalOffset(headerSpacer).top + headerSpacer.offsetHeight); 618adbf3e8cadb66666f307352b72537fbac57b916fAndy Huang prevBodyBottom = getTotalOffset(expandedBody.nextElementSibling).top; 619f70fc4052b72a850bbb9be585d0f5a4877ee9448Andy Huang } 620adbf3e8cadb66666f307352b72537fbac57b916fAndy Huang // add an extra one to mark the top/bottom of the last message footer spacer 621adbf3e8cadb66666f307352b72537fbac57b916fAndy Huang overlayTops[i] = "" + prevBodyBottom; 622e4e1c49e550171ae44e94910d6b030e866436607Andrew Sapperstein overlayBottoms[i] = "" + document.documentElement.scrollHeight; 623e4e1c49e550171ae44e94910d6b030e866436607Andrew Sapperstein 624adbf3e8cadb66666f307352b72537fbac57b916fAndy Huang window.mail.onWebContentGeometryChange(overlayTops, overlayBottoms); 625f70fc4052b72a850bbb9be585d0f5a4877ee9448Andy Huang} 626f70fc4052b72a850bbb9be585d0f5a4877ee9448Andy Huang 627eb9a4bdc53269ee05fe11870b9ebf03f18196585Scott Kennedyfunction unblockImages(messageDomIds) { 628eb9a4bdc53269ee05fe11870b9ebf03f18196585Scott Kennedy var i, j, images, imgCount, image, blockedSrc; 629eb9a4bdc53269ee05fe11870b9ebf03f18196585Scott Kennedy for (j = 0, len = messageDomIds.length; j < len; j++) { 630eb9a4bdc53269ee05fe11870b9ebf03f18196585Scott Kennedy var messageDomId = messageDomIds[j]; 631eb9a4bdc53269ee05fe11870b9ebf03f18196585Scott Kennedy var msg = document.getElementById(messageDomId); 632eb9a4bdc53269ee05fe11870b9ebf03f18196585Scott Kennedy if (!msg) { 633eb9a4bdc53269ee05fe11870b9ebf03f18196585Scott Kennedy console.log("can't unblock, no matching message for id: " + messageDomId); 634eb9a4bdc53269ee05fe11870b9ebf03f18196585Scott Kennedy continue; 635eb9a4bdc53269ee05fe11870b9ebf03f18196585Scott Kennedy } 636eb9a4bdc53269ee05fe11870b9ebf03f18196585Scott Kennedy images = msg.getElementsByTagName("img"); 637eb9a4bdc53269ee05fe11870b9ebf03f18196585Scott Kennedy for (i = 0, imgCount = images.length; i < imgCount; i++) { 638eb9a4bdc53269ee05fe11870b9ebf03f18196585Scott Kennedy image = images[i]; 639eb9a4bdc53269ee05fe11870b9ebf03f18196585Scott Kennedy blockedSrc = image.getAttribute(BLOCKED_SRC_ATTR); 640eb9a4bdc53269ee05fe11870b9ebf03f18196585Scott Kennedy if (blockedSrc) { 641eb9a4bdc53269ee05fe11870b9ebf03f18196585Scott Kennedy image.src = blockedSrc; 642eb9a4bdc53269ee05fe11870b9ebf03f18196585Scott Kennedy image.removeAttribute(BLOCKED_SRC_ATTR); 643eb9a4bdc53269ee05fe11870b9ebf03f18196585Scott Kennedy } 6443233bff8ae08a56543c9f5abf1bc6ab38f0574ceAndy Huang } 6453233bff8ae08a56543c9f5abf1bc6ab38f0574ceAndy Huang } 6463233bff8ae08a56543c9f5abf1bc6ab38f0574ceAndy Huang} 647c7543579c6a97c0ae3341578332f56d4d226f34cAndy Huang 648ab2d998506c83e82ddae25b6ba1419414e1e8122Mark Weifunction setConversationHeaderSpacerHeight(spacerHeight) { 649ab2d998506c83e82ddae25b6ba1419414e1e8122Mark Wei var spacer = document.getElementById("conversation-header"); 650ab2d998506c83e82ddae25b6ba1419414e1e8122Mark Wei if (!spacer) { 651ab2d998506c83e82ddae25b6ba1419414e1e8122Mark Wei console.log("can't set spacer for conversation header"); 652ab2d998506c83e82ddae25b6ba1419414e1e8122Mark Wei return; 653ab2d998506c83e82ddae25b6ba1419414e1e8122Mark Wei } 654ab2d998506c83e82ddae25b6ba1419414e1e8122Mark Wei spacer.style.height = spacerHeight + "px"; 655ab2d998506c83e82ddae25b6ba1419414e1e8122Mark Wei measurePositions(); 656ab2d998506c83e82ddae25b6ba1419414e1e8122Mark Wei} 657ab2d998506c83e82ddae25b6ba1419414e1e8122Mark Wei 658c7543579c6a97c0ae3341578332f56d4d226f34cAndy Huangfunction setMessageHeaderSpacerHeight(messageDomId, spacerHeight) { 659c7543579c6a97c0ae3341578332f56d4d226f34cAndy Huang var spacer = document.querySelector("#" + messageDomId + " > .mail-message-header"); 660c7543579c6a97c0ae3341578332f56d4d226f34cAndy Huang if (!spacer) { 661c7543579c6a97c0ae3341578332f56d4d226f34cAndy Huang console.log("can't set spacer for message with id: " + messageDomId); 662c7543579c6a97c0ae3341578332f56d4d226f34cAndy Huang return; 663c7543579c6a97c0ae3341578332f56d4d226f34cAndy Huang } 664c7543579c6a97c0ae3341578332f56d4d226f34cAndy Huang spacer.style.height = spacerHeight + "px"; 665c7543579c6a97c0ae3341578332f56d4d226f34cAndy Huang measurePositions(); 666c7543579c6a97c0ae3341578332f56d4d226f34cAndy Huang} 667c7543579c6a97c0ae3341578332f56d4d226f34cAndy Huang 668cee3c90574b48ccaa0f8b9f9341383c231ed41d2Andrew Sappersteinfunction setMessageBodyVisible(messageDomId, isVisible, spacerHeight, 669cee3c90574b48ccaa0f8b9f9341383c231ed41d2Andrew Sapperstein topBorderHeight, bottomBorderHeight) { 670c7543579c6a97c0ae3341578332f56d4d226f34cAndy Huang var i, len; 671c7543579c6a97c0ae3341578332f56d4d226f34cAndy Huang var visibility = isVisible ? "block" : "none"; 672c7543579c6a97c0ae3341578332f56d4d226f34cAndy Huang var messageDiv = document.querySelector("#" + messageDomId); 673c7543579c6a97c0ae3341578332f56d4d226f34cAndy Huang var collapsibleDivs = document.querySelectorAll("#" + messageDomId + " > .collapsible"); 674c7543579c6a97c0ae3341578332f56d4d226f34cAndy Huang if (!messageDiv || collapsibleDivs.length == 0) { 675c7543579c6a97c0ae3341578332f56d4d226f34cAndy Huang console.log("can't set body visibility for message with id: " + messageDomId); 676c7543579c6a97c0ae3341578332f56d4d226f34cAndy Huang return; 677c7543579c6a97c0ae3341578332f56d4d226f34cAndy Huang } 678cee3c90574b48ccaa0f8b9f9341383c231ed41d2Andrew Sapperstein 679cee3c90574b48ccaa0f8b9f9341383c231ed41d2Andrew Sapperstein // if the top border has changed, update the height of its spacer 680cee3c90574b48ccaa0f8b9f9341383c231ed41d2Andrew Sapperstein if (topBorderHeight > 0) { 681cee3c90574b48ccaa0f8b9f9341383c231ed41d2Andrew Sapperstein var border = messageDiv.previousElementSibling; 682cee3c90574b48ccaa0f8b9f9341383c231ed41d2Andrew Sapperstein if (!border) { 683cee3c90574b48ccaa0f8b9f9341383c231ed41d2Andrew Sapperstein console.log("can't set spacer for top border"); 684cee3c90574b48ccaa0f8b9f9341383c231ed41d2Andrew Sapperstein return; 685cee3c90574b48ccaa0f8b9f9341383c231ed41d2Andrew Sapperstein } 686cee3c90574b48ccaa0f8b9f9341383c231ed41d2Andrew Sapperstein border.style.height = topBorderHeight + "px"; 687cee3c90574b48ccaa0f8b9f9341383c231ed41d2Andrew Sapperstein } 688cee3c90574b48ccaa0f8b9f9341383c231ed41d2Andrew Sapperstein 689cee3c90574b48ccaa0f8b9f9341383c231ed41d2Andrew Sapperstein // if the bottom border has changed, update the height of its spacer 690cee3c90574b48ccaa0f8b9f9341383c231ed41d2Andrew Sapperstein if (bottomBorderHeight > 0) { 691cee3c90574b48ccaa0f8b9f9341383c231ed41d2Andrew Sapperstein var border = messageDiv.nextElementSibling; 692cee3c90574b48ccaa0f8b9f9341383c231ed41d2Andrew Sapperstein if (!border) { 693cee3c90574b48ccaa0f8b9f9341383c231ed41d2Andrew Sapperstein console.log("can't set spacer for bottom border"); 694cee3c90574b48ccaa0f8b9f9341383c231ed41d2Andrew Sapperstein return; 695cee3c90574b48ccaa0f8b9f9341383c231ed41d2Andrew Sapperstein } 696cee3c90574b48ccaa0f8b9f9341383c231ed41d2Andrew Sapperstein border.style.height = bottomBorderHeight + "px"; 697cee3c90574b48ccaa0f8b9f9341383c231ed41d2Andrew Sapperstein } 698cee3c90574b48ccaa0f8b9f9341383c231ed41d2Andrew Sapperstein 699c7543579c6a97c0ae3341578332f56d4d226f34cAndy Huang messageDiv.classList.toggle("expanded"); 700c7543579c6a97c0ae3341578332f56d4d226f34cAndy Huang for (i = 0, len = collapsibleDivs.length; i < len; i++) { 701c7543579c6a97c0ae3341578332f56d4d226f34cAndy Huang collapsibleDivs[i].style.display = visibility; 702c7543579c6a97c0ae3341578332f56d4d226f34cAndy Huang } 703ffc725fe4b4fa1024feb22b1d1f76c24febadcdbAndy Huang 704ffc725fe4b4fa1024feb22b1d1f76c24febadcdbAndy Huang // revealing new content should trigger width normalization, since the initial render 705ffc725fe4b4fa1024feb22b1d1f76c24febadcdbAndy Huang // skips collapsed and super-collapsed messages 706ffc725fe4b4fa1024feb22b1d1f76c24febadcdbAndy Huang if (isVisible) { 707ffc725fe4b4fa1024feb22b1d1f76c24febadcdbAndy Huang normalizeElementWidths(messageDiv.getElementsByClassName("mail-message-content")); 708ffc725fe4b4fa1024feb22b1d1f76c24febadcdbAndy Huang } 709ffc725fe4b4fa1024feb22b1d1f76c24febadcdbAndy Huang 710c7543579c6a97c0ae3341578332f56d4d226f34cAndy Huang setMessageHeaderSpacerHeight(messageDomId, spacerHeight); 711c7543579c6a97c0ae3341578332f56d4d226f34cAndy Huang} 71246dfba6160b55a582b344328067e3dafeb881dd9Andy Huang 71346dfba6160b55a582b344328067e3dafeb881dd9Andy Huangfunction replaceSuperCollapsedBlock(startIndex) { 714f500db85dd13394dd6bdcfa38824b2ca6ada77e8Andy Huang var parent, block, msg; 71546dfba6160b55a582b344328067e3dafeb881dd9Andy Huang 71646dfba6160b55a582b344328067e3dafeb881dd9Andy Huang block = document.querySelector(".mail-super-collapsed-block[index='" + startIndex + "']"); 71746dfba6160b55a582b344328067e3dafeb881dd9Andy Huang if (!block) { 71846dfba6160b55a582b344328067e3dafeb881dd9Andy Huang console.log("can't expand super collapsed block at index: " + startIndex); 71946dfba6160b55a582b344328067e3dafeb881dd9Andy Huang return; 72046dfba6160b55a582b344328067e3dafeb881dd9Andy Huang } 72146dfba6160b55a582b344328067e3dafeb881dd9Andy Huang parent = block.parentNode; 72246dfba6160b55a582b344328067e3dafeb881dd9Andy Huang block.innerHTML = window.mail.getTempMessageBodies(); 72346dfba6160b55a582b344328067e3dafeb881dd9Andy Huang 724f500db85dd13394dd6bdcfa38824b2ca6ada77e8Andy Huang // process the new block contents in one go before we pluck them out of the common ancestor 725f500db85dd13394dd6bdcfa38824b2ca6ada77e8Andy Huang processQuotedText(block, false /* showElided */); 726f500db85dd13394dd6bdcfa38824b2ca6ada77e8Andy Huang hideUnsafeImages(block.getElementsByClassName("mail-message-content")); 727f500db85dd13394dd6bdcfa38824b2ca6ada77e8Andy Huang 728f500db85dd13394dd6bdcfa38824b2ca6ada77e8Andy Huang msg = block.firstChild; 729f500db85dd13394dd6bdcfa38824b2ca6ada77e8Andy Huang while (msg) { 730f500db85dd13394dd6bdcfa38824b2ca6ada77e8Andy Huang parent.insertBefore(msg, block); 731f500db85dd13394dd6bdcfa38824b2ca6ada77e8Andy Huang msg = block.firstChild; 73246dfba6160b55a582b344328067e3dafeb881dd9Andy Huang } 73346dfba6160b55a582b344328067e3dafeb881dd9Andy Huang parent.removeChild(block); 73446dfba6160b55a582b344328067e3dafeb881dd9Andy Huang measurePositions(); 73546dfba6160b55a582b344328067e3dafeb881dd9Andy Huang} 7363bcf180f8104bc27319086a9a6ece5a3c2917c37mindyp 737986776bbd046c9569a4abb67501819bee61e7194Andy Huangfunction processNewMessageBody(msgContentDiv) { 738986776bbd046c9569a4abb67501819bee61e7194Andy Huang processQuotedText(msgContentDiv, true /* showElided */); 739986776bbd046c9569a4abb67501819bee61e7194Andy Huang hideUnsafeImages([msgContentDiv]); 740986776bbd046c9569a4abb67501819bee61e7194Andy Huang if (up(msgContentDiv, "mail-message").classList.contains("expanded")) { 741986776bbd046c9569a4abb67501819bee61e7194Andy Huang normalizeElementWidths([msgContentDiv]); 742986776bbd046c9569a4abb67501819bee61e7194Andy Huang } 743986776bbd046c9569a4abb67501819bee61e7194Andy Huang} 744986776bbd046c9569a4abb67501819bee61e7194Andy Huang 745014ea4c15d147794789b9c5bf4e243fa08781ad9Andy Huangfunction replaceMessageBodies(messageIds) { 746014ea4c15d147794789b9c5bf4e243fa08781ad9Andy Huang var i; 747014ea4c15d147794789b9c5bf4e243fa08781ad9Andy Huang var id; 748014ea4c15d147794789b9c5bf4e243fa08781ad9Andy Huang var msgContentDiv; 749014ea4c15d147794789b9c5bf4e243fa08781ad9Andy Huang 750014ea4c15d147794789b9c5bf4e243fa08781ad9Andy Huang for (i = 0, len = messageIds.length; i < len; i++) { 751014ea4c15d147794789b9c5bf4e243fa08781ad9Andy Huang id = messageIds[i]; 752014ea4c15d147794789b9c5bf4e243fa08781ad9Andy Huang msgContentDiv = document.querySelector("#" + id + " > .mail-message-content"); 753014ea4c15d147794789b9c5bf4e243fa08781ad9Andy Huang msgContentDiv.innerHTML = window.mail.getMessageBody(id); 754986776bbd046c9569a4abb67501819bee61e7194Andy Huang processNewMessageBody(msgContentDiv); 755014ea4c15d147794789b9c5bf4e243fa08781ad9Andy Huang } 75691d782abc8015bd651fb5d0252b4d1ef369ec57bAndy Huang measurePositions(); 757014ea4c15d147794789b9c5bf4e243fa08781ad9Andy Huang} 758014ea4c15d147794789b9c5bf4e243fa08781ad9Andy Huang 75906c0362f59437f3ea2b5832272fb66158bb4b8c0Andy Huang// handle the special case of adding a single new message at the end of a conversation 76006c0362f59437f3ea2b5832272fb66158bb4b8c0Andy Huangfunction appendMessageHtml() { 76106c0362f59437f3ea2b5832272fb66158bb4b8c0Andy Huang var msg = document.createElement("div"); 76206c0362f59437f3ea2b5832272fb66158bb4b8c0Andy Huang msg.innerHTML = window.mail.getTempMessageBodies(); 7631f082231c4a51eb3be37df6d2a0024634dfe4a9bAndrew Sapperstein var body = msg.children[0]; // toss the outer div, it was just to render innerHTML into 7641f082231c4a51eb3be37df6d2a0024634dfe4a9bAndrew Sapperstein var border = msg.children[1]; // get the border spacer as well 7651f082231c4a51eb3be37df6d2a0024634dfe4a9bAndrew Sapperstein document.body.appendChild(body); 7661f082231c4a51eb3be37df6d2a0024634dfe4a9bAndrew Sapperstein document.body.appendChild(border); 767986776bbd046c9569a4abb67501819bee61e7194Andy Huang processNewMessageBody(body.querySelector(".mail-message-content")); 76891d782abc8015bd651fb5d0252b4d1ef369ec57bAndy Huang measurePositions(); 76906c0362f59437f3ea2b5832272fb66158bb4b8c0Andy Huang} 77006c0362f59437f3ea2b5832272fb66158bb4b8c0Andy Huang 7713233bff8ae08a56543c9f5abf1bc6ab38f0574ceAndy Huang// END Java->JavaScript handlers 7723233bff8ae08a56543c9f5abf1bc6ab38f0574ceAndy Huang 7734cfe22a8b0fe9fb98df9c82303bacc5c1a79f19bAndy Huang// Do this first to ensure that the readiness signal comes through, 7744cfe22a8b0fe9fb98df9c82303bacc5c1a79f19bAndy Huang// even if a stray exception later occurs. 7754cfe22a8b0fe9fb98df9c82303bacc5c1a79f19bAndy HuangsetupContentReady(); 7764cfe22a8b0fe9fb98df9c82303bacc5c1a79f19bAndy Huang 777014ea4c15d147794789b9c5bf4e243fa08781ad9Andy HuangcollapseAllQuotedText(); 778f500db85dd13394dd6bdcfa38824b2ca6ada77e8Andy HuanghideAllUnsafeImages(); 779ffc725fe4b4fa1024feb22b1d1f76c24febadcdbAndy HuangnormalizeAllMessageWidths(); 78023014705ca9872cd5004a1aa76e83ae260165ecaAndy Huang//setWideViewport(); 781e964eeec3a088b3f4c29b68d41f99e43a321ac52Andy HuangrestoreScrollPosition(); 782f70fc4052b72a850bbb9be585d0f5a4877ee9448Andy HuangmeasurePositions(); 783f70fc4052b72a850bbb9be585d0f5a4877ee9448Andy Huang 784