User:Novem Linguae/histcomb.js

//

/*	Forked from User:Alex Smotrov/histcomb.js

histcomb = history combiner?

From the documentation page at User talk:Alex Smotrov/histcomb.js: Script improves readability of history pages - Consequent edits by the same user are folded together - Size is replaced with difference (like in watchlist/recent changes) - "Talk", "contribs" and "undo" are shortened to one letter - Your edits are marked with light green background - Link «Contributors» under heading goes to useful toolserver tool.

Changes by Novem Linguae since he forked it on 2023-01-22: - refactoring -

window.histComb = new function { // load any custom user settings if (!window.histCombTalk) { histCombTalk = 't'; }	if (!window.histCombContrib) { histCombContrib = 'c'; }	if (!window.histCombUndo) { histCombUndo = '×'; }	if (!window.histCombMyBg) { histCombMyBg = '#F0FFF0'; }

var pagehis, histRow, histSize, isCombEdits = false;

this.onLoad = function { pagehis = document.getElementById('pagehistory'); if (!pagehis) { return; }		histRow = pagehis.getElementsByTagName('li'); histSize = new Array(histRow.length); var row, spans, i, aa, author, author_p = '', size_digits; var sameAuthor = 0, thisMinor, allMinor = true;

// main loop: all rows bottom to top for (var rr = histRow.length - 1; rr >= 0; rr--) { row = histRow[rr]; thisMinor = false; spans = row.getElementsByTagName('span');

// check all spans for (i = 0; i < spans.length; i++) { switch (spans[i].className) { case 'history-size': // if combined diff that is collapsed, set page size to zero size_digits = spans[i].innerHTML.match(/\d+/g); histSize[rr] = size_digits ? size_digits.join('') : '0'; if (histSize[rr + 1]) { spans[i].title = spans[i].innerHTML.replace(/ /g, ' '); insertDiffValue(spans[i], histSize[rr] - histSize[rr + 1]); }						break; case 'minor': // get whether edit is marked as minor (for use later to decide if combined diff should be marked as minor) thisMinor = true; break; case 'history-user': aa = spans[i].getElementsByTagName('a'); if (aa.length && aa[1]) { // get username (for use later to decide whether we should highlight green							author = aa[1].title.split(':')[1];

// shorten "talk" aa[1].innerHTML = histCombTalk;

// shorten "contribs" if (aa.length >= 3 && (aa[2].title.indexOf(':Contributions/') != -1)) // for anons this could be 'block' {								aa[2].innerHTML = histCombContrib; }						}						break; case 'mw-history-undo': // shorten "undo" aa = spans[i].getElementsByTagName('a')[0]; aa.title = aa.innerHTML; aa.innerHTML = histCombUndo; break; }			}

// ???			if (!histSize[rr] && histSize[rr + 1]) { histSize[rr] = histSize[rr + 1]; } // assume it was '(un)protect' edit

// if this user made the edit, highlight the row green if (mw.config.get('wgUserName') == author) { histRow[rr].style.backgroundColor = histCombMyBg; }			// if needed, create a combined diff if (author == author_p) { sameAuthor++; } else { if (sameAuthor > 1) { createCombineEdit(rr + 1, sameAuthor, allMinor); }				sameAuthor = 1; author_p = author; allMinor = thisMinor; }			if (!thisMinor) { allMinor = false; }		}

// collapse top editor too if (sameAuthor > 1) { createCombineEdit(0, sameAuthor, allMinor); if (histRow.length > sameAuthor && !window.histCombNoCollapse) // if collapsing top row - make next row selected {				histRow[sameAuthor].getElementsByTagName('input')[0].click; }		}

// add "expand/collapse all" link if (isCombEdits) { var togAll = document.createElement('a'); togAll.appendChild(document.createTextNode('[±]')); togAll.href = 'javascript:histComb.toggleAll'; pagehis.parentNode.insertBefore(togAll, pagehis.previousSibling); }

// add "Contributors" link at the top of the page, after "View logs for this page" var lnk = document.createElement('a'); lnk.style.marginLeft = '10px'; lnk.href = 'https://xtools.wmflabs.org/articleinfo/' + mw.config.get('wgServer').substring(mw.config.get('wgServer').lastIndexOf('/') + 1, mw.config.get('wgServer').indexOf('.')) + mw.config.get('wgServer').substring(mw.config.get('wgServer').indexOf('.')) + '/' + mw.config.get('wgPageName') + '#top-editors'; lnk.appendChild(document.createTextNode('Contributors')); lnk.title = 'All authors sorted by edits (on Toolforge)'; if (i = document.getElementsByClassName('mw-history-subtitle')[0]) { i.appendChild(lnk); }	};

// expands all or collapses all combined diffs this.toggleAll = function { var links = $(pagehis).find('a.collapsedEdits'); var state = links[0].innerHTML == '[–]'; for (var i = 0; i < links.length; i++) { if (state == (links[i].innerHTML == '[–]')) { eval(links[i].href); }		}	};

// expands or collapses one combined diff this.toggle = function (m, len, isMinor) { var row = histRow[m]; var spans = row.getElementsByTagName('span'); var plus = row.lastChild; var topDiff = row.getElementsByTagName('a')[m > 0 ? 1 : 0]; // "diff to last" in the combined edit var i, bottomDiff, oldid; var isHiding = plus.innerHTML == '[–]'; if (isHiding) { // need to collapse − plus.innerHTML = '[' + len + ']'; row.style.borderLeft = '1px solid transparent'; // hide other rows for (i = m + 1; i < m + len; i++) { histRow[i].style.display = 'none'; }			// "diff from last" link: get oldid from the lowest collapsed edit bottomDiff = histRow[m + len - 1].getElementsByTagName('a')[1].href; if (bottomDiff.indexOf('&diff=') == -1) { topDiff.style.visibility = 'hidden'; } // the very 1st edit oldid = bottomDiff.match(/oldid=(\d+)/)[1]; topDiff.old = topDiff.href; topDiff.href = topDiff.href.replace(/&oldid=\d+/, '&oldid=' + oldid); } else { // need to expand plus.innerHTML = '[–]'; // show other rows and visually reference the whole group row.style.borderLeft = '1px dotted gray'; for (i = m + 1; i < m + len; i++) { histRow[i].style.display = 'block'; histRow[i].style.borderLeft = '1px dotted gray'; histRow[i].style.listStyle = 'none none'; }			histRow[m + len - 1].style.borderBottom = '1px dotted gray'; topDiff.href = topDiff.old; topDiff.style.visibility = 'visible'; }

// hide/show/modify spans in this row for (i = 0; i < spans.length; i++) { switch (spans[i].className.split(' ')[0]) { case 'minor': spans[i].style.display = isHiding && !isMinor ? 'none' : 'inline'; break; case 'history-size': // switch to combined diff size and back insertDiffValue(spans[i], histSize[m] - (isHiding ? histSize[m + len] : histSize[m + 1])); break; case 'comment': // hide/show spans[i].style.display = isHiding && !window.histCombLeaveComment ? 'none' : 'inline'; break; case 'mw-history-undo': var undoLnk = spans[i].getElementsByTagName('a')[0]; if (isHiding) { undoLnk.old = undoLnk.href; undoLnk.href = undoLnk.href.replace(/&undoafter=\d+/, '&undoafter=' + oldid); } else { undoLnk.href = undoLnk.old; }					break; }		}	};

// creates collapsing link for row m down to row m+len function createCombineEdit(m, len, isMinor) { var row = histRow[m]; row.style.listStyle = 'none none'; row.style.position = 'relative'; var plus = document.createElement('a'); plus.className = 'collapsedEdits'; plus.appendChild(document.createTextNode('[–]')); plus.style.position = 'absolute'; plus.style.left = '-22px'; plus.style.top = '2px'; plus.href = 'javascript:histComb.toggle(' + m + ',' + len + ',' + isMinor + ')'; row.appendChild(plus); if (!window.histCombNoCollapse) { histComb.toggle(m, len, isMinor); } // and collapse isCombEdits = true;

// unexplained IE bug: in row just under collapsed edit radios were jumping to the left, links were unclickable if (navigator.userAgent.indexOf('MSIE') != -1 && m + len < histRow.length) { // make all elements 'relative' var els = histRow[m + len].getElementsByTagName('*'); for (let i = 0; i < els.length; i++) { if (els[i].style && !els[i].style.position) { els[i].style.position = 'relative'; }			}		}	}

function insertDiffValue(span, value) { var html, class2; if (value > 0) { html = '(+' + value + ')'; class2 = ' mw-plusminus-pos'; } else if (value < 0) { html = '(' + value + ')'; class2 = ' mw-plusminus-neg'; } else { html = '(0)'; class2 = ' mw-plusminus-null'; }		span.style.fontWeight = value < -500 ? 'bold' : 'normal'; span.innerHTML = html; span.className = span.className.split(' ')[0] + class2; } };

if (mw.config.get('wgAction') == 'history') { $(histComb.onLoad); }

//