OLD | NEW |
(Empty) | |
| 1 // Coverage.py HTML report browser code. |
| 2 /*jslint browser: true, sloppy: true, vars: true, plusplus: true, maxerr: 50, in
dent: 4 */ |
| 3 /*global coverage: true, document, window, $ */ |
| 4 |
| 5 coverage = {}; |
| 6 |
| 7 // Find all the elements with shortkey_* class, and use them to assign a shotrtc
ut key. |
| 8 coverage.assign_shortkeys = function () { |
| 9 $("*[class*='shortkey_']").each(function (i, e) { |
| 10 $.each($(e).attr("class").split(" "), function (i, c) { |
| 11 if (/^shortkey_/.test(c)) { |
| 12 $(document).bind('keydown', c.substr(9), function () { |
| 13 $(e).click(); |
| 14 }); |
| 15 } |
| 16 }); |
| 17 }); |
| 18 }; |
| 19 |
| 20 // Create the events for the help panel. |
| 21 coverage.wire_up_help_panel = function () { |
| 22 $("#keyboard_icon").click(function () { |
| 23 // Show the help panel, and position it so the keyboard icon in the |
| 24 // panel is in the same place as the keyboard icon in the header. |
| 25 $(".help_panel").show(); |
| 26 var koff = $("#keyboard_icon").offset(); |
| 27 var poff = $("#panel_icon").position(); |
| 28 $(".help_panel").offset({ |
| 29 top: koff.top-poff.top, |
| 30 left: koff.left-poff.left |
| 31 }); |
| 32 }); |
| 33 $("#panel_icon").click(function () { |
| 34 $(".help_panel").hide(); |
| 35 }); |
| 36 }; |
| 37 |
| 38 // Loaded on index.html |
| 39 coverage.index_ready = function ($) { |
| 40 // Look for a cookie containing previous sort settings: |
| 41 var sort_list = []; |
| 42 var cookie_name = "COVERAGE_INDEX_SORT"; |
| 43 var i; |
| 44 |
| 45 // This almost makes it worth installing the jQuery cookie plugin: |
| 46 if (document.cookie.indexOf(cookie_name) > -1) { |
| 47 var cookies = document.cookie.split(";"); |
| 48 for (i = 0; i < cookies.length; i++) { |
| 49 var parts = cookies[i].split("="); |
| 50 |
| 51 if ($.trim(parts[0]) === cookie_name && parts[1]) { |
| 52 sort_list = eval("[[" + parts[1] + "]]"); |
| 53 break; |
| 54 } |
| 55 } |
| 56 } |
| 57 |
| 58 // Create a new widget which exists only to save and restore |
| 59 // the sort order: |
| 60 $.tablesorter.addWidget({ |
| 61 id: "persistentSort", |
| 62 |
| 63 // Format is called by the widget before displaying: |
| 64 format: function (table) { |
| 65 if (table.config.sortList.length === 0 && sort_list.length > 0) { |
| 66 // This table hasn't been sorted before - we'll use |
| 67 // our stored settings: |
| 68 $(table).trigger('sorton', [sort_list]); |
| 69 } |
| 70 else { |
| 71 // This is not the first load - something has |
| 72 // already defined sorting so we'll just update |
| 73 // our stored value to match: |
| 74 sort_list = table.config.sortList; |
| 75 } |
| 76 } |
| 77 }); |
| 78 |
| 79 // Configure our tablesorter to handle the variable number of |
| 80 // columns produced depending on report options: |
| 81 var headers = []; |
| 82 var col_count = $("table.index > thead > tr > th").length; |
| 83 |
| 84 headers[0] = { sorter: 'text' }; |
| 85 for (i = 1; i < col_count-1; i++) { |
| 86 headers[i] = { sorter: 'digit' }; |
| 87 } |
| 88 headers[col_count-1] = { sorter: 'percent' }; |
| 89 |
| 90 // Enable the table sorter: |
| 91 $("table.index").tablesorter({ |
| 92 widgets: ['persistentSort'], |
| 93 headers: headers |
| 94 }); |
| 95 |
| 96 coverage.assign_shortkeys(); |
| 97 coverage.wire_up_help_panel(); |
| 98 |
| 99 // Watch for page unload events so we can save the final sort settings: |
| 100 $(window).unload(function () { |
| 101 document.cookie = cookie_name + "=" + sort_list.toString() + "; path=/"; |
| 102 }); |
| 103 }; |
| 104 |
| 105 // -- pyfile stuff -- |
| 106 |
| 107 coverage.pyfile_ready = function ($) { |
| 108 // If we're directed to a particular line number, highlight the line. |
| 109 var frag = location.hash; |
| 110 if (frag.length > 2 && frag[1] === 'n') { |
| 111 $(frag).addClass('highlight'); |
| 112 coverage.set_sel(parseInt(frag.substr(2), 10)); |
| 113 } |
| 114 else { |
| 115 coverage.set_sel(0); |
| 116 } |
| 117 |
| 118 $(document) |
| 119 .bind('keydown', 'j', coverage.to_next_chunk_nicely) |
| 120 .bind('keydown', 'k', coverage.to_prev_chunk_nicely) |
| 121 .bind('keydown', '0', coverage.to_top) |
| 122 .bind('keydown', '1', coverage.to_first_chunk) |
| 123 ; |
| 124 |
| 125 $(".button_toggle_run").click(function (evt) {coverage.toggle_lines(evt.targ
et, "run");}); |
| 126 $(".button_toggle_exc").click(function (evt) {coverage.toggle_lines(evt.targ
et, "exc");}); |
| 127 $(".button_toggle_mis").click(function (evt) {coverage.toggle_lines(evt.targ
et, "mis");}); |
| 128 $(".button_toggle_par").click(function (evt) {coverage.toggle_lines(evt.targ
et, "par");}); |
| 129 |
| 130 coverage.assign_shortkeys(); |
| 131 coverage.wire_up_help_panel(); |
| 132 }; |
| 133 |
| 134 coverage.toggle_lines = function (btn, cls) { |
| 135 btn = $(btn); |
| 136 var hide = "hide_"+cls; |
| 137 if (btn.hasClass(hide)) { |
| 138 $("#source ."+cls).removeClass(hide); |
| 139 btn.removeClass(hide); |
| 140 } |
| 141 else { |
| 142 $("#source ."+cls).addClass(hide); |
| 143 btn.addClass(hide); |
| 144 } |
| 145 }; |
| 146 |
| 147 // Return the nth line div. |
| 148 coverage.line_elt = function (n) { |
| 149 return $("#t" + n); |
| 150 }; |
| 151 |
| 152 // Return the nth line number div. |
| 153 coverage.num_elt = function (n) { |
| 154 return $("#n" + n); |
| 155 }; |
| 156 |
| 157 // Return the container of all the code. |
| 158 coverage.code_container = function () { |
| 159 return $(".linenos"); |
| 160 }; |
| 161 |
| 162 // Set the selection. b and e are line numbers. |
| 163 coverage.set_sel = function (b, e) { |
| 164 // The first line selected. |
| 165 coverage.sel_begin = b; |
| 166 // The next line not selected. |
| 167 coverage.sel_end = (e === undefined) ? b+1 : e; |
| 168 }; |
| 169 |
| 170 coverage.to_top = function () { |
| 171 coverage.set_sel(0, 1); |
| 172 coverage.scroll_window(0); |
| 173 }; |
| 174 |
| 175 coverage.to_first_chunk = function () { |
| 176 coverage.set_sel(0, 1); |
| 177 coverage.to_next_chunk(); |
| 178 }; |
| 179 |
| 180 coverage.is_transparent = function (color) { |
| 181 // Different browsers return different colors for "none". |
| 182 return color === "transparent" || color === "rgba(0, 0, 0, 0)"; |
| 183 }; |
| 184 |
| 185 coverage.to_next_chunk = function () { |
| 186 var c = coverage; |
| 187 |
| 188 // Find the start of the next colored chunk. |
| 189 var probe = c.sel_end; |
| 190 while (true) { |
| 191 var probe_line = c.line_elt(probe); |
| 192 if (probe_line.length === 0) { |
| 193 return; |
| 194 } |
| 195 var color = probe_line.css("background-color"); |
| 196 if (!c.is_transparent(color)) { |
| 197 break; |
| 198 } |
| 199 probe++; |
| 200 } |
| 201 |
| 202 // There's a next chunk, `probe` points to it. |
| 203 var begin = probe; |
| 204 |
| 205 // Find the end of this chunk. |
| 206 var next_color = color; |
| 207 while (next_color === color) { |
| 208 probe++; |
| 209 probe_line = c.line_elt(probe); |
| 210 next_color = probe_line.css("background-color"); |
| 211 } |
| 212 c.set_sel(begin, probe); |
| 213 c.show_selection(); |
| 214 }; |
| 215 |
| 216 coverage.to_prev_chunk = function () { |
| 217 var c = coverage; |
| 218 |
| 219 // Find the end of the prev colored chunk. |
| 220 var probe = c.sel_begin-1; |
| 221 var probe_line = c.line_elt(probe); |
| 222 if (probe_line.length === 0) { |
| 223 return; |
| 224 } |
| 225 var color = probe_line.css("background-color"); |
| 226 while (probe > 0 && c.is_transparent(color)) { |
| 227 probe--; |
| 228 probe_line = c.line_elt(probe); |
| 229 if (probe_line.length === 0) { |
| 230 return; |
| 231 } |
| 232 color = probe_line.css("background-color"); |
| 233 } |
| 234 |
| 235 // There's a prev chunk, `probe` points to its last line. |
| 236 var end = probe+1; |
| 237 |
| 238 // Find the beginning of this chunk. |
| 239 var prev_color = color; |
| 240 while (prev_color === color) { |
| 241 probe--; |
| 242 probe_line = c.line_elt(probe); |
| 243 prev_color = probe_line.css("background-color"); |
| 244 } |
| 245 c.set_sel(probe+1, end); |
| 246 c.show_selection(); |
| 247 }; |
| 248 |
| 249 // Return the line number of the line nearest pixel position pos |
| 250 coverage.line_at_pos = function (pos) { |
| 251 var l1 = coverage.line_elt(1), |
| 252 l2 = coverage.line_elt(2), |
| 253 result; |
| 254 if (l1.length && l2.length) { |
| 255 var l1_top = l1.offset().top, |
| 256 line_height = l2.offset().top - l1_top, |
| 257 nlines = (pos - l1_top) / line_height; |
| 258 if (nlines < 1) { |
| 259 result = 1; |
| 260 } |
| 261 else { |
| 262 result = Math.ceil(nlines); |
| 263 } |
| 264 } |
| 265 else { |
| 266 result = 1; |
| 267 } |
| 268 return result; |
| 269 }; |
| 270 |
| 271 // Returns 0, 1, or 2: how many of the two ends of the selection are on |
| 272 // the screen right now? |
| 273 coverage.selection_ends_on_screen = function () { |
| 274 if (coverage.sel_begin === 0) { |
| 275 return 0; |
| 276 } |
| 277 |
| 278 var top = coverage.line_elt(coverage.sel_begin); |
| 279 var next = coverage.line_elt(coverage.sel_end-1); |
| 280 |
| 281 return ( |
| 282 (top.isOnScreen() ? 1 : 0) + |
| 283 (next.isOnScreen() ? 1 : 0) |
| 284 ); |
| 285 }; |
| 286 |
| 287 coverage.to_next_chunk_nicely = function () { |
| 288 coverage.finish_scrolling(); |
| 289 if (coverage.selection_ends_on_screen() === 0) { |
| 290 // The selection is entirely off the screen: select the top line on |
| 291 // the screen. |
| 292 var win = $(window); |
| 293 coverage.select_line_or_chunk(coverage.line_at_pos(win.scrollTop())); |
| 294 } |
| 295 coverage.to_next_chunk(); |
| 296 }; |
| 297 |
| 298 coverage.to_prev_chunk_nicely = function () { |
| 299 coverage.finish_scrolling(); |
| 300 if (coverage.selection_ends_on_screen() === 0) { |
| 301 var win = $(window); |
| 302 coverage.select_line_or_chunk(coverage.line_at_pos(win.scrollTop() + win
.height())); |
| 303 } |
| 304 coverage.to_prev_chunk(); |
| 305 }; |
| 306 |
| 307 // Select line number lineno, or if it is in a colored chunk, select the |
| 308 // entire chunk |
| 309 coverage.select_line_or_chunk = function (lineno) { |
| 310 var c = coverage; |
| 311 var probe_line = c.line_elt(lineno); |
| 312 if (probe_line.length === 0) { |
| 313 return; |
| 314 } |
| 315 var the_color = probe_line.css("background-color"); |
| 316 if (!c.is_transparent(the_color)) { |
| 317 // The line is in a highlighted chunk. |
| 318 // Search backward for the first line. |
| 319 var probe = lineno; |
| 320 var color = the_color; |
| 321 while (probe > 0 && color === the_color) { |
| 322 probe--; |
| 323 probe_line = c.line_elt(probe); |
| 324 if (probe_line.length === 0) { |
| 325 break; |
| 326 } |
| 327 color = probe_line.css("background-color"); |
| 328 } |
| 329 var begin = probe + 1; |
| 330 |
| 331 // Search forward for the last line. |
| 332 probe = lineno; |
| 333 color = the_color; |
| 334 while (color === the_color) { |
| 335 probe++; |
| 336 probe_line = c.line_elt(probe); |
| 337 color = probe_line.css("background-color"); |
| 338 } |
| 339 |
| 340 coverage.set_sel(begin, probe); |
| 341 } |
| 342 else { |
| 343 coverage.set_sel(lineno); |
| 344 } |
| 345 }; |
| 346 |
| 347 coverage.show_selection = function () { |
| 348 var c = coverage; |
| 349 |
| 350 // Highlight the lines in the chunk |
| 351 c.code_container().find(".highlight").removeClass("highlight"); |
| 352 for (var probe = c.sel_begin; probe > 0 && probe < c.sel_end; probe++) { |
| 353 c.num_elt(probe).addClass("highlight"); |
| 354 } |
| 355 |
| 356 c.scroll_to_selection(); |
| 357 }; |
| 358 |
| 359 coverage.scroll_to_selection = function () { |
| 360 // Scroll the page if the chunk isn't fully visible. |
| 361 if (coverage.selection_ends_on_screen() < 2) { |
| 362 // Need to move the page. The html,body trick makes it scroll in all |
| 363 // browsers, got it from http://stackoverflow.com/questions/3042651 |
| 364 var top = coverage.line_elt(coverage.sel_begin); |
| 365 var top_pos = parseInt(top.offset().top, 10); |
| 366 coverage.scroll_window(top_pos - 30); |
| 367 } |
| 368 }; |
| 369 |
| 370 coverage.scroll_window = function (to_pos) { |
| 371 $("html,body").animate({scrollTop: to_pos}, 200); |
| 372 }; |
| 373 |
| 374 coverage.finish_scrolling = function () { |
| 375 $("html,body").stop(true, true); |
| 376 }; |
OLD | NEW |