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. |
/*
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('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, 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="'+wgServer+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()
addOnloadHook(diffScript.start)