| | @@ -21,10 +21,11 @@ |
| 21 | 21 | }); |
| 22 | 22 | |
| 23 | 23 | window.fossil.onPageLoad(function(){ |
| 24 | 24 | const F = window.fossil, D = F.dom; |
| 25 | 25 | const Diff = F.diff = { |
| 26 | + e:{/*certain cached DOM elements*/}, |
| 26 | 27 | config: { |
| 27 | 28 | chunkLoadLines: 20, |
| 28 | 29 | chunkFetch: { |
| 29 | 30 | /* Default callack handlers for Diff.fetchArtifactChunk(), |
| 30 | 31 | unless overridden by options passeed to that function. */ |
| | @@ -109,16 +110,33 @@ |
| 109 | 110 | Diff.config.chunkFetch.aftersend.apply( |
| 110 | 111 | this, Array.prototype.slice.call(arguments,0) |
| 111 | 112 | ); |
| 112 | 113 | }, |
| 113 | 114 | onload: function(result){ |
| 114 | | - console.debug("Chunk result: ",result); |
| 115 | + //console.debug("Chunk result: ",result); |
| 115 | 116 | D.clearElement(tr); |
| 116 | | - D.append( |
| 117 | | - D.attr(D.td(tr), 'colspan', isSbs ? 5 : 4), |
| 118 | | - "Fetched chunk of ",result.length," line(s). TODO: insert it here." |
| 119 | | - ); |
| 117 | + const cols = [], pre = [D.pre()]; |
| 118 | + if(isSbs){ |
| 119 | + cols.push(D.addClass(D.td(tr), 'diffln', 'difflnl')); |
| 120 | + cols.push(D.addClass(D.td(tr), 'difftxt', 'difftxtl')); |
| 121 | + cols.push(D.addClass(D.td(tr), 'diffsep')); |
| 122 | + cols.push(D.addClass(D.td(tr), 'diffln', 'difflnr')); |
| 123 | + cols.push(D.addClass(D.td(tr), 'difftxt', 'difftxtr')); |
| 124 | + D.append(cols[1], pre[0]); |
| 125 | + pre.push(D.pre()); |
| 126 | + D.append(cols[4], pre[1]); |
| 127 | + }else{ |
| 128 | + cols.push(D.addClass(D.td(tr), 'diffln', 'difflnl')); |
| 129 | + cols.push(D.addClass(D.td(tr), 'diffln', 'difflnr')); |
| 130 | + cols.push(D.addClass(D.td(tr), 'diffsep')); |
| 131 | + cols.push(D.addClass(D.td(tr), 'difftxt', 'difftxtu')); |
| 132 | + D.append(cols[3], pre[0]); |
| 133 | + } |
| 134 | + const code = result.join('\n')+'\n'; |
| 135 | + pre.forEach((e)=>e.innerText = code); |
| 136 | + //console.debug("Updated TR",tr); |
| 137 | + Diff.initTableDiff(table).checkTableWidth(true); |
| 120 | 138 | /* |
| 121 | 139 | At this point we need to: |
| 122 | 140 | |
| 123 | 141 | - Read the previous TR, if any, to get the preceeding LHS/RHS |
| 124 | 142 | line numbers so that we know where to start counting. |
| | @@ -140,21 +158,28 @@ |
| 140 | 158 | Noting that the result array will end with an empty element |
| 141 | 159 | due to the trailing \n character, so a call to pop() will be |
| 142 | 160 | needed. |
| 143 | 161 | |
| 144 | 162 | SBS diff col layout: |
| 145 | | - <td><pre>...LHS line numbers...</pre></td> |
| 146 | | - <td>...code lines...</td> |
| 147 | | - <td></td> empty for this case. |
| 148 | | - <td><pre>...RHS line numbers...</pre></td> |
| 149 | | - <td>...dupe of col 2</td> |
| 163 | + <td.diffln.difflnl><pre>...LHS line numbers...</pre></td> |
| 164 | + <td.difftxt.difftxtl><pre>...code lines...</pre></td> |
| 165 | + <td.diffsep>empty for this case (common lines)</td> |
| 166 | + <td.diffln.difflnr><pre>...RHS line numbers...</pre></td> |
| 167 | + <td.difftxt.difftxtr><pre>...dupe of col 2</pre></td> |
| 150 | 168 | |
| 151 | 169 | Unified diff col layout: |
| 152 | | - <td>LHS line numbers</td> |
| 153 | | - <td>RHS line numbers</td> |
| 154 | | - <td>blank in this case</td> |
| 155 | | - <td>code line</td> |
| 170 | + <td.diffln.difflnl><pre>LHS line numbers</pre></td> |
| 171 | + <td.diffln.difflnr><pre>RHS line numbers</pre></td> |
| 172 | + <td.diffsep>empty in this case (common lines)</td> |
| 173 | + <td.difftxt.difftxtu><pre>code line</pre></td> |
| 174 | + |
| 175 | + C-side TODOs: |
| 176 | + |
| 177 | + - If we have that data readily available, it would be a big |
| 178 | + help (simplify our line calculations) if we stored the line |
| 179 | + number ranges in the (td.diffln pre) elements as |
| 180 | + data-startln and data-endln. |
| 156 | 181 | */ |
| 157 | 182 | } |
| 158 | 183 | }); |
| 159 | 184 | }; |
| 160 | 185 | |
| | @@ -170,11 +195,11 @@ |
| 170 | 195 | if(!e){ |
| 171 | 196 | console.error("Internal event-handling error: didn't find TR target."); |
| 172 | 197 | return; |
| 173 | 198 | } |
| 174 | 199 | e.removeEventListener('click',ff); |
| 175 | | - D.removeClass(e, 'jchunk'); |
| 200 | + D.removeClass(e, 'jchunk', 'diffskip'); |
| 176 | 201 | //console.debug("addDiffSkipToTr() Event:",e, event); |
| 177 | 202 | fetchTrChunk(e); |
| 178 | 203 | }; |
| 179 | 204 | } |
| 180 | 205 | tr.addEventListener('click', f._handler, false); |
| | @@ -182,11 +207,11 @@ |
| 182 | 207 | tables.forEach(function(t){ |
| 183 | 208 | t.querySelectorAll('tr.diffskip[data-startln]').forEach(addDiffSkipToTr); |
| 184 | 209 | }); |
| 185 | 210 | }; |
| 186 | 211 | |
| 187 | | - F.diff.addDiffSkipHandlers(); |
| 212 | + Diff.addDiffSkipHandlers(); |
| 188 | 213 | }); |
| 189 | 214 | |
| 190 | 215 | /** |
| 191 | 216 | 2021-09-07: refactoring the following for use in the higher-level |
| 192 | 217 | fossil.*.js framework is pending. For now it's a copy/paste copy |
| | @@ -200,69 +225,87 @@ |
| 200 | 225 | ** For a side-by-side diff, if either column is two wide to fit on the |
| 201 | 226 | ** display, scrollbars are added. The scrollbars are linked, so that |
| 202 | 227 | ** both sides scroll together. Left and right arrows also scroll. |
| 203 | 228 | */ |
| 204 | 229 | window.fossil.onPageLoad(function(){ |
| 205 | | - var SCROLL_LEN = 25; |
| 206 | | - function initDiff(diff){ |
| 207 | | - var txtCols = diff.querySelectorAll('td.difftxt'); |
| 208 | | - var txtPres = diff.querySelectorAll('td.difftxt pre'); |
| 209 | | - var width = 0; |
| 210 | | - if(txtPres.length>=2)Math.max(txtPres[0].scrollWidth, txtPres[1].scrollWidth); |
| 211 | | - var i; |
| 212 | | - for(i=0; i<txtCols.length; i++){ |
| 213 | | - txtCols[i].style.width = width + 'px'; |
| 214 | | - txtPres[i].style.maxWidth = width + 'px'; |
| 215 | | - txtPres[i].style.width = width + 'px'; |
| 216 | | - txtPres[i].onscroll = function(e){ |
| 217 | | - for(var j=0; j<txtPres.length; j++) txtPres[j].scrollLeft = this.scrollLeft; |
| 218 | | - }; |
| 219 | | - } |
| 220 | | - diff.tabIndex = 0; |
| 221 | | - diff.onkeydown = function(e){ |
| 222 | | - e = e || event; |
| 223 | | - var len = {37: -SCROLL_LEN, 39: SCROLL_LEN}[e.keyCode]; |
| 224 | | - if( !len ) return; |
| 225 | | - txtCols[0].scrollLeft += len; |
| 226 | | - return false; |
| 227 | | - }; |
| 228 | | - } |
| 229 | | - window.fossil.page.tweakSbsDiffs = function(){ |
| 230 | | - document.querySelectorAll('table.splitdiff').forEach(initDiff); |
| 231 | | - }; |
| 232 | | - var i, diffs = document.querySelectorAll('table.splitdiff') |
| 233 | | - for(i=0; i<diffs.length; i++){ |
| 234 | | - initDiff(diffs[i]); |
| 235 | | - } |
| 236 | | - const checkWidth = function f(){ |
| 230 | + const SCROLL_LEN = 25; |
| 231 | + const F = window.fossil, D = F.dom, Diff = F.diff; |
| 232 | + Diff.checkTableWidth = function f(force){ |
| 237 | 233 | if(undefined === f.lastWidth){ |
| 238 | 234 | f.lastWidth = 0; |
| 239 | 235 | } |
| 240 | | - if( document.body.clientWidth===f.lastWidth ) return; |
| 236 | + if( !force && document.body.clientWidth===f.lastWidth ) return this; |
| 241 | 237 | f.lastWidth = document.body.clientWidth; |
| 242 | | - var w = f.lastWidth*0.5 - 100; |
| 243 | | - if(!f.colsL){ |
| 238 | + let w = f.lastWidth*0.5 - 100; |
| 239 | + if(force || !f.colsL){ |
| 244 | 240 | f.colsL = document.querySelectorAll('td.difftxtl pre'); |
| 245 | 241 | } |
| 246 | | - for(let i=0; i<f.colsL.length; i++){ |
| 247 | | - f.colsL[i].style.width = w + "px"; |
| 248 | | - f.colsL[i].style.maxWidth = w + "px"; |
| 249 | | - } |
| 250 | | - if(!f.colsR){ |
| 242 | + f.colsL.forEach(function(e){ |
| 243 | + e.style.width = w + "px"; |
| 244 | + e.style.maxWidth = w + "px"; |
| 245 | + }); |
| 246 | + if(force || !f.colsR){ |
| 251 | 247 | f.colsR = document.querySelectorAll('td.difftxtr pre'); |
| 252 | 248 | } |
| 253 | | - for(let i=0; i<f.colsR.length; i++){ |
| 254 | | - f.colsR[i].style.width = w + "px"; |
| 255 | | - f.colsR[i].style.maxWidth = w + "px"; |
| 256 | | - } |
| 249 | + f.colsR.forEach(function(e){ |
| 250 | + e.style.width = w + "px"; |
| 251 | + e.style.maxWidth = w + "px"; |
| 252 | + }); |
| 257 | 253 | if(!f.allDiffs){ |
| 258 | 254 | f.allDiffs = document.querySelectorAll('table.diff'); |
| 259 | 255 | } |
| 260 | 256 | w = f.lastWidth; |
| 261 | | - for(let i=0; i<f.allDiffs.length; i++){ |
| 262 | | - f.allDiffs[i].style.maxWidth = w + "px"; |
| 257 | + f.allDiffs.forEach((e)=>e.style.maxWidth = w + "px"); |
| 258 | + return this; |
| 259 | + }; |
| 260 | + |
| 261 | + const scrollLeft = function(event){ |
| 262 | + //console.debug("scrollLeft",this,event); |
| 263 | + const table = this.parentElement/*TD*/.parentElement/*TR*/. |
| 264 | + parentElement/*TBODY*/.parentElement/*TABLE*/; |
| 265 | + table.$txtPres.forEach((e)=>e.scrollLeft = this.scrollLeft); |
| 266 | + return false; |
| 267 | + }; |
| 268 | + Diff.initTableDiff = function f(diff){ |
| 269 | + if(!diff){ |
| 270 | + let i, diffs = document.querySelectorAll('table.splitdiff'); |
| 271 | + for(i=0; i<diffs.length; ++i){ |
| 272 | + f.call(this, diffs[i]); |
| 273 | + } |
| 274 | + return this; |
| 275 | + } |
| 276 | + diff.$txtCols = diff.querySelectorAll('td.difftxt'); |
| 277 | + diff.$txtPres = diff.querySelectorAll('td.difftxt pre'); |
| 278 | + var width = 0; |
| 279 | + diff.$txtPres.forEach(function(e){ |
| 280 | + if(width < e.scrollWidth) width = e.scrollWidth; |
| 281 | + }); |
| 282 | + //console.debug("diff.$txtPres =",diff.$txtPres); |
| 283 | + diff.$txtCols.forEach((e)=>e.style.width = width + 'px'); |
| 284 | + diff.$txtPres.forEach(function(e){ |
| 285 | + e.style.maxWidth = width + 'px'; |
| 286 | + e.style.width = width + 'px'; |
| 287 | + if(!e.classList.contains('scroller')){ |
| 288 | + D.addClass(e, 'scroller'); |
| 289 | + e.addEventListener('scroll', scrollLeft, false); |
| 290 | + } |
| 291 | + }); |
| 292 | + diff.tabIndex = 0; |
| 293 | + if(!diff.classList.contains('scroller')){ |
| 294 | + D.addClass(diff, 'scroller'); |
| 295 | + diff.addEventListener('keydown', function(e){ |
| 296 | + e = e || event; |
| 297 | + const len = {37: -SCROLL_LEN, 39: SCROLL_LEN}[e.keyCode]; |
| 298 | + if( !len ) return; |
| 299 | + diff.$txtCols[0].scrollLeft += len; |
| 300 | + return false; |
| 301 | + }, false); |
| 263 | 302 | } |
| 303 | + return this; |
| 304 | + } |
| 305 | + window.fossil.page.tweakSbsDiffs = function(){ |
| 306 | + document.querySelectorAll('table.splitdiff').forEach((e)=>Diff.initTableDiff); |
| 264 | 307 | }; |
| 265 | | - checkWidth(); |
| 266 | | - window.addEventListener('resize', checkWidth); |
| 308 | + Diff.initTableDiff().checkTableWidth(); |
| 309 | + window.addEventListener('resize', ()=>Diff.checkTableWidth()); |
| 267 | 310 | }, false); |
| 268 | 311 | |
| 269 | 312 | |