User:Charibot/monaco.js

var diffScript = new function{ //wrapper var dfNoWikiParsing = window.dfNoWikiParsing, dfNoPopups = window.dfNoPopups var curTitle, tempDiv, curStripes var requestedPages = {} //aray of retreived diffs, used as cache var isIE = navigator.userAgent.indexOf('MSIE') != -1 var popupCount = 0 //, popupArray = [] var articlePath = wgArticlePath.replace('$1', '') this.start = function{ addHandler(document, 'click', onClick) if (!window.dfNoArrowKeys) addHandler(document, 'keyup', onKeyUp) if (!dfNoPopups) addCSS('a[href^="'+wgServer+'/w/index.php"][href*="diff="],\ a[href^="/w/index.php"][href*="diff="]' + (window.dfDiffLinksCSS || '{font-style:italic}')) //if (isIE && isIE6) //no CSS3 support in IE6, should make links italic manually if (document.URL.indexOf('diff=') != -1){ //this is a diff page //find diff table var content = document.getElementById('content') || document.getElementById('mw_content') || document var curTable = findDiffTable(content) if (!curTable) return var parent = curTable.parentNode //remember url and title, and cache parent.diffURL = document.URL parent.diffTitle = wgPageName requestedPages[document.URL] = ' ' //improve diff Table improveTable(curTable) parent.insertBefore(createToolbar(parent), parent.firstChild) } } function onClick(e){ cursorWait //cancel waiting indicator if something went wrong //find event and click target e = e || window.event if (e.shiftKey || e.button == 2) return // shift key or right click if ((isIE && e.button == 4) || (!isIE && e.button == 1)) return //middle click var targ = e.target || e.srcElement //log(targ) if (!targ) return //clicked on diff table // ... //clicked on diff popup if (targ.className) switch (targ.className){ case 'df-popup': closePopup(targ); return case 'df-caption': closePopup(targ.parentNode); return case 'diff-lineno': changeBlock(targ.parentNode); return case 'diff-addedline': case 'diff-deletedline': case 'diff-context': processCell(targ); return } /* if (!dfNoPopups && targ.className){ if (targ.className=='df-popup') return closePopup(targ) if (targ.className=='df-caption') return closePopup(targ.parentNode) } if (targ.className == 'diff-lineno') return changeBlock(targ.parentNode) //else if (targ.className == 'diff-marker') return changeRow(targ.parentNode) */ //clicked on a diff link var url = targ.href if (!url || url.indexOf('diff=') == -1) return //not a diff if (url.indexOf(wgServer) != 0 && url.charAt(0) != '/') return //diff, but not to this server if (targ.parentNode.className == 't-print') return //check if it was nex/prev diff link var isClickIntercepted = true if (/differences-(prev|next)link/.test(targ.id)) isClickIntercepted = followNextLink(targ) else if (!dfNoPopups) createPopup(targ) else isClickIntercepted = false //do not follow the link if (isClickIntercepted){ if (e.preventDefault) e.preventDefault; else e.returnValue = false return false }else return true } function improveTable(dTable){ if (dTable.innerHTML.length>70000) return //remove diff marker colums //var cols = dTable.getElementsByTagName('col') //var col //while(col=dTable.getElementsByTagName('col')[0]) col.parentNode.removeChild(col) //improve rows var trs = dTable.getElementsByTagName('tr') curTitle = dTable.parentNode.diffTitle //needee in processHTML for relative links curStripes = false for (var i=1; i<trs.length; i++) improveRow(trs[i]) //add CSS addDiffTableCSS } function improveRow(tr){ var tds = tr.getElementsByTagName('td'), td tr.className = 'df-change' //by default, as most common case if (tds.length == 1){ // 'One intermediate revision not shown' tr.className = 'df-message' return //plus maybe }else if (tds.length == 2){ // "Line xx:" tr.className = 'df-lineno' return }else if (tds.length == 3 && tds[1].className == 'diff-deletedline'){ tr.className += ' df-deleted' if (tds[1].innerHTML.length==0) tds[1].innerHTML = ' ' 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 = ' ' if (curStripes) tr.className += ' odd' if (//i.test(htm)) curStripes = !curStripes if (/^ ==.*== *<\/div>$/i.test(htm)) tds[2].firstChild.style.cssText = 'font-weight:bold; font-size:120%; padding-top:15px' expandCell(tds[2]) return }else if (tds[1].className == 'diff-context') { tr.className = 'df-context' if (window.dfParseContext) processHTML(tds[1]) expandCell(tds[1]) curStripes = false return } //from here we're left with normal yellow/green rows with 4 cells tds[1].colSpan = tds[3].colSpan = 2 //tds[1].style.borderRight = '10px solid white' tr.removeChild(tds[2]); tr.removeChild(tds[0]) return if (!window.dfImproveAdvanced) return //check for simple diffs var oldline = tds[1].innerHTML var newline = tds[3].innerHTML if (oldline.length < 90 && oldline.replace(/<.+?>| |\n/g,) == ){ //old empty tds[3].className = 'diff-addedline' tds[3].innerHTML = newline.replace(/ /i,).replace(/<\/span>/i,) processHTML(tds[3]) splitRowsUp(tds[1]) }else if (newline.length < 90 && newline.replace(/<.+?>| |\n/g,) == ){ //new empty tds[1].className = 'df-deletedline' // !!! replace wih tr-deleted tds[1].innerHTML = oldline.replace(/ /i,).replace(/<\/span>/i,) splitRowsUp(tds[3]) }else if (!/<span/i.test(newline)){ //simple change: something removed processHTML(tds[1]) expandCell(tds[1], 'df-deletedwords') }else if (!/<span/i.test(oldline)){ //simple change: something added processHTML(tds[3]) expandCell(tds[3], 'df-addedwords') }else{ //complex case //processHTML(tds[1]) //processHTML(tds[3]) if (window.dfOneColumn){ // separate into different rows anyway tds[1].firstChild.style.borderTop = '10px solid #FBFBFB' tds[3].firstChild.style.borderBottom = '10px solid #FBFBFB' splitRowsUp(tds[1]) }else{ //remove + / - markers ? } } function expandCell(td, clss){ while (td.nextSibling) tr.removeChild(td.nextSibling) while (td.previousSibling) tr.removeChild(td.previousSibling) td.colSpan = 4 if (clss) td.className = clss } function splitRowsUp(tdGoesUp){ tds[1].colSpan = 4 tds[3].colSpan = 4 tr.removeChild(tds[2]) tr.removeChild(tds[0]) var trnew = document.createElement('tr') trnew.className = 'df-change' trnew.appendChild(tdGoesUp) tr.parentNode.insertBefore(trnew, tr) i++ //increment i in for loop } } //improveRow function changeTable(e){ //switch between original diff table and improved e = e || window.event var butt = e.target || e.srcElement var curTable = getClickedTable(e) if (dfImprovementSheet.disabled) improveTable(curTable) else replaceTable(curTable, requestedPages[curTable.parentNode.diffURL]) dfImprovementSheet.disabled = !dfImprovementSheet.disabled } function changeBlock(row){ //switch improvement level for this part of diff table var dTbody = row.parentNode, rowIdx = 1, isImproved //find clicked row number while (rowIdx < dTbody.rows.length && dTbody.rows[rowIdx] != row) rowIdx++ if (dTbody.rows[rowIdx] != row) return //check if rows are improved or not if (row.className == 'df-lineno'){ isImproved = true var origTable = createTableFromHTML(requestedPages[dTbody.parentNode.parentNode.diffURL]) }else dfImprovementSheet.disabled = false //improve / de-improve rows do{ if (isImproved) dTbody.replaceChild(origTable.rows[rowIdx].cloneNode(true), row) else improveRow(row) }while((row=dTbody.rows[++rowIdx]) && row.cells[0].className != 'diff-lineno') } function processCell(cell){ //parse wikicode in already improved row when clicked on white border above row if (cell.origHTML){ //restore cell.innerHTML = cell.origHTML cell.origHTML = null }else{ processHTML(cell) } } // NOT USED function changeRow(row){ //switch one rowl improvement level when clicked on +- marker on the left var dTbody = row.parentNode, rowIdx = 1 //find clicked row number while (rowIdx < dTbody.rows.length && dTbody.rows[rowIdx] != row) rowIdx++ if (dTbody.rows[rowIdx] != row) return //check if rows are improved or not if (row.className.indexOf('df-change') != -1){ var origTable = createTableFromHTML(requestedPages[dTbody.parentNode.parentNode.diffURL]) dTbody.replaceChild(origTable.rows[rowIdx].cloneNode(true), row) }else{ dfImprovementSheet.disabled = false improveRow(row) var tds = row.cells processHTML(tds[1]) processHTML(tds[3]) } } function createToolbar(parent){ var dToolbar = document.createElement('div') dToolbar.tableParent = parent //reference so we can find table later dToolbar.className = 'df-toolbar' dToolbar.appendChild(btn(changeTable, '¤', 'Enable/disable improvements', 'df-improve-btn')) //÷ dToolbar.appendChild(btn(highlightDiffs, 'π', 'Highlight differences with red border', 'df-highlight-btn')) dToolbar.appendChild(btn(diffJSEngine, 'Δ', 'Javascript diff engine')) //references back and forth return dToolbar } function btn(func, htm, tooltip, clss){ //creates 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(/(\*)?\]/g, // function (str,link,name){  var output = ' 70)) name = name.substring(0,60) + '… …'  return output + ' title="' + tip + '">[' + name + ']' }) elem.innerHTML = html function tryDecodeURI(s){ try{s=decodeURIComponent(s)}catch (e){}; return s } } function followNextLink(clickedLink){ //loads next/prev diff using next/prev diff link //find old table var el = clickedLink while (el && el.nodeName != 'TABLE') el = el.parentNode if (!el || el.className != 'diff') return false var oldTable = el if (oldTable.parentNode.className != 'df-popup'){ //normal diff page, not a popup if (window.dfNoAjaxDiff) return false if (el=document.getElementById('t-print')) el.style.display = 'none' //hide "printable" link which becomes outdated } //replace diff with new table loadDiff(clickedLink, oldTable) return true } function replaceTable(oldTable, html){ //append new table var newTable = createTableFromHTML(html) oldTable.parentNode.insertBefore(newTable, oldTable) //remove everything below new table: old table, (now outdated) prevew, js engine diff var el while ((el=newTable.nextSibling) && !/visualClear|df-caption/.test(el.className)) el.parentNode.removeChild(el) return newTable } function createTableFromHTML(html){ if (!tempDiv) tempDiv = document.createElement('div') tempDiv.innerHTML = html return findDiffTable(tempDiv) } function findDiffTable(el){ var i = 0, tables = el.getElementsByTagName('table') while (i < tables.length && tables[i].className != 'diff') i++ if (i < tables.length) return tables[i]; else return null //then it's div.firstrevisionheader } // *** POPUP *** function createPopup(clickedLink){ //initialize clickedLink.style.backgroundColor = '#F5F5FF' addDiffPopupCSS if (isIE) hideAllSelectElements(true) //create popup popupCount++ var pop = document.createElement('div') pop.className = 'df-popup' pop.style.top = windowScrolled + 30 + popupCount*10 + 'px' pop.style.left = 10 + popupCount*10 + 'px' //load diff var oldTable = document.createElement('table') pop.appendChild(oldTable) document.body.appendChild(pop) //have to append now, otherwise table is broken in Safari 3 loadDiff(clickedLink, oldTable, showPopup) } function showPopup(clickedLink, diffTable){ clickedLink.style.backgroundColor = '#DDDDFF' var pop = diffTable.parentNode pop.appendChild(createCaption) pop.insertBefore(createCaption, diffTable) pop.style.visibility = 'visible' return true function createCaption{ var dCaption = document.createElement('div') dCaption.className = 'df-caption' //on special pages if (wgNamespaceNumber == -1){ dCaption.appendChild( btn(function(e){neighborDiff(e,clickedLink, 1)}, '↓', 'Open next diff link on that page')) dCaption.appendChild( btn(function(e){neighborDiff(e,clickedLink, -1)}, '↑', 'Open previous diff link on that page')) } //add page title var sp = document.createElement('span') var dTitle = diffTable.parentNode.diffTitle sp.innerHTML = +outputLink(dTitle)+ + ' (' + 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 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') 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(/&amp;/gi,'&') var k = page.indexOf('#') if (k != -1) page = page.substring(0,k) + '#' + guessSectionName(page.substring(k+1)) return '' + name + '' //' } function guessTOCName(txt){ //make header into TOC item, will not work 100% txt = txt.replace(/^ */,).replace(/ *$/,) //trim spaces txt = txt.replace(/\[\([^\+)\]\]/g, '$1') //bar -> bar txt = txt.replace(/\[\[([^\]]+)\]\]/g, '$1') //bar -> bar txt = txt.replace(/<.*?>/g, '').replace(/ /g,'_') //strip tags, spaces -> _ return txt } function guessSectionName(txt){ //make header into URL anchor, will not work 100% //should behave like like Parser.php::guessSectionNameFromWikiText and Sanitizer.php txt = guessTOCName(txt) //... skipping step "HTML entities are turned into their proper characters" txt = encodeURIComponent(txt)  //maybe encodeURI(p1.replace(/\?/g,'%3F').replace(/&/g,'%26')) txt = txt.replace('%3A', ':').replace(/%([0-9A-F][0-9A-F])/g, '.$1') return txt } function cursorWait(isWait){ if (window.dfNoWaitCursor) return document.body.style.cursor = isWait ? 'wait' : '' } // *** CSS/JS *** var dfHighlightSheet, dfImprovementSheet, dfPopupSheet function addDiffTableCSS{ if (dfImprovementSheet) return addCSS('\ div.df-toolbar {float:right}\ div.df-toolbar span\ {cursor:pointer; padding:0 3px 0 3px; margin:0 3px 0 3px; border:1px solid #EEEEEE}\ ') dfImprovementSheet = addCSS('\ table.diff {width:99%}\ body table.diff, td.diff-otitle, td.diff-ntitle {background:#FBFBFB}\ table.diff td.diff-lineno {border-top: 25px solid #FBFBFB}\ tr.df-deleted td {background-color:#FEC}\ table.diff td div {min-height:1em}\ td.df-deletedwords, td.df-addedwords\ {background:white; border:1px dotted gray; padding:2px}\ td.df-deletedwords span.diffchange {background-color:#FFA}\ td.df-addedwords span.diffchange {background-color:#CFC; color:black; font-weight:normal}\ tr.odd td.diff-addedline {background-color:#BEB}\ span.sig {border:1px dotted gray; border-bottom:none; font-family:cursive; font-size:90%}\ tr.df-change td {font-size:100%}\ tr.df-added ins.diffchange {color:inherit; font-weight:normal; border:none}\ div.df-toolbar span.df-improve-btn {border:1px inset #EEEEEE}\ table.diff td {cursor:help}\ table.diff td div, table.diff td.diff-multi {margin:0 8px 0 2px; cursor:default}' + (window.dfDiffTableCSS ? dfDiffTableCSS : '')) //user CSS //cursor stuff shows that TD is clickable (sticking out from under DIV inside) //padding: 0 8px 0 2px //different approach to make cells clickable //+ 'table.diff {border-spacing:0} table.diff td {border-top:4px solid #FBFBFB} table.diff td.diff-deletedline {border-right: 6px solid #FBFBFB}' } function addDiffPopupCSS{ if (dfPopupSheet) return if (document.URL.indexOf('&diff=') == -1) importStylesheetURI('/skins-1.5/common/diff.css') dfPopupSheet = addCSS('\ div.df-popup{position:absolute; margin-right:15px; border:1px solid #000033; z-index:50; \ font-size:130%; background-color:white; visibility:hidden; min-width:75%}\ div.df-popup div.df-caption{float:none; background:#F0F0FF; font-size:120%;\ border:1px outset gray; padding:2px}\ div.df-popup table.diff {width:97%; margin:0 1% 0 1% }') } //div.df-popup div.df-toolbar {}\ //div.df-popup table.diff {width:auto}\ // min-width was added for Safari function highlightDiffs(e){ if (!dfHighlightSheet)  dfHighlightSheet = addCSS('.diffchange-inline, span.diffchange {border:1px solid red}\ div.df-toolbar span.df-highlight-btn {border:1px inset #EEEEEE}') else dfHighlightSheet.disabled = !dfHighlightSheet.disabled } function addCSS(text){ var s = appendCSS(text) //from wikibits return s.sheet || s //Safari compat } function importScriptAndRun(url, func) { var s = document.createElement('script') s.type = 'text/javascript' s.src = url + '&action=raw&ctype=text/javascript' if (isIE) s.onreadystatechange = function{    if (this.readyState == 'loaded' || this.readyState == 'complete') func   } else s.onload = func document.getElementsByTagName('head')[0].appendChild(s) } // *** AJAX *** function requestPage(url, func){ if (requestedPages[url]) {func(requestedPages[url]); return } var aj = sajax_init_object aj.open('GET', url, true) aj.onreadystatechange=function {   if (aj.readyState != 4) return   if (aj.status == 200) {      requestedPages[url] = aj.responseText      func(aj.responseText) }else func(null) } aj.send(null) } function loadDiff(clickedLink, diffTable, func){ diffTable.style.opacity = '0.5' cursorWait(true) var url = clickedLink.href + '&action=render&diffonly=yes' requestPage(url, loadDiff2) function loadDiff2(html){ diffTable = replaceTable(diffTable, html) //remember diff url and title diffTable.parentNode.diffURL = url var td = getElementsByClassName(diffTable, 'td', 'diff-ntitle')[0] diffTable.parentNode.diffTitle = td ? getTitleFromURL(td.getElementsByTagName('a')[1].href) : '' //insert permalink to this diff var dv = document.createElement('span') dv.innerHTML = '[]' dv.style.cssText = 'float:right; font-size:smaller' td = getElementsByClassName(diffTable, 'td', 'diff-otitle')[0] if (td) td.firstChild.insertBefore(dv, td.firstChild.firstChild) //td.lastChild.insertBefore(dv,td.lastChild.firstChild) //improve improveTable(diffTable) cursorWait if (func) func(clickedLink, diffTable) } } } //wrapper if (doneOnloadHook) diffScript.start addOnloadHook(diffScript.start)