script.js revision 46dfba6160b55a582b344328067e3dafeb881dd9
1/* 2 * Copyright (C) 2012 Google Inc. 3 * Licensed to The Android Open Source Project. 4 * 5 * Licensed under the Apache License, Version 2.0 (the "License"); 6 * you may not use this file except in compliance with the License. 7 * You may obtain a copy of the License at 8 * 9 * http://www.apache.org/licenses/LICENSE-2.0 10 * 11 * Unless required by applicable law or agreed to in writing, software 12 * distributed under the License is distributed on an "AS IS" BASIS, 13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 * See the License for the specific language governing permissions and 15 * limitations under the License. 16 */ 17 18var BLOCKED_SRC_ATTR = "blocked-src"; 19 20/** 21 * Returns the page offset of an element. 22 * 23 * @param {Element} element The element to return the page offset for. 24 * @return {left: number, top: number} A tuple including a left and top value representing 25 * the page offset of the element. 26 */ 27function getTotalOffset(el) { 28 var result = { 29 left: 0, 30 top: 0 31 }; 32 var parent = el; 33 34 while (parent) { 35 result.left += parent.offsetLeft; 36 result.top += parent.offsetTop; 37 parent = parent.offsetParent; 38 } 39 40 return result; 41} 42 43function toggleQuotedText(e) { 44 var toggleElement = e.target; 45 var elidedTextElement = toggleElement.nextSibling; 46 var isHidden = getComputedStyle(elidedTextElement).display == 'none'; 47 toggleElement.innerHTML = isHidden ? MSG_HIDE_ELIDED : MSG_SHOW_ELIDED; 48 elidedTextElement.style.display = isHidden ? 'block' : 'none'; 49 measurePositions(); 50} 51 52function collapseQuotedText() { 53 var i; 54 var elements = document.getElementsByClassName("elided-text"); 55 var elidedElement, toggleElement; 56 for (i = 0; i < elements.length; i++) { 57 elidedElement = elements[i]; 58 toggleElement = document.createElement("div"); 59 toggleElement.display = "mail-elided-text"; 60 toggleElement.innerHTML = MSG_SHOW_ELIDED; 61 toggleElement.onclick = toggleQuotedText; 62 elidedElement.parentNode.insertBefore(toggleElement, elidedElement); 63 } 64} 65 66function shrinkWideMessages() { 67 var i; 68 var elements = document.getElementsByClassName("mail-message-content"); 69 var messageElement; 70 var documentWidth = document.documentElement.offsetWidth; 71 var scale; 72 for (i = 0; i < elements.length; i++) { 73 messageElement = elements[i]; 74 if (messageElement.scrollWidth > documentWidth) { 75 scale = documentWidth / messageElement.scrollWidth; 76 77 // TODO: 'zoom' is nice because it does a proper layout, but WebView seems to clamp the 78 // minimum 'zoom' level. 79 if (false) { 80 // TODO: this alternative works well in Chrome but doesn't work in WebView. 81 messageElement.style.webkitTransformOrigin = "left top"; 82 messageElement.style.webkitTransform = "scale(" + scale + ")"; 83 messageElement.style.height = (messageElement.offsetHeight * scale) + "px"; 84 messageElement.style.overflowX = "visible"; 85 } else { 86 messageElement.style.zoom = documentWidth / messageElement.scrollWidth; 87 } 88 } 89 } 90} 91 92function hideUnsafeImages() { 93 var i, bodyCount; 94 var j, imgCount; 95 var body, image; 96 var images; 97 var showImages; 98 var bodies = document.getElementsByClassName("mail-message-content"); 99 for (i = 0, bodyCount = bodies.length; i < bodyCount; i++) { 100 body = bodies[i]; 101 showImages = body.classList.contains("mail-show-images"); 102 103 images = body.getElementsByTagName("img"); 104 for (j = 0, imgCount = images.length; j < imgCount; j++) { 105 image = images[j]; 106 attachImageLoadListener(image); 107 // TODO: handle inline image attachments for all supported protocols 108 if (!showImages) { 109 blockImage(image); 110 } 111 } 112 } 113} 114 115function attachImageLoadListener(imageElement) { 116 // Reset the src attribute to the empty string because onload will only fire if the src 117 // attribute is set after the onload listener. 118 var originalSrc = imageElement.src; 119 imageElement.src = ''; 120 imageElement.onload = measurePositions; 121 imageElement.src = originalSrc; 122} 123 124function blockImage(imageElement) { 125 var src = imageElement.src; 126 if (src.indexOf("http://") == 0 || src.indexOf("https://") == 0) { 127 imageElement.setAttribute(BLOCKED_SRC_ATTR, src); 128 imageElement.src = "data:"; 129 } 130} 131 132function measurePositions() { 133 var overlayBottoms; 134 var h; 135 var i; 136 var len; 137 138 var expandedSpacerDivs = document.querySelectorAll(".expanded > .spacer"); 139 140 overlayBottoms = new Array(expandedSpacerDivs.length + 1); 141 for (i = 0, len = expandedSpacerDivs.length; i < len; i++) { 142 h = expandedSpacerDivs[i].offsetHeight; 143 // addJavascriptInterface handler only supports string arrays 144 overlayBottoms[i] = "" + (getTotalOffset(expandedSpacerDivs[i]).top + h); 145 } 146 // add an extra one to mark the bottom of the last message 147 overlayBottoms[i] = "" + document.body.offsetHeight; 148 149 window.mail.onWebContentGeometryChange(overlayBottoms); 150} 151 152// BEGIN Java->JavaScript handlers 153function unblockImages(messageDomId) { 154 var i, images, imgCount, image, blockedSrc; 155 var msg = document.getElementById(messageDomId); 156 if (!msg) { 157 console.log("can't unblock, no matching message for id: " + messageDomId); 158 return; 159 } 160 images = msg.getElementsByTagName("img"); 161 for (i = 0, imgCount = images.length; i < imgCount; i++) { 162 image = images[i]; 163 blockedSrc = image.getAttribute(BLOCKED_SRC_ATTR); 164 if (blockedSrc) { 165 image.src = blockedSrc; 166 image.removeAttribute(BLOCKED_SRC_ATTR); 167 } 168 } 169} 170 171function setMessageHeaderSpacerHeight(messageDomId, spacerHeight) { 172 var spacer = document.querySelector("#" + messageDomId + " > .mail-message-header"); 173 if (!spacer) { 174 console.log("can't set spacer for message with id: " + messageDomId); 175 return; 176 } 177 spacer.style.height = spacerHeight + "px"; 178 measurePositions(); 179} 180 181function setMessageBodyVisible(messageDomId, isVisible, spacerHeight) { 182 var i, len; 183 var visibility = isVisible ? "block" : "none"; 184 var messageDiv = document.querySelector("#" + messageDomId); 185 var collapsibleDivs = document.querySelectorAll("#" + messageDomId + " > .collapsible"); 186 if (!messageDiv || collapsibleDivs.length == 0) { 187 console.log("can't set body visibility for message with id: " + messageDomId); 188 return; 189 } 190 messageDiv.classList.toggle("expanded"); 191 for (i = 0, len = collapsibleDivs.length; i < len; i++) { 192 collapsibleDivs[i].style.display = visibility; 193 } 194 setMessageHeaderSpacerHeight(messageDomId, spacerHeight); 195} 196 197function replaceSuperCollapsedBlock(startIndex) { 198 var parent, block, header; 199 200 block = document.querySelector(".mail-super-collapsed-block[index='" + startIndex + "']"); 201 if (!block) { 202 console.log("can't expand super collapsed block at index: " + startIndex); 203 return; 204 } 205 parent = block.parentNode; 206 block.innerHTML = window.mail.getTempMessageBodies(); 207 208 header = block.firstChild; 209 while (header) { 210 parent.insertBefore(header, block); 211 header = block.firstChild; 212 } 213 parent.removeChild(block); 214 measurePositions(); 215} 216// END Java->JavaScript handlers 217 218collapseQuotedText(); 219hideUnsafeImages(); 220shrinkWideMessages(); 221measurePositions(); 222 223