| OLD | NEW | 
| (Empty) |  | 
 |    1 // Coverage.py HTML report browser code. | 
 |    2 /*jslint browser: true, sloppy: true, vars: true, plusplus: true, maxerr: 50, in
     dent: 4 */ | 
 |    3 /*global coverage: true, document, window, $ */ | 
 |    4  | 
 |    5 coverage = {}; | 
 |    6  | 
 |    7 // Find all the elements with shortkey_* class, and use them to assign a shotrtc
     ut 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     }); | 
 |   18 }; | 
 |   19  | 
 |   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     }); | 
 |   36 }; | 
 |   37  | 
 |   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; | 
 |   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  | 
 |  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     } | 
 |  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     $(".button_toggle_run").click(function (evt) {coverage.toggle_lines(evt.targ
     et, "run");}); | 
 |  126     $(".button_toggle_exc").click(function (evt) {coverage.toggle_lines(evt.targ
     et, "exc");}); | 
 |  127     $(".button_toggle_mis").click(function (evt) {coverage.toggle_lines(evt.targ
     et, "mis");}); | 
 |  128     $(".button_toggle_par").click(function (evt) {coverage.toggle_lines(evt.targ
     et, "par");}); | 
 |  129  | 
 |  130     coverage.assign_shortkeys(); | 
 |  131     coverage.wire_up_help_panel(); | 
 |  132 }; | 
 |  133  | 
 |  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     } | 
 |  145 }; | 
 |  146  | 
 |  147 // Return the nth line div. | 
 |  148 coverage.line_elt = function (n) { | 
 |  149     return $("#t" + n); | 
 |  150 }; | 
 |  151  | 
 |  152 // Return the nth line number div. | 
 |  153 coverage.num_elt = function (n) { | 
 |  154     return $("#n" + n); | 
 |  155 }; | 
 |  156  | 
 |  157 // Return the container of all the code. | 
 |  158 coverage.code_container = function () { | 
 |  159     return $(".linenos"); | 
 |  160 }; | 
 |  161  | 
 |  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; | 
 |  168 }; | 
 |  169  | 
 |  170 coverage.to_top = function () { | 
 |  171     coverage.set_sel(0, 1); | 
 |  172     coverage.scroll_window(0); | 
 |  173 }; | 
 |  174  | 
 |  175 coverage.to_first_chunk = function () { | 
 |  176     coverage.set_sel(0, 1); | 
 |  177     coverage.to_next_chunk(); | 
 |  178 }; | 
 |  179  | 
 |  180 coverage.is_transparent = function (color) { | 
 |  181     // Different browsers return different colors for "none". | 
 |  182     return color === "transparent" || color === "rgba(0, 0, 0, 0)"; | 
 |  183 }; | 
 |  184  | 
 |  185 coverage.to_next_chunk = function () { | 
 |  186     var c = coverage; | 
 |  187  | 
 |  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     } | 
 |  201  | 
 |  202     // There's a next chunk, `probe` points to it. | 
 |  203     var begin = probe; | 
 |  204  | 
 |  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(); | 
 |  214 }; | 
 |  215  | 
 |  216 coverage.to_prev_chunk = function () { | 
 |  217     var c = coverage; | 
 |  218  | 
 |  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     } | 
 |  234  | 
 |  235     // There's a prev chunk, `probe` points to its last line. | 
 |  236     var end = probe+1; | 
 |  237  | 
 |  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(); | 
 |  247 }; | 
 |  248  | 
 |  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; | 
 |  269 }; | 
 |  270  | 
 |  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     } | 
 |  277  | 
 |  278     var top = coverage.line_elt(coverage.sel_begin); | 
 |  279     var next = coverage.line_elt(coverage.sel_end-1); | 
 |  280  | 
 |  281     return ( | 
 |  282         (top.isOnScreen() ? 1 : 0) + | 
 |  283         (next.isOnScreen() ? 1 : 0) | 
 |  284     ); | 
 |  285 }; | 
 |  286  | 
 |  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(); | 
 |  296 }; | 
 |  297  | 
 |  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(); | 
 |  305 }; | 
 |  306  | 
 |  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; | 
 |  330  | 
 |  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         } | 
 |  339  | 
 |  340         coverage.set_sel(begin, probe); | 
 |  341     } | 
 |  342     else { | 
 |  343         coverage.set_sel(lineno); | 
 |  344     } | 
 |  345 }; | 
 |  346  | 
 |  347 coverage.show_selection = function () { | 
 |  348     var c = coverage; | 
 |  349  | 
 |  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     } | 
 |  355  | 
 |  356     c.scroll_to_selection(); | 
 |  357 }; | 
 |  358  | 
 |  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     } | 
 |  368 }; | 
 |  369  | 
 |  370 coverage.scroll_window = function (to_pos) { | 
 |  371     $("html,body").animate({scrollTop: to_pos}, 200); | 
 |  372 }; | 
 |  373  | 
 |  374 coverage.finish_scrolling = function () { | 
 |  375     $("html,body").stop(true, true); | 
 |  376 }; | 
| OLD | NEW |