MediaWiki:Gadget-diffpopups.js
Перейти к навигации
Перейти к поиску
Замечание: Чтобы после сохранения вступили в силу изменения стилей, перезагрузите файл //traditio.wiki/w/load.php?debug=false&lang=ru&modules=site&only=styles&skin=vector&*, если используете скин Vector, или //traditio.wiki/w/load.php?debug=false&lang=ru&modules=site&only=styles&skin=common&*, если используете скин Common.
Чтобы вступили в силу изменения скриптов, перезагрузите файл //traditio.wiki/w/load.php?debug=false&lang=ru&modules=site&only=scripts&skin=vector&*, если используете скин Vector, или //traditio.wiki/w/load.php?debug=false&lang=ru&modules=site&only=scripts&skin=common&*, если используете скин Common.
Гаджеты и импортируемые скрипты загружаются отдельными файлами.
var popIdx = 0;
var gotPages = {}; //aray of retreived pages
var html;
var needCSSImported = true;
$(function(){
var body = document.getElementById('bodyContent');
if (!body) return;
document.write('<style>\
table.diff td div {overflow-x: auto !important; overflow-y:hidden !important;} \
span.sig { border:1px dotted gray; border-bottom:none;\
font-family:cursive; font-size:90%;}\
td.diff-addedline, diff-deletedline {font-size:100%}\
</style>');
// text-decoration:underline;
// white-space:nowrap
//if (document.URL.match('diff=')) processRows(body);
markDiffLinks(body);
});
function markDiffLinks(el){
addEvent(el, 'click', diffPopup);
var links = el.getElementsByTagName('a');
for (var i=0; i<links.length; i++)
if (links[i].href.indexOf('diff=') >= 0)
links[i].style.fontStyle='italic';
//links[i].onclick=diffPopup; //addEvent(links[i], 'click', diffPopup);
}
function diffPopup(e){
//check if click was on a diff link
var targ;
if (!e) var e = window.event;
if (e.target) targ = e.target;
else if (e.srcElement) targ = e.srcElement;
if (e.shiftKey) return;
if (!targ.href || targ.href.indexOf('diff=')<0) return;
if (needCSSImported) importDiffCSS();
//prevent browser from followint the link
if (e.preventDefault) e.preventDefault()
else e.returnValue = false;
if(wgCanonicalNamespace == 'Special' || !wgCanonicalSpecialPageName) // watchlist/recent and history
targ.style.textDecoration='underline';
//workaround for image diffs: doesn't work with &action=render
if (targ.href.match(/title=%D0%98%D0%B7%D0%BE%D0%B1%D1%80%D0%B0%D0%B6%D0%B5%D0%BD%D0%B8%D0%B5%3A/) ||
targ.href.match(/title=Image:/))
return false
//get and process html code
var url = targ.href + '&diffonly=yes&action=render';
html = getPage(url);
var j = html.indexOf('</tr>');
var header = html.substring(0,j+5); //info about diffs
html = html.substring(j+6); //diffs
processHTML();
//create popup box
if (targ.id != 'differences-prevlink' && targ.id != 'differences-nextlink' )
pop = createPopup();
pop['url'] = url;
var caption = '<div style="background:#F0F0F0;font-size:120%;border:2px outset gray;padding:2px;cursor:pointer" class=caption></div>'
pop.innerHTML = caption + '<div>' + header + html + '</div>' + caption ;
var title = header.match(/title=[^&>"]+/);
if (title){
title = title[0].split('=')[1];
pop['caption'] = title;//!!!
title = '<a href='+wgServer+'/wiki/'+title+'>'+decodeURIComponent(title).replace(/_/g,' ')+'</a>'+
' <a href='+wgServer+'/wiki/'+title+'?action=history>(h)</a>'
} else title = '---';
//title += '<a href=javascript:showRaw()>¶</a>';
title = '<b>'+title+'</b>';
//title += '<div style="background:yellow;width:auto"></div>'
var td1 = pop.getElementsByTagName('td')[1];
if (td1 && td1.className == 'diff-ntitle'){
var el, time;
if ((el=td1.childNodes[2]) && el.href){ //make last author bold
el.style.border='2px solid green'; el.style.fontWeight = 'bold'; el.style.padding='1px';
}
if (time = td1.innerHTML.match(/\d\d:\d\d, \d\d? [^ ]+ \d\d\d\d/)) //get "time ago"
if (time = timeAgo(time[0])) title += ': ' + time + ' ago';
}
pop.firstChild.innerHTML = '<span></span> ' + title;
pop.firstChild.onclick = closePopup;
//pop.lastChild.innerHTML = title;
if (html.length < 30000) processRows()
else setTimeout(processRows, 1000);
markDiffLinks(pop);
//if it's too wide
//if (elementWidth(pop) +10 > windowWidth()) scrollBy(elementWidth(pop), 0);
return false;
}
function closePopup(e){
var targ;
if (!e) var e = window.event;
if (e.target) targ = e.target;
else if (e.srcElement) targ = e.srcElement;
if (targ && targ.className && targ.className=='caption'){
targ.parentNode.style.display='none';
popIdx--;
}
}
function showRaw(){
html = getPage(pop['url']);
//pop.childNodes[1].innerHTML =
}
function processHTML(){
var ss='';
//disabled: breaks real link too
//text = text.replace(/http:\/\/ru\.wikipedia\.org\/w\/index\.php\?title=/g,'вики:');
var alink = '<a href='+wgServer+'/wiki/';
//выделить подпись
html = html.replace(/(\[\[|\{\{)[^\[\{]{4,55} \d\d:\d\d, \d\d? \S{3,9} 20\d\d \(UTC\)/g, '<span class=sig>$&</span>');
html = html.replace(/\[\[([^\]><}{|]+)\|?([^\]><]*)?\]\]/g, //[[link]]
function(str,p1,p2){
if (p1.match(/^(Изображение|Image):/)) p2=p1+(p2?p2:'');
if (p1.match(/http:\/\//)) return str; //user made mistake
if (!p2) p2=p1; //empty link name
var firstChar = p1.substring(0,1);
//need this!!! //if (firstChar=='#' || firstChar=='/') p1 = pop['caption'] + p1;
return alink + encodeURI(p1)+' + title=\'' + str + '\'>' + p2 + '</a>';
});
html = html.replace(/\{\{(Участник:|User:)([^\}]*)\}\}/g, //{{User:subpage}}, usually this is sig
function (str,p1,p2){
return alink + encodeURI(p1+p2)+'>' + str + '</a>'; //title=\''+str+'\'
});
html = html.replace(/\[(https?:\/\/[^ \]><]*)( [^\]]*)?\]/g, //[http://...]
function (str,p1,p2){
var link = '<a href=' + p1;
var name = p2;
var t, d;
var tip = tryDecodeURI(p1); //tooltip
if (p1.substring(0,36) == (wgServer+'/w/index.php?')){//local link
tip = tip.substring(36);
if (!p2){
t = tip.match(/title=[^&]+/);
t = t ? '::'+t[0].split('=')[1].replace('_',' ') : '';
if (d=tip.match(/diff=[^&]+/)) name = d[0] + t
else if (tip.match(/action=history/)) name = 'hist: ' + t
else name = 'wiki: ' + tip;
}
} else { //ext link
tip = tip.substring(7);
link += ' class="external text"';
if (!p2) name = tip;
}
if (!p2 && (name.length > 70)) name = name.substring(0,60) + '… …'
return link + ' title="' + tip + '">[' + name + ']</a>';
});
//html = html.replace(/\http:\/\/.*\]/g, function (str) //decode % sequences in URLS to avoid very wide table
//{ try{str=decodeURIComponent(str)}catch (e){}; });
}
function tryDecodeURI(str){ try{str=decodeURIComponent(str)}catch (e){}; return str; };
function processRows(){
var container = pop;
var table = container.getElementsByTagName('table')[0];
if (!table) return;
table.style.fontSize = '110%';
var cntAdded = 0; var cntRemoved = 0;
var tds, td, tr, html;
var stripes = false;
var firstColWidthSet = false;
//var
trs = table.getElementsByTagName('tr');
for (var i=1; i<trs.length; i++){
tr = trs[i];
tds = tr.getElementsByTagName('td');
if (tds.length == 1)
tr.className = 'message'
else if (tds.length == 2){ // "Line xx"
tr.className = 'line';
tr.style.fontSize='90%';
}else if (tds.length == 3 && tds[1].className == 'diff-deletedline'){ //line removed
tr.className = 'change';
tds[1].style.backgroundColor = '#FFEECC'; //make it pink
if (tds[1].innerHTML.length==0) tds[1].innerHTML=' '
else if (tds[1].innerHTML.match(/^===?.*===?$/)) tds[1].style.fontWeight = 'bold';
tds[1].colSpan = 4;
tr.removeChild(tds[2]); tr.removeChild(tds[0]);
}else if (tds.length == 3 && tds[2].className == 'diff-addedline'){ //line added
tr.className = 'change';
if (stripes) tds[2].style.backgroundColor = '#beb';
if (tds[2].innerHTML.length==0) tds[1].innerHTML=' '
else if (tds[2].innerHTML.match(/^===?.*===?$/)) tds[2].style.fontWeight = 'bold'
else if (tds[2].innerHTML.match(/\d\d:\d\d, \d\d? \S{3,9} 20\d\d \(UTC\)/)) stripes = !stripes; //sig found
tds[2].colSpan = 4;
tr.removeChild(tds[1]); tr.removeChild(tds[0]);
// rows with 4 cells
}else if (tds[1].className == 'diff-context') {
tr.className = 'context';
stripes = false;
tds[1].style.fontSize = '90%';
tds[1].colSpan = 4;
tr.removeChild(tds[3]); tr.removeChild(tds[2]); tr.removeChild(tds[0]);
}else{
tr.className = 'change';
if (!firstColWidthSet) {tds[0].width = '5px'; tds[2].width = '5px'; firstColWidthSet = true; }
if (tds[1].innerHTML.replace(/<span class="diffchange"> <\/span>/g,' ')==tds[3].innerHTML){
tr.className = 'nobr';
cntRemoved++;
tr.style.display='none';
}else if (tds[1].innerHTML==tds[3].innerHTML.replace(/<span class="diffchange"> <\/span>/g,' ')){
tr.className = 'nobr';
cntAdded++;
tr.style.display='none';
}
}
}
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(/context|line/)
&& !trs[i-1].className.match(/change/) && !trs[i+1].className.match(/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 expandCell(td, style){
var tr = td.parentNode;
while (td.nextSibling) tr.removeChild(td.nextSibling); //remove all behind
while (td.previousSibling) tr.removeChild(td.previousSibling); //remove all in front
td.colSpan = 4;
if (td.innerHTML.match(/^===?.*===?$/)){ //header
td.style.fontSize = '100%'; td.style.fontWeight = 'bold';
}
return;
}
function getStyle(el, cssRule){
if(document.defaultView && document.defaultView.getComputedStyle)
var value = document.defaultView.getComputedStyle(el, '').getPropertyValue(
cssRule.replace( /[A-Z]/g, function(char) {return "-" + char.toLowerCase();} ));
else if (el.currentStyle)
var value = el.currentStyle[cssRule];
else
var value = false;
return value;
}
// Get the computed css property
function getStyle1( element, cssRule )
{
if( document.defaultView && document.defaultView.getComputedStyle )
{
var value = document.defaultView.getComputedStyle( element, '' ).getPropertyValue(
cssRule.replace( /[A-Z]/g, function( match, char )
{
return "-" + char.toLowerCase();
} )
);
}
else if ( element.currentStyle ) var value = element.currentStyle[ cssRule ];
else var value = false;
return value;
}
//var trs = pop.getElementsByTagName('tr');
//var tds = trs[4].getElementsByTagName('td');
//tds[3].style.display='none';
//trs[4].removeChild(tds[2]);
//tds[1].colSpan = 3
//tds[1].style.paddingLeft = '10%';
// && trs[i-1].className != 'change' && i+1<trs.length && trs[i+1].className != 'change')
function timeAgo(ss){ //accepts '05:53, 7 марта 2007', returns 'xx days, xx hours, xx mins'
var s = ss.split(' ');
var curTime = new Date();
var diffTime = new Date();
diffTime.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;
diffTime.setMonth(month/3);
diffTime.setDate(s[1]);
diffTime.setHours(s[0].substring(0,2));
diffTime.setMinutes(s[0].substring(3,5));
var mins = (curTime - diffTime)/60000;
var hours = Math.floor (mins/60);
mins = Math.floor(mins - hours * 60);
var days = Math.floor (hours/24)
hours = hours - days * 24;
var result = mins + ' min';
if (hours) result = hours + ' hrs ' + result;
if (days) result = days + ' days, ' + result;
return result;
}
function createPopup(){
var pop = document.createElement('div');
document.body.appendChild(pop);
pop.style.position = 'absolute';
pop.style.border = '3px outset yellow';
pop.style.top = windowScrolled() + 10 + 'px';
pop.style.backgroundColor = 'white';
pop.style.zIndex = 100;
pop.style.fontSize = '10pt';
//pop.onclick = function(){this.style.display='none'}
var offset = 20 + (popIdx++) * 10;
pop.style.left = offset + 'px';
pop.style.width = windowWidth() - (50 + offset) + 'px';
return (pop);
}
function importDiffCSS(){
needCSSImported = false;
var styleElem = document.createElement('style');
styleElem.setAttribute('type', 'text/css' );
styleElem.appendChild(document.createTextNode('@import "/skins-1.5/common/diff.css";' ));
document.getElementsByTagName('head')[0].appendChild(styleElem);
}
function getPage(url){
if (!gotPages[url]) {
var a = sajax_init_object();
if (a.overrideMimeType) a.overrideMimeType('text/html');
a.open('GET', url, false);
a.send(null);
gotPages[url] = a.responseText;
}
return(gotPages[url]);
}
function addEvent(obj, event, func) {
if (obj.addEventListener) obj.addEventListener( event, func, false );
else if (obj.attachEvent) obj.attachEvent ('on'+event, func)
}
function elementWidth(el){
return Math.max(el.scrollWidth, el.offsetWidth);
}
function windowWidth(){
if (self.innerWidth) // all except Explorer
return self.innerWidth
else if (document.documentElement && document.documentElement.clientWidth)// Explorer 6 Strict Mode
return document.documentElement.clientWidth
else if (document.body) // other Explorers
return document.body.clientWidth;
else return 0;
}
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;
}