User:Microchip08/uberdiff.js
Note: After publishing, you may have to bypass your browser's cache to see the changes.
- Firefox / Safari: Hold Shift while clicking Reload, or press either Ctrl-F5 or Ctrl-R (⌘-R on a Mac)
- Google Chrome: Press Ctrl-Shift-R (⌘-Shift-R on a Mac)
- Internet Explorer / Edge: Hold Ctrl while clicking Refresh, or press Ctrl-F5
- Opera: Press Ctrl-F5.
/*
This script is not supported by Microchip08
See [[:en:User:Js/diff]] for directions
http://en.wikipedia.org/w/index.php?title=User:Js/diffs.js&oldid=279812200
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
dfHighlightOn : turn diff highlighting (red borders) on by default
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
-----------------
dfMaxImproveSize : diffs over this size (in Kb) will not be improved automatically
*/
ffNoPopups=true
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', '')
var clickedLinkLast
this.start = function(){
addHandler(document, 'click', onClick)
if (!window.dfNoArrowKeys) addHandler(document, 'keyup', onKeyUp)
if (!dfNoPopups) appendCSS('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 (window.dfMaxImproveSize && dTable.innerHTML.length>dfMaxImproveSize) 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
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,'')
processHTML(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
processHTML(tds[0])
expandCell(tds[0], 'df-deletedwords')
}else if (!/<span/i.test(oldline)){ //simple change: something added
processHTML(tds[1])
expandCell(tds[1], 'df-addedwords')
}else{ //complex case
//processHTML(tds[1])
//processHTML(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 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 = ' '
html = html.replace(/({\{userlinks\|)([^}]+)}\}/, function(str,tmpl,user){
return tmpl + outputLink('special:contributions/'+user,'',user) + '}}' })
//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
}
if (/^[a-z]{2,7}:/.test(page)) //possible interproject link, and some are not "local"
page = 'Special:Search/'+page
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
if (clickedLinkLast)
changeClass(clickedLinkLast, 'df-clicked-last', 'df-clicked')
clickedLinkLast = clickedLink
changeClass(clickedLinkLast, 'df-clicked', 'df-clicked-last')
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)
if (window.dfHighlightOn) highlightDiffs()
}
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 = 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, 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
appendCSS('\
div.df-toolbar {float:right; margin-left:10px}\
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:90%}\
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% }\
a.df-clicked {background-color:#E5E5E5}\
a.df-clicked-last {background-color:#FFDDDD}\
')
}
// 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)
}
}
function changeClass(el, oldC, newC){
el.className = el.className.replace(oldC, '').replace(/ +/g,' ') + ' ' + newC
}
} //wrapper
$(diffScript.start)