summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorNed Batchelder <ned@nedbatchelder.com>2011-06-26 22:41:31 -0400
committerNed Batchelder <ned@nedbatchelder.com>2011-06-26 22:41:31 -0400
commit73027f06a42d6d3c10aec4fa8cc0c070c0981fe2 (patch)
tree0cf6a3784dc00c11b40fcb1f20b3bace1f646d49
parentf1cca3a1da7c87b48583e871bf8770fe6df4d3f2 (diff)
downloadpython-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.txt8
-rw-r--r--coverage/htmlfiles/coverage_html.js126
-rw-r--r--test/js/tests.js45
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);
+ });
+ });
+});