Jump to content

User:Js/diffs.js

From Wikipedia, the free encyclopedia
This is an old revision of this page, as edited by Js (talk | contribs) at 22:27, 24 March 2008 (see user:js/diffs). The present address (URL) is a permanent link to this revision, which may differ significantly from the current revision.
(diff) ← Previous revision | Latest revision (diff) | Newer revision → (diff)
Note: After saving, you have to bypass your browser's cache to see the changes. Google Chrome, Firefox, Microsoft Edge and Safari: Hold down the ⇧ Shift key and click the Reload toolbar button. For details and instructions about other browsers, see Wikipedia:Bypass your cache.
//additional parameter:
//dfImproveAdvanced = true


var diffPage = new function(){ //wrapper

var dfNoWikiParsing = window.dfNoWikiParsing
var ajax, noImprove, lastRequestTime, currentDiffTitle
var gotPages = {} //aray of retreived diffs
var isIE = navigator.userAgent.indexOf('MSIE') != -1

this.start = function(){

 addHandler(document, 'click', onClick)
 if (!window.dfNoArrowKeys) addHandler(document, 'keyup', onKeyUp)
 if (!window.dfNoPopups) addCSS('a[href^="'+wgServer+'/w/index.php"][href*="diff="],\
  a[href^="/w/index.php"][href*="diff="] {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
   var dTable = tables[i]
   //improve diff Table
   currentDiffTitle = wgPageName
   dTable.parentNode.diffURL = document.URL
   gotPages[document.URL] = '<table class=diff">' + dTable.innerHTML + '</table>'
   improveDiff(dTable)
   dTable.parentNode.insertBefore(createToolbar(dTable), dTable.parentNode.firstChild)
 }

}


 

function improveDiff(dTable){

 //log(dTable.innerHTML.length)
 if (noImprove || dTable.innerHTML.length>70000) return
 addDiffTableCSS()

 var trs = dTable.getElementsByTagName('tr'), tr, tds, td,  stripes = false
 //trs[0].className = 'df-header' 

for (var i=1; i<trs.length; i++){

 tr = trs[i]
 tds = tr.getElementsByTagName('td')
 tr.className = 'df-change' //by default, as most common case

 if (tds.length == 1){  // 'One intermediate revision not shown'
   //tr.className = 'message'
   continue
 
 }else if (tds.length == 2){ // "Line xx:"
   tr.className = 'df-lineno'
   expandCell(tds[1])
   continue

 }else if (tds.length == 3 && tds[1].className == 'diff-deletedline'){
   if (tds[1].innerHTML.length==0) tds[1].innerHTML = '&nbsp;'
   expandCell(tds[1], 'df-deletedline') //new class, means the line was simply deleted, has pink background
   continue

 }else if (tds.length == 3 && tds[2].className == 'diff-addedline'){
   processHTML(tds[2])
   htm = tds[2].innerHTML
   if (htm.length==0) tds[2].innerHTML = '&nbsp;'
   if (stripes) tr.className += ' odd'
   if (/<span class="?sig"?>/i.test(htm)) stripes = !stripes
   if (/^<div>==.*== *<\/div>$/i.test(htm)) 
      tds[2].style.cssText = 'font-weight:bold; font-size:120%; padding-top:15px'
   expandCell(tds[2])
   continue

 }else if (tds[1].className == 'diff-context') {
   tr.className = 'df-context'
   processHTML(tds[1])
   expandCell(tds[1])
   stripes = false
   continue
 }

 //from here we're left with normal yellow/green rows with 4 cells
 if (!window.dfImproveAdvanced) continue

 //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 = '5px solid transparent'
    tds[3].firstChild.style.borderBottom = '5px solid transparent'
    splitRowsUp(tds[1]) 
   }
  }

} // for



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
}


} //improveDiff()



function changeLevel(e){
 e = e || window.event
 var butt = e.target || e.srcElement
 var dTable = getClickedTable(e)
 var dfLevel = butt.innerHTML
 if (dfLevel == '-'){
   noImprove = false
   //dfNoWikiParsing = true
   butt.innerHTML = '='
 }else if (dfLevel == '='){
//   dfNoWikiParsing = false
//   butt.innerHTML = 'Ξ'
// }else if (dfLevel == 'Ξ'){
   noImprove = true
   butt.innerHTML = '-'
 }
 dTable = restoreTable(dTable)
 improveDiff(dTable)
}



function createToolbar(dTable){
 var dToolbar = document.createElement('div')
 //dToolbar.diffTable = dTable
 dToolbar.className = 'df-toolbar'
 //addDButton(restoreTable, '¶', 'Switch to or from original diff table')
 //dToolbar.innerHTML = '<span class=diff-time>.</span> '
 dToolbar.appendChild(btn(changeLevel, '=', 'Enable/disable diff improvement'))
 dToolbar.appendChild(btn(diffJSEngine, 'js', 'Show diffs using JS engine'))
 dToolbar.appendChild(btn(highlightDiffs, 'hl', 'Highlight diffs with red border', 'df-but-highlight'))
 //references back and forth
 dToolbar.tableParent = dTable.parentNode
 dTable.parentNode.diffToolbar = dToolbar
 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 = 'df-but'
 if (clss) bt.className += ' ' + clss
 bt.style.cssText = 'cursor:pointer; padding:0 3px 0 3px; margin:0 3px 0 3px;'
 return bt
}



function getClickedTable(e){
 e = e || window.event
 var button = e.target || e.srcElement
 return button.parentNode.tableParent.getElementsByTagName('table')[0]
}

function restoreTable(dTable){
 return replaceTable(dTable, gotPages[dTable.parentNode.diffURL])
}

function checkNOBRs(){
 var cntAdded = cntRemoved = 0
if (cntRemoved>0 || cntAdded>0){
  //hide context rows that are not needed anymore
 for (var i=1; i<trs.length-1; i++)
  if (tr.className.match(/df-context|df-lineno/)
    && !trs[i-1].className.match(/df-change/) && !trs[i+1].className.match(/df-change/))
    tr.style.display='none'

 //add notice that 0x0A changes are hidden
 var newtd = document.createElement('td')
 newtd.colSpan=4;  newtd.style.textAlign='center'; newtd.style.fontWeight = 'bold'
 var notice = (cntRemoved>0)?' задушено: '+cntRemoved:''
 notice += (cntAdded>0)?' вставлено: '+cntAdded:''
 newtd.innerHTML = '<span style="border:2px solid orange; padding:2px">Неразрывных пробелов' + notice + '</span>'
 trs[1].parentNode.insertBefore(newtd, trs[1])
}
}





function processHTML(elem){
 
 if (dfNoWikiParsing) return

 var html = elem.innerHTML
 if (html.length == 0) return  //elem.innerHTML = '&nbsp;'

 //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>')

 //[[link]]
 html = html.replace(/\[\[([^\]><}{|]+)\|?([^\]><]*)?\]\]/g,
 function(wikicode,page,name){
  if (/http:\/\//i.test(page)) return wikicode //user made a mistake
  if (isImage(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 = currentDiffTitle + 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 loadNextDiff(lnk){
 //find old table
 var el = lnk
 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
   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(oldTable, lnk.href)
 return true
}



function replaceTable(oldTable, html){
 //create temp div
 var el, newTable, tempDiv = document.createElement('div')
 tempDiv.innerHTML = html
 newTable = tempDiv.getElementsByTagName('table')[0]
 //insert temp div
 oldTable.parentNode.insertBefore(tempDiv, oldTable)
 //remove old table and (now outdated) prevew below
 while ((el=tempDiv.nextSibling) && !/visualClear|df-caption/.test(el.className))
   el.parentNode.removeChild(el)
 //get rid of temporary DIV
 while (el=tempDiv.firstChild) 
   tempDiv.parentNode.insertBefore(el, tempDiv)
 tempDiv.parentNode.removeChild(tempDiv)
 //return new table
 return newTable
}










// *** POPUP ***

var popupCount = 0

function onClick(e){
 //check if click was on a diff link
 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 lnk = e.target || e.srcElement
 var url = lnk.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 (lnk.parentNode.className == 't-print') return
 
 //workaround: for image diffs: doesn't work with &action=render
 if (isImage(getTitleFromURL(url))){
  jsMsg('Sorry, diffPopup doesn\'t work with diffs to images pages')
  return false
 }

 var isClickIntercepted = false
 if (/differences-(prev|next)link/.test(lnk.id)) isClickIntercepted = loadNextDiff(lnk)
 else if (!window.dfNoPopups) isClickIntercepted = createPopup(lnk)
 
 if (isClickIntercepted){ //do not follow the link 
   if (e.preventDefault) e.preventDefault(); else e.returnValue = false 
   return false
 }else 
   return true
 
}



function createPopup(lnk){

 lnk.style.backgroundColor = '#DDDDFF' //mark link as 'clicked'. especially useful for watchlist/RC
 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
 var dTable = document.createElement('table')
 pop.appendChild(dTable)
 dTable = loadDiff(dTable, lnk.href)
 var dTitle = currentDiffTitle

 //add bottom and top captions
 pop.appendChild(createCaption(dTable))
 pop.insertBefore(createCaption(dTable), pop.firstChild)



 document.body.appendChild(pop)
 return true

 //if it's too wide
 //if (elementWidth(pop) +10 > windowWidth()) scrollBy(elementWidth(pop), 0)
 function createCaption(){
  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,lnk,  1)}, 
     '↓', 'Show the following diff on this page')) 
   dCaption.appendChild( btn(function(e){neighborDiff(e,lnk, -1)}, 
     '↑', 'Show previous diff on this page')) 
  }
  //diff title 
  var sp = document.createElement('span')
  sp.innerHTML = '<b>'+outputLink(dTitle)+'</b>' 
   + ' (' + outputLink(dTitle+'?action=history', 'h') + ')'
  dCaption.appendChild(sp)
  //toolbar
  dCaption.insertBefore(createToolbar(dTable), dCaption.firstChild)
  //parseSigStamp(dTable.diffTime)
  return dCaption
 }
}


function captionClick(e){
 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'
 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) loadNextDiff(lnk) // or  document.location.href = link.href
}

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){
 var dTable = getClickedTable(e)
 dTable = restoreTable(dTable)
 importScriptAndRun('http://en.wikipedia.org/w/index.php?title=User:Cacycle/diff.js', diffJSGo)

 function diffJSGo(){
  var oldVer = newVer = ''
  var rows = []
  tds = dTable.getElementsByTagName('td')
  for (var i=1; i<tds.length; i++){
    td = tds[i]
    switch(td.className){
    case 'diff-context':
     i++ // and then the same as below
    case 'diff-lineno':
     marker = '\x03' + rows.length + '\x04'
     marker = '\x03'
     oldVer += marker
     newVer += marker
     rows[rows.length] = td
     i++
     break
    case 'diff-deletedline':
     oldVer += td.innerHTML.replace(/<.+?>/g,'')
     break
    case 'diff-addedline':
     newVer += td.innerHTML.replace(/<.+?>/g,'')
     break
    }
   }
  var diffText = WDiffString(oldVer, newVer)
  diffText = diffText.replace(/¶/g,'<br>').replace(/\x03/g, '<br><br><hr><br><br>')
  if (!window.fullDiff) diffText = WDiffShortenOutput(diffText)
  diffDiv = document.createElement('div')
  diffDiv.innerHTML = '<br><br><h3>JS Engine diff</h3><hr style="height:5px" />' + diffText
  dTable.parentNode.insertBefore(diffDiv, dTable.nextSibling)
  improveDiff(dTable) //improve it back to the old level
 }
}




// *** 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 getTitleFromURL(url){
 var tt = url.match(/title=([^&>"]+)/) //"
 if (!tt) return ''
 else return decodeURIComponent(tt[1]).replace(/_/g,' ')
}

function isImage(page){
 return /^image:|\.(jpg|png|svg|gif)$/i.test(page)
}

function outputLink(page, name, tooltip){
 if (!name) name = page
 if (!tooltip) tooltip = name //.replace(/'/g,'`')
 page = page.replace(/&amp;/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
}



// *** CSS/JS ***
var doneDiffTableCSS, doneDiffPopupCSS, highlighDiffCSS

function  addDiffTableCSS(){
//table.diff td {padding-left:3px}\
//td.diff-addedline, td.diff-deletedline, td.df-deletedline 
 if (doneDiffTableCSS) return
 addCSS('\
tr.df-change td {font-size:100%; padding-left:3px}\
table.diff, td.diff-otitle, td.diff-ntitle {background:#FBFBFB}\
tr.df-lineno td.diff-lineno {padding-top:30px; font-size:80%; font-weight:normal}\
td.df-deletedline {background-color:#FEC}\
table.diff td div {min-height:1em}\
td.df-deletedwords, td.df-addedwords\
 {background:white; border-left:1px dotted gray; border-right:1px dotted gray}\
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%}\
div.df-toolbar{float:right; border:1px solid gray}')
 doneDiffTableCSS = true
}

function addDiffPopupCSS(){
 if (doneDiffPopupCSS) return
 importCSS('/skins-1.5/common/diff.css')
 addCSS('\
div.df-popup{position:absolute; margin-right:15px; border:3px outset yellow; z-index:50; \
 font-size:130%; background-color:white}\
div.df-popup div.df-caption{float:none; background:#F0F0F0; font-size:120%;\
 border:2px outset gray; padding:2px; cursor:pointer}\
div.df-popup div.df-toolbar {border:none}')
 doneDiffPopupCSS = true
}
//div.df-popup table.diff {width:auto}\

function highlightDiffs(e){
 if (!highlighDiffCSS) 
   highlighDiffCSS = addCSS('span.diffchange{border:1px solid red}\
 span.df-but-highlight {border:1px inset gray}')
 else highlighDiffCSS.disabled = !highlighDiffCSS.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){ //could use createStyleSheet for IE as well
 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 //so we can disable it later, Safari insists on .sheet 
}

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 getPage(url){
 if (!gotPages[url]) {
   document.body.style.cursor = 'wait'
   if (!ajax) ajax = sajax_init_object()
   //if (ajax.overrideMimeType) ajax.overrideMimeType('text/html')
   ajax.open('GET', url, false)
   ajax.send(null)
   gotPages[url] = ajax.responseText
   lastRequestTime = parseServerTime(ajax.getResponseHeader('Date'))
   document.body.style.cursor = ''
 }
 return(gotPages[url])
}


function loadDiff(oldTable, url){
 oldTable.style.opacity = '0.6'
 url += '&diffonly=yes&action=render&diffonly=true'
 var html = getPage(url)
 var newTable = replaceTable(oldTable, html)
 newTable.parentNode.diffURL = url
 dispDiffInfo(newTable)
 improveDiff(newTable)
 return newTable
}


function dispDiffInfo(dTable){
 var td = getElementsByClassName(dTable, 'td', 'diff-ntitle')[0]
 if (!td) return
 // emphasize if this is current revision
 //var aa = tds[1].getElementsByTagName('a')[0]
 //if (!/oldid=/.test(aa.href)) aa.style.cssText = 'border:2px solid green; padding:0 2px 0 2px'  
 //get title from (edit) link
 currentDiffTitle = getTitleFromURL(td.getElementsByTagName('a')[1].href)
 return
 //get edit  time
 var ma = td.innerHTML.match(/\d\d:\d\d, \d\d? [^ ]+ 20\d\d/)
 var dT = dTable.parentNode.diffToolbar
 if (!ma || !dT || !lastRequestTime) return
 var dTimeSpan = getElementsByClassName(dT, 'span', 'diff-time')[0]
 var diffTime = parseSigStamp(ma[0])
 var nowTime = parseServerTime(lastRequestTime) // !!!  GET OFFSET too
 dTime[0].innerHTML = ma[0]
 // guessTimezone from wikibits?  
 //use lastEdited.js  !!!! 
} 


function parseServerTime(ts){ //"Tue, 29 Jan 2008 22:32:21 GMT" -> date
 if (!ts) return null
 var ma = ts.match(/(\d\d?) ([A-Z][a-z][a-z]) (\d\d\d\d) (\d\d):(\d\d):(\d\d)/)
 if (ma){
   var d = new Date()
   d.setYear(ma[3])
   d.setMonth('janfebmaraprmayjunjulaugsepoctnovdec'.indexOf(ma[2].toLowerCase()) / 3)
   d.setDate(ma[1])
   d.setHours(ma[4])
   d.setMinutes(ma[5])
   d.setSeconds(ma[6])
 }else
   var d = new Date(ts.substring(0, ts.length-4)) //cut "GMT" part
 return d
} 

function parseSigStamp(sig){ // '05:53, 7 марта 2007' -> date
 var s = sig.split(' ')
 var sigTime = new Date()
 sigTime.setYear(s[3])
 var month_name = s[2].substring(0,3).toLowerCase()
 var month = 'янвфевмарапрмаяиюниюлавгсеноктноядек'.indexOf(month_name)
 if (month == -1) month = 'janfebmaraprmayjunjulaugsepoctnovdec'.indexOf(month_name)
 if (month == -1) return null
 sigTime.setMonth(month/3)
 sigTime.setDate(s[1])
 sigTime.setHours(s[0].substring(0,2))
 sigTime.setMinutes(s[0].substring(3,5))
 sigTime.setSeconds(0)
 return sigTime
}

} //wrapper


addOnloadHook(diffPage.start)