/* [[:en:User:Js/diffs.js]] */
/*
Switches
--------
(these should be set to true to override standard behaviour)
dfNoAjaxDiff: no quick next/prev loading on usual diff pages
dfNoPopups: no popups
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 : disable "wait" cursor
wikEdFullDiff: do not shorten JS Diff Engine output (seems useless)
CSS parameters
--------------
dfDiffLinksCSS: CSS for diff links, default: "font-style:italic"
dfDiffTableCSS: extra CSS for diff table
*/
var currentLink, currentTable // !! debugging
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 = []
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 i = 0, tables = content.getElementsByTagName('table')
while (i < tables.length && tables[i].className != 'diff') i++
if (i == tables.length) return //then it's div.firstrevisionheader
currentTable = tables[i]
//remember url and title
currentTable.parentNode.diffURL = document.URL
currentTable.parentNode.diffTitle = wgPageName
//improve diff Table
requestedPages[document.URL] = '<table class=diff>' + currentTable.innerHTML + '</table>'
improveCurrentTable()
currentTable.parentNode.insertBefore(createToolbar(), currentTable.parentNode.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
currentLink = targ
var isClickIntercepted = true
if (/differences-(prev|next)link/.test(targ.id)) isClickIntercepted = followNextLink()
else if (!dfNoPopups) createPopup()
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 improveCurrentTable(){
if (currentTable.innerHTML.length>70000) return
addDiffTableCSS()
var trs = currentTable.getElementsByTagName('tr')
curTitle = currentTable.parentNode.diffTitle //to be used in processHTML()
curStripes = false
for (var i=1; i<trs.length; i++) improveRow(trs[i])
}
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'
return //plus maybe //tr.className = 'df-message'
}else if (tds.length == 2){ // "Line xx:"
tr.className = 'df-lineno'
return
}else if (tds.length == 3 && tds[1].className == 'diff-deletedline'){
if (tds[1].innerHTML.length==0) tds[1].innerHTML = ' '
expandCell(tds[1], 'df-deletedline') //new class, means the line was simply deleted, has pink background
return
}else if (tds.length == 3 && tds[2].className == 'diff-addedline'){
processHTML(tds[2])
htm = tds[2].innerHTML
if (htm.length==0) tds[2].innerHTML = ' '
if (curStripes) tr.className += ' odd'
if (/<span class="?sig"?>/i.test(htm)) curStripes = !curStripes
if (/^<div>==.*== *<\/div>$/i.test(htm))
tds[2].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'
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){
e = e || window.event
var butt = e.target || e.srcElement
currentTable = getClickedTable(e)
var dfLevel = butt.innerHTML
if (dfImprovementSheet.disabled){
improveCurrentTable()
dfImprovementSheet.disabled = false
}else{
//butt.innerHTML = '-'
replaceCurrentTable(requestedPages[currentTable.parentNode.diffURL])
dfImprovementSheet.disabled = true
}
}
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 == 'df-change'){
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(){
var dToolbar = document.createElement('div')
//dToolbar.diffTable = currentTable
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
dToolbar.tableParent = currentTable.parentNode //reference so we can find table later
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(){ //loads next/prev diff using next/prev diff link
//find old table
var el = currentLink
while (el && el.nodeName != 'TABLE') el = el.parentNode
if (!el || el.className != 'diff') return false
currentTable = el
if (currentTable.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()
return true
}
function replaceCurrentTable(html){
var oldTable = currentTable, parent = oldTable.parentNode, el
//append new table
currentTable = createTableFromHTML(html)
parent.insertBefore(currentTable, oldTable)
//remove everything below new table: old table, (now outdated) prevew, js engine diff
while ((el=currentTable.nextSibling) && !/visualClear|df-caption/.test(el.className))
parent.removeChild(el)
}
function createTableFromHTML(html){
if (!tempDiv) tempDiv = document.createElement('div')
tempDiv.innerHTML = html
return tempDiv.getElementsByTagName('table')[0]
}
// *** POPUP ***
function createPopup(lnk){
if (lnk) currentLink = lnk
//unfortunately, image diffs do not work with &action=render
//initialize
markLink(currentLink)
addDiffPopupCSS()
if (isIE) hideAllSelectElements()
//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
document.body.appendChild(pop) //have to append now, otherwise table is broken in Safari 3
currentTable = document.createElement('table')
pop.appendChild(currentTable)
loadDiff(createPopup2)
}
function createPopup2(){
var pop = currentTable.parentNode
pop.style.visibility = 'visible'
//add bottom and top captions
pop.appendChild(createCaption())
pop.insertBefore(createCaption(), pop.firstChild)
return true
//if it's too wide
//if (elementWidth(pop) +10 > windowWidth()) scrollBy(elementWidth(pop), 0)
function createCaption(){ //for popup
var dCaption = document.createElement('div')
dCaption.className = 'df-caption'
//dCaption.onclick = captionClick
//on special pages
if (wgNamespaceNumber == -1){
dCaption.appendChild( btn(function(e){neighborDiff(e,currentLink, 1)},
'↓', 'Open next diff link on that page'))
dCaption.appendChild( btn(function(e){neighborDiff(e,currentLink, -1)},
'↑', 'Open previous diff link on that page'))
}
//add page title
var sp = document.createElement('span')
var dTitle = currentTable.parentNode.diffTitle
sp.innerHTML = '<b>'+outputLink(dTitle)+'</b>'
+ ' (' + outputLink(dTitle+'?action=history', 'h') + ')'
dCaption.appendChild(sp)
//add toolbar
dCaption.insertBefore(createToolbar(), dCaption.firstChild)
return dCaption
}
}
function captionClick(e){ // !! obsolete?
e = e || window.event
var el = e.target || e.srcElement
if (el && el.className && el.className == 'df-caption') closePopup(el.parentNode)
}
function closePopup(div){
div.style.display = 'none'
//purge(div)
div.parentNode.removeChild(div)
popupCount--
if (isIE && (popupCount==0)) hideAllSelectElements(true) //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
currentLink = lnk
if (!followNextLink()) document.location.href = lnk.href
}
function markLink(lnk, isError){ //mark link as 'clicked'. especially useful for watchlist/RC
lnk.style.backgroundColor = isError ? '#FFDDDD' :'#DDDDFF'
}
function hideAllSelectElements(isRestore){ //workaround for IE <select> zIndex bug
var sels = document.getElementsByTagName('select')
for (var i=0; i<sels.length; i++)
sels[i].style.visibility = isRestore ? 'visible' : 'hidden'
}
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('https://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 = mw.config.get('wgServer') + mw.config.get('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, name, tooltip){
if (!name) name = page
if (!tooltip) tooltip = name //.replace(/'/g,'`')
page = page.replace(/&/gi,'&')
var k = page.indexOf('#')
if (k != -1) page = page.substring(0,k) + '#' + guessSectionName(page.substring(k+1))
return '<a href="'+mw.config.get('wgServer')+mw.config.get('wgArticlePath').replace('$1', page)
+'" title="' + tooltip.replace(/"/g,'%22') + '">' + 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(){
//table.diff td {padding-left:3px}\
//td.diff-addedline, td.diff-deletedline, td.df-deletedline
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%}\
table.diff td {padding-left:2px}\
table.diff, td.diff-otitle, td.diff-ntitle {background:#FBFBFB}\
table.diff td.diff-lineno {border-top: 25px solid #FBFBFB}\
td.df-deletedline {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%}\
div.df-toolbar span.df-improve-btn {border:1px inset #EEEEEE}\
table.diff td {padding-right:8px; cursor:help}\
table.diff td div, table.diff td.diff-multi {cursor:default}' //make TD clickable (sticking out from under DIV inside)
+ (window.dfDiffTableCSS ? dfDiffTableCSS : '')) //user CSS
//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) importCSS('/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('span.diffchange{border:1px solid red}\
div.df-toolbar span.df-highlight-btn {border:1px inset #EEEEEE}')
else dfHighlightSheet.disabled = !dfHighlightSheet.disabled
}
function importCSS(url){
if (document.createStyleSheet) var s = document.createStyleSheet(url) //IE
else {
var s = document.createElement('style')
s.type = 'text/css'
s.appendChild (document.createTextNode('@import "' + url + '";'))
document.getElementsByTagName('head')[0].appendChild(s)
}
return s
}
function addCSS(text){
var s = document.createElement('style')
s.setAttribute('type', 'text/css')
if (s.styleSheet) s.styleSheet.cssText = text //IE
else s.appendChild(document.createTextNode(text))
document.getElementsByTagName('head')[0].appendChild(s)
return s.sheet || s
}
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(func){
currentTable.style.opacity = '0.5'
cursorWait(true)
var url = currentLink.href + '&action=render&diffonly=yes'
requestPage(url, loadDiff2)
function loadDiff2(html){
replaceCurrentTable(html)
//remember diff url and title
currentTable.parentNode.diffURL = url
var td = getElementsByClassName(currentTable, 'td', 'diff-ntitle')[0]
currentTable.parentNode.diffTitle = td ? getTitleFromURL(td.getElementsByTagName('a')[1].href) : '??'
//improve
improveCurrentTable()
if (func) func()
cursorWait()
}
}
} //wrapper
if (doneOnloadHook) diffScript.start()
$(diffScript.start)