1 | // Licensed under the Apache License: http://www.apache.org/licenses/LICENSE-2.0 |
||
2 | // For details: https://github.com/nedbat/coveragepy/blob/master/NOTICE.txt |
||
3 | |||
4 | // Coverage.py HTML report browser code. |
||
5 | /*jslint browser: true, sloppy: true, vars: true, plusplus: true, maxerr: 50, indent: 4 */ |
||
6 | /*global coverage: true, document, window, $ */ |
||
7 | |||
8 | coverage = {}; |
||
0 ignored issues
–
show
Bug
introduced
by
![]() |
|||
9 | |||
10 | // Find all the elements with shortkey_* class, and use them to assign a shortcut key. |
||
11 | coverage.assign_shortkeys = function () { |
||
12 | $("*[class*='shortkey_']").each(function (i, e) { |
||
13 | $.each($(e).attr("class").split(" "), function (i, c) { |
||
14 | if (/^shortkey_/.test(c)) { |
||
15 | $(document).bind('keydown', c.substr(9), function () { |
||
16 | $(e).click(); |
||
17 | }); |
||
18 | } |
||
19 | }); |
||
20 | }); |
||
21 | }; |
||
22 | |||
23 | // Create the events for the help panel. |
||
24 | coverage.wire_up_help_panel = function () { |
||
25 | $("#keyboard_icon").click(function () { |
||
26 | // Show the help panel, and position it so the keyboard icon in the |
||
27 | // panel is in the same place as the keyboard icon in the header. |
||
28 | $(".help_panel").show(); |
||
29 | var koff = $("#keyboard_icon").offset(); |
||
30 | var poff = $("#panel_icon").position(); |
||
31 | $(".help_panel").offset({ |
||
32 | top: koff.top-poff.top, |
||
33 | left: koff.left-poff.left |
||
34 | }); |
||
35 | }); |
||
36 | $("#panel_icon").click(function () { |
||
37 | $(".help_panel").hide(); |
||
38 | }); |
||
39 | }; |
||
40 | |||
41 | // Create the events for the filter box. |
||
42 | coverage.wire_up_filter = function () { |
||
43 | // Cache elements. |
||
44 | var table = $("table.index"); |
||
45 | var table_rows = table.find("tbody tr"); |
||
46 | var table_row_names = table_rows.find("td.name a"); |
||
47 | var no_rows = $("#no_rows"); |
||
48 | |||
49 | // Create a duplicate table footer that we can modify with dynamic summed values. |
||
50 | var table_footer = $("table.index tfoot tr"); |
||
51 | var table_dynamic_footer = table_footer.clone(); |
||
52 | table_dynamic_footer.attr('class', 'total_dynamic hidden'); |
||
53 | table_footer.after(table_dynamic_footer); |
||
54 | |||
55 | // Observe filter keyevents. |
||
56 | $("#filter").on("keyup change", $.debounce(150, function (event) { |
||
0 ignored issues
–
show
|
|||
57 | var filter_value = $(this).val(); |
||
58 | |||
59 | if (filter_value === "") { |
||
60 | // Filter box is empty, remove all filtering. |
||
61 | table_rows.removeClass("hidden"); |
||
62 | |||
63 | // Show standard footer, hide dynamic footer. |
||
64 | table_footer.removeClass("hidden"); |
||
65 | table_dynamic_footer.addClass("hidden"); |
||
66 | |||
67 | // Hide placeholder, show table. |
||
68 | if (no_rows.length > 0) { |
||
69 | no_rows.hide(); |
||
70 | } |
||
71 | table.show(); |
||
72 | |||
73 | } |
||
74 | else { |
||
75 | // Filter table items by value. |
||
76 | var hidden = 0; |
||
77 | var shown = 0; |
||
78 | |||
79 | // Hide / show elements. |
||
80 | $.each(table_row_names, function () { |
||
81 | var element = $(this).parents("tr"); |
||
82 | |||
83 | if ($(this).text().indexOf(filter_value) === -1) { |
||
84 | // hide |
||
85 | element.addClass("hidden"); |
||
86 | hidden++; |
||
87 | } |
||
88 | else { |
||
89 | // show |
||
90 | element.removeClass("hidden"); |
||
91 | shown++; |
||
92 | } |
||
93 | }); |
||
94 | |||
95 | // Show placeholder if no rows will be displayed. |
||
96 | if (no_rows.length > 0) { |
||
97 | if (shown === 0) { |
||
98 | // Show placeholder, hide table. |
||
99 | no_rows.show(); |
||
100 | table.hide(); |
||
101 | } |
||
102 | else { |
||
103 | // Hide placeholder, show table. |
||
104 | no_rows.hide(); |
||
105 | table.show(); |
||
106 | } |
||
107 | } |
||
108 | |||
109 | // Manage dynamic header: |
||
110 | if (hidden > 0) { |
||
111 | // Calculate new dynamic sum values based on visible rows. |
||
112 | for (var column = 2; column < 20; column++) { |
||
113 | // Calculate summed value. |
||
114 | var cells = table_rows.find('td:nth-child(' + column + ')'); |
||
115 | if (!cells.length) { |
||
116 | // No more columns...! |
||
117 | break; |
||
118 | } |
||
119 | |||
120 | var sum = 0, numer = 0, denom = 0; |
||
121 | $.each(cells.filter(':visible'), function () { |
||
122 | var ratio = $(this).data("ratio"); |
||
123 | if (ratio) { |
||
124 | var splitted = ratio.split(" "); |
||
125 | numer += parseInt(splitted[0], 10); |
||
0 ignored issues
–
show
|
|||
126 | denom += parseInt(splitted[1], 10); |
||
0 ignored issues
–
show
|
|||
127 | } |
||
128 | else { |
||
129 | sum += parseInt(this.innerHTML, 10); |
||
0 ignored issues
–
show
|
|||
130 | } |
||
131 | }); |
||
132 | |||
133 | // Get footer cell element. |
||
134 | var footer_cell = table_dynamic_footer.find('td:nth-child(' + column + ')'); |
||
135 | |||
136 | // Set value into dynamic footer cell element. |
||
137 | if (cells[0].innerHTML.indexOf('%') > -1) { |
||
138 | // Percentage columns use the numerator and denominator, |
||
139 | // and adapt to the number of decimal places. |
||
140 | var match = /\.([0-9]+)/.exec(cells[0].innerHTML); |
||
141 | var places = 0; |
||
142 | if (match) { |
||
143 | places = match[1].length; |
||
144 | } |
||
145 | var pct = numer * 100 / denom; |
||
146 | footer_cell.text(pct.toFixed(places) + '%'); |
||
147 | } |
||
148 | else { |
||
149 | footer_cell.text(sum); |
||
150 | } |
||
151 | } |
||
152 | |||
153 | // Hide standard footer, show dynamic footer. |
||
154 | table_footer.addClass("hidden"); |
||
155 | table_dynamic_footer.removeClass("hidden"); |
||
156 | } |
||
157 | else { |
||
158 | // Show standard footer, hide dynamic footer. |
||
159 | table_footer.removeClass("hidden"); |
||
160 | table_dynamic_footer.addClass("hidden"); |
||
161 | } |
||
162 | } |
||
163 | })); |
||
164 | |||
165 | // Trigger change event on setup, to force filter on page refresh |
||
166 | // (filter value may still be present). |
||
167 | $("#filter").trigger("change"); |
||
168 | }; |
||
169 | |||
170 | // Loaded on index.html |
||
171 | coverage.index_ready = function ($) { |
||
172 | // Look for a localStorage item containing previous sort settings: |
||
173 | var sort_list = []; |
||
174 | var storage_name = "COVERAGE_INDEX_SORT"; |
||
175 | var stored_list = undefined; |
||
0 ignored issues
–
show
Unused Code
Comprehensibility
introduced
by
|
|||
176 | try { |
||
177 | stored_list = localStorage.getItem(storage_name); |
||
0 ignored issues
–
show
The variable
localStorage seems to be never declared. If this is a global, consider adding a /** global: localStorage */ comment.
This checks looks for references to variables that have not been declared. This is most likey a typographical error or a variable has been renamed. To learn more about declaring variables in Javascript, see the MDN. ![]() |
|||
178 | } catch(err) {} |
||
0 ignored issues
–
show
Coding Style
Comprehensibility
Best Practice
introduced
by
|
|||
179 | |||
180 | if (stored_list) { |
||
181 | sort_list = JSON.parse('[[' + stored_list + ']]'); |
||
182 | } |
||
183 | |||
184 | // Create a new widget which exists only to save and restore |
||
185 | // the sort order: |
||
186 | $.tablesorter.addWidget({ |
||
187 | id: "persistentSort", |
||
188 | |||
189 | // Format is called by the widget before displaying: |
||
190 | format: function (table) { |
||
191 | if (table.config.sortList.length === 0 && sort_list.length > 0) { |
||
192 | // This table hasn't been sorted before - we'll use |
||
193 | // our stored settings: |
||
194 | $(table).trigger('sorton', [sort_list]); |
||
195 | } |
||
196 | else { |
||
197 | // This is not the first load - something has |
||
198 | // already defined sorting so we'll just update |
||
199 | // our stored value to match: |
||
200 | sort_list = table.config.sortList; |
||
201 | } |
||
202 | } |
||
203 | }); |
||
204 | |||
205 | // Configure our tablesorter to handle the variable number of |
||
206 | // columns produced depending on report options: |
||
207 | var headers = []; |
||
208 | var col_count = $("table.index > thead > tr > th").length; |
||
209 | |||
210 | headers[0] = { sorter: 'text' }; |
||
211 | for (i = 1; i < col_count-1; i++) { |
||
0 ignored issues
–
show
|
|||
212 | headers[i] = { sorter: 'digit' }; |
||
213 | } |
||
214 | headers[col_count-1] = { sorter: 'percent' }; |
||
215 | |||
216 | // Enable the table sorter: |
||
217 | $("table.index").tablesorter({ |
||
218 | widgets: ['persistentSort'], |
||
219 | headers: headers |
||
220 | }); |
||
221 | |||
222 | coverage.assign_shortkeys(); |
||
223 | coverage.wire_up_help_panel(); |
||
224 | coverage.wire_up_filter(); |
||
225 | |||
226 | // Watch for page unload events so we can save the final sort settings: |
||
227 | $(window).unload(function () { |
||
228 | try { |
||
229 | localStorage.setItem(storage_name, sort_list.toString()) |
||
0 ignored issues
–
show
The variable
localStorage seems to be never declared. If this is a global, consider adding a /** global: localStorage */ comment.
This checks looks for references to variables that have not been declared. This is most likey a typographical error or a variable has been renamed. To learn more about declaring variables in Javascript, see the MDN. ![]() |
|||
230 | } catch(err) {} |
||
0 ignored issues
–
show
Coding Style
Comprehensibility
Best Practice
introduced
by
|
|||
231 | }); |
||
232 | }; |
||
233 | |||
234 | // -- pyfile stuff -- |
||
235 | |||
236 | coverage.pyfile_ready = function ($) { |
||
237 | // If we're directed to a particular line number, highlight the line. |
||
238 | var frag = location.hash; |
||
239 | if (frag.length > 2 && frag[1] === 't') { |
||
240 | $(frag).addClass('highlight'); |
||
241 | coverage.set_sel(parseInt(frag.substr(2), 10)); |
||
242 | } |
||
243 | else { |
||
244 | coverage.set_sel(0); |
||
245 | } |
||
246 | |||
247 | $(document) |
||
248 | .bind('keydown', 'j', coverage.to_next_chunk_nicely) |
||
249 | .bind('keydown', 'k', coverage.to_prev_chunk_nicely) |
||
250 | .bind('keydown', '0', coverage.to_top) |
||
251 | .bind('keydown', '1', coverage.to_first_chunk) |
||
252 | ; |
||
253 | |||
254 | $(".button_toggle_run").click(function (evt) {coverage.toggle_lines(evt.target, "run");}); |
||
255 | $(".button_toggle_exc").click(function (evt) {coverage.toggle_lines(evt.target, "exc");}); |
||
256 | $(".button_toggle_mis").click(function (evt) {coverage.toggle_lines(evt.target, "mis");}); |
||
257 | $(".button_toggle_par").click(function (evt) {coverage.toggle_lines(evt.target, "par");}); |
||
258 | |||
259 | coverage.assign_shortkeys(); |
||
260 | coverage.wire_up_help_panel(); |
||
261 | |||
262 | coverage.init_scroll_markers(); |
||
263 | |||
264 | // Rebuild scroll markers when the window height changes. |
||
265 | $(window).resize(coverage.build_scroll_markers); |
||
266 | }; |
||
267 | |||
268 | coverage.toggle_lines = function (btn, cls) { |
||
269 | btn = $(btn); |
||
270 | var show = "show_"+cls; |
||
271 | if (btn.hasClass(show)) { |
||
272 | $("#source ." + cls).removeClass(show); |
||
273 | btn.removeClass(show); |
||
274 | } |
||
275 | else { |
||
276 | $("#source ." + cls).addClass(show); |
||
277 | btn.addClass(show); |
||
278 | } |
||
279 | coverage.build_scroll_markers(); |
||
280 | }; |
||
281 | |||
282 | // Return the nth line div. |
||
283 | coverage.line_elt = function (n) { |
||
284 | return $("#t" + n); |
||
285 | }; |
||
286 | |||
287 | // Return the nth line number div. |
||
288 | coverage.num_elt = function (n) { |
||
289 | return $("#n" + n); |
||
290 | }; |
||
291 | |||
292 | // Set the selection. b and e are line numbers. |
||
293 | coverage.set_sel = function (b, e) { |
||
294 | // The first line selected. |
||
295 | coverage.sel_begin = b; |
||
296 | // The next line not selected. |
||
297 | coverage.sel_end = (e === undefined) ? b+1 : e; |
||
298 | }; |
||
299 | |||
300 | coverage.to_top = function () { |
||
301 | coverage.set_sel(0, 1); |
||
302 | coverage.scroll_window(0); |
||
303 | }; |
||
304 | |||
305 | coverage.to_first_chunk = function () { |
||
306 | coverage.set_sel(0, 1); |
||
307 | coverage.to_next_chunk(); |
||
308 | }; |
||
309 | |||
310 | // Return a string indicating what kind of chunk this line belongs to, |
||
311 | // or null if not a chunk. |
||
312 | coverage.chunk_indicator = function (line_elt) { |
||
313 | var klass = line_elt.attr('class'); |
||
314 | if (klass) { |
||
315 | var m = klass.match(/\bshow_\w+\b/); |
||
316 | if (m) { |
||
317 | return m[0]; |
||
318 | } |
||
319 | } |
||
320 | return null; |
||
321 | }; |
||
322 | |||
323 | coverage.to_next_chunk = function () { |
||
324 | var c = coverage; |
||
325 | |||
326 | // Find the start of the next colored chunk. |
||
327 | var probe = c.sel_end; |
||
328 | var chunk_indicator, probe_line; |
||
329 | while (true) { |
||
330 | probe_line = c.line_elt(probe); |
||
331 | if (probe_line.length === 0) { |
||
332 | return; |
||
333 | } |
||
334 | chunk_indicator = c.chunk_indicator(probe_line); |
||
335 | if (chunk_indicator) { |
||
336 | break; |
||
337 | } |
||
338 | probe++; |
||
339 | } |
||
340 | |||
341 | // There's a next chunk, `probe` points to it. |
||
342 | var begin = probe; |
||
343 | |||
344 | // Find the end of this chunk. |
||
345 | var next_indicator = chunk_indicator; |
||
0 ignored issues
–
show
|
|||
346 | while (next_indicator === chunk_indicator) { |
||
347 | probe++; |
||
348 | probe_line = c.line_elt(probe); |
||
349 | next_indicator = c.chunk_indicator(probe_line); |
||
350 | } |
||
351 | c.set_sel(begin, probe); |
||
352 | c.show_selection(); |
||
353 | }; |
||
354 | |||
355 | coverage.to_prev_chunk = function () { |
||
356 | var c = coverage; |
||
357 | |||
358 | // Find the end of the prev colored chunk. |
||
359 | var probe = c.sel_begin-1; |
||
360 | var probe_line = c.line_elt(probe); |
||
361 | if (probe_line.length === 0) { |
||
362 | return; |
||
363 | } |
||
364 | var chunk_indicator = c.chunk_indicator(probe_line); |
||
365 | while (probe > 0 && !chunk_indicator) { |
||
366 | probe--; |
||
367 | probe_line = c.line_elt(probe); |
||
368 | if (probe_line.length === 0) { |
||
369 | return; |
||
370 | } |
||
371 | chunk_indicator = c.chunk_indicator(probe_line); |
||
372 | } |
||
373 | |||
374 | // There's a prev chunk, `probe` points to its last line. |
||
375 | var end = probe+1; |
||
376 | |||
377 | // Find the beginning of this chunk. |
||
378 | var prev_indicator = chunk_indicator; |
||
379 | while (prev_indicator === chunk_indicator) { |
||
380 | probe--; |
||
381 | probe_line = c.line_elt(probe); |
||
382 | prev_indicator = c.chunk_indicator(probe_line); |
||
383 | } |
||
384 | c.set_sel(probe+1, end); |
||
385 | c.show_selection(); |
||
386 | }; |
||
387 | |||
388 | // Return the line number of the line nearest pixel position pos |
||
389 | coverage.line_at_pos = function (pos) { |
||
390 | var l1 = coverage.line_elt(1), |
||
391 | l2 = coverage.line_elt(2), |
||
392 | result; |
||
393 | if (l1.length && l2.length) { |
||
394 | var l1_top = l1.offset().top, |
||
395 | line_height = l2.offset().top - l1_top, |
||
396 | nlines = (pos - l1_top) / line_height; |
||
397 | if (nlines < 1) { |
||
398 | result = 1; |
||
399 | } |
||
400 | else { |
||
401 | result = Math.ceil(nlines); |
||
402 | } |
||
403 | } |
||
404 | else { |
||
405 | result = 1; |
||
406 | } |
||
407 | return result; |
||
408 | }; |
||
409 | |||
410 | // Returns 0, 1, or 2: how many of the two ends of the selection are on |
||
411 | // the screen right now? |
||
412 | coverage.selection_ends_on_screen = function () { |
||
413 | if (coverage.sel_begin === 0) { |
||
414 | return 0; |
||
415 | } |
||
416 | |||
417 | var top = coverage.line_elt(coverage.sel_begin); |
||
418 | var next = coverage.line_elt(coverage.sel_end-1); |
||
419 | |||
420 | return ( |
||
421 | (top.isOnScreen() ? 1 : 0) + |
||
422 | (next.isOnScreen() ? 1 : 0) |
||
423 | ); |
||
424 | }; |
||
425 | |||
426 | coverage.to_next_chunk_nicely = function () { |
||
427 | coverage.finish_scrolling(); |
||
428 | if (coverage.selection_ends_on_screen() === 0) { |
||
429 | // The selection is entirely off the screen: select the top line on |
||
430 | // the screen. |
||
431 | var win = $(window); |
||
432 | coverage.select_line_or_chunk(coverage.line_at_pos(win.scrollTop())); |
||
433 | } |
||
434 | coverage.to_next_chunk(); |
||
435 | }; |
||
436 | |||
437 | coverage.to_prev_chunk_nicely = function () { |
||
438 | coverage.finish_scrolling(); |
||
439 | if (coverage.selection_ends_on_screen() === 0) { |
||
440 | var win = $(window); |
||
441 | coverage.select_line_or_chunk(coverage.line_at_pos(win.scrollTop() + win.height())); |
||
442 | } |
||
443 | coverage.to_prev_chunk(); |
||
444 | }; |
||
445 | |||
446 | // Select line number lineno, or if it is in a colored chunk, select the |
||
447 | // entire chunk |
||
448 | coverage.select_line_or_chunk = function (lineno) { |
||
449 | var c = coverage; |
||
450 | var probe_line = c.line_elt(lineno); |
||
451 | if (probe_line.length === 0) { |
||
452 | return; |
||
453 | } |
||
454 | var the_indicator = c.chunk_indicator(probe_line); |
||
455 | if (the_indicator) { |
||
456 | // The line is in a highlighted chunk. |
||
457 | // Search backward for the first line. |
||
458 | var probe = lineno; |
||
459 | var indicator = the_indicator; |
||
460 | while (probe > 0 && indicator === the_indicator) { |
||
461 | probe--; |
||
462 | probe_line = c.line_elt(probe); |
||
463 | if (probe_line.length === 0) { |
||
464 | break; |
||
465 | } |
||
466 | indicator = c.chunk_indicator(probe_line); |
||
467 | } |
||
468 | var begin = probe + 1; |
||
469 | |||
470 | // Search forward for the last line. |
||
471 | probe = lineno; |
||
472 | indicator = the_indicator; |
||
473 | while (indicator === the_indicator) { |
||
474 | probe++; |
||
475 | probe_line = c.line_elt(probe); |
||
476 | indicator = c.chunk_indicator(probe_line); |
||
477 | } |
||
478 | |||
479 | coverage.set_sel(begin, probe); |
||
480 | } |
||
481 | else { |
||
482 | coverage.set_sel(lineno); |
||
483 | } |
||
484 | }; |
||
485 | |||
486 | coverage.show_selection = function () { |
||
487 | var c = coverage; |
||
488 | |||
489 | // Highlight the lines in the chunk |
||
490 | $(".linenos .highlight").removeClass("highlight"); |
||
491 | for (var probe = c.sel_begin; probe > 0 && probe < c.sel_end; probe++) { |
||
492 | c.num_elt(probe).addClass("highlight"); |
||
493 | } |
||
494 | |||
495 | c.scroll_to_selection(); |
||
496 | }; |
||
497 | |||
498 | coverage.scroll_to_selection = function () { |
||
499 | // Scroll the page if the chunk isn't fully visible. |
||
500 | if (coverage.selection_ends_on_screen() < 2) { |
||
501 | // Need to move the page. The html,body trick makes it scroll in all |
||
502 | // browsers, got it from http://stackoverflow.com/questions/3042651 |
||
503 | var top = coverage.line_elt(coverage.sel_begin); |
||
504 | var top_pos = parseInt(top.offset().top, 10); |
||
505 | coverage.scroll_window(top_pos - 30); |
||
506 | } |
||
507 | }; |
||
508 | |||
509 | coverage.scroll_window = function (to_pos) { |
||
510 | $("html,body").animate({scrollTop: to_pos}, 200); |
||
511 | }; |
||
512 | |||
513 | coverage.finish_scrolling = function () { |
||
514 | $("html,body").stop(true, true); |
||
515 | }; |
||
516 | |||
517 | coverage.init_scroll_markers = function () { |
||
518 | var c = coverage; |
||
519 | // Init some variables |
||
520 | c.lines_len = $('#source p').length; |
||
521 | c.body_h = $('body').height(); |
||
522 | c.header_h = $('div#header').height(); |
||
523 | |||
524 | // Build html |
||
525 | c.build_scroll_markers(); |
||
526 | }; |
||
527 | |||
528 | coverage.build_scroll_markers = function () { |
||
529 | var c = coverage, |
||
530 | min_line_height = 3, |
||
531 | max_line_height = 10, |
||
532 | visible_window_h = $(window).height(); |
||
533 | |||
534 | c.lines_to_mark = $('#source').find('p.show_run, p.show_mis, p.show_exc, p.show_exc, p.show_par'); |
||
535 | $('#scroll_marker').remove(); |
||
536 | // Don't build markers if the window has no scroll bar. |
||
537 | if (c.body_h <= visible_window_h) { |
||
538 | return; |
||
539 | } |
||
540 | |||
541 | $("body").append("<div id='scroll_marker'> </div>"); |
||
542 | var scroll_marker = $('#scroll_marker'), |
||
543 | marker_scale = scroll_marker.height() / c.body_h, |
||
544 | line_height = scroll_marker.height() / c.lines_len; |
||
545 | |||
546 | // Line height must be between the extremes. |
||
547 | if (line_height > min_line_height) { |
||
548 | if (line_height > max_line_height) { |
||
549 | line_height = max_line_height; |
||
550 | } |
||
551 | } |
||
552 | else { |
||
553 | line_height = min_line_height; |
||
554 | } |
||
555 | |||
556 | var previous_line = -99, |
||
557 | last_mark, |
||
558 | last_top, |
||
559 | offsets = {}; |
||
560 | |||
561 | // Calculate line offsets outside loop to prevent relayouts |
||
562 | c.lines_to_mark.each(function() { |
||
563 | offsets[this.id] = $(this).offset().top; |
||
564 | }); |
||
565 | c.lines_to_mark.each(function () { |
||
566 | var id_name = $(this).attr('id'), |
||
567 | line_top = Math.round(offsets[id_name] * marker_scale), |
||
568 | line_number = parseInt(id_name.substring(1, id_name.length)); |
||
569 | |||
570 | if (line_number === previous_line + 1) { |
||
571 | // If this solid missed block just make previous mark higher. |
||
572 | last_mark.css({ |
||
573 | 'height': line_top + line_height - last_top |
||
574 | }); |
||
575 | } |
||
576 | else { |
||
577 | // Add colored line in scroll_marker block. |
||
578 | scroll_marker.append('<div id="m' + line_number + '" class="marker"></div>'); |
||
579 | last_mark = $('#m' + line_number); |
||
580 | last_mark.css({ |
||
581 | 'height': line_height, |
||
582 | 'top': line_top |
||
583 | }); |
||
584 | last_top = line_top; |
||
585 | } |
||
586 | |||
587 | previous_line = line_number; |
||
588 | }); |
||
589 | }; |
||
590 |