diff options
author | Ned Batchelder <ned@nedbatchelder.com> | 2011-06-26 22:41:31 -0400 |
---|---|---|
committer | Ned Batchelder <ned@nedbatchelder.com> | 2011-06-26 22:41:31 -0400 |
commit | 73027f06a42d6d3c10aec4fa8cc0c070c0981fe2 (patch) | |
tree | 0cf6a3784dc00c11b40fcb1f20b3bace1f646d49 | |
parent | f1cca3a1da7c87b48583e871bf8770fe6df4d3f2 (diff) | |
download | python-coveragepy-git-73027f06a42d6d3c10aec4fa8cc0c070c0981fe2.tar.gz |
HTML report hotkeys work differently if the current chunk is off-screen. A chunk on-screen will be selected next.
-rw-r--r-- | CHANGES.txt | 8 | ||||
-rw-r--r-- | coverage/htmlfiles/coverage_html.js | 126 | ||||
-rw-r--r-- | test/js/tests.js | 45 |
3 files changed, 167 insertions, 12 deletions
diff --git a/CHANGES.txt b/CHANGES.txt index 4c2cba5b..edc921cd 100644 --- a/CHANGES.txt +++ b/CHANGES.txt @@ -2,6 +2,14 @@ Change history for Coverage.py ------------------------------ +Version 3.5b2 +------------- + +- The HTML report hotkeys now behave slightly differently when the current + chunk isn't visible at all: a chunk on the screen will be selected, + instead of the old behavior of jumping to the literal next chunk. + The hotkeys now work in Google Chrome. Thanks, Guido van Rossum. + Version 3.5b1 --- 5 June 2011 ----------------------------- diff --git a/coverage/htmlfiles/coverage_html.js b/coverage/htmlfiles/coverage_html.js index 38c7c5cc..f9a2cb8b 100644 --- a/coverage/htmlfiles/coverage_html.js +++ b/coverage/htmlfiles/coverage_html.js @@ -116,8 +116,8 @@ coverage.pyfile_ready = function ($) { } $(document) - .bind('keydown', 'j', coverage.to_next_chunk) - .bind('keydown', 'k', coverage.to_prev_chunk) + .bind('keydown', 'j', coverage.to_next_chunk_nicely) + .bind('keydown', 'k', coverage.to_prev_chunk_nicely) .bind('keydown', '0', coverage.to_top) .bind('keydown', '1', coverage.to_first_chunk) ; @@ -139,12 +139,12 @@ coverage.toggle_lines = function (btn, cls) { } }; -// Return the nth line. +// Return the nth line div. coverage.line_elt = function (n) { return $("#t" + n); }; -// Return the nth line number. +// Return the nth line number div. coverage.num_elt = function (n) { return $("#n" + n); }; @@ -154,6 +154,7 @@ coverage.code_container = function () { return $(".linenos"); }; +// Set the selection. b and e are line numbers. coverage.set_sel = function (b, e) { // The first line selected. coverage.sel_begin = b; @@ -163,7 +164,7 @@ coverage.set_sel = function (b, e) { coverage.to_top = function () { coverage.set_sel(0, 1); - $("html,body").animate({scrollTop: 0}, 200); + coverage.scroll_window(0); }; coverage.to_first_chunk = function () { @@ -240,6 +241,104 @@ coverage.to_prev_chunk = function () { c.show_selection(); }; +// Return the line number of the line nearest pixel position pos +coverage.line_at_pos = function (pos) { + var l1 = coverage.line_elt(1), + l2 = coverage.line_elt(2), + result; + if (l1.length && l2.length) { + var l1_top = l1.offset().top, + line_height = l2.offset().top - l1_top, + nlines = (pos - l1_top) / line_height; + if (nlines < 1) { + result = 1; + } + else { + result = Math.ceil(nlines); + } + } + else { + result = 1; + } + return result; +}; + +// Returns 0, 1, or 2: how many of the two ends of the selection are on +// the screen right now? +coverage.selection_ends_on_screen = function () { + if (coverage.sel_begin === 0) { + return 0; + } + + var top = coverage.line_elt(coverage.sel_begin); + var next = coverage.line_elt(coverage.sel_end-1); + + return ( + (top.isOnScreen() ? 1 : 0) + + (next.isOnScreen() ? 1 : 0) + ); +}; + +coverage.to_next_chunk_nicely = function () { + coverage.finish_scrolling(); + if (coverage.selection_ends_on_screen() === 0) { + // The selection is entirely off the screen: select the top line on + // the screen. + var win = $(window); + coverage.select_line_or_chunk(coverage.line_at_pos(win.scrollTop())); + } + coverage.to_next_chunk(); +}; + +coverage.to_prev_chunk_nicely = function () { + coverage.finish_scrolling(); + if (coverage.selection_ends_on_screen() === 0) { + var win = $(window); + coverage.select_line_or_chunk(coverage.line_at_pos(win.scrollTop() + win.height())); + } + coverage.to_prev_chunk(); +}; + +// Select line number lineno, or if it is in a colored chunk, select the +// entire chunk +coverage.select_line_or_chunk = function (lineno) { + var c = coverage; + var probe_line = c.line_elt(lineno); + if (probe_line.length === 0) { + return; + } + var the_color = probe_line.css("background-color"); + if (!c.is_transparent(the_color)) { + // The line is in a highlighted chunk. + // Search backward for the first line. + var probe = lineno; + var color = the_color; + while (probe > 0 && color === the_color) { + probe--; + probe_line = c.line_elt(probe); + if (probe_line.length === 0) { + break; + } + color = probe_line.css("background-color"); + } + var begin = probe + 1; + + // Search forward for the last line. + probe = lineno; + color = the_color; + while (color === the_color) { + probe++; + probe_line = c.line_elt(probe); + color = probe_line.css("background-color"); + } + + coverage.set_sel(begin, probe); + } + else { + coverage.set_sel(lineno); + } +}; + coverage.show_selection = function () { var c = coverage; @@ -254,13 +353,20 @@ coverage.show_selection = function () { coverage.scroll_to_selection = function () { // Scroll the page if the chunk isn't fully visible. - var top = coverage.line_elt(coverage.sel_begin); - var next = coverage.line_elt(coverage.sel_end); - - if (!top.isOnScreen() || !next.isOnScreen()) { + if (coverage.selection_ends_on_screen() < 2) { // Need to move the page. The html,body trick makes it scroll in all // browsers, got it from http://stackoverflow.com/questions/3042651 + var top = coverage.line_elt(coverage.sel_begin); var top_pos = parseInt(top.offset().top, 10); - $("html,body").animate({scrollTop: top_pos-30}, 300); + coverage.scroll_window(top_pos - 30); } }; + +coverage.scroll_window = function (to_pos) { + $("html,body").animate({scrollTop: to_pos}, 200); +}; + +coverage.finish_scrolling = function () { + $("html,body").stop(true, true); +}; + diff --git a/test/js/tests.js b/test/js/tests.js index 3c04e075..73b4ce2b 100644 --- a/test/js/tests.js +++ b/test/js/tests.js @@ -1,13 +1,19 @@ // Tests of coverage.py HTML report chunk navigation. -/* global: coverage, test, module, equals, jQuery, $ */ +/*global coverage, test, module, equals, jQuery, $ */ // Test helpers function selection_is(sel) { + raw_selection_is(sel, true); +} + +function raw_selection_is(sel, check_highlight) { var beg = sel[0], end = sel[1]; equals(coverage.sel_begin, beg); equals(coverage.sel_end, end); - equals(coverage.code_container().find(".highlight").length, end-beg); + if (check_highlight) { + equals(coverage.code_container().find(".highlight").length, end-beg); + } } function build_fixture(spec) { @@ -161,3 +167,38 @@ test("Jump from a line selected", function () { coverage.to_next_chunk(); selection_is([5,7]); }); + +// Tests of select_line_or_chunk. + +$.each([ + // The data for each test: a spec for the fixture to build, and an array + // of the selection that will be selected by select_line_or_chunk for + // each line in the fixture. + ['rrwwrr', [[1,3], [1,3], [3,4], [4,5], [5,7], [5,7]]], + ['rb', [[1,2], [2,3]]], + ['r', [[1,2]]], + ['w', [[1,2]]], + ['www', [[1,2], [2,3], [3,4]]], + ['wwwrrr', [[1,2], [2,3], [3,4], [4,7], [4,7], [4,7]]], + ['rrrwww', [[1,4], [1,4], [1,4], [4,5], [5,6], [6,7]]], + ['rrrbbb', [[1,4], [1,4], [1,4], [4,7], [4,7], [4,7]]] +], function (i, params) { + + // Each of these tests uses a fixture with two highlighted chunks. + var id = params[0]; + var sels = params[1]; + + module("Select line or chunk - " + id, { + setup: function () { + build_fixture(id); + } + }); + + $.each(sels, function (i, sel) { + i++; + test("Select line " + i, function () { + coverage.select_line_or_chunk(i); + raw_selection_is(sel); + }); + }); +}); |