No edit summary |
No edit summary |
||
Line 3: | Line 3: | ||
// Load various external scripts |
// Load various external scripts |
||
// ***************************************************************** |
// ***************************************************************** |
||
− | |||
− | importScriptURI('http://en.wikipedia.org/w/index.php?title=User:Js/diffs.js&action=raw&ctype=text/javascript'); |
||
importScriptURI('http://janitor.wikia.com/index.php?title=User:Exlex/scripts.js&action=raw&ctype=text/javascript'); |
importScriptURI('http://janitor.wikia.com/index.php?title=User:Exlex/scripts.js&action=raw&ctype=text/javascript'); |
||
+ | |||
+ | |||
+ | |||
+ | $(function(){ |
||
+ | |||
+ | |||
+ | var dfPopupSheet |
||
+ | |||
+ | |||
+ | mw.util.addCSS('\ |
||
+ | td.diff-addedline:hover .diffchange, td.diff-deletedline:hover .diffchange {background:#fdd}\ |
||
+ | ') |
||
+ | var localDomain = new RegExp('^https?:' + wgServer.replace(/([\.\/])/g,'\\$1') + '\/') |
||
+ | |||
+ | |||
+ | $(function(){ |
||
+ | |||
+ | var $tbl = $('table.diff') |
||
+ | if( $tbl.length ){ |
||
+ | improveTable($tbl) |
||
+ | dfAddToolbar($tbl, '#contentSub') |
||
+ | } |
||
+ | |||
+ | mw.util.$content.click(dfClick) |
||
+ | |||
+ | mw.util.addCSS('\ |
||
+ | a[href*="diff="][href^="/w"],\ |
||
+ | a[href*="diff="][href*="' + wgServer + '"]' + |
||
+ | (window.dfDiffLinksCSS || '{font-style:italic}') +'\ |
||
+ | a[href*="diff="][href^="/w"]:hover,\ |
||
+ | a[href*="diff="][href*="' + wgServer + '"]:hover\ |
||
+ | {color:red !important}\ |
||
+ | .df-popup {margin:0.5em}\ |
||
+ | ') |
||
+ | |||
+ | |||
+ | }) |
||
+ | |||
+ | $(document).keyup( function(e){ //close popup on Escape |
||
+ | if( e.which == 27 ) popupClose('.df-instance:last') |
||
+ | }) |
||
+ | |||
+ | |||
+ | |||
+ | function dfClick(e){ |
||
+ | |||
+ | cursorWait() //cancel waiting indicator if something went wrong |
||
+ | if( e.shiftKey || e.which != 1) return |
||
+ | |||
+ | //is it a diff link? |
||
+ | var lnk = $(e.target).closest('a') |
||
+ | if( !lnk.length ) return |
||
+ | var url = lnk.attr('href').replace(localDomain, '/') |
||
+ | if( ! /^\//.test(url) ) return //external URL |
||
+ | |||
+ | var loadURL, dfContainer |
||
+ | |||
+ | if( /[&?]diff=/.test(url) ){ |
||
+ | // diff |
||
+ | if( /differences-(next|prev)link/.test( lnk.attr('id') ) )//prev/next link in diff table |
||
+ | dfContainer = lnk.closest('table.diff').parent() |
||
+ | else |
||
+ | markClickedLink(lnk) |
||
+ | if( /:Undelete/.test(url) ) |
||
+ | loadURL = url + '&useskin=myskin #content' |
||
+ | else |
||
+ | loadURL = url + '&action=render&diffonly=true' |
||
+ | |||
+ | }else if( wgCanonicalSpecialPageName == 'Watchlist' |
||
+ | && window.dfPinWatchlist //popup for any link |
||
+ | && ! lnk.closest('fieldset').length ){ |
||
+ | |||
+ | if( ! /\?/.test(url) && ! /(special|служебная):/i.test(url) ) |
||
+ | loadURL = url + '?action=render' |
||
+ | else |
||
+ | loadURL = url + '&useskin=myskin #content' |
||
+ | |||
+ | }else{ |
||
+ | return |
||
+ | } |
||
+ | |||
+ | //load diff |
||
+ | e.preventDefault() |
||
+ | cursorWait(true) |
||
+ | dfContainer = dfContainer || popupCreate(e) |
||
+ | dfContainer |
||
+ | .attr('dfURL', url) |
||
+ | .load( loadURL, afterDiffLoaded ) |
||
+ | |||
+ | } |
||
+ | |||
+ | |||
+ | |||
+ | |||
+ | function afterDiffLoaded(){ |
||
+ | |||
+ | cursorWait() |
||
+ | var $container = $(this) |
||
+ | |||
+ | var url = $container.attr('dfURL') |
||
+ | var dfLink = outputLink2('', $container.attr('dfURL'), 'Δ', 'current diff') |
||
+ | |||
+ | var $tbl = $container.find('table.diff') |
||
+ | if( $tbl.length ) improveTable( $tbl ) |
||
+ | |||
+ | if ( $container.hasClass('df-popup') ){ |
||
+ | |||
+ | var pgTitle = getTitleFromURL( $tbl.find('td.diff-ntitle a').attr('href') ) |
||
+ | var caption = $( |
||
+ | '<div class=df-caption>' + |
||
+ | '<b>' + outputLink2(pgTitle) + '</b>' + |
||
+ | ' (' + outputLink2(pgTitle, '?action=history', 'h') + ' ' + dfLink + ')' + |
||
+ | '</div>' |
||
+ | ) |
||
+ | .prependTo($container) |
||
+ | |||
+ | dfAddToolbar($tbl, caption) |
||
+ | $container.parent().appendTo('body') |
||
+ | |||
+ | }else{ |
||
+ | $('#contentSub') |
||
+ | .children('.df-link').remove().end() |
||
+ | .append( |
||
+ | $('<span class=df-link style="margin-left:1em; font-weight:bold" />') |
||
+ | .append( dfLink ) |
||
+ | ) |
||
+ | } |
||
+ | |||
+ | } |
||
+ | |||
+ | |||
+ | |||
+ | |||
+ | |||
+ | |||
+ | |||
+ | function popupCreate(e){ |
||
+ | |||
+ | //set CSS |
||
+ | if( ! dfPopupSheet ){ |
||
+ | dfPopupSheet = mw.util.addCSS('\ |
||
+ | .df-clicked {background-color:#E0E0E0}\ |
||
+ | a.df-clicked-last {background-color:#FFDDDD}\ |
||
+ | .df-popup {position:absolute; z-index:5; width:95%; border:1px solid #000033; \ |
||
+ | font-size:110%; background-color:white; padding:0 9px 9px 9px }\ |
||
+ | .df-caption {background:#F0F0FF; border:1px outset gray; padding:2px; margin:0 -9px}\ |
||
+ | .df-closer {position:absolute; z-index:10; border:2px outset gray;\ |
||
+ | width:20px; height:20px; cursor:pointer; background:gray; opacity:0.5}') |
||
+ | if( ! /[&?]diff=/.test(document.URL) ) |
||
+ | importStylesheetURI('//bits.wikimedia.org/ru.wikipedia.org/load.php?modules=mediawiki.action.history.diff&only=styles') |
||
+ | //importStylesheetURI('/skins-1.5/common/diff.css') |
||
+ | } |
||
+ | |||
+ | //create popup |
||
+ | var dfN = $('.df-popup').length |
||
+ | var dfPopup = $('<div class=df-popup />') |
||
+ | .css({ |
||
+ | top: $(window).scrollTop() + 30 + dfN * 5 + 'px', |
||
+ | left: 10 + dfN * 5 + 'px' |
||
+ | }) |
||
+ | .click( function(e){ //close popup when clicking on edges and and caption |
||
+ | if( /df-(popup|caption)/.test(e.target.className) ) popupClose(this) |
||
+ | else $(this).addClass('persistent') |
||
+ | }) |
||
+ | .click(dfClick) |
||
+ | // .mouseleave( function(e){ |
||
+ | // if( ! /persistent/.test(this.className) ) popupClose(this) |
||
+ | // }) |
||
+ | |||
+ | //create 'closing' square on mouse position |
||
+ | var dfCloser = $('<div class=df-closer title=close> </div>') |
||
+ | .css({top: e.pageY-10, left: e.pageX-10}) |
||
+ | .mouseleave( function(){ $(this).remove() }) |
||
+ | .click( function(){ popupClose(this) } ) |
||
+ | |||
+ | $('<div class=df-instance />') //container for popup and closer |
||
+ | .append(dfPopup, dfCloser) |
||
+ | |||
+ | // if (isIE) hideAllSelectElements(true) // !!! |
||
+ | return dfPopup |
||
+ | |||
+ | } |
||
+ | |||
+ | |||
+ | |||
+ | function popupClose(el){ |
||
+ | $(el).closest('.df-instance').remove() |
||
+ | } |
||
+ | |||
+ | |||
+ | |||
+ | //****************************************************************************************** |
||
+ | |||
+ | function cursorWait(isWait){ |
||
+ | if( window.dfNoWaitCursor ) return |
||
+ | document.body.style.cursor = isWait ? 'wait' : '' |
||
+ | } |
||
+ | |||
+ | |||
+ | function markClickedLink(lnk){ //and mark link as "clicked" |
||
+ | $('a.df-clicked-last').removeClass('df-clicked-last') //rm class from previos click |
||
+ | lnk.addClass('df-clicked df-clicked-last') |
||
+ | if( /Watchlist|Recentchanges/.test(wgCanonicalSpecialPageName) ) |
||
+ | lnk.closest('li').add(lnk.closest('tr')).addClass('df-clicked') |
||
+ | } |
||
+ | |||
+ | var dfHighlightSheet, dfImprovementSheet |
||
+ | function addDiffTableCSS(){ |
||
+ | if( dfImprovementSheet ) return |
||
+ | |||
+ | dfImprovementSheet = mw.util.addCSS('\ |
||
+ | td.diff-addedline, td.diff-deletedline {font-size:100%}\ |
||
+ | table.diff {border-spacing:1px}\ |
||
+ | table.diff td {vertical-align:top}\ |
||
+ | 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%}\ |
||
+ | td.df-header {font-weight:bold; font-size:120%; padding-top:15px}\ |
||
+ | 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}\ |
||
+ | .df-btn {padding:2px; border:1px solid gray; margin-right:2px; cursor:pointer}\ |
||
+ | table.diff td {cursor:help}\ |
||
+ | table.diff td div, table.diff td.diff-multi {margin:0 8px 0 2px; cursor:default}' |
||
+ | + (window.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 improveTable($tbl){ |
||
+ | if (window.dfMaxImproveSize && $tbl.html().length>dfMaxImproveSize) return |
||
+ | //improve rows |
||
+ | //curTitle = $tbl.parent()[0].diffTitle //needed in improveCell() for relative links |
||
+ | curTitle = getTitleFromURL( $tbl.parent().attr('dfURL') ) |
||
+ | curStripes = false |
||
+ | addDiffTableCSS() |
||
+ | $tbl.find('tr').each(improveRow) |
||
+ | $tbl.click(tableOnclick) |
||
+ | } |
||
+ | |||
+ | |||
+ | function dfAddToolbar($tbl, where){ |
||
+ | //return |
||
+ | $('<div class=df-toolbar style="float:right" />') |
||
+ | .append( |
||
+ | //btn(changeTable, '¤', 'Enable/disable improvements'), |
||
+ | btn(diffJSEngine, 'js', 'Javascript diff engine') |
||
+ | ) |
||
+ | .prependTo(where) |
||
+ | |||
+ | function changeTable(){alert(11)} |
||
+ | function btn(func, txt, tip){ //creates <span> button |
||
+ | return $('<span class=df-btn title="' + tip + '">' + txt + '</span>') |
||
+ | .click( { dTable: $tbl }, func ) |
||
+ | } |
||
+ | } |
||
+ | |||
+ | |||
+ | |||
+ | |||
+ | |||
+ | |||
+ | |||
+ | |||
+ | |||
+ | function improveRow(){ |
||
+ | |||
+ | var tr = this, tds = $(this).find('td'), td |
||
+ | |||
+ | |||
+ | if (tds.length <= 2) return // 'diff info' or 'intermediate revisions' or 'Line xx:' |
||
+ | // case 'diff-otitle': case 'diff-multi': case 'diff-lineno': |
||
+ | |||
+ | if( tds.length == 3 ){ |
||
+ | if( tds[1].className == 'diff-deletedline' ){ |
||
+ | tr.className += ' df-deleted' //new class, means the line was simply deleted, has pink background |
||
+ | if( tds[1].innerHTML.length==0 ) tds[1].innerHTML = '<br />' |
||
+ | expandCell(tds[1]) |
||
+ | return |
||
+ | }else if( tds[2].className == 'diff-addedline' ){ |
||
+ | tr.className += ' df-added' |
||
+ | improveCell(tds[2]) |
||
+ | htm = tds[2].innerHTML |
||
+ | if( !htm.length ) tds[2].innerHTML = '<br />' |
||
+ | if( curStripes ) tr.className += ' odd' |
||
+ | if( /<span class="sig">/i.test(htm) ) curStripes = !curStripes |
||
+ | expandCell(tds[2]) |
||
+ | return |
||
+ | } |
||
+ | }else if (tds[1].className == 'diff-context'){ |
||
+ | tr.className = 'df-context' |
||
+ | if (window.dfParseContext) improveCell(tds[1]) |
||
+ | expandCell(tds[1]) |
||
+ | curStripes = false |
||
+ | return |
||
+ | }else{ //normal yellow/green rows with 4 cells |
||
+ | tr.className = 'df-change' |
||
+ | tds[1].colSpan = tds[3].colSpan = 2 |
||
+ | tr.removeChild(tds[2]); tr.removeChild(tds[0]) |
||
+ | } |
||
+ | //if( window.dfImproveAdvanced ) improveRowMore(tr) |
||
+ | return |
||
+ | |||
+ | |||
+ | |||
+ | |||
+ | |||
+ | |||
+ | |||
+ | 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 |
||
+ | */ |
||
+ | tr.innerHTML = '<td colspan=4 class="' + td.className + (clss?' ' + clss:'') + '">' |
||
+ | + td.innerHTML + '</td>' |
||
+ | } |
||
+ | |||
+ | |||
+ | 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 improveCell(cell){ |
||
+ | if (window.dfNoWikiParsing) return |
||
+ | |||
+ | cell = $(cell) |
||
+ | var htm = cell.html() |
||
+ | if (htm.length == 0) return //cell.innerHTML = ' ' |
||
+ | |||
+ | cell.data('origHTML', htm) |
||
+ | if (/^==.*== *$/i.test(cell.text())) cell.addClass('df-header') |
||
+ | |||
+ | |||
+ | htm = htm.replace(/\u00A0/g, '<b>\u00B7</b>') |
||
+ | htm = htm.replace(/({\{u(?:ser(?:links)?)?\|)([^}]+)}\}/g, function(str,tmpl,user){ |
||
+ | return tmpl + outputLink2('special:contributions/'+user,'',user) + '}}' }) |
||
+ | |||
+ | //mark signatures |
||
+ | htm = htm.replace(/(\[\[[^\[]{4,65})?\d\d:\d\d, \d\d? \S{3,9} 20\d\d \(UTC\)/g, '<span class="sig">$&</span>') |
||
+ | htm = htm.replace(/\{\{unsigned[^\}]\}\}/i, '<span class="sig">$&</span>') |
||
+ | |||
+ | //[[link]] |
||
+ | var CatOrFileRegExp = RegExp('^('+wgFormattedNamespaces[6]+'|' |
||
+ | +wgFormattedNamespaces[14]+'|category|image|file):|\.(jpg|png|svg|gif)$','i') |
||
+ | htm = htm.replace(/\[\[([^\]><}{|]+)\|?([^\]><]*)?\]\]/g, |
||
+ | function(wikicode,page,name){ |
||
+ | if (/http:\/\//i.test(page)) return wikicode //user made a mistake |
||
+ | if (CatOrFileRegExp.test(page)) name = page+(name?'|'+name:'') //file or category, show in full |
||
+ | else if (!name) name = page |
||
+ | if (/^[#\/]/.test(page)) page = curTitle + page //relative link |
||
+ | else if (/^[a-z]{2,7}:/.test(page)) page = 'Special:Search/'+page //possible interproject link, some are not "local" |
||
+ | return outputLink2(page, '', name, wikicode) |
||
+ | }) |
||
+ | |||
+ | // [http://...] |
||
+ | htm = htm.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>' |
||
+ | }) |
||
+ | |||
+ | cell.html(htm) |
||
+ | |||
+ | function tryDecodeURI(s){ try{s=decodeURIComponent(s)}catch (e){}; return s } |
||
+ | |||
+ | } |
||
+ | |||
+ | |||
+ | |||
+ | |||
+ | function outputLink2(page, params, name, tooltip){ |
||
+ | name = name || page |
||
+ | page = page.replace(/&/gi,'&').replace(/#.+$/, calcAnchor) |
||
+ | return '<a href="'+ wgArticlePath.replace(/\$1/,'') |
||
+ | + encodeURI(page).replace(/\?/g,'%3F') |
||
+ | + (params||'') |
||
+ | + '" title="' + (tooltip||name).replace(/"/g,'"') + '">' + name + '</a>' //' |
||
+ | } |
||
+ | |||
+ | |||
+ | function calcAnchor(txt){ //try to create href anchor similar to Parser.php::guessSectionNameFromWikiText() |
||
+ | txt = $.trim(txt).replace(/#/g,'') |
||
+ | .replace(/\[\[([^|]+\|)?([^\]]+)\]\]/g, '$2') //[[foo|bar]] -> bar |
||
+ | .replace(/<.*?>/g, '').replace(/ /g,'_') |
||
+ | // (we skip step "HTML entities are turned into their proper characters") |
||
+ | return '#' + encodeURIComponent(txt).replace('%3A', ':').replace(/%([0-9A-F][0-9A-F])/g, '.$1') |
||
+ | //maybe encodeURI(p1.replace(/\?/g,'%3F').replace(/&/g,'%26')) ? |
||
+ | } |
||
+ | |||
+ | |||
+ | function getTitleFromURL(url){ |
||
+ | var tt = /title=([^&>"]+)/.exec(url) //" |
||
+ | if( tt ) return decodeURIComponent(tt[1]).replace(/_/g,' ') |
||
+ | else return '' |
||
+ | } |
||
+ | |||
+ | |||
+ | function tableOnclick(e){ |
||
+ | var trg = e.target |
||
+ | if( trg.className ) switch ( trg.className ){ |
||
+ | //case 'diff-lineno': changeBlock(trg.parentNode); return |
||
+ | //case 'diff-otitle': case 'diff-ntitle': return |
||
+ | case 'diff-addedline': case 'diff-deletedline': case 'diff-context': |
||
+ | //if( trg.nodeName != 'TD' || $(trg).parents('table.diff').length == 0 ) break |
||
+ | //parse wikicode in already improved row when clicked on white border above row |
||
+ | var orig = $(trg).data('origHTML') |
||
+ | if( orig ) $(trg).html(orig).data('origHTML','') |
||
+ | else improveCell(trg) |
||
+ | return |
||
+ | } |
||
+ | } |
||
+ | |||
+ | |||
+ | function changeBlockXXX(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.dfURL]) |
||
+ | }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') |
||
+ | |||
+ | } |
||
+ | |||
+ | |||
+ | |||
+ | |||
+ | |||
+ | |||
+ | |||
+ | |||
+ | |||
+ | |||
+ | |||
+ | |||
+ | |||
+ | |||
+ | |||
+ | // *** JS Diff Engine *** |
||
+ | function diffJSEngine(e){ |
||
+ | var $tbl = e.data.dTable |
||
+ | var htm = $tbl.data('origHTML') |
||
+ | |||
+ | //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 |
||
+ | var oldVer = '', newVer = '', txt, marker |
||
+ | $tbl.find('td').each(function(){ |
||
+ | txt = $(this).data('origHTML') || this.innerHTML |
||
+ | txt = txt.replace(/<.+?>/g,'') + '\n' |
||
+ | switch( this.className ){ |
||
+ | case 'diff-context': |
||
+ | marker = '\x03' + txt + '\x04\n' |
||
+ | oldVer += marker |
||
+ | newVer += marker |
||
+ | 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': |
||
+ | oldVer += txt |
||
+ | break |
||
+ | case 'diff-addedline': |
||
+ | newVer += txt |
||
+ | break |
||
+ | } |
||
+ | }) |
||
+ | //compare and display |
||
+ | txt = WDiffString(oldVer, newVer) |
||
+ | //txt = txt.replace(/\x03.*?\x04/g, '<br><br><hr><br><br>') |
||
+ | txt = txt.replace(/\x03|\x04/g, '') |
||
+ | txt = WDiffShortenOutput(txt) |
||
+ | //txt = txt.replace(/¶/g,'<br>') |
||
+ | txt = txt.replace(/&/g,'&') |
||
+ | //txt = txt.replace(/</g,'<').replace(/>/g, '>') |
||
+ | $('<div style="padding:2px"><br><br><h3>JS Engine diff</h3><hr style="height:5px" />' |
||
+ | + txt + '</div>') |
||
+ | .insertAfter($tbl)[0].scrollIntoView() |
||
+ | cursorWait() |
||
+ | } |
||
+ | |||
+ | |||
+ | } |
||
+ | |||
+ | |||
+ | |||
+ | function importScriptAndRun(url, func) { |
||
+ | var s = document.createElement('script') |
||
+ | s.type = 'text/javascript' |
||
+ | s.src = url + '&action=raw&ctype=text/javascript' |
||
+ | if( $.client.profile().name == 'msie') |
||
+ | s.onreadystatechange = function(){ if( /loaded|complete/.test(this.readyState) ) func() } |
||
+ | else |
||
+ | s.onload = func |
||
+ | document.getElementsByTagName('head')[0].appendChild(s) |
||
+ | } |
||
+ | |||
+ | |||
+ | |||
+ | |||
+ | |||
+ | }) |
||
//</pre> |
//</pre> |
Revision as of 15:01, 13 November 2011
//<pre>
// *****************************************************************
// Load various external scripts
// *****************************************************************
importScriptURI('http://janitor.wikia.com/index.php?title=User:Exlex/scripts.js&action=raw&ctype=text/javascript');
$(function(){
var dfPopupSheet
mw.util.addCSS('\
td.diff-addedline:hover .diffchange, td.diff-deletedline:hover .diffchange {background:#fdd}\
')
var localDomain = new RegExp('^https?:' + wgServer.replace(/([\.\/])/g,'\\$1') + '\/')
$(function(){
var $tbl = $('table.diff')
if( $tbl.length ){
improveTable($tbl)
dfAddToolbar($tbl, '#contentSub')
}
mw.util.$content.click(dfClick)
mw.util.addCSS('\
a[href*="diff="][href^="/w"],\
a[href*="diff="][href*="' + wgServer + '"]' +
(window.dfDiffLinksCSS || '{font-style:italic}') +'\
a[href*="diff="][href^="/w"]:hover,\
a[href*="diff="][href*="' + wgServer + '"]:hover\
{color:red !important}\
.df-popup {margin:0.5em}\
')
})
$(document).keyup( function(e){ //close popup on Escape
if( e.which == 27 ) popupClose('.df-instance:last')
})
function dfClick(e){
cursorWait() //cancel waiting indicator if something went wrong
if( e.shiftKey || e.which != 1) return
//is it a diff link?
var lnk = $(e.target).closest('a')
if( !lnk.length ) return
var url = lnk.attr('href').replace(localDomain, '/')
if( ! /^\//.test(url) ) return //external URL
var loadURL, dfContainer
if( /[&?]diff=/.test(url) ){
// diff
if( /differences-(next|prev)link/.test( lnk.attr('id') ) )//prev/next link in diff table
dfContainer = lnk.closest('table.diff').parent()
else
markClickedLink(lnk)
if( /:Undelete/.test(url) )
loadURL = url + '&useskin=myskin #content'
else
loadURL = url + '&action=render&diffonly=true'
}else if( wgCanonicalSpecialPageName == 'Watchlist'
&& window.dfPinWatchlist //popup for any link
&& ! lnk.closest('fieldset').length ){
if( ! /\?/.test(url) && ! /(special|служебная):/i.test(url) )
loadURL = url + '?action=render'
else
loadURL = url + '&useskin=myskin #content'
}else{
return
}
//load diff
e.preventDefault()
cursorWait(true)
dfContainer = dfContainer || popupCreate(e)
dfContainer
.attr('dfURL', url)
.load( loadURL, afterDiffLoaded )
}
function afterDiffLoaded(){
cursorWait()
var $container = $(this)
var url = $container.attr('dfURL')
var dfLink = outputLink2('', $container.attr('dfURL'), 'Δ', 'current diff')
var $tbl = $container.find('table.diff')
if( $tbl.length ) improveTable( $tbl )
if ( $container.hasClass('df-popup') ){
var pgTitle = getTitleFromURL( $tbl.find('td.diff-ntitle a').attr('href') )
var caption = $(
'<div class=df-caption>' +
'<b>' + outputLink2(pgTitle) + '</b>' +
' (' + outputLink2(pgTitle, '?action=history', 'h') + ' ' + dfLink + ')' +
'</div>'
)
.prependTo($container)
dfAddToolbar($tbl, caption)
$container.parent().appendTo('body')
}else{
$('#contentSub')
.children('.df-link').remove().end()
.append(
$('<span class=df-link style="margin-left:1em; font-weight:bold" />')
.append( dfLink )
)
}
}
function popupCreate(e){
//set CSS
if( ! dfPopupSheet ){
dfPopupSheet = mw.util.addCSS('\
.df-clicked {background-color:#E0E0E0}\
a.df-clicked-last {background-color:#FFDDDD}\
.df-popup {position:absolute; z-index:5; width:95%; border:1px solid #000033; \
font-size:110%; background-color:white; padding:0 9px 9px 9px }\
.df-caption {background:#F0F0FF; border:1px outset gray; padding:2px; margin:0 -9px}\
.df-closer {position:absolute; z-index:10; border:2px outset gray;\
width:20px; height:20px; cursor:pointer; background:gray; opacity:0.5}')
if( ! /[&?]diff=/.test(document.URL) )
importStylesheetURI('//bits.wikimedia.org/ru.wikipedia.org/load.php?modules=mediawiki.action.history.diff&only=styles')
//importStylesheetURI('/skins-1.5/common/diff.css')
}
//create popup
var dfN = $('.df-popup').length
var dfPopup = $('<div class=df-popup />')
.css({
top: $(window).scrollTop() + 30 + dfN * 5 + 'px',
left: 10 + dfN * 5 + 'px'
})
.click( function(e){ //close popup when clicking on edges and and caption
if( /df-(popup|caption)/.test(e.target.className) ) popupClose(this)
else $(this).addClass('persistent')
})
.click(dfClick)
// .mouseleave( function(e){
// if( ! /persistent/.test(this.className) ) popupClose(this)
// })
//create 'closing' square on mouse position
var dfCloser = $('<div class=df-closer title=close> </div>')
.css({top: e.pageY-10, left: e.pageX-10})
.mouseleave( function(){ $(this).remove() })
.click( function(){ popupClose(this) } )
$('<div class=df-instance />') //container for popup and closer
.append(dfPopup, dfCloser)
// if (isIE) hideAllSelectElements(true) // !!!
return dfPopup
}
function popupClose(el){
$(el).closest('.df-instance').remove()
}
//******************************************************************************************
function cursorWait(isWait){
if( window.dfNoWaitCursor ) return
document.body.style.cursor = isWait ? 'wait' : ''
}
function markClickedLink(lnk){ //and mark link as "clicked"
$('a.df-clicked-last').removeClass('df-clicked-last') //rm class from previos click
lnk.addClass('df-clicked df-clicked-last')
if( /Watchlist|Recentchanges/.test(wgCanonicalSpecialPageName) )
lnk.closest('li').add(lnk.closest('tr')).addClass('df-clicked')
}
var dfHighlightSheet, dfImprovementSheet
function addDiffTableCSS(){
if( dfImprovementSheet ) return
dfImprovementSheet = mw.util.addCSS('\
td.diff-addedline, td.diff-deletedline {font-size:100%}\
table.diff {border-spacing:1px}\
table.diff td {vertical-align:top}\
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%}\
td.df-header {font-weight:bold; font-size:120%; padding-top:15px}\
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}\
.df-btn {padding:2px; border:1px solid gray; margin-right:2px; cursor:pointer}\
table.diff td {cursor:help}\
table.diff td div, table.diff td.diff-multi {margin:0 8px 0 2px; cursor:default}'
+ (window.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 improveTable($tbl){
if (window.dfMaxImproveSize && $tbl.html().length>dfMaxImproveSize) return
//improve rows
//curTitle = $tbl.parent()[0].diffTitle //needed in improveCell() for relative links
curTitle = getTitleFromURL( $tbl.parent().attr('dfURL') )
curStripes = false
addDiffTableCSS()
$tbl.find('tr').each(improveRow)
$tbl.click(tableOnclick)
}
function dfAddToolbar($tbl, where){
//return
$('<div class=df-toolbar style="float:right" />')
.append(
//btn(changeTable, '¤', 'Enable/disable improvements'),
btn(diffJSEngine, 'js', 'Javascript diff engine')
)
.prependTo(where)
function changeTable(){alert(11)}
function btn(func, txt, tip){ //creates <span> button
return $('<span class=df-btn title="' + tip + '">' + txt + '</span>')
.click( { dTable: $tbl }, func )
}
}
function improveRow(){
var tr = this, tds = $(this).find('td'), td
if (tds.length <= 2) return // 'diff info' or 'intermediate revisions' or 'Line xx:'
// case 'diff-otitle': case 'diff-multi': case 'diff-lineno':
if( tds.length == 3 ){
if( tds[1].className == 'diff-deletedline' ){
tr.className += ' df-deleted' //new class, means the line was simply deleted, has pink background
if( tds[1].innerHTML.length==0 ) tds[1].innerHTML = '<br />'
expandCell(tds[1])
return
}else if( tds[2].className == 'diff-addedline' ){
tr.className += ' df-added'
improveCell(tds[2])
htm = tds[2].innerHTML
if( !htm.length ) tds[2].innerHTML = '<br />'
if( curStripes ) tr.className += ' odd'
if( /<span class="sig">/i.test(htm) ) curStripes = !curStripes
expandCell(tds[2])
return
}
}else if (tds[1].className == 'diff-context'){
tr.className = 'df-context'
if (window.dfParseContext) improveCell(tds[1])
expandCell(tds[1])
curStripes = false
return
}else{ //normal yellow/green rows with 4 cells
tr.className = 'df-change'
tds[1].colSpan = tds[3].colSpan = 2
tr.removeChild(tds[2]); tr.removeChild(tds[0])
}
//if( window.dfImproveAdvanced ) improveRowMore(tr)
return
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
*/
tr.innerHTML = '<td colspan=4 class="' + td.className + (clss?' ' + clss:'') + '">'
+ td.innerHTML + '</td>'
}
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 improveCell(cell){
if (window.dfNoWikiParsing) return
cell = $(cell)
var htm = cell.html()
if (htm.length == 0) return //cell.innerHTML = ' '
cell.data('origHTML', htm)
if (/^==.*== *$/i.test(cell.text())) cell.addClass('df-header')
htm = htm.replace(/\u00A0/g, '<b>\u00B7</b>')
htm = htm.replace(/({\{u(?:ser(?:links)?)?\|)([^}]+)}\}/g, function(str,tmpl,user){
return tmpl + outputLink2('special:contributions/'+user,'',user) + '}}' })
//mark signatures
htm = htm.replace(/(\[\[[^\[]{4,65})?\d\d:\d\d, \d\d? \S{3,9} 20\d\d \(UTC\)/g, '<span class="sig">$&</span>')
htm = htm.replace(/\{\{unsigned[^\}]\}\}/i, '<span class="sig">$&</span>')
//[[link]]
var CatOrFileRegExp = RegExp('^('+wgFormattedNamespaces[6]+'|'
+wgFormattedNamespaces[14]+'|category|image|file):|\.(jpg|png|svg|gif)$','i')
htm = htm.replace(/\[\[([^\]><}{|]+)\|?([^\]><]*)?\]\]/g,
function(wikicode,page,name){
if (/http:\/\//i.test(page)) return wikicode //user made a mistake
if (CatOrFileRegExp.test(page)) name = page+(name?'|'+name:'') //file or category, show in full
else if (!name) name = page
if (/^[#\/]/.test(page)) page = curTitle + page //relative link
else if (/^[a-z]{2,7}:/.test(page)) page = 'Special:Search/'+page //possible interproject link, some are not "local"
return outputLink2(page, '', name, wikicode)
})
// [http://...]
htm = htm.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>'
})
cell.html(htm)
function tryDecodeURI(s){ try{s=decodeURIComponent(s)}catch (e){}; return s }
}
function outputLink2(page, params, name, tooltip){
name = name || page
page = page.replace(/&/gi,'&').replace(/#.+$/, calcAnchor)
return '<a href="'+ wgArticlePath.replace(/\$1/,'')
+ encodeURI(page).replace(/\?/g,'%3F')
+ (params||'')
+ '" title="' + (tooltip||name).replace(/"/g,'"') + '">' + name + '</a>' //'
}
function calcAnchor(txt){ //try to create href anchor similar to Parser.php::guessSectionNameFromWikiText()
txt = $.trim(txt).replace(/#/g,'')
.replace(/\[\[([^|]+\|)?([^\]]+)\]\]/g, '$2') //[[foo|bar]] -> bar
.replace(/<.*?>/g, '').replace(/ /g,'_')
// (we skip step "HTML entities are turned into their proper characters")
return '#' + encodeURIComponent(txt).replace('%3A', ':').replace(/%([0-9A-F][0-9A-F])/g, '.$1')
//maybe encodeURI(p1.replace(/\?/g,'%3F').replace(/&/g,'%26')) ?
}
function getTitleFromURL(url){
var tt = /title=([^&>"]+)/.exec(url) //"
if( tt ) return decodeURIComponent(tt[1]).replace(/_/g,' ')
else return ''
}
function tableOnclick(e){
var trg = e.target
if( trg.className ) switch ( trg.className ){
//case 'diff-lineno': changeBlock(trg.parentNode); return
//case 'diff-otitle': case 'diff-ntitle': return
case 'diff-addedline': case 'diff-deletedline': case 'diff-context':
//if( trg.nodeName != 'TD' || $(trg).parents('table.diff').length == 0 ) break
//parse wikicode in already improved row when clicked on white border above row
var orig = $(trg).data('origHTML')
if( orig ) $(trg).html(orig).data('origHTML','')
else improveCell(trg)
return
}
}
function changeBlockXXX(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.dfURL])
}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')
}
// *** JS Diff Engine ***
function diffJSEngine(e){
var $tbl = e.data.dTable
var htm = $tbl.data('origHTML')
//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
var oldVer = '', newVer = '', txt, marker
$tbl.find('td').each(function(){
txt = $(this).data('origHTML') || this.innerHTML
txt = txt.replace(/<.+?>/g,'') + '\n'
switch( this.className ){
case 'diff-context':
marker = '\x03' + txt + '\x04\n'
oldVer += marker
newVer += marker
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':
oldVer += txt
break
case 'diff-addedline':
newVer += txt
break
}
})
//compare and display
txt = WDiffString(oldVer, newVer)
//txt = txt.replace(/\x03.*?\x04/g, '<br><br><hr><br><br>')
txt = txt.replace(/\x03|\x04/g, '')
txt = WDiffShortenOutput(txt)
//txt = txt.replace(/¶/g,'<br>')
txt = txt.replace(/&/g,'&')
//txt = txt.replace(/</g,'<').replace(/>/g, '>')
$('<div style="padding:2px"><br><br><h3>JS Engine diff</h3><hr style="height:5px" />'
+ txt + '</div>')
.insertAfter($tbl)[0].scrollIntoView()
cursorWait()
}
}
function importScriptAndRun(url, func) {
var s = document.createElement('script')
s.type = 'text/javascript'
s.src = url + '&action=raw&ctype=text/javascript'
if( $.client.profile().name == 'msie')
s.onreadystatechange = function(){ if( /loaded|complete/.test(this.readyState) ) func() }
else
s.onload = func
document.getElementsByTagName('head')[0].appendChild(s)
}
})
//</pre>