User:Khanson/dabfixer.js
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.
if (!window.$j) mw.loader.load('http://bits.wikimedia.org/skins-1.5/common/jquery.min.js')
if ((wgNamespaceNumber == 0 || wgNamespaceNumber == 2 || wgNamespaceNumber == 10 || wgNamespaceNumber == 14 || wgNamespaceNumber == 100) &&
/edit|submit/.test(wgAction) &&
wgServer.indexOf('wikipedia') != -1)
$(function () {
addPortletLink('p-cactions','javascript:dabLinksStart()', 'DAB')
var tlb = $('#toolbar')
if (tlb.length==0) return
$('<input type=button\ style="height:22px;width:24px;vertical-align:top;padding:0;\
background:url(https://upload.wikimedia.org/wikipedia/commons/6/62/Button_desambig.png)"\
title="Уточнить ссылки на неоднозначности" />')
.click(dabLinksStart).appendTo(tlb)
})
function dabLinksStart(){
var dis=null, disIdx = -1, changes=[], dabMsgTimeout
var dabPgTitle, lnkRegExp, wikiLink, wikiLinkOrig, wikiLinkPos, snippetBefore, snippetAfter
var $i = {
requesting:'Ждём ответа от тулсервера...',
unlink_tip:'Убрать ссылку',
undo_tip:'Отменить сделанное исправление',
choose_tip:'Уточните ссылку, кликнув на более точном значении ниже',
x_tip:'отменить изменение',
cancel:'отменить',
cancel_tip:'отменить все сделанные изменения и закрыть диалог',
next_tip:'перейти к следующей ссылке на неоднозначность',
linksback:'есть <b>обратная ссылка</b>, вероятно исправления не нужно',
nolinks:'В тексте не найдено ссылок на $1',
cancelled:'Все изменения отменены',
finished:'Исправлено ссылок:'
}
var tBox = $('#wpTextbox1')
var wikiText = tBox.val()
appendCSS('#dabMsg {background:#cec; border:1px solid; padding:0 10px}')
showMsg($i.requesting||'Making request to toolserver...', 8000)
window.dabLinksProcess = dabLinksProcess
mw.loader.load('http://toolserver.org/~dispenser/cgi-bin/dablinks.py?\
format=json&callback=dabLinksProcess\
&titles='+wgContentLanguage+':'+encodeURIComponent(mw.config.get('wgPageName'))
+'&nocache='+Math.random())
return
function dabLinksProcess(data){
try { dis=data.query.pages[0].disambiguationlinks } catch(e){}
if (!dis) return showMsg('В статье не найдено ссылок на неоднозначности')
$('#bodyContent').hide().parent().append('<div id=dabFrame>\
<pre id=dabText style="padding-left:2px;font-family:monospace, sans-serif" />\
<div id=dabTitle style="float:left; border:2px outset; border-bottom:none; padding:0 5px; margin-right:1em">\
<span class=title />\
<span class=choose style="cursor:help">↓ </span></div>\
<div id=dabMenu>\
<div style="float:right">\
<span class=dabCount />\
<button class="next">→</button>\
<button class="cancel" /></div>\
<button class="unlink" style="opacity:0.6"><s>[\[</s> <s>]]</s></button>\
<button class="x"/>\
<span class=info> </span> <span class=linksback /></div>\
<div id=dabPage/>\
</div>')
appendCSS('\
#dabFrame {padding:2px; border:1px solid gray}\
#dabFrame button {background:#cce; padding:0 5px; opacity:0.8; margin-left:0.5em;\
font-size:85%; line-height:1.5em; vertical-align:top; cursor:pointer;}\
#dabText.text {word-wrap: break-word; white-space:pre-wrap; border:2px inset}\
#dabText .highlighted {background:#FFFF00}\
#dabText .changed {background:#A0E0A0}\
#dabPage {width:100%; border:2px outset; padding:10px 0;\
max-height:230px; overflow-y:auto}\
#dabPage #disambig {font-size:75%; margin-bottom:0 !important; line-height:1em; padding:0}\
#dabPage span.editsection {display:none}\
#dabPage li.highlight {background-color:#F0F5F0; border:1px dotted gray}\
#dabPage a:hover {border-top:1px dotted green; border-top:1px dotted green}\
')
$('#dabFrame button').click(buttonClicked)
$('#dabPage').click(linkClicked)
$('#dabFrame span').add('#dabFrame button').each(function(){
var el = $(this), cl = el.attr('class').split(' ')[0], txt
if (!cl) return
if (txt=$i[cl]) el.html(txt)
if (txt=$i[cl+'_tip']) el.attr('title', txt)
if (!el.text()) el.text(cl)
})
$('#dabText')[0].scrollIntoView(true)
nextLink()
return false
}
function buttonClicked(){
switch(this.className.split(' ')[0]){
case 'next':
nextLink()
break
case 'cancel':
close($i.cancelled || 'All changes cancelled')
break
case 'unlink':
wikiLink = wikiLinkOrig.replace(/^\[\[|\]\]|.+\|/g,'')
showText()
break
case 'x':
wikiLink = wikiLinkOrig
showText()
break
}
return false
}
function close(msg){
$('#dabFrame').remove()
$('#bodyContent').show()
if (msg) showMsg(msg)
}
function showMsg(msg, time){
if (dabMsgTimeout) { clearTimeout(dabMsgTimeout); $('#dabMsg').remove() }
$('<div id=dabMsg />').append(msg).prependTo('#editform')[0].scrollIntoView()
dabMsgTimeout = setTimeout("$('#dabMsg').remove()",time||3000)
}
function nextLink(){
//save previous change
if (wikiLink && (wikiLink != wikiLinkOrig)){
wikiText = wikiText.substring(0,wikiLinkPos) + wikiLink
+ wikiText.substr(wikiLinkPos+wikiLinkOrig.length)
changes.push([wikiLinkOrig, wikiLink])
}
if (findNextLink()) return showText()
if (++disIdx >= dis.length) return finish()
$('#dabFrame .dabCount').empty().append((disIdx+1)+'/'+dis.length)
//show current disambig page
var item = dis[disIdx]
dabPgTitle = item.target || item.title
$('#dabTitle .title').empty()
.append(outputWikiLink(dabPgTitle).attr('target','_blank'))
$('#dabMenu .linksback').toggle(item.linksback==1)
$("#dabPage").empty()
lnkRegExp = createLinkRegexp(item.title)
if (!findNextLink()){
$('#dabText').removeClass('text')
.html('<i><center>'+
($i.nolinks||'No links found in wikitext for $1')
.replace(/\$1/,'<b>[\['+item.title+']]</b>') + '</center></i>')
return
}
showText()
$("#dabPage").html('<img src=/skins-1.5/common/images/spinner.gif />')
.load(wgScript+'?action=render&title='+encodeURIComponent(item.title), guessDab)
}
function findNextLink(){
if (!lnkRegExp || !(wikiLink=lnkRegExp.exec(wikiText))) return false
wikiLink = wikiLinkOrig = wikiLink[0]
wikiLinkPos = lnkRegExp.lastIndex - wikiLink.length
var p = wikiText.lastIndexOf('\n', wikiLinkPos-100)+1
if (wikiLinkPos-p > 500) p = wikiText.lastIndexOf('. ', wikiLinkPos-150)+2
if (wikiLinkPos-p > 500) p = wikiText.lastIndexOf(' ', wikiLinkPos-200)+1
if (wikiLinkPos-p > 500) p = wikiLinkPos-200
snippetBefore = safe(wikiText.substring(p,wikiLinkPos))
p = wikiText.indexOf('\n', wikiLinkPos + 100)
if (p-wikiLinkPos > 500) p = wikiText.indexOf('. ', wikiLinkPos+150)
if (p-wikiLinkPos > 500) p = wikiText.indexOf(' ', wikiLinkPos+200)
if (p-wikiLinkPos > 500) p = wikiLinkPos+200
snippetAfter = safe(wikiText.substring(wikiLinkPos+wikiLink.length, p))
return true
}
function showText(){
var isChanged = wikiLink != wikiLinkOrig
$('#dabText').empty().addClass('text').append(snippetBefore
+'<span class=highlighted>'+safe(wikiLink)+'</span>'+snippetAfter)
$('#dabText .highlighted').toggleClass('changed', isChanged)
$('#dabMenu button.x').css('visibility', isChanged?'visible':'hidden')
$('#dabMenu button.unlink').css('visibility', /^\[/.test(wikiLink)?'visible':'hidden')
}
function finish(){
tBox.val(wikiText)
appendSummary()
close(($i.finished || 'Changed links:') + ' ' + changes.length)
}
function safe(s){ return s.replace(/>/g,'>').replace(/</g,'<') }
function outputWikiLink(name){
return $('<a>').append(name).attr('title',name)
.attr('href', wgArticlePath.replace(/\$1/,'')+encodeURI(name).replace(/\?/g,'%3F'))
}
function linkClicked(e){
e.preventDefault()
var targ = $(e.target)
if (targ.attr('nodeName') != 'A') return
// !!! check for parent metadata
if (targ.hasClass('new')) targ = targ.attr('href').match(/\?title=([^&]+)/)
else targ = targ.attr('href').match(/\/wiki\/([^\?]+)/)
if (!targ) return
targ = decodeURIComponent(targ[1]).replace(/_/g,' ')
wikiLink = wikiLinkOrig.replace(/\[\[(.+\|)?(.+)\]\](.+)?/, function(str, lnk, name, trail){return '[\['+targ+'|'+name+(trail||'')+']]'})
showText()
return false
}
function appendSummary(){
var sm = $('#wpSummary')
if (sm.val().indexOf('disambiguation') == -1)
sm.val(sm.val()+'[[Wikipedia:Disambiguation]]')
}
function createLinkRegexp(title){
var i, ch, re = ''
for (i=0; ch=title.charAt(i), i<title.length; i++)
re += ('(){}^$.+*|/\\'.indexOf(ch) != -1 ? '\\' :'') + ch
ch = re.charAt(0)
if (/^[\wА-Я]/.test(ch)) re = '('+ch+'|'+ch.toLowerCase()+')'+re.substring(1)
re = new RegExp('\\[\\[\\s*'+re+'\\s*(\\|[^\\[\\]]+)?\\]\\][a-zа-яё]*', 'g')
return re
}
function guessDab(){
$('#floating_object').remove()
var words, word, score, count, ma, lis = $("#dabPage li")
for (var l=0; l<lis.length;l++){
score = 0; count = 0
words = lis.eq(l).text().replace(/[^\wа-яё]+/gi,' ').split(' ')
for (var i=0; i<words.length; i++){
word = words[i]
if (/^[а-яё]+$/i.test(word)) word = word.substr(0, word.length-2) //rus suffix
if (word.length < 4) continue //too short
if (dis[disIdx].title.match(RegExp('^'+word,'i'))) continue //disambig title
count++
ma = wikiText.match(RegExp(word, 'ig'))
if (!ma) continue
score += ma.length
}
lis[l].score = score / count
}
lis.sort(function(a,b){return b.score-a.score})
lis.eq(0).addClass('highlight')
}
}