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. |
/*
Parameters:
These parameters can be set to true to override standard behaviour
------------------------------
dfNoPopups: no popups
dfNoAjaxDiff: no quick next/prev loading on usual diff pages
dfNoArrowKeys : disable keyboard shortcuts (left/right arrow keys) for next/prev diff
dfNoWikiParsing : completely disable wikicode parsing in diffs
dfParseContext : also parse gray columns
dfNoWaitCursor : set to true to disable cursor changing to "wait"
wikEdFullDiff: do not shorten JS Diff Engine output (pretty much useless)
dfDiffLinksCSS: set this to CSS string to replace default "{font-style:italic}" for all diff links
dfDiffTableCSS: extra CSS for diff table
dfImproveAdvanced : imrove diffs even more (make simple diffs as one column)
dfOneColumn : convert all diffs to one column view
*/
var diffScript = new function(){ //wrapper
var dfNoWikiParsing = window.dfNoWikiParsing, dfNoPopups = window.dfNoPopups
var curTitle, tempDiv, curStripes
var requestedPages = {} //aray of retreived diffs, used as cache
var isIE = navigator.userAgent.indexOf('MSIE') != -1
var popupCount = 0 //, popupArray = []
var articlePath = wgArticlePath.replace('$1', '')
this.start = function(){
addHandler(document, 'click', onClick)
if (!window.dfNoArrowKeys) addHandler(document, 'keyup', onKeyUp)
if (!dfNoPopups) addCSS('a[href^="'+wgServer+'/w/index.php"][href*="diff="],\
a[href^="/w/index.php"][href*="diff="]' + (window.dfDiffLinksCSS || '{font-style:italic}'))
//if (isIE && isIE6) //no CSS3 support in IE6, should make links italic manually
if (document.URL.indexOf('diff=') != -1){ //this is a diff page
//find diff table
var content = document.getElementById('content') || document.getElementById('mw_content') || document
var curTable = findDiffTable(content)
if (!curTable) return
var parent = curTable.parentNode
//remember url and title, and cache
parent.diffURL = document.URL
parent.diffTitle = wgPageName
requestedPages[document.URL] = '<table class=diff>' + curTable.innerHTML + '</table>'
//improve diff Table
improveTable(curTable)
parent.insertBefore(createToolbar(parent), parent.firstChild)
}
}
function onClick(e){
cursorWait() //cancel waiting indicator if something went wrong
//find event and click target
e = e || window.event
if (e.shiftKey || e.button == 2) return // shift key or right click
if ((isIE && e.button == 4) || (!isIE && e.button == 1)) return //middle click
var targ = e.target || e.srcElement
//log(targ)
if (!targ) return
//clicked on diff table
// ...
//clicked on diff popup
if (targ.className)
switch (targ.className){
case 'df-popup': closePopup(targ); return
case 'df-caption': closePopup(targ.parentNode); return
case 'diff-lineno': changeBlock(targ.parentNode); return
case 'diff-addedline': case 'diff-deletedline': case 'diff-context': processCell(targ); return
}
/*
if (!dfNoPopups && targ.className){
if (targ.className=='df-popup') return closePopup(targ)
if (targ.className=='df-caption') return closePopup(targ.parentNode)
}
if (targ.className == 'diff-lineno') return changeBlock(targ.parentNode)
//else if (targ.className == 'diff-marker') return changeRow(targ.parentNode)
*/
//clicked on a diff link
var url = targ.href
if (!url || url.indexOf('diff=') == -1) return //not a diff
if (url.indexOf(wgServer) != 0 && url.charAt(0) != '/') return //diff, but not to this server
if (targ.parentNode.className == 't-print') return
//check if it was nex/prev diff link
var isClickIntercepted = true
if (/differences-(prev|next)link/.test(targ.id)) isClickIntercepted = followNextLink(targ)
else if (!dfNoPopups) createPopup(targ)
else isClickIntercepted = false
//do not follow the link
if (isClickIntercepted){
if (e.preventDefault) e.preventDefault(); else e.returnValue = false
return false
}else
return true
}
function improveTable(dTable){
if (dTable.innerHTML.length>70000) return
//remove diff marker colums
//var cols = dTable.getElementsByTagName('col')
//var col
//while(col=dTable.getElementsByTagName('col')[0]) col.parentNode.removeChild(col)
//improve rows
var trs = dTable.getElementsByTagName('tr')
curTitle = dTable.parentNode.diffTitle //needee in processHTML() for relative links
curStripes = false
for (var i=1; i<trs.length; i++) improveRow(trs[i])
//add CSS
addDiffTableCSS()
}
function improveRow(tr){
var tds = tr.getElementsByTagName('td'), td
tr.className = 'df-change' //by default, as most common case
if (tds.length == 1){ // 'One intermediate revision not shown'
tr.className = 'df-message'
return //plus maybe
}else if (tds.length == 2){ // "Line xx:"
tr.className = 'df-lineno'
return
}else if (tds.length == 3 && tds[1].className == 'diff-deletedline'){
tr.className += ' df-deleted'
if (tds[1].innerHTML.length==0) tds[1].innerHTML = '<div> </div>'
expandCell(tds[1]) //new class, means the line was simply deleted, has pink background
return
}else if (tds.length == 3 && tds[2].className == 'diff-addedline'){
tr.className += ' df-added'
processHTML(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
if (/^<div>==.*== *<\/div>$/i.test(htm))
tds[2].firstChild.style.cssText = 'font-weight:bold; font-size:120%; padding-top:15px'
expandCell(tds[2])
return
}else if (tds[1].className == 'diff-context') {
tr.className = 'df-context'
if (window.dfParseContext) processHTML(tds[1])
expandCell(tds[1])
curStripes = false
return
}
//from here we're left with normal yellow/green rows with 4 cells
tds[1].colSpan = tds[3].colSpan = 2
//tds[1].style.borderRight = '10px solid white'
tr.removeChild(tds[2]); tr.removeChild(tds[0])
return
if (!window.dfImproveAdvanced) return
//check for simple diffs
var oldline = tds[1].innerHTML
var newline = tds[3].innerHTML
if (oldline.length < 90 && oldline.replace(/<.+?>| |\n/g,'') == ''){ //old empty
tds[3].className = 'diff-addedline'
tds[3].innerHTML = newline.replace(/<span class="diffchange">/i,'').replace(/<\/span>/i,'')
processHTML(tds[3])
splitRowsUp(tds[1])
}else if (newline.length < 90 && newline.replace(/<.+?>| |\n/g,'') == ''){ //new empty
tds[1].className = 'df-deletedline' // !!! replace wih tr-deleted
tds[1].innerHTML = oldline.replace(/<span class="diffchange">/i,'').replace(/<\/span>/i,'')
splitRowsUp(tds[3])
}else if (!/<span/i.test(newline)){ //simple change: something removed
processHTML(tds[1])
expandCell(tds[1], 'df-deletedwords')
}else if (!/<span/i.test(oldline)){ //simple change: something added
processHTML(tds[3])
expandCell(tds[3], 'df-addedwords')
}else{ //complex case
//processHTML(tds[1])
//processHTML(tds[3])
if (window.dfOneColumn){ // separate into different rows anyway
tds[1].firstChild.style.borderTop = '10px solid #FBFBFB'
tds[3].firstChild.style.borderBottom = '10px solid #FBFBFB'
splitRowsUp(tds[1])
}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[1].colSpan = 4
tds[3].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)
i++ //increment i in for loop
}
} //improveRow()
function changeTable(e){ //switch between original diff table and improved
e = e || window.event
var butt = e.target || e.srcElement
var curTable = getClickedTable(e)
if (dfImprovementSheet.disabled) improveTable(curTable)
else replaceTable(curTable, requestedPages[curTable.parentNode.diffURL])
dfImprovementSheet.disabled = !dfImprovementSheet.disabled
}
function changeBlock(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')
}
function processCell(cell){ //parse wikicode in already improved row when clicked on white border above row
if (cell.origHTML){ //restore
cell.innerHTML = cell.origHTML
cell.origHTML = null
}else{
processHTML(cell)
}
}
// NOT USED
function changeRow(row){ //switch one rowl improvement level when clicked on +- marker on the left
var dTbody = row.parentNode, rowIdx = 1
//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.indexOf('df-change') != -1){
var origTable = createTableFromHTML(requestedPages[dTbody.parentNode.parentNode.diffURL])
dTbody.replaceChild(origTable.rows[rowIdx].cloneNode(true), row)
}else{
dfImprovementSheet.disabled = false
improveRow(row)
var tds = row.cells
processHTML(tds[1])
processHTML(tds[3])
}
}
function createToolbar(parent){
var dToolbar = document.createElement('div')
dToolbar.tableParent = parent //reference so we can find table later
dToolbar.className = 'df-toolbar'
dToolbar.appendChild(btn(changeTable, '¤', 'Enable/disable improvements', 'df-improve-btn')) //÷
dToolbar.appendChild(btn(highlightDiffs, 'π', 'Highlight differences with red border', 'df-highlight-btn'))
dToolbar.appendChild(btn(diffJSEngine, 'Δ', 'Javascript diff engine'))
//references back and forth
return dToolbar
}
function btn(func, htm, tooltip, clss){ //creates <span> button
var bt = document.createElement('span')
bt.innerHTML = htm
bt.onclick = func
bt.title = tooltip
bt.className = clss || 'df-btn'
return bt
}
function getClickedTable(e){
e = e || window.event
var button = e.target || e.srcElement
return button.parentNode.tableParent.getElementsByTagName('table')[0]
}
function processHTML(elem){
if (dfNoWikiParsing) return
var html = elem.innerHTML
elem.origHTML = html
if (html.length == 0) return //elem.innerHTML = ' '
//mark signatures
html = html.replace(/(\[\[[^\[]{4,65})?\d\d:\d\d, \d\d? \S{3,9} 20\d\d \(UTC\)/g, '<span class=sig>$&</span>')
html = html.replace(/\{\{unsigned[^\}]\}\}/i, '<span class=sig>$&</span>')
//[[link]]
html = html.replace(/\[\[([^\]><}{|]+)\|?([^\]><]*)?\]\]/g,
function(wikicode,page,name){
if (/http:\/\//i.test(page)) return wikicode //user made a mistake
if (/^image:|\.(jpg|png|svg|gif)$/i.test(page) && name) name = page + name //display full image link, including "image:"
if (!name) name = page
if (page.substring(0,1)=='#' || page.substring(0,1)=='/') {
page = curTitle + page //relative link
}
return outputLink(page, '', name, wikicode)
})
// [http://...]
html = html.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>'
})
elem.innerHTML = html
function tryDecodeURI(s){ try{s=decodeURIComponent(s)}catch (e){}; return s }
}
function followNextLink(clickedLink){ //loads next/prev diff using next/prev diff link
//find old table
var el = clickedLink
while (el && el.nodeName != 'TABLE') el = el.parentNode
if (!el || el.className != 'diff') return false
var oldTable = el
if (oldTable.parentNode.className != 'df-popup'){ //normal diff page, not a popup
if (window.dfNoAjaxDiff) return false
if (el=document.getElementById('t-print')) el.style.display = 'none' //hide "printable" link which becomes outdated
}
//replace diff with new table
loadDiff(clickedLink, oldTable)
return true
}
function replaceTable(oldTable, html){
//append new table
var newTable = createTableFromHTML(html)
oldTable.parentNode.insertBefore(newTable, oldTable)
//remove everything below new table: old table, (now outdated) prevew, js engine diff
var el
while ((el=newTable.nextSibling) && !/visualClear|df-caption/.test(el.className))
el.parentNode.removeChild(el)
return newTable
}
function createTableFromHTML(html){
if (!tempDiv) tempDiv = document.createElement('div')
tempDiv.innerHTML = html
return findDiffTable(tempDiv)
}
function findDiffTable(el){
var i = 0, tables = el.getElementsByTagName('table')
while (i < tables.length && tables[i].className != 'diff') i++
if (i < tables.length) return tables[i]; else return null //then it's div.firstrevisionheader
}
// *** POPUP ***
function createPopup(clickedLink){
//initialize
clickedLink.style.backgroundColor = '#F5F5FF'
addDiffPopupCSS()
if (isIE) hideAllSelectElements(true)
//create popup
popupCount++
var pop = document.createElement('div')
pop.className = 'df-popup'
pop.style.top = windowScrolled() + 30 + popupCount*10 + 'px'
pop.style.left = 10 + popupCount*10 + 'px'
//load diff
var oldTable = document.createElement('table')
pop.appendChild(oldTable)
document.body.appendChild(pop) //have to append now, otherwise table is broken in Safari 3
loadDiff(clickedLink, oldTable, showPopup)
}
function showPopup(clickedLink, diffTable){
clickedLink.style.backgroundColor = '#DDDDFF'
var pop = diffTable.parentNode
pop.appendChild(createCaption())
pop.insertBefore(createCaption(), diffTable)
pop.style.visibility = 'visible'
return true
function createCaption(){
var dCaption = document.createElement('div')
dCaption.className = 'df-caption'
//on special pages
if (wgNamespaceNumber == -1){
dCaption.appendChild( btn(function(e){neighborDiff(e,clickedLink, 1)},
'↓', 'Open next diff link on that page'))
dCaption.appendChild( btn(function(e){neighborDiff(e,clickedLink, -1)},
'↑', 'Open previous diff link on that page'))
}
//add page title
var sp = document.createElement('span')
var dTitle = diffTable.parentNode.diffTitle
sp.innerHTML = '<b>'+outputLink(dTitle)+'</b>'
+ ' (' + outputLink(dTitle, '?action=history', 'h') + ')'
dCaption.appendChild(sp)
//add toolbar
dCaption.insertBefore(createToolbar(pop), dCaption.firstChild)
return dCaption
}
}
function closePopup(div){
div.style.display = 'none'
//purge(div)
div.parentNode.removeChild(div)
popupCount--
if (isIE && (popupCount==0)) hideAllSelectElements() //IE select zIndex bug
}
function onKeyUp(e){
e = e || window.event
var lnk
if (e.keyCode == 37) lnk = document.getElementById('differences-prevlink')
else if (e.keyCode == 39) lnk = document.getElementById('differences-nextlink')
if (!lnk) return
if (!followNextLink(lnk)) document.location.href = lnk.href
}
function hideAllSelectElements(isHide){ //workaround for IE <select> zIndex bug
var sels = document.getElementsByTagName('select')
for (var i=0; i<sels.length; i++)
sels[i].style.visibility = isHide ? 'hidden' : 'visible'
}
function neighborDiff(e, lnk, dir){
//close old popup
e = e || window.event
var el = e.target || e.srcElement
closePopup (el.parentNode.parentNode)
//try to find diff in neghbor TR (this happens inside expanded section of enhanced RC/WL)
if ((el=findParentWithTag(lnk,/TR/)) && (el=findNeighborBlock(el)) && (el=findDiffIn(el)))
createPopup(el)
//try to find diff in neghbor LI (on contrib page and simple RC) or TABLE (on enhanced RC and WL)
else if ((el=findParentWithTag(lnk,/LI|TABLE/)) && (el=findNeighborBlock(el)) && (el=findDiffIn(el)))
createPopup(el)
//functions
function findParentWithTag(el, regexp){
while ((el=el.parentNode) && !regexp.test(el.nodeName));
return el
}
function findNeighborBlock(el){ //looks for next/prev block with the same tag
var tag = el.nodeName
do{ el = (dir == -1) ? el.previousSibling : el.nextSibling } while (el && el.nodeName != tag)
return el
}
function findDiffIn(block){
var aa = block.getElementsByTagName('a')
for (var i=0; i<aa.length; i++)
if (/diff=/.test(aa[i].href)) return aa[i]
}
}
// *** JS Diff Engine ***
function diffJSEngine(e){
//create temporary table with original diff
var dTable = getClickedTable(e)
var curTitle = dTable.parentNode.diffTitle
var tempTable = createTableFromHTML(requestedPages[dTable.parentNode.diffURL])
//create "full comparison" button
var btFull = document.createElement('input'); btFull.type = 'button'
btFull.value = 'Perform full comparison'
btFull.title = 'Compare full revisions, in case MediaWiki diff engine is wrong'
btFull.onclick = diffJSFull
//call and run JS diff engine
if (window.WDiffString) diffJSGo()
else importScriptAndRun('http://en.wikipedia.org/w/index.php?title=User:Cacycle/diff.js', diffJSGo)
function diffJSGo(){
cursorWait(true)
//var
oldVer = newVer = ''
tds = tempTable.getElementsByTagName('td')
var txt, isContent
for (var i=1; i<tds.length; i++){
txt = tds[i].innerHTML.replace(/<.+?>/g,'') + '\n'
switch(tds[i].className){
case 'diff-context':
marker = '\x03' + txt + '\x04\n'
oldVer += marker
newVer += marker
isContent = false
i += 2 //skip other context cell
break
case 'diff-lineno':
//oldVer += '\n\n\n\n\n\n'
//newVer += '\n\n\n\n\n\n'
break // !!!
case 'diff-deletedline':
isContent = true
oldVer += txt
break
case 'diff-addedline':
isContent = true
newVer += txt
break
}
}
difDiv = document.createElement('div')
difDiv.style.cssText = 'padding:2px'
difDiv.innerHTML = '<br><br><h3>JS Engine diff</h3><hr style="height:5px" />'
diffJSDisplay()
difDiv.appendChild(document.createElement('hr'))
difDiv.appendChild(btFull)
dTable.parentNode.insertBefore(difDiv, dTable.nextSibling)
scrollToElement(difDiv)
}
function diffJSFull(){
btFull.parentNode.removeChild(btFull)
//get versions Ids
var ma, newId, oldId
ma = tempTable.rows[0].cells[0].innerHTML.match(/oldid=(\d+)/)
if (ma) oldId = ma[1]; else { difDiv.innerHTML += '<p class=error>Could not find oldid</p>'; return }
ma = tempTable.rows[0].cells[1].innerHTML.match(/oldid=(\d+)/)
if (ma) newId = ma[1]; else newId = ''
//request versions
difDiv.innerHTML += '<br><br><h3>Full revisions comparison</h3><hr style="height:5px" />'
cursorWait(true)
oldVer = newVer = null
var url = wgServer + wgScript + '?action=raw&maxage=0&title=' + encodeURIComponent(curTitle)
requestPage(url + '&oldid=' + oldId, function(txt) {
oldVer = txt
if (newVer) diffJSDisplay()
})
requestPage(url + '&oldid=' + newId, function(txt) {
newVer = txt
if (oldVer) diffJSDisplay()
})
}
function diffJSDisplay(){
var txt = WDiffString(oldVer, newVer)
//txt = txt.replace(/\x03.*?\x04/g, '<br><br><hr><br><br>')
txt = txt.replace(/\x03|\x04/g, '')
if (!window.wikEdFullDiff ) txt = WDiffShortenOutput(txt)
//txt = txt.replace(/¶/g,'<br>')
txt = txt.replace(/&/g,'&')
//txt = txt.replace(/</g,'<').replace(/>/g, '>')
difDiv.innerHTML += txt
cursorWait()
}
}//diffJSEngine
// *** COMMON ***
function windowScrolled(){
if (self.pageYOffset) // all except Explorer
return self.pageYOffset
else if (document.documentElement && document.documentElement.scrollTop) // Explorer 6 Strict
return document.documentElement.scrollTop
else if (document.body) // all other Explorers
return document.body.scrollTop
}
function scrollToElement (el){
var yy = el.offsetTop
while (el = el.offsetParent) yy += el.offsetTop
scrollTo(0, yy)
}
function getTitleFromURL(url){
var tt = url.match(/title=([^&>"]+)/) //"
if (!tt) return ''
else return decodeURIComponent(tt[1]).replace(/_/g,' ')
}
function outputLink(page, params, name, tooltip){
if (!name) name = page
if (!tooltip) tooltip = name //.replace(/'/g,'`')
params = params || ''
page = page.replace(/&/gi,'&')
var k = page.indexOf('#')
if (k != -1) page = page.substring(0,k) + '#' + guessSectionName(page.substring(k+1))
return '<a href="'+ articlePath + encodeURI(page).replace(/\?/g,'%3F') + params
+'" title="' + tooltip.replace(/"/g,'"') + '">' + name + '</a>' //'
}
function guessTOCName(txt){ //make header into TOC item, will not work 100%
txt = txt.replace(/^ */,'').replace(/ *$/,'') //trim spaces
txt = txt.replace(/\[\[[^|]+\|([^\]]+)\]\]/g, '$1') //[[foo|bar]] -> bar
txt = txt.replace(/\[\[([^\]]+)\]\]/g, '$1') //[[bar]] -> bar
txt = txt.replace(/<.*?>/g, '').replace(/ /g,'_') //strip tags, spaces -> _
return txt
}
function guessSectionName(txt){ //make header into URL anchor, will not work 100%
//should behave like like Parser.php::guessSectionNameFromWikiText() and Sanitizer.php
txt = guessTOCName(txt)
//... skipping step "HTML entities are turned into their proper characters"
txt = encodeURIComponent(txt) //maybe encodeURI(p1.replace(/\?/g,'%3F').replace(/&/g,'%26'))
txt = txt.replace('%3A', ':').replace(/%([0-9A-F][0-9A-F])/g, '.$1')
return txt
}
function cursorWait(isWait){
if (window.dfNoWaitCursor) return
document.body.style.cursor = isWait ? 'wait' : ''
}
// *** CSS/JS ***
var dfHighlightSheet, dfImprovementSheet, dfPopupSheet
function addDiffTableCSS(){
if (dfImprovementSheet) return
addCSS('\
div.df-toolbar {float:right}\
div.df-toolbar span\
{cursor:pointer; padding:0 3px 0 3px; margin:0 3px 0 3px; border:1px solid #EEEEEE}\
')
dfImprovementSheet = addCSS('\
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%}\
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}\
table.diff td {cursor:help}\
table.diff td div, table.diff td.diff-multi {margin:0 8px 0 2px; cursor:default}'
+ (window.dfDiffTableCSS ? 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 addDiffPopupCSS(){
if (dfPopupSheet) return
if (document.URL.indexOf('&diff=') == -1) importStylesheetURI('/skins-1.5/common/diff.css')
dfPopupSheet = addCSS('\
div.df-popup{position:absolute; margin-right:15px; border:1px solid #000033; z-index:50; \
font-size:130%; background-color:white; visibility:hidden; min-width:75%}\
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% }')
}
//div.df-popup div.df-toolbar {}\
//div.df-popup table.diff {width:auto}\
// min-width was added for Safari
function highlightDiffs(e){
if (!dfHighlightSheet)
dfHighlightSheet = addCSS('.diffchange-inline, span.diffchange {border:1px solid red}\
div.df-toolbar span.df-highlight-btn {border:1px inset #EEEEEE}')
else dfHighlightSheet.disabled = !dfHighlightSheet.disabled
}
function addCSS(text){
var s = appendCSS(text) //from wikibits
return s.sheet || s //Safari compat
}
function importScriptAndRun(url, func) {
var s = document.createElement('script')
s.type = 'text/javascript'
s.src = url + '&action=raw&ctype=text/javascript'
if (isIE) s.onreadystatechange = function(){
if (this.readyState == 'loaded' || this.readyState == 'complete') func()
}
else s.onload = func
document.getElementsByTagName('head')[0].appendChild(s)
}
// *** AJAX ***
function requestPage(url, func){
if (requestedPages[url]) {func(requestedPages[url]); return }
var aj = sajax_init_object()
aj.open('GET', url, true)
aj.onreadystatechange=function() {
if (aj.readyState != 4) return
if (aj.status == 200) {
requestedPages[url] = aj.responseText
func(aj.responseText)
}else func(null)
}
aj.send(null)
}
function loadDiff(clickedLink, diffTable, func){
diffTable.style.opacity = '0.5'
cursorWait(true)
var url = clickedLink.href + '&action=render&diffonly=yes'
requestPage(url, loadDiff2)
function loadDiff2(html){
diffTable = replaceTable(diffTable, html)
//remember diff url and title
diffTable.parentNode.diffURL = url
var td = getElementsByClassName(diffTable, 'td', 'diff-ntitle')[0]
diffTable.parentNode.diffTitle = td ? getTitleFromURL(td.getElementsByTagName('a')[1].href) : ''
//insert permalink to this diff
var dv = document.createElement('span')
dv.innerHTML = '<a href="'+clickedLink.href+'" title="direct link to this diff" style="font-style:normal">[]</a>'
dv.style.cssText = 'float:right; font-size:smaller'
td = getElementsByClassName(diffTable, 'td', 'diff-otitle')[0]
if (td) td.firstChild.insertBefore(dv, td.firstChild.firstChild)
//td.lastChild.insertBefore(dv,td.lastChild.firstChild)
//improve
improveTable(diffTable)
cursorWait()
if (func) func(clickedLink, diffTable)
}
}
} //wrapper
if (doneOnloadHook) diffScript.start()
addOnloadHook(diffScript.start)