@@ -116,8 +116,8 @@ coverage.pyfile_ready = function ($) {
116
116
}
117
117
118
118
$ ( document )
119
- . bind ( 'keydown' , 'j' , coverage . to_next_chunk )
120
- . bind ( 'keydown' , 'k' , coverage . to_prev_chunk )
119
+ . bind ( 'keydown' , 'j' , coverage . to_next_chunk_nicely )
120
+ . bind ( 'keydown' , 'k' , coverage . to_prev_chunk_nicely )
121
121
. bind ( 'keydown' , '0' , coverage . to_top )
122
122
. bind ( 'keydown' , '1' , coverage . to_first_chunk )
123
123
;
@@ -139,12 +139,12 @@ coverage.toggle_lines = function (btn, cls) {
139
139
}
140
140
} ;
141
141
142
- // Return the nth line.
142
+ // Return the nth line div .
143
143
coverage . line_elt = function ( n ) {
144
144
return $ ( "#t" + n ) ;
145
145
} ;
146
146
147
- // Return the nth line number.
147
+ // Return the nth line number div .
148
148
coverage . num_elt = function ( n ) {
149
149
return $ ( "#n" + n ) ;
150
150
} ;
@@ -154,6 +154,7 @@ coverage.code_container = function () {
154
154
return $ ( ".linenos" ) ;
155
155
} ;
156
156
157
+ // Set the selection. b and e are line numbers.
157
158
coverage . set_sel = function ( b , e ) {
158
159
// The first line selected.
159
160
coverage . sel_begin = b ;
@@ -163,7 +164,7 @@ coverage.set_sel = function (b, e) {
163
164
164
165
coverage . to_top = function ( ) {
165
166
coverage . set_sel ( 0 , 1 ) ;
166
- $ ( "html,body" ) . animate ( { scrollTop : 0 } , 200 ) ;
167
+ coverage . scroll_window ( 0 ) ;
167
168
} ;
168
169
169
170
coverage . to_first_chunk = function ( ) {
@@ -240,6 +241,104 @@ coverage.to_prev_chunk = function () {
240
241
c . show_selection ( ) ;
241
242
} ;
242
243
244
+ // Return the line number of the line nearest pixel position pos
245
+ coverage . 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?
268
+ coverage . 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
+
282
+ coverage . 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
+
293
+ coverage . 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
304
+ coverage . 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
+
243
342
coverage . show_selection = function ( ) {
244
343
var c = coverage ;
245
344
@@ -254,13 +353,20 @@ coverage.show_selection = function () {
254
353
255
354
coverage . scroll_to_selection = function ( ) {
256
355
// Scroll the page if the chunk isn't fully visible.
257
- var top = coverage . line_elt ( coverage . sel_begin ) ;
258
- var next = coverage . line_elt ( coverage . sel_end ) ;
259
-
260
- if ( ! top . isOnScreen ( ) || ! next . isOnScreen ( ) ) {
356
+ if ( coverage . selection_ends_on_screen ( ) < 2 ) {
261
357
// Need to move the page. The html,body trick makes it scroll in all
262
358
// browsers, got it from http://stackoverflow.com/questions/3042651
359
+ var top = coverage . line_elt ( coverage . sel_begin ) ;
263
360
var top_pos = parseInt ( top . offset ( ) . top , 10 ) ;
264
- $ ( "html,body" ) . animate ( { scrollTop : top_pos - 30 } , 300 ) ;
361
+ coverage . scroll_window ( top_pos - 30 ) ;
265
362
}
266
363
} ;
364
+
365
+ coverage . scroll_window = function ( to_pos ) {
366
+ $ ( "html,body" ) . animate ( { scrollTop : to_pos } , 200 ) ;
367
+ } ;
368
+
369
+ coverage . finish_scrolling = function ( ) {
370
+ $ ( "html,body" ) . stop ( true , true ) ;
371
+ } ;
372
+
0 commit comments