UNPKG

10.8 kBJavaScriptView Raw
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, $ */
4
5coverage = {};
6
7// Find all the elements with shortkey_* class, and use them to assign a shotrtcut key.
8coverage.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.
21coverage.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
39coverage.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
107coverage.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 coverage.assign_shortkeys();
126 coverage.wire_up_help_panel();
127};
128
129coverage.toggle_lines = function (btn, cls) {
130 btn = $(btn);
131 var hide = "hide_"+cls;
132 if (btn.hasClass(hide)) {
133 $("#source ."+cls).removeClass(hide);
134 btn.removeClass(hide);
135 }
136 else {
137 $("#source ."+cls).addClass(hide);
138 btn.addClass(hide);
139 }
140};
141
142// Return the nth line div.
143coverage.line_elt = function (n) {
144 return $("#t" + n);
145};
146
147// Return the nth line number div.
148coverage.num_elt = function (n) {
149 return $("#n" + n);
150};
151
152// Return the container of all the code.
153coverage.code_container = function () {
154 return $(".linenos");
155};
156
157// Set the selection. b and e are line numbers.
158coverage.set_sel = function (b, e) {
159 // The first line selected.
160 coverage.sel_begin = b;
161 // The next line not selected.
162 coverage.sel_end = (e === undefined) ? b+1 : e;
163};
164
165coverage.to_top = function () {
166 coverage.set_sel(0, 1);
167 coverage.scroll_window(0);
168};
169
170coverage.to_first_chunk = function () {
171 coverage.set_sel(0, 1);
172 coverage.to_next_chunk();
173};
174
175coverage.is_transparent = function (color) {
176 // Different browsers return different colors for "none".
177 return color === "transparent" || color === "rgba(0, 0, 0, 0)";
178};
179
180coverage.to_next_chunk = function () {
181 var c = coverage;
182
183 // Find the start of the next colored chunk.
184 var probe = c.sel_end;
185 while (true) {
186 var probe_line = c.line_elt(probe);
187 if (probe_line.length === 0) {
188 return;
189 }
190 var color = probe_line.css("background-color");
191 if (!c.is_transparent(color)) {
192 break;
193 }
194 probe++;
195 }
196
197 // There's a next chunk, `probe` points to it.
198 var begin = probe;
199
200 // Find the end of this chunk.
201 var next_color = color;
202 while (next_color === color) {
203 probe++;
204 probe_line = c.line_elt(probe);
205 next_color = probe_line.css("background-color");
206 }
207 c.set_sel(begin, probe);
208 c.show_selection();
209};
210
211coverage.to_prev_chunk = function () {
212 var c = coverage;
213
214 // Find the end of the prev colored chunk.
215 var probe = c.sel_begin-1;
216 var probe_line = c.line_elt(probe);
217 if (probe_line.length === 0) {
218 return;
219 }
220 var color = probe_line.css("background-color");
221 while (probe > 0 && c.is_transparent(color)) {
222 probe--;
223 probe_line = c.line_elt(probe);
224 if (probe_line.length === 0) {
225 return;
226 }
227 color = probe_line.css("background-color");
228 }
229
230 // There's a prev chunk, `probe` points to its last line.
231 var end = probe+1;
232
233 // Find the beginning of this chunk.
234 var prev_color = color;
235 while (prev_color === color) {
236 probe--;
237 probe_line = c.line_elt(probe);
238 prev_color = probe_line.css("background-color");
239 }
240 c.set_sel(probe+1, end);
241 c.show_selection();
242};
243
244// Return the line number of the line nearest pixel position pos
245coverage.line_at_pos = function (pos) {
246 var l1 = coverage.line_elt(1),
247 l2 = coverage.line_elt(2),
248 result;
249 if (l1.length && l2.length) {
250 var l1_top = l1.offset().top,
251 line_height = l2.offset().top - l1_top,
252 nlines = (pos - l1_top) / line_height;
253 if (nlines < 1) {
254 result = 1;
255 }
256 else {
257 result = Math.ceil(nlines);
258 }
259 }
260 else {
261 result = 1;
262 }
263 return result;
264};
265
266// Returns 0, 1, or 2: how many of the two ends of the selection are on
267// the screen right now?
268coverage.selection_ends_on_screen = function () {
269 if (coverage.sel_begin === 0) {
270 return 0;
271 }
272
273 var top = coverage.line_elt(coverage.sel_begin);
274 var next = coverage.line_elt(coverage.sel_end-1);
275
276 return (
277 (top.isOnScreen() ? 1 : 0) +
278 (next.isOnScreen() ? 1 : 0)
279 );
280};
281
282coverage.to_next_chunk_nicely = function () {
283 coverage.finish_scrolling();
284 if (coverage.selection_ends_on_screen() === 0) {
285 // The selection is entirely off the screen: select the top line on
286 // the screen.
287 var win = $(window);
288 coverage.select_line_or_chunk(coverage.line_at_pos(win.scrollTop()));
289 }
290 coverage.to_next_chunk();
291};
292
293coverage.to_prev_chunk_nicely = function () {
294 coverage.finish_scrolling();
295 if (coverage.selection_ends_on_screen() === 0) {
296 var win = $(window);
297 coverage.select_line_or_chunk(coverage.line_at_pos(win.scrollTop() + win.height()));
298 }
299 coverage.to_prev_chunk();
300};
301
302// Select line number lineno, or if it is in a colored chunk, select the
303// entire chunk
304coverage.select_line_or_chunk = function (lineno) {
305 var c = coverage;
306 var probe_line = c.line_elt(lineno);
307 if (probe_line.length === 0) {
308 return;
309 }
310 var the_color = probe_line.css("background-color");
311 if (!c.is_transparent(the_color)) {
312 // The line is in a highlighted chunk.
313 // Search backward for the first line.
314 var probe = lineno;
315 var color = the_color;
316 while (probe > 0 && color === the_color) {
317 probe--;
318 probe_line = c.line_elt(probe);
319 if (probe_line.length === 0) {
320 break;
321 }
322 color = probe_line.css("background-color");
323 }
324 var begin = probe + 1;
325
326 // Search forward for the last line.
327 probe = lineno;
328 color = the_color;
329 while (color === the_color) {
330 probe++;
331 probe_line = c.line_elt(probe);
332 color = probe_line.css("background-color");
333 }
334
335 coverage.set_sel(begin, probe);
336 }
337 else {
338 coverage.set_sel(lineno);
339 }
340};
341
342coverage.show_selection = function () {
343 var c = coverage;
344
345 // Highlight the lines in the chunk
346 c.code_container().find(".highlight").removeClass("highlight");
347 for (var probe = c.sel_begin; probe > 0 && probe < c.sel_end; probe++) {
348 c.num_elt(probe).addClass("highlight");
349 }
350
351 c.scroll_to_selection();
352};
353
354coverage.scroll_to_selection = function () {
355 // Scroll the page if the chunk isn't fully visible.
356 if (coverage.selection_ends_on_screen() < 2) {
357 // Need to move the page. The html,body trick makes it scroll in all
358 // browsers, got it from http://stackoverflow.com/questions/3042651
359 var top = coverage.line_elt(coverage.sel_begin);
360 var top_pos = parseInt(top.offset().top, 10);
361 coverage.scroll_window(top_pos - 30);
362 }
363};
364
365coverage.scroll_window = function (to_pos) {
366 $("html,body").animate({scrollTop: to_pos}, 200);
367};
368
369coverage.finish_scrolling = function () {
370 $("html,body").stop(true, true);
371};
372