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, $ */
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 () {
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
33 $("#panel_icon").click(function () {
34 $(".help_panel").hide();
38 // Loaded on index.html
39 coverage
.index_ready = function ($) {
40 // Look for a cookie containing previous sort settings:
42 var cookie_name
= "COVERAGE_INDEX_SORT";
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] + "]]");
58 // Create a new widget which exists only to save and restore
60 $.tablesorter
.addWidget({
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
]);
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
;
79 // Configure our tablesorter to handle the variable number of
80 // columns produced depending on report options:
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' };
88 headers
[col_count
-1] = { sorter
: 'percent' };
90 // Enable the table sorter:
91 $("table.index").tablesorter({
92 widgets
: ['persistentSort'],
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=/";
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));
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
)
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
) {
136 var hide
= "hide_"+cls
;
137 if (btn
.hasClass(hide
)) {
138 $("#source ."+cls
).removeClass(hide
);
139 btn
.removeClass(hide
);
142 $("#source ."+cls
).addClass(hide
);
147 // Return the nth line div.
148 coverage
.line_elt = function (n
) {
152 // Return the nth line number div.
153 coverage
.num_elt = function (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 () {
188 // Find the start of the next colored chunk.
189 var probe
= c
.sel_end
;
191 var probe_line
= c
.line_elt(probe
);
192 if (probe_line
.length
=== 0) {
195 var color
= probe_line
.css("background-color");
196 if (!c
.is_transparent(color
)) {
202 // There's a next chunk, `probe` points to it.
205 // Find the end of this chunk.
206 var next_color
= color
;
207 while (next_color
=== color
) {
209 probe_line
= c
.line_elt(probe
);
210 next_color
= probe_line
.css("background-color");
212 c
.set_sel(begin
, probe
);
216 coverage
.to_prev_chunk = function () {
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) {
225 var color
= probe_line
.css("background-color");
226 while (probe
> 0 && c
.is_transparent(color
)) {
228 probe_line
= c
.line_elt(probe
);
229 if (probe_line
.length
=== 0) {
232 color
= probe_line
.css("background-color");
235 // There's a prev chunk, `probe` points to its last line.
238 // Find the beginning of this chunk.
239 var prev_color
= color
;
240 while (prev_color
=== color
) {
242 probe_line
= c
.line_elt(probe
);
243 prev_color
= probe_line
.css("background-color");
245 c
.set_sel(probe
+1, end
);
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),
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
;
262 result
= Math
.ceil(nlines
);
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) {
278 var top
= coverage
.line_elt(coverage
.sel_begin
);
279 var next
= coverage
.line_elt(coverage
.sel_end
-1);
282 (top
.isOnScreen() ? 1 : 0) +
283 (next
.isOnScreen() ? 1 : 0)
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
293 coverage
.select_line_or_chunk(coverage
.line_at_pos(win
.scrollTop()));
295 coverage
.to_next_chunk();
298 coverage
.to_prev_chunk_nicely = function () {
299 coverage
.finish_scrolling();
300 if (coverage
.selection_ends_on_screen() === 0) {
302 coverage
.select_line_or_chunk(coverage
.line_at_pos(win
.scrollTop() + win
.height()));
304 coverage
.to_prev_chunk();
307 // Select line number lineno, or if it is in a colored chunk, select the
309 coverage
.select_line_or_chunk = function (lineno
) {
311 var probe_line
= c
.line_elt(lineno
);
312 if (probe_line
.length
=== 0) {
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.
320 var color
= the_color
;
321 while (probe
> 0 && color
=== the_color
) {
323 probe_line
= c
.line_elt(probe
);
324 if (probe_line
.length
=== 0) {
327 color
= probe_line
.css("background-color");
329 var begin
= probe
+ 1;
331 // Search forward for the last line.
334 while (color
=== the_color
) {
336 probe_line
= c
.line_elt(probe
);
337 color
= probe_line
.css("background-color");
340 coverage
.set_sel(begin
, probe
);
343 coverage
.set_sel(lineno
);
347 coverage
.show_selection = function () {
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");
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);
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);