Fossil SCM

Removed some dead code. Internal cleanups and reorg in prep for upcoming changes.

stephan 2021-09-10 21:30 diff-js-refactoring
Commit bc5dc16e55134b035d23f3df60026d8e40537cc0749302670e930662c02c78bb
1 file changed +95 -92
+95 -92
--- src/fossil.diff.js
+++ src/fossil.diff.js
@@ -204,30 +204,27 @@
204204
}
205205
});
206206
};
207207
208208
/**
209
- Installs chunk-loading controls into TR element tr. isSplit is true
210
- if the parent table is a split diff, else false.
209
+ Installs chunk-loading controls into TR.diffskip element tr.
210
+ Each instance corresponds to a single TR.diffskip element.
211211
212
- The goal is to base these controls closely on github's, a good example
213
- of which, for use as a model, is:
212
+ The goal is to base these controls roughly on github's, a good
213
+ example of which, for use as a model, is:
214214
215215
https://github.com/msteveb/autosetup/commit/235925e914a52a542
216
-
217
- Each instance corresponds to a single TR.diffskip element.
218216
*/
219
- Diff.ChunkLoadControls = function(isSplit, tr){
220
- this.isSplit = isSplit;
217
+ Diff.ChunkLoadControls = function(tr){
221218
this.e = {/*DOM elements*/
222219
tr: tr,
223220
table: tr.parentElement/*TBODY*/.parentElement
224221
};
222
+ this.isSplit = this.e.table.classList.contains('splitdiff')/*else udiff*/;
225223
this.fileHash = this.e.table.dataset.lefthash;
226224
tr.$chunker = this /* keep GC from reaping this */;
227225
this.pos = {
228
- //hash: F.hashDigits(this.fileHash),
229226
/* These line numbers correspond to the LHS file. Because the
230227
contents are common to both sides, we have the same number
231228
for the RHS, but need to extract those line numbers from the
232229
neighboring TR blocks */
233230
startLhs: +tr.dataset.startln,
@@ -234,11 +231,11 @@
234231
endLhs: +tr.dataset.endln
235232
};
236233
D.clearElement(tr);
237234
this.e.td = D.addClass(
238235
/* Holder for our UI controls */
239
- D.attr(D.td(tr), 'colspan', isSplit ? 5 : 4),
236
+ D.attr(D.td(tr), 'colspan', this.isSplit ? 5 : 4),
240237
'chunkctrl'
241238
);
242239
this.e.btnWrapper = D.div();
243240
D.append(this.e.td, this.e.btnWrapper);
244241
/**
@@ -252,18 +249,18 @@
252249
253250
- A single button to load the final chunk incrementally
254251
*/
255252
if(tr.nextElementSibling){
256253
this.pos.next = {
257
- startLhs: extractLineNo(true, true, tr.nextElementSibling, isSplit),
258
- startRhs: extractLineNo(false, true, tr.nextElementSibling, isSplit)
254
+ startLhs: extractLineNo(true, true, tr.nextElementSibling, this.isSplit),
255
+ startRhs: extractLineNo(false, true, tr.nextElementSibling, this.isSplit)
259256
};
260257
}
261258
if(tr.previousElementSibling){
262259
this.pos.prev = {
263
- endLhs: extractLineNo(true, false, tr.previousElementSibling, isSplit),
264
- endRhs: extractLineNo(false, false, tr.previousElementSibling, isSplit)
260
+ endLhs: extractLineNo(true, false, tr.previousElementSibling, this.isSplit),
261
+ endRhs: extractLineNo(false, false, tr.previousElementSibling, this.isSplit)
265262
};
266263
}
267264
let btnUp = false, btnDown = false;
268265
/**
269266
this.pos.next refers to the line numbers in the next TR's chunk.
@@ -275,39 +272,22 @@
275272
&& ((this.pos.next.startLhs - this.pos.prev.endLhs)
276273
<= Diff.config.chunkLoadLines))){
277274
/* Place a single button to load the whole block, rather
278275
than separate up/down buttons. */
279276
btnDown = false;
280
- btnUp = D.append(
281
- D.addClass(D.span(), 'button', 'up', 'down'),
282
- D.span(/*glyph holder*/)
283
- );
277
+ btnUp = this.createButton(0);
284278
}else{
285279
/* Figure out which chunk-load buttons to add... */
286280
if(this.pos.prev){
287
- btnDown = D.append(
288
- D.addClass(D.span(), 'button', 'down'),
289
- D.span(/*glyph holder*/)
290
- );
281
+ btnDown = this.createButton(1);
291282
}
292283
if(this.pos.next){
293
- btnUp = D.append(
294
- D.addClass(D.span(), 'button', 'up'),
295
- D.span(/*glyph holder*/)
296
- );
297
- }
298
- }
299
- if(btnDown){
300
- D.append(this.e.btnWrapper, btnDown);
301
- btnDown.addEventListener('click', ()=>this.fetchChunk(1),false);
302
- }
303
- if(btnUp){
304
- D.append(this.e.btnWrapper, btnUp);
305
- btnUp.addEventListener(
306
- 'click', ()=>this.fetchChunk(btnUp.classList.contains('down') ? 0 : -1),
307
- false);
308
- }
284
+ btnUp = this.createButton(-1);
285
+ }
286
+ }
287
+ if(btnDown) D.append(this.e.btnWrapper, btnDown);
288
+ if(btnUp) D.append(this.e.btnWrapper, btnUp);
309289
/* For debugging only... */
310290
this.e.posState = D.span();
311291
D.append(this.e.btnWrapper, this.e.posState);
312292
this.updatePosDebug();
313293
};
@@ -317,56 +297,59 @@
317297
/*
318298
glyphUp: '⇡', //'&#uarr;',
319299
glyphDown: '⇣' //'&#darr;'
320300
*/
321301
},
302
+
303
+ /**
304
+ Creates and returns a button element for fetching a chunk in
305
+ the given direction (as documented for fetchChunk()).
306
+ */
307
+ createButton: function(direction){
308
+ let b;
309
+ switch(direction){
310
+ case 1:
311
+ b = D.append(
312
+ D.addClass(D.span(), 'button', 'down'),
313
+ D.span(/*glyph holder*/)
314
+ );
315
+ break;
316
+ case 0:
317
+ b = D.append(
318
+ D.addClass(D.span(), 'button', 'up', 'down'),
319
+ D.span(/*glyph holder*/)
320
+ );
321
+ break;
322
+ case -1:
323
+ b = D.append(
324
+ D.addClass(D.span(), 'button', 'up'),
325
+ D.span(/*glyph holder*/)
326
+ );
327
+ break;
328
+ default:
329
+ throw new Error("Internal API misuse: unexpected direction value "+direction);
330
+ }
331
+ b.addEventListener('click', ()=>this.fetchChunk(direction),false);
332
+ return b;
333
+ },
334
+
322335
updatePosDebug: function(){
323336
if(this.e.posState){
324337
D.append(D.clearElement(this.e.posState), JSON.stringify(this.pos));
325338
}
326339
return this;
327340
},
328
-
341
+
342
+ /* Attempt to clean up resources and remove some circular references to
343
+ that GC can do the right thing. */
329344
destroy: function(){
330345
D.remove(this.e.tr);
331346
delete this.e.tr.$chunker;
332347
delete this.e.tr;
333348
delete this.e;
334349
delete this.pos;
335350
},
336
- /**
337
- Creates a new TR element, including its TD elements (depending
338
- on this.isSplit), but does not fill it with any information nor
339
- inject it into the table (it doesn't know where to do
340
- so). Returns an object containing the TR element and various TD
341
- elements which will likely be needed by the routine which
342
- called this. See this code for details.
343
- */
344
- newTR: function(){
345
- const tr = D.tr(), rc = {
346
- tr,
347
- preLnL: D.pre(),
348
- preLnR: D.pre(),
349
- preSep: D.pre()
350
- };
351
- if(this.isSplit){
352
- D.append(D.addClass( D.td(tr), 'diffln', 'difflnl' ), rc.preLnL);
353
- rc.preTxtL = D.pre();
354
- D.append(D.addClass( D.td(tr), 'difftxt', 'difftxtl' ), rc.preTxtL);
355
- D.append(D.addClass( D.td(tr), 'diffsep' ), rc.preSep);
356
- D.append(D.addClass( D.td(tr), 'diffln', 'difflnr' ), rc.preLnR);
357
- rc.preTxtR = D.pre();
358
- D.append(D.addClass( D.td(tr), 'difftxt', 'difftxtr' ), rc.preTxtR);
359
- }else{
360
- D.append(D.addClass( D.td(tr), 'diffln', 'difflnl' ), rc.preLnL);
361
- D.append(D.addClass( D.td(tr), 'diffln', 'difflnr' ), rc.preLnR);
362
- D.append(D.addClass( D.td(tr), 'diffsep' ), rc.preSep);
363
- rc.preTxtU = D.pre();
364
- D.append(D.addClass( D.td(tr), 'difftxt', 'difftxtu' ), rc.preTxtU);
365
- }
366
- return rc;
367
- },
368351
369352
injectResponse: function(direction/*as for fetchChunk()*/,
370353
urlParam/*from fetchChunk()*/,
371354
lines/*response lines*/){
372355
console.debug("Loading line range ",urlParam.from,"-",urlParam.to);
@@ -464,45 +447,66 @@
464447
console.debug("TODO: handle load of partial next/prev");
465448
this.updatePosDebug();
466449
}
467450
},
468451
469
- fetchChunk: function(direction/*-1=down from prev chunk,
470
- 1=up from next chunk,
471
- 0=full-gap filler for any neighoring
472
- chunk(s)*/){
452
+ /**
453
+ Fetches and inserts a line chunk. direction is:
454
+
455
+ -1 = upwards from next chunk (this.pos.next)
456
+
457
+ 0 = the whole gap between this.pos.prev and this.pos.next, or
458
+ the whole gap before/after the initial/final chunk in the diff.
459
+
460
+ 1 = downwards from the previous chunk (this.pos.prev)
461
+
462
+ Those values are set at the time this object is initialized but
463
+ one instance of this class may have 2 buttons, one each for
464
+ directions -1 and 1.
465
+
466
+ This is an async operation. While it is in transit, any calls
467
+ to this function will have no effect except (possibly) to emit
468
+ a warning. Returns this object.
469
+ */
470
+ fetchChunk: function(direction){
473471
/* Forewarning, this is a bit confusing: when fetching the
474472
previous lines, we're doing so on behalf of the *next* diff
475473
chunk (this.pos.next), and vice versa. */
476474
if(this.$isFetching){
477
- console.debug("Cannot load chunk while a load is pending.");
475
+ F.toast.warning("Cannot load chunk while a load is pending.");
478476
return this;
479477
}
480
- if(direction<0/*prev chunk*/ && !this.pos.next){
481
- console.error("Attempt to fetch previous diff lines but don't have any.");
482
- return this;
483
- }else if(direction>0/*next chunk*/ && !this.pos.prev){
484
- console.error("Attempt to fetch next diff lines but don't have any.");
478
+ if(direction<0 && !this.pos.next
479
+ || direction>0 && !this.pos.prev){
480
+ console.error("Attempt to fetch diff lines but don't have any.");
485481
return this;
486482
}
487483
const fOpt = {
488484
urlParams:{
489485
name: this.fileHash, from: 0, to: 0
490486
},
491
- aftersend: ()=>delete this.$isFetching
487
+ aftersend: ()=>delete this.$isFetching,
488
+ onload: (list)=>this.injectResponse(direction,up,list)
492489
};
493
- const self = this;
494
- if(direction!=0){
495
- console.debug("Skipping partial fetch for now.");
490
+ const up = fOpt.urlParams;
491
+ if(direction===0){
492
+ up.from = this.pos.startLhs;
493
+ up.to = this.pos.endLhs;
494
+ }else if(1===direction){
495
+ /* Expand previous TR downwards. */
496
+ if(!this.pos.prev){
497
+ console.error("Attempt to fetch next diff lines but don't have any.");
498
+ return this;
499
+ }
500
+ console.debug("fetchChunk(",direction,")");
496501
return this;
497502
}else{
498
- fOpt.urlParams.from = this.pos.startLhs;
499
- fOpt.urlParams.to = this.pos.endLhs;
500
- fOpt.onload = function(list){
501
- self.injectResponse(direction,fOpt.urlParams,list);
502
- };
503
+ /* Expand next TR upwards */
504
+ console.debug("fetchChunk(",direction,")");
505
+ return this;
503506
}
507
+
504508
this.$isFetching = true;
505509
Diff.fetchArtifactChunk(fOpt);
506510
return this;
507511
}
508512
};
@@ -512,13 +516,12 @@
512516
/* Potential performance-related TODO: instead of installing all
513517
of these at once, install them as the corresponding TR is
514518
scrolled into view. */
515519
tables.forEach(function(table){
516520
D.addClass(table, 'diffskipped'/*avoid processing these more than once */);
517
- const isSplit = table.classList.contains('splitdiff')/*else udiff*/;
518521
table.querySelectorAll('tr.diffskip[data-startln]').forEach(function(tr){
519
- new Diff.ChunkLoadControls(isSplit, D.addClass(tr, 'jchunk'));
522
+ new Diff.ChunkLoadControls(D.addClass(tr, 'jchunk'));
520523
});
521524
});
522525
return F;
523526
};
524527
Diff.addDiffSkipHandlers();
525528
--- src/fossil.diff.js
+++ src/fossil.diff.js
@@ -204,30 +204,27 @@
204 }
205 });
206 };
207
208 /**
209 Installs chunk-loading controls into TR element tr. isSplit is true
210 if the parent table is a split diff, else false.
211
212 The goal is to base these controls closely on github's, a good example
213 of which, for use as a model, is:
214
215 https://github.com/msteveb/autosetup/commit/235925e914a52a542
216
217 Each instance corresponds to a single TR.diffskip element.
218 */
219 Diff.ChunkLoadControls = function(isSplit, tr){
220 this.isSplit = isSplit;
221 this.e = {/*DOM elements*/
222 tr: tr,
223 table: tr.parentElement/*TBODY*/.parentElement
224 };
 
225 this.fileHash = this.e.table.dataset.lefthash;
226 tr.$chunker = this /* keep GC from reaping this */;
227 this.pos = {
228 //hash: F.hashDigits(this.fileHash),
229 /* These line numbers correspond to the LHS file. Because the
230 contents are common to both sides, we have the same number
231 for the RHS, but need to extract those line numbers from the
232 neighboring TR blocks */
233 startLhs: +tr.dataset.startln,
@@ -234,11 +231,11 @@
234 endLhs: +tr.dataset.endln
235 };
236 D.clearElement(tr);
237 this.e.td = D.addClass(
238 /* Holder for our UI controls */
239 D.attr(D.td(tr), 'colspan', isSplit ? 5 : 4),
240 'chunkctrl'
241 );
242 this.e.btnWrapper = D.div();
243 D.append(this.e.td, this.e.btnWrapper);
244 /**
@@ -252,18 +249,18 @@
252
253 - A single button to load the final chunk incrementally
254 */
255 if(tr.nextElementSibling){
256 this.pos.next = {
257 startLhs: extractLineNo(true, true, tr.nextElementSibling, isSplit),
258 startRhs: extractLineNo(false, true, tr.nextElementSibling, isSplit)
259 };
260 }
261 if(tr.previousElementSibling){
262 this.pos.prev = {
263 endLhs: extractLineNo(true, false, tr.previousElementSibling, isSplit),
264 endRhs: extractLineNo(false, false, tr.previousElementSibling, isSplit)
265 };
266 }
267 let btnUp = false, btnDown = false;
268 /**
269 this.pos.next refers to the line numbers in the next TR's chunk.
@@ -275,39 +272,22 @@
275 && ((this.pos.next.startLhs - this.pos.prev.endLhs)
276 <= Diff.config.chunkLoadLines))){
277 /* Place a single button to load the whole block, rather
278 than separate up/down buttons. */
279 btnDown = false;
280 btnUp = D.append(
281 D.addClass(D.span(), 'button', 'up', 'down'),
282 D.span(/*glyph holder*/)
283 );
284 }else{
285 /* Figure out which chunk-load buttons to add... */
286 if(this.pos.prev){
287 btnDown = D.append(
288 D.addClass(D.span(), 'button', 'down'),
289 D.span(/*glyph holder*/)
290 );
291 }
292 if(this.pos.next){
293 btnUp = D.append(
294 D.addClass(D.span(), 'button', 'up'),
295 D.span(/*glyph holder*/)
296 );
297 }
298 }
299 if(btnDown){
300 D.append(this.e.btnWrapper, btnDown);
301 btnDown.addEventListener('click', ()=>this.fetchChunk(1),false);
302 }
303 if(btnUp){
304 D.append(this.e.btnWrapper, btnUp);
305 btnUp.addEventListener(
306 'click', ()=>this.fetchChunk(btnUp.classList.contains('down') ? 0 : -1),
307 false);
308 }
309 /* For debugging only... */
310 this.e.posState = D.span();
311 D.append(this.e.btnWrapper, this.e.posState);
312 this.updatePosDebug();
313 };
@@ -317,56 +297,59 @@
317 /*
318 glyphUp: '⇡', //'&#uarr;',
319 glyphDown: '⇣' //'&#darr;'
320 */
321 },
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
322 updatePosDebug: function(){
323 if(this.e.posState){
324 D.append(D.clearElement(this.e.posState), JSON.stringify(this.pos));
325 }
326 return this;
327 },
328
 
 
329 destroy: function(){
330 D.remove(this.e.tr);
331 delete this.e.tr.$chunker;
332 delete this.e.tr;
333 delete this.e;
334 delete this.pos;
335 },
336 /**
337 Creates a new TR element, including its TD elements (depending
338 on this.isSplit), but does not fill it with any information nor
339 inject it into the table (it doesn't know where to do
340 so). Returns an object containing the TR element and various TD
341 elements which will likely be needed by the routine which
342 called this. See this code for details.
343 */
344 newTR: function(){
345 const tr = D.tr(), rc = {
346 tr,
347 preLnL: D.pre(),
348 preLnR: D.pre(),
349 preSep: D.pre()
350 };
351 if(this.isSplit){
352 D.append(D.addClass( D.td(tr), 'diffln', 'difflnl' ), rc.preLnL);
353 rc.preTxtL = D.pre();
354 D.append(D.addClass( D.td(tr), 'difftxt', 'difftxtl' ), rc.preTxtL);
355 D.append(D.addClass( D.td(tr), 'diffsep' ), rc.preSep);
356 D.append(D.addClass( D.td(tr), 'diffln', 'difflnr' ), rc.preLnR);
357 rc.preTxtR = D.pre();
358 D.append(D.addClass( D.td(tr), 'difftxt', 'difftxtr' ), rc.preTxtR);
359 }else{
360 D.append(D.addClass( D.td(tr), 'diffln', 'difflnl' ), rc.preLnL);
361 D.append(D.addClass( D.td(tr), 'diffln', 'difflnr' ), rc.preLnR);
362 D.append(D.addClass( D.td(tr), 'diffsep' ), rc.preSep);
363 rc.preTxtU = D.pre();
364 D.append(D.addClass( D.td(tr), 'difftxt', 'difftxtu' ), rc.preTxtU);
365 }
366 return rc;
367 },
368
369 injectResponse: function(direction/*as for fetchChunk()*/,
370 urlParam/*from fetchChunk()*/,
371 lines/*response lines*/){
372 console.debug("Loading line range ",urlParam.from,"-",urlParam.to);
@@ -464,45 +447,66 @@
464 console.debug("TODO: handle load of partial next/prev");
465 this.updatePosDebug();
466 }
467 },
468
469 fetchChunk: function(direction/*-1=down from prev chunk,
470 1=up from next chunk,
471 0=full-gap filler for any neighoring
472 chunk(s)*/){
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
473 /* Forewarning, this is a bit confusing: when fetching the
474 previous lines, we're doing so on behalf of the *next* diff
475 chunk (this.pos.next), and vice versa. */
476 if(this.$isFetching){
477 console.debug("Cannot load chunk while a load is pending.");
478 return this;
479 }
480 if(direction<0/*prev chunk*/ && !this.pos.next){
481 console.error("Attempt to fetch previous diff lines but don't have any.");
482 return this;
483 }else if(direction>0/*next chunk*/ && !this.pos.prev){
484 console.error("Attempt to fetch next diff lines but don't have any.");
485 return this;
486 }
487 const fOpt = {
488 urlParams:{
489 name: this.fileHash, from: 0, to: 0
490 },
491 aftersend: ()=>delete this.$isFetching
 
492 };
493 const self = this;
494 if(direction!=0){
495 console.debug("Skipping partial fetch for now.");
 
 
 
 
 
 
 
 
496 return this;
497 }else{
498 fOpt.urlParams.from = this.pos.startLhs;
499 fOpt.urlParams.to = this.pos.endLhs;
500 fOpt.onload = function(list){
501 self.injectResponse(direction,fOpt.urlParams,list);
502 };
503 }
 
504 this.$isFetching = true;
505 Diff.fetchArtifactChunk(fOpt);
506 return this;
507 }
508 };
@@ -512,13 +516,12 @@
512 /* Potential performance-related TODO: instead of installing all
513 of these at once, install them as the corresponding TR is
514 scrolled into view. */
515 tables.forEach(function(table){
516 D.addClass(table, 'diffskipped'/*avoid processing these more than once */);
517 const isSplit = table.classList.contains('splitdiff')/*else udiff*/;
518 table.querySelectorAll('tr.diffskip[data-startln]').forEach(function(tr){
519 new Diff.ChunkLoadControls(isSplit, D.addClass(tr, 'jchunk'));
520 });
521 });
522 return F;
523 };
524 Diff.addDiffSkipHandlers();
525
--- src/fossil.diff.js
+++ src/fossil.diff.js
@@ -204,30 +204,27 @@
204 }
205 });
206 };
207
208 /**
209 Installs chunk-loading controls into TR.diffskip element tr.
210 Each instance corresponds to a single TR.diffskip element.
211
212 The goal is to base these controls roughly on github's, a good
213 example of which, for use as a model, is:
214
215 https://github.com/msteveb/autosetup/commit/235925e914a52a542
 
 
216 */
217 Diff.ChunkLoadControls = function(tr){
 
218 this.e = {/*DOM elements*/
219 tr: tr,
220 table: tr.parentElement/*TBODY*/.parentElement
221 };
222 this.isSplit = this.e.table.classList.contains('splitdiff')/*else udiff*/;
223 this.fileHash = this.e.table.dataset.lefthash;
224 tr.$chunker = this /* keep GC from reaping this */;
225 this.pos = {
 
226 /* These line numbers correspond to the LHS file. Because the
227 contents are common to both sides, we have the same number
228 for the RHS, but need to extract those line numbers from the
229 neighboring TR blocks */
230 startLhs: +tr.dataset.startln,
@@ -234,11 +231,11 @@
231 endLhs: +tr.dataset.endln
232 };
233 D.clearElement(tr);
234 this.e.td = D.addClass(
235 /* Holder for our UI controls */
236 D.attr(D.td(tr), 'colspan', this.isSplit ? 5 : 4),
237 'chunkctrl'
238 );
239 this.e.btnWrapper = D.div();
240 D.append(this.e.td, this.e.btnWrapper);
241 /**
@@ -252,18 +249,18 @@
249
250 - A single button to load the final chunk incrementally
251 */
252 if(tr.nextElementSibling){
253 this.pos.next = {
254 startLhs: extractLineNo(true, true, tr.nextElementSibling, this.isSplit),
255 startRhs: extractLineNo(false, true, tr.nextElementSibling, this.isSplit)
256 };
257 }
258 if(tr.previousElementSibling){
259 this.pos.prev = {
260 endLhs: extractLineNo(true, false, tr.previousElementSibling, this.isSplit),
261 endRhs: extractLineNo(false, false, tr.previousElementSibling, this.isSplit)
262 };
263 }
264 let btnUp = false, btnDown = false;
265 /**
266 this.pos.next refers to the line numbers in the next TR's chunk.
@@ -275,39 +272,22 @@
272 && ((this.pos.next.startLhs - this.pos.prev.endLhs)
273 <= Diff.config.chunkLoadLines))){
274 /* Place a single button to load the whole block, rather
275 than separate up/down buttons. */
276 btnDown = false;
277 btnUp = this.createButton(0);
 
 
 
278 }else{
279 /* Figure out which chunk-load buttons to add... */
280 if(this.pos.prev){
281 btnDown = this.createButton(1);
 
 
 
282 }
283 if(this.pos.next){
284 btnUp = this.createButton(-1);
285 }
286 }
287 if(btnDown) D.append(this.e.btnWrapper, btnDown);
288 if(btnUp) D.append(this.e.btnWrapper, btnUp);
 
 
 
 
 
 
 
 
 
 
 
289 /* For debugging only... */
290 this.e.posState = D.span();
291 D.append(this.e.btnWrapper, this.e.posState);
292 this.updatePosDebug();
293 };
@@ -317,56 +297,59 @@
297 /*
298 glyphUp: '⇡', //'&#uarr;',
299 glyphDown: '⇣' //'&#darr;'
300 */
301 },
302
303 /**
304 Creates and returns a button element for fetching a chunk in
305 the given direction (as documented for fetchChunk()).
306 */
307 createButton: function(direction){
308 let b;
309 switch(direction){
310 case 1:
311 b = D.append(
312 D.addClass(D.span(), 'button', 'down'),
313 D.span(/*glyph holder*/)
314 );
315 break;
316 case 0:
317 b = D.append(
318 D.addClass(D.span(), 'button', 'up', 'down'),
319 D.span(/*glyph holder*/)
320 );
321 break;
322 case -1:
323 b = D.append(
324 D.addClass(D.span(), 'button', 'up'),
325 D.span(/*glyph holder*/)
326 );
327 break;
328 default:
329 throw new Error("Internal API misuse: unexpected direction value "+direction);
330 }
331 b.addEventListener('click', ()=>this.fetchChunk(direction),false);
332 return b;
333 },
334
335 updatePosDebug: function(){
336 if(this.e.posState){
337 D.append(D.clearElement(this.e.posState), JSON.stringify(this.pos));
338 }
339 return this;
340 },
341
342 /* Attempt to clean up resources and remove some circular references to
343 that GC can do the right thing. */
344 destroy: function(){
345 D.remove(this.e.tr);
346 delete this.e.tr.$chunker;
347 delete this.e.tr;
348 delete this.e;
349 delete this.pos;
350 },
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
351
352 injectResponse: function(direction/*as for fetchChunk()*/,
353 urlParam/*from fetchChunk()*/,
354 lines/*response lines*/){
355 console.debug("Loading line range ",urlParam.from,"-",urlParam.to);
@@ -464,45 +447,66 @@
447 console.debug("TODO: handle load of partial next/prev");
448 this.updatePosDebug();
449 }
450 },
451
452 /**
453 Fetches and inserts a line chunk. direction is:
454
455 -1 = upwards from next chunk (this.pos.next)
456
457 0 = the whole gap between this.pos.prev and this.pos.next, or
458 the whole gap before/after the initial/final chunk in the diff.
459
460 1 = downwards from the previous chunk (this.pos.prev)
461
462 Those values are set at the time this object is initialized but
463 one instance of this class may have 2 buttons, one each for
464 directions -1 and 1.
465
466 This is an async operation. While it is in transit, any calls
467 to this function will have no effect except (possibly) to emit
468 a warning. Returns this object.
469 */
470 fetchChunk: function(direction){
471 /* Forewarning, this is a bit confusing: when fetching the
472 previous lines, we're doing so on behalf of the *next* diff
473 chunk (this.pos.next), and vice versa. */
474 if(this.$isFetching){
475 F.toast.warning("Cannot load chunk while a load is pending.");
476 return this;
477 }
478 if(direction<0 && !this.pos.next
479 || direction>0 && !this.pos.prev){
480 console.error("Attempt to fetch diff lines but don't have any.");
 
 
481 return this;
482 }
483 const fOpt = {
484 urlParams:{
485 name: this.fileHash, from: 0, to: 0
486 },
487 aftersend: ()=>delete this.$isFetching,
488 onload: (list)=>this.injectResponse(direction,up,list)
489 };
490 const up = fOpt.urlParams;
491 if(direction===0){
492 up.from = this.pos.startLhs;
493 up.to = this.pos.endLhs;
494 }else if(1===direction){
495 /* Expand previous TR downwards. */
496 if(!this.pos.prev){
497 console.error("Attempt to fetch next diff lines but don't have any.");
498 return this;
499 }
500 console.debug("fetchChunk(",direction,")");
501 return this;
502 }else{
503 /* Expand next TR upwards */
504 console.debug("fetchChunk(",direction,")");
505 return this;
 
 
506 }
507
508 this.$isFetching = true;
509 Diff.fetchArtifactChunk(fOpt);
510 return this;
511 }
512 };
@@ -512,13 +516,12 @@
516 /* Potential performance-related TODO: instead of installing all
517 of these at once, install them as the corresponding TR is
518 scrolled into view. */
519 tables.forEach(function(table){
520 D.addClass(table, 'diffskipped'/*avoid processing these more than once */);
 
521 table.querySelectorAll('tr.diffskip[data-startln]').forEach(function(tr){
522 new Diff.ChunkLoadControls(D.addClass(tr, 'jchunk'));
523 });
524 });
525 return F;
526 };
527 Diff.addDiffSkipHandlers();
528

Keyboard Shortcuts

Open search /
Next entry (timeline) j
Previous entry (timeline) k
Open focused entry Enter
Show this help ?
Toggle theme Top nav button