Merge Chromium + Blink git repositories
[chromium-blink-merge.git] / third_party / pycoverage / coverage / htmlfiles / coverage_html.js
blobb24006d25e0005e37baf5500cdc7ee04e271609c
1 // Coverage.py HTML report browser code.
2 /*jslint browser: true, sloppy: true, vars: true, plusplus: true, maxerr: 50, indent: 4 */
3 /*global coverage: true, document, window, $ */
5 coverage = {};
7 // Find all the elements with shortkey_* class, and use them to assign a shotrtcut 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     });
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     });
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;
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("=");
51             if ($.trim(parts[0]) === cookie_name && parts[1]) {
52                 sort_list = eval("[[" + parts[1] + "]]");
53                 break;
54             }
55         }
56     }
58     // Create a new widget which exists only to save and restore
59     // the sort order:
60     $.tablesorter.addWidget({
61         id: "persistentSort",
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     });
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;
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' };
90     // Enable the table sorter:
91     $("table.index").tablesorter({
92         widgets: ['persistentSort'],
93         headers: headers
94     });
96     coverage.assign_shortkeys();
97     coverage.wire_up_help_panel();
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     });
105 // -- pyfile stuff --
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     }
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         ;
125     $(".button_toggle_run").click(function (evt) {coverage.toggle_lines(evt.target, "run");});
126     $(".button_toggle_exc").click(function (evt) {coverage.toggle_lines(evt.target, "exc");});
127     $(".button_toggle_mis").click(function (evt) {coverage.toggle_lines(evt.target, "mis");});
128     $(".button_toggle_par").click(function (evt) {coverage.toggle_lines(evt.target, "par");});
130     coverage.assign_shortkeys();
131     coverage.wire_up_help_panel();
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     }
147 // Return the nth line div.
148 coverage.line_elt = function (n) {
149     return $("#t" + n);
152 // Return the nth line number div.
153 coverage.num_elt = function (n) {
154     return $("#n" + n);
157 // Return the container of all the code.
158 coverage.code_container = function () {
159     return $(".linenos");
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;
170 coverage.to_top = function () {
171     coverage.set_sel(0, 1);
172     coverage.scroll_window(0);
175 coverage.to_first_chunk = function () {
176     coverage.set_sel(0, 1);
177     coverage.to_next_chunk();
180 coverage.is_transparent = function (color) {
181     // Different browsers return different colors for "none".
182     return color === "transparent" || color === "rgba(0, 0, 0, 0)";
185 coverage.to_next_chunk = function () {
186     var c = coverage;
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     }
202     // There's a next chunk, `probe` points to it.
203     var begin = probe;
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();
216 coverage.to_prev_chunk = function () {
217     var c = coverage;
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     }
235     // There's a prev chunk, `probe` points to its last line.
236     var end = probe+1;
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();
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;
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     }
278     var top = coverage.line_elt(coverage.sel_begin);
279     var next = coverage.line_elt(coverage.sel_end-1);
281     return (
282         (top.isOnScreen() ? 1 : 0) +
283         (next.isOnScreen() ? 1 : 0)
284     );
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();
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();
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;
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         }
340         coverage.set_sel(begin, probe);
341     }
342     else {
343         coverage.set_sel(lineno);
344     }
347 coverage.show_selection = function () {
348     var c = coverage;
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     }
356     c.scroll_to_selection();
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     }
370 coverage.scroll_window = function (to_pos) {
371     $("html,body").animate({scrollTop: to_pos}, 200);
374 coverage.finish_scrolling = function () {
375     $("html,body").stop(true, true);