Fossil SCM
Refactored tr.diffsplit to hold enough information to allow partial chunk loads in either direction and to know where the next/previous chunks (if any) start/end. Actual loading is currently disabled, pending addition of controls which make use of this new state.
Commit
cedcd3585b4cd8bd9997bca5de7e1f94541d7f5686f95715b0251f8a06a55376
Parent
566b7f116529365…
2 files changed
+14
+103
-32
+14
| --- src/default.css | ||
| +++ src/default.css | ||
| @@ -549,10 +549,24 @@ | ||
| 549 | 549 | /* jchunk gets added from JS to diffskip rows when they are |
| 550 | 550 | plugged into the /jchunk route and removed after that data |
| 551 | 551 | is fetched. */ |
| 552 | 552 | background-color: rgba(127,127,127,0.5); |
| 553 | 553 | cursor: pointer; |
| 554 | +} | |
| 555 | +tr.diffskip > td.chunkctrl { | |
| 556 | + text-align: left; | |
| 557 | + font-family: monospace; | |
| 558 | + /* Border is only for visibility during development. Remove it when done. */ | |
| 559 | + border-width: 1px; | |
| 560 | + border-style: dotted; | |
| 561 | +} | |
| 562 | +tr.diffskip > td.chunkctrl > .button { | |
| 563 | + min-width: 1.5em; | |
| 564 | + min-height: 1.5em; | |
| 565 | + max-width: 1.5em; | |
| 566 | + max-height: 1.5em; | |
| 567 | + text-align: center; | |
| 554 | 568 | } |
| 555 | 569 | td.diffln { |
| 556 | 570 | width: 1px; |
| 557 | 571 | text-align: right; |
| 558 | 572 | padding: 0 1em 0 0; |
| 559 | 573 |
| --- src/default.css | |
| +++ src/default.css | |
| @@ -549,10 +549,24 @@ | |
| 549 | /* jchunk gets added from JS to diffskip rows when they are |
| 550 | plugged into the /jchunk route and removed after that data |
| 551 | is fetched. */ |
| 552 | background-color: rgba(127,127,127,0.5); |
| 553 | cursor: pointer; |
| 554 | } |
| 555 | td.diffln { |
| 556 | width: 1px; |
| 557 | text-align: right; |
| 558 | padding: 0 1em 0 0; |
| 559 |
| --- src/default.css | |
| +++ src/default.css | |
| @@ -549,10 +549,24 @@ | |
| 549 | /* jchunk gets added from JS to diffskip rows when they are |
| 550 | plugged into the /jchunk route and removed after that data |
| 551 | is fetched. */ |
| 552 | background-color: rgba(127,127,127,0.5); |
| 553 | cursor: pointer; |
| 554 | } |
| 555 | tr.diffskip > td.chunkctrl { |
| 556 | text-align: left; |
| 557 | font-family: monospace; |
| 558 | /* Border is only for visibility during development. Remove it when done. */ |
| 559 | border-width: 1px; |
| 560 | border-style: dotted; |
| 561 | } |
| 562 | tr.diffskip > td.chunkctrl > .button { |
| 563 | min-width: 1.5em; |
| 564 | min-height: 1.5em; |
| 565 | max-width: 1.5em; |
| 566 | max-height: 1.5em; |
| 567 | text-align: center; |
| 568 | } |
| 569 | td.diffln { |
| 570 | width: 1px; |
| 571 | text-align: right; |
| 572 | padding: 0 1em 0 0; |
| 573 |
+103
-32
| --- src/fossil.diff.js | ||
| +++ src/fossil.diff.js | ||
| @@ -80,10 +80,34 @@ | ||
| 80 | 80 | if(!fetchOpt.onerror) fetchOpt.onerror = Diff.config.chunkFetch.onerror; |
| 81 | 81 | fetchOpt.responseType = 'json'; |
| 82 | 82 | return F.fetch('jchunk', fetchOpt); |
| 83 | 83 | }; |
| 84 | 84 | |
| 85 | + | |
| 86 | + /** | |
| 87 | + Extracts either the starting or ending line number from a | |
| 88 | + line-numer column in the given tr. isSplit must be true if tr | |
| 89 | + represents a split diff, else false. Expects its tr to be valid: | |
| 90 | + GIGO applies. Returns the starting line number if getStart, else | |
| 91 | + the ending line number. Returns the line number from the LHS file | |
| 92 | + if getLHS is true, else the RHS. | |
| 93 | + */ | |
| 94 | + const extractLineNo = function f(getLHS, getStart, tr, isSplit){ | |
| 95 | + if(!f.rx){ | |
| 96 | + f.rx = { | |
| 97 | + start: /^\s*(\d+)/, | |
| 98 | + end: /(\d+)\n?$/ | |
| 99 | + } | |
| 100 | + } | |
| 101 | + const td = tr.querySelector('td:nth-child('+( | |
| 102 | + /* TD element with the line numbers */ | |
| 103 | + getLHS ? 1 : (isSplit ? 4 : 2) | |
| 104 | + )+')'); | |
| 105 | + const m = f.rx[getStart ? 'start' : 'end'].exec(td.innerText); | |
| 106 | + return m ? +m[1] : undefined/*"shouldn't happen"*/; | |
| 107 | + }; | |
| 108 | + | |
| 85 | 109 | /** |
| 86 | 110 | Fetches /jchunk for the given TR element then replaces the TR's |
| 87 | 111 | contents with data from the result of that request. |
| 88 | 112 | */ |
| 89 | 113 | const fetchTrChunk = function(tr){ |
| @@ -147,37 +171,18 @@ | ||
| 147 | 171 | let lineno = [], i; |
| 148 | 172 | for( i = lineFrom; i <= lineTo; ++i ){ |
| 149 | 173 | lineno.push(i); |
| 150 | 174 | } |
| 151 | 175 | preLines[0].append(lineno.join('\n')+'\n'); |
| 152 | - const code = result.join('\n')+'\n'; | |
| 153 | - preCode.forEach((e)=>e.innerText = code); | |
| 176 | + if(1){ | |
| 177 | + const code = result.join('\n')+'\n'; | |
| 178 | + preCode.forEach((e)=>e.innerText = code); | |
| 179 | + } | |
| 154 | 180 | //console.debug("Updated TR",tr); |
| 155 | 181 | Diff.initTableDiff(table).checkTableWidth(true); |
| 156 | 182 | /* |
| 157 | - At this point we need to: | |
| 158 | - | |
| 159 | - - Read the previous TR, if any, to get the preceeding LHS/RHS | |
| 160 | - line numbers so that we know where to start counting. | |
| 161 | - | |
| 162 | - - If there is no previous TR, we're at the top and we | |
| 163 | - instead need to get the LHS/RHS line numbers from the | |
| 164 | - following TR's children. | |
| 165 | - | |
| 166 | - - D.clearElement(tr) and insert columns appropriate for the | |
| 167 | - parent table's diff type. | |
| 168 | - | |
| 169 | - We can fish the line numbers out of the PRE columns with something | |
| 170 | - like this inefficient but effective hack: | |
| 171 | - | |
| 172 | - theElement.innerText.split(/\n+/) | |
| 173 | - | |
| 174 | - (need /\n+/ instead of '\n' b/c of INS/DEL elements) | |
| 175 | - | |
| 176 | - Noting that the result array will end with an empty element | |
| 177 | - due to the trailing \n character, so a call to pop() will be | |
| 178 | - needed. | |
| 183 | + Reminders to self during development: | |
| 179 | 184 | |
| 180 | 185 | SBS diff col layout: |
| 181 | 186 | <td.diffln.difflnl><pre>...LHS line numbers...</pre></td> |
| 182 | 187 | <td.difftxt.difftxtl><pre>...code lines...</pre></td> |
| 183 | 188 | <td.diffsep>empty for this case (common lines)</td> |
| @@ -192,34 +197,100 @@ | ||
| 192 | 197 | |
| 193 | 198 | C-side TODOs: |
| 194 | 199 | |
| 195 | 200 | - If we have that data readily available, it would be a big |
| 196 | 201 | help (simplify our line calculations) if we stored the line |
| 197 | - number ranges in the (td.diffln pre) elements as | |
| 198 | - data-startln and data-endln. | |
| 202 | + number ranges in all elements which have that state handy. | |
| 199 | 203 | */ |
| 200 | 204 | } |
| 201 | 205 | }); |
| 202 | 206 | }; |
| 203 | 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 | + Diff.ChunkLoadControls = function(isSplit, tr){ | |
| 213 | + this.isSplit = isSplit; | |
| 214 | + this.e = {/*DOM elements*/}; | |
| 215 | + this.pos = { | |
| 216 | + start: +tr.dataset.startln, | |
| 217 | + end: +tr.dataset.endln | |
| 218 | + }; | |
| 219 | + this.e.tr = tr; | |
| 220 | + D.clearElement(tr); | |
| 221 | + this.e.td = D.addClass( | |
| 222 | + D.attr(D.td(tr), 'colspan', isSplit ? 5 : 4), | |
| 223 | + 'chunkctrl' | |
| 224 | + ); | |
| 225 | + /** | |
| 226 | + Depending on various factors, we need one of: | |
| 227 | + | |
| 228 | + - A single button to load all lines then remove this control | |
| 229 | + | |
| 230 | + - A single button to load the initial chunk | |
| 231 | + | |
| 232 | + - Two buttons: one to load upwards, one to load downwards | |
| 233 | + */ | |
| 234 | + if(tr.nextElementSibling){ | |
| 235 | + this.pos.next = { | |
| 236 | + startLhs: extractLineNo(true, true, tr.nextElementSibling, isSplit), | |
| 237 | + startRhs: extractLineNo(false, true, tr.nextElementSibling, isSplit) | |
| 238 | + }; | |
| 239 | + } | |
| 240 | + if(tr.previousElementSibling){ | |
| 241 | + this.pos.prev = { | |
| 242 | + endLhs: extractLineNo(true, false, tr.previousElementSibling, isSplit), | |
| 243 | + endRhs: extractLineNo(false, false, tr.previousElementSibling, isSplit) | |
| 244 | + }; | |
| 245 | + } | |
| 246 | + D.append(this.e.td,"Controls pending: ",JSON.stringify(this.pos)); | |
| 247 | + }; | |
| 248 | + | |
| 249 | + Diff.ChunkLoadControls.prototype = { | |
| 250 | + config: { | |
| 251 | + glyphUp: '&#uarr;', | |
| 252 | + glyphDown: '&#darr;' | |
| 253 | + } | |
| 254 | + }; | |
| 255 | + | |
| 204 | 256 | Diff.addDiffSkipHandlers = function(){ |
| 205 | 257 | const tables = document.querySelectorAll('table.diff[data-lefthash]'); |
| 206 | 258 | if(!tables.length) return F; |
| 207 | - const addDiffSkipToTr = function f(tr){ | |
| 259 | + const addDiffSkipToTr = function f(isSplit, tr){ | |
| 208 | 260 | D.addClass(tr, 'jchunk'); |
| 209 | 261 | if(!f._handler){ |
| 210 | 262 | f._handler = function ff(event){ |
| 211 | 263 | const e = this; |
| 212 | 264 | e.removeEventListener('click',ff); |
| 213 | 265 | D.removeClass(e, 'jchunk', 'diffskip'); |
| 214 | 266 | fetchTrChunk(e); |
| 215 | 267 | }; |
| 216 | 268 | } |
| 217 | - tr.addEventListener('click', f._handler, false); | |
| 269 | + /* TODO: | |
| 270 | + | |
| 271 | + Depending on tr.dataset.{startln,endln}, install one or two | |
| 272 | + controls for loading the next diff chunk. For both types of | |
| 273 | + diff, put the control(s) into tr->td[0], delete tr->td[1], | |
| 274 | + give tr->td[0] a colspan of 2. Change the click handler to | |
| 275 | + address those controls, instead of the TR element, for | |
| 276 | + purposes of figuring out which lines to fetch. Use a helper | |
| 277 | + class to encapsulate the activation and updates of the | |
| 278 | + controls (e.g. removing controls which are no longer relevant | |
| 279 | + once a chunk is fully loaded). | |
| 280 | + | |
| 281 | + Good example from github to use as a model: | |
| 282 | + | |
| 283 | + https://github.com/msteveb/autosetup/commit/235925e914a52a542 | |
| 284 | + */ | |
| 285 | + //tr.addEventListener('click', f._handler, false); | |
| 286 | + new Diff.ChunkLoadControls(isSplit, tr); | |
| 218 | 287 | }; |
| 219 | - tables.forEach(function(t){ | |
| 220 | - t.querySelectorAll('tr.diffskip[data-startln]').forEach(addDiffSkipToTr); | |
| 288 | + tables.forEach(function(table){ | |
| 289 | + table.querySelectorAll('tr.diffskip[data-startln]').forEach(function(tr){ | |
| 290 | + addDiffSkipToTr(table.classList.contains('splitdiff')/*else udiff*/, tr); | |
| 291 | + }); | |
| 221 | 292 | }); |
| 222 | 293 | }; |
| 223 | 294 | |
| 224 | 295 | Diff.addDiffSkipHandlers(); |
| 225 | 296 | }); |
| @@ -272,11 +343,11 @@ | ||
| 272 | 343 | |
| 273 | 344 | const scrollLeft = function(event){ |
| 274 | 345 | //console.debug("scrollLeft",this,event); |
| 275 | 346 | const table = this.parentElement/*TD*/.parentElement/*TR*/. |
| 276 | 347 | parentElement/*TBODY*/.parentElement/*TABLE*/; |
| 277 | - table.$txtPres.forEach((e)=>e.scrollLeft = this.scrollLeft); | |
| 348 | + table.$txtPres.forEach((e)=>(e===this) ? 1 : (e.scrollLeft = this.scrollLeft)); | |
| 278 | 349 | return false; |
| 279 | 350 | }; |
| 280 | 351 | Diff.initTableDiff = function f(diff){ |
| 281 | 352 | if(!diff){ |
| 282 | 353 | let i, diffs = document.querySelectorAll('table.splitdiff'); |
| @@ -306,11 +377,11 @@ | ||
| 306 | 377 | D.addClass(diff, 'scroller'); |
| 307 | 378 | diff.addEventListener('keydown', function(e){ |
| 308 | 379 | e = e || event; |
| 309 | 380 | const len = {37: -SCROLL_LEN, 39: SCROLL_LEN}[e.keyCode]; |
| 310 | 381 | if( !len ) return; |
| 311 | - diff.$txtCols[0].scrollLeft += len; | |
| 382 | + this.$txtPres[0].scrollLeft += len; | |
| 312 | 383 | return false; |
| 313 | 384 | }, false); |
| 314 | 385 | } |
| 315 | 386 | return this; |
| 316 | 387 | } |
| 317 | 388 |
| --- src/fossil.diff.js | |
| +++ src/fossil.diff.js | |
| @@ -80,10 +80,34 @@ | |
| 80 | if(!fetchOpt.onerror) fetchOpt.onerror = Diff.config.chunkFetch.onerror; |
| 81 | fetchOpt.responseType = 'json'; |
| 82 | return F.fetch('jchunk', fetchOpt); |
| 83 | }; |
| 84 | |
| 85 | /** |
| 86 | Fetches /jchunk for the given TR element then replaces the TR's |
| 87 | contents with data from the result of that request. |
| 88 | */ |
| 89 | const fetchTrChunk = function(tr){ |
| @@ -147,37 +171,18 @@ | |
| 147 | let lineno = [], i; |
| 148 | for( i = lineFrom; i <= lineTo; ++i ){ |
| 149 | lineno.push(i); |
| 150 | } |
| 151 | preLines[0].append(lineno.join('\n')+'\n'); |
| 152 | const code = result.join('\n')+'\n'; |
| 153 | preCode.forEach((e)=>e.innerText = code); |
| 154 | //console.debug("Updated TR",tr); |
| 155 | Diff.initTableDiff(table).checkTableWidth(true); |
| 156 | /* |
| 157 | At this point we need to: |
| 158 | |
| 159 | - Read the previous TR, if any, to get the preceeding LHS/RHS |
| 160 | line numbers so that we know where to start counting. |
| 161 | |
| 162 | - If there is no previous TR, we're at the top and we |
| 163 | instead need to get the LHS/RHS line numbers from the |
| 164 | following TR's children. |
| 165 | |
| 166 | - D.clearElement(tr) and insert columns appropriate for the |
| 167 | parent table's diff type. |
| 168 | |
| 169 | We can fish the line numbers out of the PRE columns with something |
| 170 | like this inefficient but effective hack: |
| 171 | |
| 172 | theElement.innerText.split(/\n+/) |
| 173 | |
| 174 | (need /\n+/ instead of '\n' b/c of INS/DEL elements) |
| 175 | |
| 176 | Noting that the result array will end with an empty element |
| 177 | due to the trailing \n character, so a call to pop() will be |
| 178 | needed. |
| 179 | |
| 180 | SBS diff col layout: |
| 181 | <td.diffln.difflnl><pre>...LHS line numbers...</pre></td> |
| 182 | <td.difftxt.difftxtl><pre>...code lines...</pre></td> |
| 183 | <td.diffsep>empty for this case (common lines)</td> |
| @@ -192,34 +197,100 @@ | |
| 192 | |
| 193 | C-side TODOs: |
| 194 | |
| 195 | - If we have that data readily available, it would be a big |
| 196 | help (simplify our line calculations) if we stored the line |
| 197 | number ranges in the (td.diffln pre) elements as |
| 198 | data-startln and data-endln. |
| 199 | */ |
| 200 | } |
| 201 | }); |
| 202 | }; |
| 203 | |
| 204 | Diff.addDiffSkipHandlers = function(){ |
| 205 | const tables = document.querySelectorAll('table.diff[data-lefthash]'); |
| 206 | if(!tables.length) return F; |
| 207 | const addDiffSkipToTr = function f(tr){ |
| 208 | D.addClass(tr, 'jchunk'); |
| 209 | if(!f._handler){ |
| 210 | f._handler = function ff(event){ |
| 211 | const e = this; |
| 212 | e.removeEventListener('click',ff); |
| 213 | D.removeClass(e, 'jchunk', 'diffskip'); |
| 214 | fetchTrChunk(e); |
| 215 | }; |
| 216 | } |
| 217 | tr.addEventListener('click', f._handler, false); |
| 218 | }; |
| 219 | tables.forEach(function(t){ |
| 220 | t.querySelectorAll('tr.diffskip[data-startln]').forEach(addDiffSkipToTr); |
| 221 | }); |
| 222 | }; |
| 223 | |
| 224 | Diff.addDiffSkipHandlers(); |
| 225 | }); |
| @@ -272,11 +343,11 @@ | |
| 272 | |
| 273 | const scrollLeft = function(event){ |
| 274 | //console.debug("scrollLeft",this,event); |
| 275 | const table = this.parentElement/*TD*/.parentElement/*TR*/. |
| 276 | parentElement/*TBODY*/.parentElement/*TABLE*/; |
| 277 | table.$txtPres.forEach((e)=>e.scrollLeft = this.scrollLeft); |
| 278 | return false; |
| 279 | }; |
| 280 | Diff.initTableDiff = function f(diff){ |
| 281 | if(!diff){ |
| 282 | let i, diffs = document.querySelectorAll('table.splitdiff'); |
| @@ -306,11 +377,11 @@ | |
| 306 | D.addClass(diff, 'scroller'); |
| 307 | diff.addEventListener('keydown', function(e){ |
| 308 | e = e || event; |
| 309 | const len = {37: -SCROLL_LEN, 39: SCROLL_LEN}[e.keyCode]; |
| 310 | if( !len ) return; |
| 311 | diff.$txtCols[0].scrollLeft += len; |
| 312 | return false; |
| 313 | }, false); |
| 314 | } |
| 315 | return this; |
| 316 | } |
| 317 |
| --- src/fossil.diff.js | |
| +++ src/fossil.diff.js | |
| @@ -80,10 +80,34 @@ | |
| 80 | if(!fetchOpt.onerror) fetchOpt.onerror = Diff.config.chunkFetch.onerror; |
| 81 | fetchOpt.responseType = 'json'; |
| 82 | return F.fetch('jchunk', fetchOpt); |
| 83 | }; |
| 84 | |
| 85 | |
| 86 | /** |
| 87 | Extracts either the starting or ending line number from a |
| 88 | line-numer column in the given tr. isSplit must be true if tr |
| 89 | represents a split diff, else false. Expects its tr to be valid: |
| 90 | GIGO applies. Returns the starting line number if getStart, else |
| 91 | the ending line number. Returns the line number from the LHS file |
| 92 | if getLHS is true, else the RHS. |
| 93 | */ |
| 94 | const extractLineNo = function f(getLHS, getStart, tr, isSplit){ |
| 95 | if(!f.rx){ |
| 96 | f.rx = { |
| 97 | start: /^\s*(\d+)/, |
| 98 | end: /(\d+)\n?$/ |
| 99 | } |
| 100 | } |
| 101 | const td = tr.querySelector('td:nth-child('+( |
| 102 | /* TD element with the line numbers */ |
| 103 | getLHS ? 1 : (isSplit ? 4 : 2) |
| 104 | )+')'); |
| 105 | const m = f.rx[getStart ? 'start' : 'end'].exec(td.innerText); |
| 106 | return m ? +m[1] : undefined/*"shouldn't happen"*/; |
| 107 | }; |
| 108 | |
| 109 | /** |
| 110 | Fetches /jchunk for the given TR element then replaces the TR's |
| 111 | contents with data from the result of that request. |
| 112 | */ |
| 113 | const fetchTrChunk = function(tr){ |
| @@ -147,37 +171,18 @@ | |
| 171 | let lineno = [], i; |
| 172 | for( i = lineFrom; i <= lineTo; ++i ){ |
| 173 | lineno.push(i); |
| 174 | } |
| 175 | preLines[0].append(lineno.join('\n')+'\n'); |
| 176 | if(1){ |
| 177 | const code = result.join('\n')+'\n'; |
| 178 | preCode.forEach((e)=>e.innerText = code); |
| 179 | } |
| 180 | //console.debug("Updated TR",tr); |
| 181 | Diff.initTableDiff(table).checkTableWidth(true); |
| 182 | /* |
| 183 | Reminders to self during development: |
| 184 | |
| 185 | SBS diff col layout: |
| 186 | <td.diffln.difflnl><pre>...LHS line numbers...</pre></td> |
| 187 | <td.difftxt.difftxtl><pre>...code lines...</pre></td> |
| 188 | <td.diffsep>empty for this case (common lines)</td> |
| @@ -192,34 +197,100 @@ | |
| 197 | |
| 198 | C-side TODOs: |
| 199 | |
| 200 | - If we have that data readily available, it would be a big |
| 201 | help (simplify our line calculations) if we stored the line |
| 202 | number ranges in all elements which have that state handy. |
| 203 | */ |
| 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 | Diff.ChunkLoadControls = function(isSplit, tr){ |
| 213 | this.isSplit = isSplit; |
| 214 | this.e = {/*DOM elements*/}; |
| 215 | this.pos = { |
| 216 | start: +tr.dataset.startln, |
| 217 | end: +tr.dataset.endln |
| 218 | }; |
| 219 | this.e.tr = tr; |
| 220 | D.clearElement(tr); |
| 221 | this.e.td = D.addClass( |
| 222 | D.attr(D.td(tr), 'colspan', isSplit ? 5 : 4), |
| 223 | 'chunkctrl' |
| 224 | ); |
| 225 | /** |
| 226 | Depending on various factors, we need one of: |
| 227 | |
| 228 | - A single button to load all lines then remove this control |
| 229 | |
| 230 | - A single button to load the initial chunk |
| 231 | |
| 232 | - Two buttons: one to load upwards, one to load downwards |
| 233 | */ |
| 234 | if(tr.nextElementSibling){ |
| 235 | this.pos.next = { |
| 236 | startLhs: extractLineNo(true, true, tr.nextElementSibling, isSplit), |
| 237 | startRhs: extractLineNo(false, true, tr.nextElementSibling, isSplit) |
| 238 | }; |
| 239 | } |
| 240 | if(tr.previousElementSibling){ |
| 241 | this.pos.prev = { |
| 242 | endLhs: extractLineNo(true, false, tr.previousElementSibling, isSplit), |
| 243 | endRhs: extractLineNo(false, false, tr.previousElementSibling, isSplit) |
| 244 | }; |
| 245 | } |
| 246 | D.append(this.e.td,"Controls pending: ",JSON.stringify(this.pos)); |
| 247 | }; |
| 248 | |
| 249 | Diff.ChunkLoadControls.prototype = { |
| 250 | config: { |
| 251 | glyphUp: '&#uarr;', |
| 252 | glyphDown: '&#darr;' |
| 253 | } |
| 254 | }; |
| 255 | |
| 256 | Diff.addDiffSkipHandlers = function(){ |
| 257 | const tables = document.querySelectorAll('table.diff[data-lefthash]'); |
| 258 | if(!tables.length) return F; |
| 259 | const addDiffSkipToTr = function f(isSplit, tr){ |
| 260 | D.addClass(tr, 'jchunk'); |
| 261 | if(!f._handler){ |
| 262 | f._handler = function ff(event){ |
| 263 | const e = this; |
| 264 | e.removeEventListener('click',ff); |
| 265 | D.removeClass(e, 'jchunk', 'diffskip'); |
| 266 | fetchTrChunk(e); |
| 267 | }; |
| 268 | } |
| 269 | /* TODO: |
| 270 | |
| 271 | Depending on tr.dataset.{startln,endln}, install one or two |
| 272 | controls for loading the next diff chunk. For both types of |
| 273 | diff, put the control(s) into tr->td[0], delete tr->td[1], |
| 274 | give tr->td[0] a colspan of 2. Change the click handler to |
| 275 | address those controls, instead of the TR element, for |
| 276 | purposes of figuring out which lines to fetch. Use a helper |
| 277 | class to encapsulate the activation and updates of the |
| 278 | controls (e.g. removing controls which are no longer relevant |
| 279 | once a chunk is fully loaded). |
| 280 | |
| 281 | Good example from github to use as a model: |
| 282 | |
| 283 | https://github.com/msteveb/autosetup/commit/235925e914a52a542 |
| 284 | */ |
| 285 | //tr.addEventListener('click', f._handler, false); |
| 286 | new Diff.ChunkLoadControls(isSplit, tr); |
| 287 | }; |
| 288 | tables.forEach(function(table){ |
| 289 | table.querySelectorAll('tr.diffskip[data-startln]').forEach(function(tr){ |
| 290 | addDiffSkipToTr(table.classList.contains('splitdiff')/*else udiff*/, tr); |
| 291 | }); |
| 292 | }); |
| 293 | }; |
| 294 | |
| 295 | Diff.addDiffSkipHandlers(); |
| 296 | }); |
| @@ -272,11 +343,11 @@ | |
| 343 | |
| 344 | const scrollLeft = function(event){ |
| 345 | //console.debug("scrollLeft",this,event); |
| 346 | const table = this.parentElement/*TD*/.parentElement/*TR*/. |
| 347 | parentElement/*TBODY*/.parentElement/*TABLE*/; |
| 348 | table.$txtPres.forEach((e)=>(e===this) ? 1 : (e.scrollLeft = this.scrollLeft)); |
| 349 | return false; |
| 350 | }; |
| 351 | Diff.initTableDiff = function f(diff){ |
| 352 | if(!diff){ |
| 353 | let i, diffs = document.querySelectorAll('table.splitdiff'); |
| @@ -306,11 +377,11 @@ | |
| 377 | D.addClass(diff, 'scroller'); |
| 378 | diff.addEventListener('keydown', function(e){ |
| 379 | e = e || event; |
| 380 | const len = {37: -SCROLL_LEN, 39: SCROLL_LEN}[e.keyCode]; |
| 381 | if( !len ) return; |
| 382 | this.$txtPres[0].scrollLeft += len; |
| 383 | return false; |
| 384 | }, false); |
| 385 | } |
| 386 | return this; |
| 387 | } |
| 388 |