OLD | NEW |
1 <!DOCTYPE html> | 1 <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" |
2 <html> | 2 "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> |
| 3 <html xmlns="http://www.w3.org/1999/xhtml"> |
3 <head> | 4 <head> |
4 <link rel="stylesheet" type="text/css" href="static/style.css" /> | 5 <meta http-equiv="Content-Type" content="text/html; charset=utf-8" /> |
5 <title>{% block title %}{% endblock %}Chromium Build Master</title> | 6 {% if reloadarg %} |
| 7 <meta http-equiv="refresh" content="{{ reloadarg }}" /> |
| 8 {% endif %} |
| 9 <title>{{ title }}</title> |
| 10 <link rel="stylesheet" href="default.css" type="text/css" /> |
| 11 |
| 12 <script type="text/javascript"> |
| 13 // <![CDATA[ |
| 14 // |
| 15 |
| 16 // |
| 17 // Functions used to display the build status bubble on box click. |
| 18 // |
| 19 |
| 20 // show the build status box. This is called when the user clicks on a block. |
| 21 function showBuildBox(url, event) { |
| 22 // Find the current curson position. |
| 23 var cursorPosTop = (window.event ? window.event.clientY : event.pageY) |
| 24 var cursorPosLeft = (window.event ? window.event.clientX : event.pageX) |
| 25 |
| 26 // Offset the position by 5, to make the window appears under the cursor. |
| 27 cursorPosTop = cursorPosTop + document.body.scrollTop -5 ; |
| 28 cursorPosLeft = cursorPosLeft + document.body.scrollLeft - 5; |
| 29 |
| 30 // Move the div (hidden) under the cursor. |
| 31 var divBox = document.getElementById('divBox'); |
| 32 divBox.style.top = parseInt(cursorPosTop) + 'px'; |
| 33 divBox.style.left = parseInt(cursorPosLeft) + 'px'; |
| 34 |
| 35 // Reload the hidden frame with the build page we want to show. |
| 36 // The onload even on this frame will update the div and make it visible. |
| 37 document.getElementById("frameBox").src = url |
| 38 |
| 39 // We don't want to reload the page. |
| 40 return false; |
| 41 } |
| 42 |
| 43 // OnLoad handler for the iframe containing the build to show. |
| 44 function updateDiv(event) { |
| 45 // Get the frame innerHTML. |
| 46 var iframeContent = document.getElementById("frameBox").contentWindow.docume
nt.body.innerHTML; |
| 47 |
| 48 // If there is any content, update the div, and make it visible. |
| 49 if (iframeContent) { |
| 50 var divBox = document.getElementById('divBox'); |
| 51 divBox.innerHTML = iframeContent ; |
| 52 divBox.style.display = "block"; |
| 53 } |
| 54 } |
| 55 |
| 56 // Util functions to know if an element is contained inside another element. |
| 57 // We use this to know when we mouse out our build status div. |
| 58 function containsDOM (container, containee) { |
| 59 var isParent = false; |
| 60 do { |
| 61 if ((isParent = container == containee)) |
| 62 break; |
| 63 containee = containee.parentNode; |
| 64 } while (containee != null); |
| 65 |
| 66 return isParent; |
| 67 } |
| 68 |
| 69 // OnMouseOut handler. Returns true if the mouse moved out of the element. |
| 70 // It is false if the mouse is still in the element, but in a blank part of it, |
| 71 // like in an empty table cell. |
| 72 function checkMouseLeave(element, event) { |
| 73 if (element.contains && event.toElement) { |
| 74 return !element.contains(event.toElement); |
| 75 } |
| 76 else if (event.relatedTarget) { |
| 77 return !containsDOM(element, event.relatedTarget); |
| 78 } |
| 79 } |
| 80 |
| 81 // Creates a new cookie. |
| 82 function createCookie(name, value, day) { |
| 83 var date = new Date(); |
| 84 date.setTime(date.getTime() + (day * 24 * 60 * 60 * 1000)); |
| 85 var expires = "; expires=" + date.toGMTString(); |
| 86 document.cookie = name + "=" + value+expires + "; path=/"; |
| 87 } |
| 88 |
| 89 // Returns the vaue of a cookie, or null if it does not exist. |
| 90 function readCookie(name) { |
| 91 var begin = name + "="; |
| 92 var data = document.cookie.split(';'); |
| 93 for(var i = 0; i < data.length; i++) { |
| 94 var cookie = data[i]; |
| 95 while (cookie.charAt(0) == ' ') |
| 96 cookie = cookie.substring(1, cookie.length); |
| 97 if (cookie.indexOf(begin) == 0) |
| 98 return cookie.substring(begin.length, cookie.length); |
| 99 } |
| 100 |
| 101 return null; |
| 102 } |
| 103 |
| 104 // Deletes a cookie. |
| 105 function eraseCookie(name) { |
| 106 createCookie(name, "", -1); |
| 107 } |
| 108 |
| 109 // Hides all "details" and "comments" section. |
| 110 function collapse() { |
| 111 // Hide all Comments sections. |
| 112 var comments = document.querySelectorAll('.DevComment'); |
| 113 for(var i = 0; i < comments.length; i++) { |
| 114 comments[i].style.display = "none"; |
| 115 } |
| 116 |
| 117 // Hide all details sections. |
| 118 var details = document.querySelectorAll('.DevDetails'); |
| 119 for(var i = 0; i < details.length; i++) { |
| 120 details[i].style.display = "none"; |
| 121 } |
| 122 |
| 123 // Fix the rounding on the Revision box. (Lower right corner must be round) |
| 124 var revisions = document.querySelectorAll('.DevRev'); |
| 125 for(var i = 0; i < revisions.length; i++) { |
| 126 revisions[i].className = revisions[i].className + ' DevRevCollapse'; |
| 127 } |
| 128 |
| 129 // Fix the rounding on the last category box. (Lower left corner must be rou
nd) |
| 130 var status = document.querySelectorAll('.last'); |
| 131 for(var i = 0; i < status.length; i++) { |
| 132 status[i].className = status[i].className + ' DevStatusCollapse'; |
| 133 } |
| 134 |
| 135 // Create a cookie to remember that we want the view to be collapsed. |
| 136 createCookie('collapsed', 'true', 30) |
| 137 |
| 138 // Hide the collapse and the unmerge buttons. |
| 139 document.querySelectorAll('.collapse')[0].style.display = 'none' |
| 140 document.querySelectorAll('.unmerge')[0].style.display = 'none' |
| 141 |
| 142 // Activate the merge and expand buttons. |
| 143 document.querySelectorAll('.uncollapse')[0].style.display = 'inline' |
| 144 document.querySelectorAll('.merge')[0].style.display = 'inline' |
| 145 } |
| 146 |
| 147 // Expands the view. This is the opposite of "Collapse" |
| 148 function uncollapse() { |
| 149 unmerge(); |
| 150 |
| 151 // Make the comments visible. |
| 152 var comments = document.querySelectorAll('.DevComment'); |
| 153 for(var i = 0; i < comments.length; i++) { |
| 154 comments[i].style.display = ""; |
| 155 } |
| 156 |
| 157 // Make the details visible. |
| 158 var details = document.querySelectorAll('.DevDetails'); |
| 159 for(var i = 0; i < details.length; i++) { |
| 160 details[i].style.display = ""; |
| 161 } |
| 162 |
| 163 // Remove the round corner (lower right) for the Revision box. |
| 164 var revisions = document.querySelectorAll('.DevRev'); |
| 165 for(var i = 0; i < revisions.length; i++) { |
| 166 revisions[i].className = revisions[i].className.replace('DevRevCollapse'
, ''); |
| 167 } |
| 168 |
| 169 // Remoe the round corner (lower left) for the last category box. |
| 170 var status = document.querySelectorAll('.DevStatus'); |
| 171 for(var i = 0; i < status.length; i++) { |
| 172 status[i].className = status[i].className.replace('DevStatusCollapse', '
'); |
| 173 } |
| 174 |
| 175 // Delete the cookies that say that we want to be collapsed or merged. |
| 176 eraseCookie('collapsed') |
| 177 eraseCookie('merged') |
| 178 |
| 179 // Display the "collapse" and "merge" buttons. |
| 180 document.querySelectorAll('.collapse')[0].style.display = 'inline' |
| 181 document.querySelectorAll('.merge')[0].style.display = 'inline' |
| 182 |
| 183 // Remove the "uncollapse" and "unmerge" buttons. |
| 184 document.querySelectorAll('.uncollapse')[0].style.display = 'none' |
| 185 document.querySelectorAll('.unmerge')[0].style.display = 'none' |
| 186 } |
| 187 |
| 188 // Merge all the status boxes together. |
| 189 function merge() { |
| 190 collapse(); |
| 191 |
| 192 // Hide all the spacing. |
| 193 var spacing = document.querySelectorAll('.DevStatusSpacing'); |
| 194 for(var i = 0; i < spacing.length; i++) { |
| 195 spacing[i].style.display = "none"; |
| 196 } |
| 197 |
| 198 // Each boxes have, in the className, a tag that uniquely represents the |
| 199 // build where this data comes from. |
| 200 // Since we want to merge all the boxes coming from the same build, we |
| 201 // parse the document to find all the builds, and then, for each build, we |
| 202 // concatenate the boxes. |
| 203 |
| 204 var allTags = []; |
| 205 all = document.getElementsByTagName('*') |
| 206 for(var i = 0; i < all.length; i++) { |
| 207 var element = all[i]; |
| 208 start = element.className.indexOf('Tag') |
| 209 if (start != -1) { |
| 210 var className = "" |
| 211 end = element.className.indexOf(' ', start) |
| 212 if (end != -1) { |
| 213 className = element.className.substring(start, end); |
| 214 } else { |
| 215 className = element.className.substring(start); |
| 216 } |
| 217 allTags[className] = 1; |
| 218 } |
| 219 } |
| 220 |
| 221 // Mergeall tags that we found |
| 222 for (i in allTags) { |
| 223 var current = document.querySelectorAll('.' + i); |
| 224 |
| 225 // We do the work only if there is more than 1 box with the same |
| 226 // build. |
| 227 if (current.length > 1) { |
| 228 // Add the noround class to all the boxes. |
| 229 for(var i = 0; i < current.length; i++) { |
| 230 current[i].className = current[i].className + ' noround'; |
| 231 } |
| 232 |
| 233 // Add the begin class to the first box. |
| 234 current[0].className = current[0].className + ' begin'; |
| 235 |
| 236 // Add the end class to the last box. |
| 237 last = current.length - 1; |
| 238 current[last].className = current[last].className + ' end'; |
| 239 } |
| 240 } |
| 241 |
| 242 // Display the "unmerge" button. |
| 243 document.querySelectorAll('.unmerge')[0].style.display = 'inline' |
| 244 document.querySelectorAll('.uncollapse')[0].style.display = 'inline' |
| 245 |
| 246 // Remove the "merge" button. |
| 247 document.querySelectorAll('.collapse')[0].style.display = 'none' |
| 248 document.querySelectorAll('.merge')[0].style.display = 'none' |
| 249 |
| 250 // Create a cookie to remember that we want to be merged. |
| 251 createCookie('merged', 'true', 30) |
| 252 } |
| 253 |
| 254 // Un-merge the view. This is the opposite of "merge". |
| 255 function unmerge() { |
| 256 // We put back all the spacing. |
| 257 var spacing = document.querySelectorAll('.DevStatusSpacing'); |
| 258 for(var i = 0; i < spacing.length; i++) { |
| 259 spacing[i].style.display = ""; |
| 260 } |
| 261 |
| 262 // We remove the class added to all the boxes we modified. |
| 263 var noround = document.querySelectorAll('.noround'); |
| 264 for(var i = 0; i < noround.length; i++) { |
| 265 noround[i].className = noround[i].className.replace("begin", ''); |
| 266 noround[i].className = noround[i].className.replace("end", ''); |
| 267 noround[i].className = noround[i].className.replace("noround", ''); |
| 268 } |
| 269 |
| 270 // Delete the cookie, we don't want to be merged anymore. |
| 271 eraseCookie('merged') |
| 272 |
| 273 // Display the "merge" button. |
| 274 document.querySelectorAll('.merge')[0].style.display = 'inline' |
| 275 |
| 276 // Hide the "unmerge" button. |
| 277 document.querySelectorAll('.unmerge')[0].style.display = 'none' |
| 278 } |
| 279 |
| 280 function SetupView() { |
| 281 if (readCookie('merged')) { |
| 282 merge(); |
| 283 } else if (readCookie('collapsed')) { |
| 284 collapse(); |
| 285 } |
| 286 } |
| 287 |
| 288 document.addEventListener("DOMContentLoaded", SetupView, false); |
| 289 |
| 290 // ]]> |
| 291 </script> |
| 292 |
| 293 {% if additional_head %} |
| 294 {{ additional_head }} |
| 295 {% endif %} |
| 296 |
6 </head> | 297 </head> |
7 | 298 |
8 <body> | 299 <body{% if body_class %} class="{{ body_class }}"{% endif %}> |
9 {% block content %}{% endblock %} | 300 <div style="text-align:right; float: right;"> |
| 301 {% if user %} |
| 302 {{ user_nickname }} |
| 303 - <a href="{{ logout_url }}">Sign Out</a> |
| 304 {% else %} |
| 305 <a href="{{ login_url }}">Sign In</a> |
| 306 {% endif %} |
| 307 </div> |
| 308 |
| 309 <div class="header"> |
| 310 <a href="{{ offsite_base }}/.">Home</a> |
| 311 - <a href="{{ offsite_base }}/waterfall">Waterfall</a> |
| 312 - <a href="{{ offsite_base }}/console">Console</a> |
| 313 - <a href="{{ offsite_base }}/builders">Builders</a> |
| 314 - <a href="{{ offsite_base }}/one_line_per_build">Recent Builds</a> |
| 315 - <a href="{{ offsite_base }}/buildslaves">Buildslaves</a> |
| 316 - <a href="{{ offsite_base }}/changes">Changesources</a> |
| 317 - <a href="{{ offsite_base }}/json/help">JSON API</a> |
| 318 - <a href="{{ offsite_base }}/about">About</a> |
| 319 </div> |
| 320 |
| 321 <hr /> |
| 322 {% autoescape off %} |
| 323 {{ content }} |
| 324 {% endautoescape %} |
10 </body> | 325 </body> |
11 </html> | 326 </html> |
OLD | NEW |