User:Js/diffs.js
Appearance
< User:Js
Code that you insert on this page could contain malicious content capable of compromising your account. If you import a script from another page with "importScript", "mw.loader.load", "iusc", or "lusc", take note that this causes you to dynamically load a remote script, which could be changed by others. Editors are responsible for all edits and actions they perform, including by scripts. User scripts are not centrally supported and may malfunction or become inoperable due to software changes. A guide to help you find broken scripts is available. If you are unsure whether code you are adding to this page is safe, you can ask at the appropriate village pump. This code will be executed when previewing this page. |
![]() | This user script seems to have a documentation page at User:Js/diffs. |
$(function(){
dfImproveAdvanced = true
var dfPopupSheet
var clickedLink
//if( wgCanonicalSpecialPageName == 'Recentchanges'){
mw.util.addCSS(
'a[href^="/w"][href*="diff="]' + (window.dfDiffLinksCSS || '{font-style:italic}') +
'a[href^="/w"][href*="diff="]:hover {color:red}' +
'.popup {margin:0.5em}'
)
mw.loader.load( 'jquery.ui.dialog' )
setTimeout(addPopupLinks, 100)
//}
var tbl = $('table.diff')
if( tbl.length ) improveTable(tbl)
function addPopupLinks(){
//mw.util.$content.find('a').click(clickPopup)
mw.util.$content.click(dfClick)
}
function dfClick(e){
cursorWait() //cancel waiting indicator if something went wrong
if( e.shiftKey || e.which != 1) return
var aa = $(e.target).closest('a')
if( !aa ) return
var url = decodeURI(aa.attr('href'))
if( /^#/.test(url) ) return
if( /diff=/.test(url) ) return requestDiff(aa, url)
/*
else if( ! /\?/.test(url) && ! /(special|служебная):/i.test(url) ){
url += '?action=render'
}else{
url += (/\?/.test(url) ? '&' : '?') + 'useskin=myskin #content'
}
*/
}
function requestDiff(lnk, url){
addDiffPopupCSS()
addDiffTableCSS()
//mark link as "clicked"
clickedLink = lnk
$('a.df-clicked-last').removeClass('df-clicked-last') //rm class from previos click
lnk.addClass('df-clicked df-clicked-last')
if( /Watchlist|Recentchanges/.test(wgCanonicalSpecialPageName) )
lnk.closest('li').add(lnk.closest('tr')).addClass('df-clicked')
url += '&action=render&diffonly=true'
$('<div class=popup />').hide().insertAfter(lnk)
.load(url, showPopup)
return false
}
function showPopup(){
improveTable( $(this).find('table') )
$(this)
.dialog(
{width: $(window).width() - 100
//,maxHeight: $(window).height() - 100
}
)
.click( function(e){
if( $(e.target).hasClass('ui-dialog-content') )
$(this).dialog('close')
})
//.mouseleave( function(){ $(this).dialog('close') })
}
//******************************************************************************************
function cursorWait(isWait){
if (window.dfNoWaitCursor) return
document.body.style.cursor = isWait ? 'wait' : ''
}
function addDiffPopupCSS(){
if (dfPopupSheet) return
if (document.URL.indexOf('&diff=') == -1) importStylesheetURI('/skins-1.5/common/diff.css')
dfPopupSheet = mw.util.addCSS('\
.df-clicked {background-color:#E0E0E0}\
a.df-clicked-last {background-color:#FFDDDD}\
.ui-widget-content a {color:#0645AD}\
')
}
/*
div.df-popup{position:absolute; z-index:5; width:95%; border:1px solid #000033; \
font-size:110%; background-color:white; visibility:hidden;}\
div.df-popup div.df-caption{float:none; background:#F0F0FF; font-size:120%;\
border:1px outset gray; padding:2px}\
div.df-popup table.diff {width:97%; margin:0 1% 0 1% }\
*/
var dfHighlightSheet, dfImprovementSheet
function addDiffTableCSS(){
if( dfImprovementSheet ) return
dfImprovementSheet = mw.util.addCSS('\
td.diff-addedline, td.diff-deletedline {font-size:100%}\
table.diff {border-spacing:1px}\
table.diff td {vertical-align:top}\
table.diff {width:99%}\
body table.diff, td.diff-otitle, td.diff-ntitle {background:#FBFBFB}\
table.diff td.diff-lineno {border-top: 25px solid #FBFBFB}\
tr.df-deleted td {background-color:#FEC}\
table.diff td div {min-height:1em}\
td.df-deletedwords, td.df-addedwords\
{background:white; border:1px dotted gray; padding:2px}\
td.df-deletedwords span.diffchange {background-color:#FFA}\
td.df-addedwords span.diffchange {background-color:#CFC; color:black; font-weight:normal}\
tr.odd td.diff-addedline {background-color:#BEB}\
span.sig {border:1px dotted gray; border-bottom:none; font-family:cursive; font-size:90%}\
td.df-header {font-weight:bold; font-size:120%; padding-top:15px}\
tr.df-change td {font-size:100%}\
tr.df-added ins.diffchange {color:inherit; font-weight:normal; border:none}\
div.df-toolbar span.df-improve-btn {border:1px inset #EEEEEE}\
.df-btn {padding:2px; border:1px solid gray; margin-right:2px}\
table.diff td {cursor:help}\
table.diff td div, table.diff td.diff-multi {margin:0 8px 0 2px; cursor:default}'
+ (window.dfDiffTableCSS || '')) //user CSS
//cursor stuff shows that TD is clickable (sticking out from under DIV inside)
//padding: 0 8px 0 2px
//different approach to make cells clickable
//+ 'table.diff {border-spacing:0} table.diff td {border-top:4px solid #FBFBFB} table.diff td.diff-deletedline {border-right: 6px solid #FBFBFB}'
}
//==============================================================================
function improveTable(tbl){
if (window.dfMaxImproveSize && tbl.html().length>dfMaxImproveSize) return
//improve rows
//curTitle = tbl.parent()[0].diffTitle //needed in improveCell() for relative links
curTitle = 'AA' // !!!!
curStripes = false
addDiffTableCSS()
tbl.find('tr').each(improveRow)
tbl.click(tableOnclick)
}
function improveRow(){
var tr = this, tds = $(this).find('td'), td
if (tds.length <= 2) return // 'diff info' or 'intermediate revisions' or 'Line xx:'
// case 'diff-otitle': case 'diff-multi': case 'diff-lineno':
if (tds.length == 3){
if (tds[1].className == 'diff-deletedline'){
tr.className += ' df-deleted' //new class, means the line was simply deleted, has pink background
//if (tds[1].innerHTML.length==0) tds[1].innerHTML = '<div> </div>'
expandCell(tds[1])
return
}else if (tds[2].className == 'diff-addedline'){
tr.className += ' df-added'
improveCell(tds[2])
htm = tds[2].innerHTML
if (htm.length==0) tds[2].innerHTML = '<div> </div>'
if (curStripes) tr.className += ' odd'
if (/<span class="sig">/i.test(htm)) curStripes = !curStripes
expandCell(tds[2])
return
}
}else if (tds[1].className == 'diff-context'){
tr.className = 'df-context'
if (window.dfParseContext) improveCell(tds[1])
expandCell(tds[1])
curStripes = false
return
}
//normal yellow/green rows with 4 cells
tr.className = 'df-change'
tds[1].colSpan = tds[3].colSpan = 2
tr.removeChild(tds[2]); tr.removeChild(tds[0])
if (!window.dfImproveAdvanced) return
tds = tr.getElementsByTagName('td')
var oldline = tds[0].innerHTML
var newline = tds[1].innerHTML
//check for simple diffs
if (oldline.length < 90 && oldline.replace(/<.+?>| |\n/g,'') == ''){ //old empty
tds[1].className = 'diff-addedline'
tds[1].innerHTML = newline.replace(/<span class="diffchange">/i,'').replace(/<\/span>/i,'')
improveCell(tds[1])
splitRowsUp(tds[0])
}else if (newline.length < 90 && newline.replace(/<.+?>| |\n/g,'') == ''){ //new empty
tds[0].className = 'df-deletedline' // !!! replace wih tr-deleted
tds[0].innerHTML = oldline.replace(/<span class="diffchange">/i,'').replace(/<\/span>/i,'')
splitRowsUp(tds[1])
}else if (!/<span/i.test(newline)){ //simple change: something removed
improveCell(tds[0])
expandCell(tds[0], 'df-deletedwords')
}else if (!/<span/i.test(oldline)){ //simple change: something added
improveCell(tds[1])
expandCell(tds[1], 'df-addedwords')
}else{ //complex case
//improveCell(tds[1])
//improveCell(tds[3])
if (window.dfOneColumn){ // separate into different rows anyway
tds[0].firstChild.style.borderTop = '10px solid #FBFBFB'
tds[1].firstChild.style.borderBottom = '10px solid #FBFBFB'
splitRowsUp(tds[0])
}else{
//remove + / - markers ?
}
}
function expandCell(td, clss){
while (td.nextSibling) tr.removeChild(td.nextSibling)
while (td.previousSibling) tr.removeChild(td.previousSibling)
td.colSpan = 4
if (clss) td.className = clss
}
function splitRowsUp(tdGoesUp){
tds[0].colSpan = 4
tds[1].colSpan = 4
//tr.removeChild(tds[2])
//tr.removeChild(tds[0])
var trnew = document.createElement('tr')
trnew.className = 'df-change'
trnew.appendChild(tdGoesUp)
tr.parentNode.insertBefore(trnew, tr)
}
} //improveRow()
function improveCell(cell){
if (window.dfNoWikiParsing) return
cell = $(cell)
var htm = cell.html()
if (htm.length == 0) return //cell.innerHTML = ' '
cell.data('origHTML', htm)
if (/^==.*== *$/i.test(cell.text())) cell.addClass('df-header')
htm = htm.replace(/\u00A0/g, '<b>\u00B7</b>')
htm = htm.replace(/({\{u(?:ser(?:links)?)?\|)([^}]+)}\}/g, function(str,tmpl,user){
return tmpl + outputLink2('special:contributions/'+user,'',user) + '}}' })
//mark signatures
htm = htm.replace(/(\[\[[^\[]{4,65})?\d\d:\d\d, \d\d? \S{3,9} 20\d\d \(UTC\)/g, '<span class="sig">$&</span>')
htm = htm.replace(/\{\{unsigned[^\}]\}\}/i, '<span class="sig">$&</span>')
//[[link]]
var CatOrFileRegExp = RegExp('^('+wgFormattedNamespaces[6]+'|'
+wgFormattedNamespaces[14]+'|category|image|file):|\.(jpg|png|svg|gif)$','i')
htm = htm.replace(/\[\[([^\]><}{|]+)\|?([^\]><]*)?\]\]/g,
function(wikicode,page,name){
if (/http:\/\//i.test(page)) return wikicode //user made a mistake
if (CatOrFileRegExp.test(page)) name = page+(name?'|'+name:'') //file or category, show in full
else if (!name) name = page
if (/^[#\/]/.test(page)) page = curTitle + page //relative link
else if (/^[a-z]{2,7}:/.test(page)) page = 'Special:Search/'+page //possible interproject link, some are not "local"
return outputLink2(page, '', name, wikicode)
})
// [http://...]
htm = htm.replace(/\[(https?:\/\/[^ \]><]*)( [^\]]*)?\]/g, //
function (str,link,name){
var output = '<a href=' + link, title, tip, nameWas = name
if (link.indexOf(wgServer+wgScript) == 0){ //local link
tip = tryDecodeURI(link.substring((wgServer+wgScript).length+1))
if (!name){
name = getTitleFromURL(link) || tip
if (/diff=/.test(link)) name = 'diff: ' + name
else if (tip.match(/action=history/)) name = 'hist: ' + name
else if (tip.match(/oldid=/)) name = 'oldid: ' + name
else name = 'wiki: ' + name
}
} else { //ext link
tip = tryDecodeURI(link.substring(7))
output += ' class="external text"'
if (!name) name = tip
}
if (!nameWas && (name.length > 70)) name = name.substring(0,60) + '… …'
return output + ' title="' + tip + '">[' + name + ']</a>'
})
cell.html(htm)
function tryDecodeURI(s){ try{s=decodeURIComponent(s)}catch (e){}; return s }
}
function outputLink2(page, params, name, tooltip){
name = name || page
page = page.replace(/&/gi,'&').replace(/#.+$/, calcAnchor)
return '<a href="'+ wgArticlePath.replace(/\$1/,'')
+ encodeURI(page).replace(/\?/g,'%3F')
+ (params||'')
+ '" title="' + (tooltip||name).replace(/"/g,'"') + '">' + name + '</a>' //'
}
function calcAnchor(txt){ //try to create href anchor similar to Parser.php::guessSectionNameFromWikiText()
txt = $.trim(txt).replace(/#/g,'')
.replace(/\[\[([^|]+\|)?([^\]]+)\]\]/g, '$2') //[[foo|bar]] -> bar
.replace(/<.*?>/g, '').replace(/ /g,'_')
// (we skip step "HTML entities are turned into their proper characters")
return '#' + encodeURIComponent(txt).replace('%3A', ':').replace(/%([0-9A-F][0-9A-F])/g, '.$1')
//maybe encodeURI(p1.replace(/\?/g,'%3F').replace(/&/g,'%26')) ?
}
function getTitleFromURL(url){
var tt = /title=([^&>"]+)/.exec(url) //"
if( tt ) decodeURIComponent(tt[1]).replace(/_/g,' ')
else return ''
}
function tableOnclick(e){
var trg = e.target
if( trg.className ) switch ( trg.className ){
//case 'diff-lineno': changeBlock(trg.parentNode); return
//case 'diff-otitle': case 'diff-ntitle': return
case 'diff-addedline': case 'diff-deletedline': case 'diff-context':
//if( trg.nodeName != 'TD' || $(trg).parents('table.diff').length == 0 ) break
//parse wikicode in already improved row when clicked on white border above row
var orig = $(trg).data('origHTML')
if( orig ) $(trg).html(orig).data('origHTML','')
else improveCell(trg)
return
}
}
function changeBlockXXX(row){ //switch improvement level for this part of diff table
var dTbody = row.parentNode, rowIdx = 1, isImproved
//find clicked row number
while (rowIdx < dTbody.rows.length && dTbody.rows[rowIdx] != row) rowIdx++
if (dTbody.rows[rowIdx] != row) return
//check if rows are improved or not
if (row.className == 'df-lineno'){
isImproved = true
var origTable = createTableFromHTML(requestedPages[dTbody.parentNode.parentNode.diffURL])
}else
dfImprovementSheet.disabled = false
//improve / de-improve rows
do{
if (isImproved) dTbody.replaceChild(origTable.rows[rowIdx].cloneNode(true), row)
else improveRow(row)
}while((row=dTbody.rows[++rowIdx]) && row.cells[0].className != 'diff-lineno')
}
})