MediaWiki:Gadget-popups.js: различия между версиями
>Edward Chernenko м тест новой версии из enwiki |
>Edward Chernenko м rv к прежней версии. Она работала, в новой ещё копаться и копаться |
||
| Строка 1: | Строка 1: | ||
var popupVersion=" | importScript('Участник:Edward_Chernenko/strings-ru.js'); | ||
var popupVersion="Sat Mar 10 21:40:16 UTC 2007"; | |||
// STARTFILE: main.js | // STARTFILE: main.js | ||
// ********************************************************************** | // ********************************************************************** | ||
| Строка 15: | Строка 17: | ||
// ** ** | // ** ** | ||
// ********************************************************************** | // ********************************************************************** | ||
//////////////////////////////////////////////////////////////////// | |||
// Import stylesheet(s) | |||
// | |||
if ( window.localCSS ) { | |||
document.write('<link rel="stylesheet" type="text/css" href="http://localhost:8080/js/navpop.css">'); | |||
} else { | |||
document.write('<link rel="stylesheet" type="text/css" href="' + | |||
'http://en.wikipedia.org/w/index.php?title=User:Lupin/navpop.css' + | |||
'&action=raw&ctype=text/css&dontcountme=s">'); | |||
} | |||
////////////////////////////////////////////////// | ////////////////////////////////////////////////// | ||
// Globals | // Globals | ||
// | // | ||
// Trying to shove as many of these as possible into the pg (popup globals) object | // Trying to shove as many of these as possible into the pg (popup globals) object | ||
function pg(){}; // dummy to stop errors | function pg(){}; // dummy to stop errors | ||
| Строка 49: | Строка 64: | ||
return true; | return true; | ||
} | } | ||
//////////////////////////////////////////////////////////////////// | |||
// Run things | |||
//////////////////////////////////////////////////////////////////// | |||
hookEvent('load', setupPopups); | |||
/// Local Variables: /// | /// Local Variables: /// | ||
/// mode:c /// | /// mode:c /// | ||
| Строка 60: | Строка 80: | ||
//<NOLITE> | //<NOLITE> | ||
// the main initial call | // the main initial call | ||
if (getValueOf('popupOnEditSelection') && window.doSelectionPopup | if (getValueOf('popupOnEditSelection') && window.doSelectionPopup ) { | ||
document.editform.wpTextbox1.onmouseup=doSelectionPopup; | try { | ||
document.editform.wpTextbox1.onmouseup=function() { doSelectionPopup(); }; | |||
} catch (neverMind) {} | |||
} | } | ||
//</NOLITE> | //</NOLITE> | ||
| Строка 67: | Строка 89: | ||
container = defaultPopupsContainer(); | container = defaultPopupsContainer(); | ||
} | } | ||
if (!remove && !force && container.ranSetupTooltipsAlready) { return; } | if (!remove && !force && container.ranSetupTooltipsAlready) { return; } | ||
container.ranSetupTooltipsAlready = !remove; | container.ranSetupTooltipsAlready = !remove; | ||
var anchors; | var anchors; | ||
anchors=container.getElementsByTagName('A'); | anchors=container.getElementsByTagName('A'); | ||
setupTooltipsLoop(anchors, 0, 250, 100, remove, popData); | setupTooltipsLoop(anchors, 0, 250, 100, remove, popData); | ||
} | } | ||
function defaultPopupsContainer() { | function defaultPopupsContainer() { | ||
if (getValueOf('popupOnlyArticleLinks')) { | if (getValueOf('popupOnlyArticleLinks')) { | ||
return document.getElementById('article') || | return document.getElementById('article') || | ||
document.getElementById('content | document.getElementById('content') || document; | ||
} | } | ||
return document; | return document; | ||
} | } | ||
function setupTooltipsLoop(anchors,begin,howmany,sleep, remove, popData) { | function setupTooltipsLoop(anchors,begin,howmany,sleep, remove, popData) { | ||
log(simplePrintf('setupTooltipsLoop(%s,%s,%s,%s,%s)', arguments)); | log(simplePrintf('setupTooltipsLoop(%s,%s,%s,%s,%s)', arguments)); | ||
| Строка 113: | Строка 134: | ||
} | } | ||
} | } | ||
// eliminate popups from the TOC | // eliminate popups from the TOC | ||
// This also kills any onclick stuff that used to be going on in the toc | // This also kills any onclick stuff that used to be going on in the toc | ||
| Строка 126: | Строка 147: | ||
} | } | ||
} | } | ||
function addTooltip(a, popData) { | function addTooltip(a, popData) { | ||
if ( !isPopupLink(a) ) { return; } | if ( !isPopupLink(a) ) { return; } | ||
| Строка 135: | Строка 156: | ||
a.popData = popData; | a.popData = popData; | ||
} | } | ||
function removeTooltip(a) { | function removeTooltip(a) { | ||
if ( !a.hasPopup ) { return; } | if ( !a.hasPopup ) { return; } | ||
| Строка 143: | Строка 164: | ||
a.hasPopup=false; | a.hasPopup=false; | ||
} | } | ||
function removeTitle(a) { | function removeTitle(a) { | ||
if (a.originalTitle) { return; } | if (a.originalTitle) { return; } | ||
| Строка 149: | Строка 170: | ||
a.title=''; | a.title=''; | ||
} | } | ||
function restoreTitle(a) { | function restoreTitle(a) { | ||
if ( a.title || !a.originalTitle ) { return; } | if ( a.title || !a.originalTitle ) { return; } | ||
| Строка 155: | Строка 176: | ||
a.originalTitle=''; | a.originalTitle=''; | ||
} | } | ||
function registerHooks(np) { | function registerHooks(np) { | ||
var popupMaxWidth=getValueOf('popupMaxWidth'); | var popupMaxWidth=getValueOf('popupMaxWidth'); | ||
if (typeof popupMaxWidth == 'number') { | if (typeof popupMaxWidth == 'number') { | ||
var setMaxWidth = function () { | var setMaxWidth = function () { | ||
np.mainDiv.style.maxWidth = popupMaxWidth + 'px'; | np.mainDiv.style.maxWidth = popupMaxWidth + 'px'; | ||
np.maxWidth = popupMaxWidth; | np.maxWidth = popupMaxWidth; | ||
// hack for IE | |||
// see http://www.svendtofte.com/code/max_width_in_ie/ | |||
// use setExpression as documented here on msdn: http://tinyurl dot com/dqljn | |||
if (np.mainDiv.style.setExpression) { | |||
np.mainDiv.style.setExpression( | |||
'width', 'document.body.clientWidth > ' + | |||
popupMaxWidth + ' ? "' +popupMaxWidth + 'px": "auto"'); | |||
} | |||
}; | }; | ||
np.addHook(setMaxWidth, 'unhide', 'before'); | np.addHook(setMaxWidth, 'unhide', 'before'); | ||
| Строка 188: | Строка 204: | ||
//</NOLITE> | //</NOLITE> | ||
} | } | ||
function mouseOverWikiLink(evt) { | function mouseOverWikiLink(evt) { | ||
if (!window.popupsReady || !window.popupsReady()) { return; } | if (!window.popupsReady || !window.popupsReady()) { return; } | ||
| Строка 195: | Строка 211: | ||
return mouseOverWikiLink2(this, evt); | return mouseOverWikiLink2(this, evt); | ||
} | } | ||
function footnoteTarget(a) { | function footnoteTarget(a) { | ||
var aTitle=Title.fromAnchor(a); | var aTitle=Title.fromAnchor(a); | ||
// We want ".3A" rather than "%3A" or "?" here, so use the anchor property directly | // We want ".3A" rather than "%3A" or "?" here, so use the anchor property directly | ||
var anch = aTitle.anchor; | var anch = aTitle.anchor; | ||
if ( ! /^( | if ( ! /^(_note-|endnote)/.test(anch) ) { return false; } | ||
var lTitle=Title.fromURL(location.href); | var lTitle=Title.fromURL(location.href); | ||
if ( lTitle.toString(true) != aTitle.toString(true) ) { return false; } | if ( lTitle.toString(true) != aTitle.toString(true) ) { return false; } | ||
var el=document.getElementById(anch); | var el=document.getElementById(anch); | ||
while ( el && typeof el.nodeName == 'string') { | while ( el && typeof el.nodeName == 'string') { | ||
| Строка 215: | Строка 231: | ||
return false; | return false; | ||
} | } | ||
function footnotePreview(x, navpop) { | function footnotePreview(x, navpop) { | ||
setPopupHTML('<hr>' + x.innerHTML, 'popupPreview', navpop.idNumber, | setPopupHTML('<hr>' + x.innerHTML, 'popupPreview', navpop.idNumber, | ||
| Строка 222: | Строка 238: | ||
} : null); | } : null); | ||
} | } | ||
// var modid=0; | // var modid=0; | ||
// if(!window.opera) { window.opera={postError: console.log}; } | // if(!window.opera) { window.opera={postError: console.log}; } | ||
function modifierKeyHandler(a) { | function modifierKeyHandler(a) { | ||
return function(evt) { | return function(evt) { | ||
// opera.postError('modifierKeyHandler called' + (++modid)); | |||
// opera.postError(''+evt + modid); | |||
// for (var i in evt) { | |||
// opera.postError('' + modid + ' ' + i + ' ' + evt[i]); | |||
// } | |||
// opera.postError(''+evt.ctrlKey + modid); | |||
var mod=getValueOf('popupModifier'); | var mod=getValueOf('popupModifier'); | ||
if (!mod) { return true; } | if (!mod) { return true; } | ||
if (!evt && window.event) {evt=window.event}; | if (!evt && window.event) {evt=window.event}; | ||
// opera.postError('And now....'+modid); | // opera.postError('And now....'+modid); | ||
// opera.postError(''+evt+modid); | // opera.postError(''+evt+modid); | ||
// opera.postError(''+evt.ctrlKey+modid); | // opera.postError(''+evt.ctrlKey+modid); | ||
if ( evt && mod && !evt[mod.toLowerCase() + 'Key'] ) { return true; } | |||
mouseOverWikiLink2(a, evt); | |||
}; | |||
} | } | ||
function | function mouseOverWikiLink2(a, evt) { | ||
// try not to duplicate effort | |||
var | var mod=getValueOf('popupModifier'); | ||
if ( | if ( evt && mod && !evt[mod.toLowerCase() + 'Key'] ) { | ||
// if the modifier is needed and not pressed, listen for it until | // if the modifier is needed and not pressed, listen for it until | ||
// we mouseout of this link. | // we mouseout of this link. | ||
| Строка 285: | Строка 281: | ||
return; | return; | ||
} | } | ||
a.modifierKeyHandler=modifierKeyHandler(a); | a.modifierKeyHandler=modifierKeyHandler(a); | ||
document[addHandler](on+'keydown', a.modifierKeyHandler, false); | |||
a[addHandler](on+'mouseout', function() { | |||
document[rmHandler](on+'keydown', | |||
a.modifierKeyHandler, false); | |||
}, true); | |||
return; | |||
return | |||
} | } | ||
if ( getValueOf('removeTitles') ) { removeTitle(a); } | if ( getValueOf('removeTitles') ) { removeTitle(a); } | ||
if ( a==pg.current.link && a.navpopup && a.navpopup.isVisible() ) { return; } | if ( a==pg.current.link && a.navpopup && a.navpopup.isVisible() ) { return; } | ||
pg.current.link=a; | pg.current.link=a; | ||
if (getValueOf('simplePopups') && pg.option.popupStructure===null) { | if (getValueOf('simplePopups') && pg.option.popupStructure===null) { | ||
// reset *default value* of popupStructure | // reset *default value* of popupStructure | ||
setDefault('popupStructure', 'original'); | setDefault('popupStructure', 'original'); | ||
} | } | ||
var article=(new Title()).fromAnchor(a); | var article=(new Title()).fromAnchor(a); | ||
// set global variable (ugh) to hold article (wikipage) | // set global variable (ugh) to hold article (wikipage) | ||
| Строка 324: | Строка 307: | ||
pg.counter.checkImages=0; | pg.counter.checkImages=0; | ||
} | } | ||
if (!a.navpopup) { | if (!a.navpopup) { | ||
// FIXME: this doesn't behave well if you mouse out of a popup | // FIXME: this doesn't behave well if you mouse out of a popup | ||
| Строка 342: | Строка 325: | ||
} | } | ||
a.navpopup.showSoonIfStable(a.navpopup.delay); | a.navpopup.showSoonIfStable(a.navpopup.delay); | ||
getValueOf('popupInitialWidth'); | getValueOf('popupInitialWidth'); | ||
clearInterval(pg.timer.checkPopupPosition); | clearInterval(pg.timer.checkPopupPosition); | ||
pg.timer.checkPopupPosition=setInterval(checkPopupPosition, 600); | pg.timer.checkPopupPosition=setInterval(checkPopupPosition, 600); | ||
if(getValueOf('simplePopups')) { | if(getValueOf('simplePopups')) { return; } | ||
if (a.navpopup.pending!==0 ) { | if (a.navpopup.pending!==0 ) { | ||
nonsimplePopupContent(a, article); | nonsimplePopupContent(a, article); | ||
} | } | ||
} | } | ||
// simplePopupContent: the content that is shown even when simplePopups is true | // simplePopupContent: the content that is shown even when simplePopups is true | ||
function simplePopupContent(a, article) { | function simplePopupContent(a, article) { | ||
| Строка 375: | Строка 343: | ||
a.navpopup.setInnerHTML(popupHTML(a)); | a.navpopup.setInnerHTML(popupHTML(a)); | ||
fillEmptySpans({navpopup:a.navpopup}); | fillEmptySpans({navpopup:a.navpopup}); | ||
var dragHandle = getValueOf('popupDragHandle') || null; | |||
if (dragHandle && dragHandle != 'all') { | |||
dragHandle += a.navpopup.idNumber; | |||
} | } | ||
setTimeout(function(){a.navpopup.makeDraggable(dragHandle);}, 150); | |||
//<NOLITE> | //<NOLITE> | ||
if (getValueOf('popupRedlinkRemoval') && a.className=='new') { | if (getValueOf('popupRedlinkRemoval') && a.className=='new') { | ||
| Строка 391: | Строка 355: | ||
//</NOLITE> | //</NOLITE> | ||
} | } | ||
function debugData(navpopup) { | function debugData(navpopup) { | ||
if(getValueOf('popupDebugging') && navpopup.idNumber) { | if(getValueOf('popupDebugging') && navpopup.idNumber) { | ||
| Строка 398: | Строка 362: | ||
} | } | ||
} | } | ||
function newNavpopup(a, article) { | function newNavpopup(a, article) { | ||
var navpopup = new Navpopup(); | var navpopup = new Navpopup(); | ||
| Строка 411: | Строка 375: | ||
return navpopup; | return navpopup; | ||
} | } | ||
function nonsimplePopupContent(a, article) { | function nonsimplePopupContent(a, article) { | ||
var diff=null, history=null; | var diff=null, history=null; | ||
| Строка 421: | Строка 385: | ||
diff=params.diff; | diff=params.diff; | ||
} | } | ||
if(getValueOf('popupPreviewHistory')) { | if(getValueOf('popupPreviewHistory') && getValueOf('popupUseQueryInterface')) { | ||
history=(params.action=='history'); | history=(params.action=='history'); | ||
} | } | ||
//</NOLITE> | //</NOLITE> | ||
a.navpopup.pending=0; | a.navpopup.pending=0; | ||
var previewImage=true; | |||
var x; | var x; | ||
pg.misc.gImage=null; | pg.misc.gImage=null; | ||
| Строка 432: | Строка 397: | ||
//<NOLITE> | //<NOLITE> | ||
} else if ( diff || diff === 0 ) { | } else if ( diff || diff === 0 ) { | ||
//alert([article,oldid,diff]); | |||
loadDiff(article, oldid, diff, a.navpopup); | loadDiff(article, oldid, diff, a.navpopup); | ||
} else if ( history ) { | } else if ( history && getValueOf('popupUseQueryInterface') ) { | ||
loadQueryPreview('history', article, a.navpopup); | |||
} else if ( pg.re.contribs.test(a.href) ) { | } else if ( pg.re.contribs.test(a.href) && getValueOf('popupUseQueryInterface')) { | ||
loadQueryPreview('contribs', article, a.navpopup); | |||
} else if ( pg.re.backlinks.test(a.href) ) { | } else if ( pg.re.backlinks.test(a.href) && getValueOf('popupUseQueryInterface')) { | ||
loadQueryPreview('backlinks', article, a.navpopup); | |||
} else if ( // FIXME should be able to get all preview combinations with options | |||
article.namespace()==pg.ns.image && | article.namespace()==pg.ns.image && | ||
( getValueOf('imagePopupsForImages') || ! anchorContainsImage(a) ) | ( getValueOf('imagePopupsForImages') || ! anchorContainsImage(a) ) | ||
) { | ) { | ||
if (getValueOf('popupUseQueryInterface')) { | |||
loadQueryPreview('imagepagepreview', article, a.navpopup); | |||
} else { startArticlePreview(article, oldid, a.navpopup); } | |||
loadImages(article); | loadImages(article); | ||
//</NOLITE> | //</NOLITE> | ||
} else | } else if (article.namespace() == pg.ns.category && | ||
getValueOf('popupCategoryMembers')) { | |||
getValueOf('popupUseQueryInterface') && | |||
loadQueryPreview('category', article, a.navpopup); | |||
} else if ( | startArticlePreview(article, oldid, a.navpopup); | ||
} | |||
else if (!article.namespace()!=pg.ns.image && previewImage ) { | |||
startArticlePreview(article, oldid, a.navpopup); | startArticlePreview(article, oldid, a.navpopup); | ||
} | } | ||
} | } | ||
function pendingNavpopTask(navpop) { | function pendingNavpopTask(navpop) { | ||
if (navpop && navpop.pending===null) { navpop.pending=0; } | if (navpop && navpop.pending===null) { navpop.pending=0; } | ||
| Строка 463: | Строка 430: | ||
debugData(navpop); | debugData(navpop); | ||
} | } | ||
function completedNavpopTask(navpop) { | function completedNavpopTask(navpop) { | ||
if (navpop && navpop.pending) { --navpop.pending; } | if (navpop && navpop.pending) { --navpop.pending; } | ||
debugData(navpop); | debugData(navpop); | ||
} | } | ||
function startArticlePreview(article, oldid, navpop) { | function startArticlePreview(article, oldid, navpop) { | ||
navpop.redir=0; | navpop.redir=0; | ||
loadPreview(article, oldid, navpop); | loadPreview(article, oldid, navpop); | ||
} | } | ||
function loadPreview(article, oldid, navpop) { | function loadPreview(article, oldid, navpop) { | ||
pendingNavpopTask(navpop); | pendingNavpopTask(navpop); | ||
| Строка 486: | Строка 453: | ||
} | } | ||
} | } | ||
function loadPreviewFromRedir(redirMatch, navpop) { | function loadPreviewFromRedir(redirMatch, navpop) { | ||
// redirMatch is a regex match | // redirMatch is a regex match | ||
| Строка 506: | Строка 473: | ||
return loadPreview(target, null, navpop); | return loadPreview(target, null, navpop); | ||
} | } | ||
function insertPreview(download) { | function insertPreview(download) { | ||
if (!download.owner) { return; } | if (!download.owner) { return; } | ||
var redirMatch = pg.re.redirect.exec(download.data); | var redirMatch = pg.re.redirect.exec(download.data); | ||
if (download.owner.redir===0 && redirMatch) { | if (download.owner.redir===0 && redirMatch) { | ||
| Строка 516: | Строка 483: | ||
return; | return; | ||
} | } | ||
if (download.owner.visible || !getValueOf('popupLazyPreviews')) { | if (download.owner.visible || !getValueOf('popupLazyPreviews')) { | ||
insertPreviewNow(download); | insertPreviewNow(download); | ||
| Строка 525: | Строка 492: | ||
} | } | ||
} | } | ||
function insertPreviewNow(download) { | function insertPreviewNow(download) { | ||
if (!download.owner) { return; } | if (!download.owner) { return; } | ||
| Строка 532: | Строка 499: | ||
completedNavpopTask(navpop); | completedNavpopTask(navpop); | ||
var art=navpop.redirTarget || navpop.originalArticle; | var art=navpop.redirTarget || navpop.originalArticle; | ||
//<NOLITE> | //<NOLITE> | ||
makeFixDabs(wikiText, navpop); | makeFixDabs(wikiText, navpop); | ||
| Строка 539: | Строка 506: | ||
setPopupTrailer(getPageInfo(wikiText, download), navpop.idNumber); | setPopupTrailer(getPageInfo(wikiText, download), navpop.idNumber); | ||
} | } | ||
var imagePage=''; | var imagePage=''; | ||
if (art.namespace()==pg.ns.image) { imagePage=art.toString(); } | if (art.namespace()==pg.ns.image) { imagePage=art.toString(); } | ||
| Строка 545: | Строка 512: | ||
if(imagePage) { loadImages(Title.fromWikiText(imagePage)); } | if(imagePage) { loadImages(Title.fromWikiText(imagePage)); } | ||
//</NOLITE> | //</NOLITE> | ||
if (getValueOf('popupPreviews')) { insertArticlePreview(download, art, navpop); } | if (getValueOf('popupPreviews')) { insertArticlePreview(download, art, navpop); } | ||
} | } | ||
function insertArticlePreview(download, art, navpop) { | function insertArticlePreview(download, art, navpop) { | ||
if (download && typeof download.data == typeof ''){ | if (download && typeof download.data == typeof ''){ | ||
| Строка 563: | Строка 530: | ||
} | } | ||
} | } | ||
function prepPreviewmaker(data, article, navpop) { | function prepPreviewmaker(data, article, navpop) { | ||
// deal with tricksy anchors | // deal with tricksy anchors | ||
| Строка 571: | Строка 538: | ||
return p; | return p; | ||
} | } | ||
// Try to imitate the way mediawiki generates HTML anchors from section titles | // Try to imitate the way mediawiki generates HTML anchors from section titles | ||
function anchorize(d, anch) { | function anchorize(d, anch) { | ||
| Строка 579: | Строка 546: | ||
var match=d.match(anchRe); | var match=d.match(anchRe); | ||
if(match && match.length > 0 && match[0]) { return d.substring(d.indexOf(match[0])); } | if(match && match.length > 0 && match[0]) { return d.substring(d.indexOf(match[0])); } | ||
// now try to deal with == foo [[bar|baz]] boom == -> #foo_baz_boom | // now try to deal with == foo [[bar|baz]] boom == -> #foo_baz_boom | ||
var lines=d.split('\n'); | var lines=d.split('\n'); | ||
| Строка 591: | Строка 558: | ||
return d; | return d; | ||
} | } | ||
function killPopup() { | function killPopup() { | ||
if (getValueOf('popupShortcutKeys') && window.rmPopupShortcuts) { rmPopupShortcuts(); } | if (getValueOf('popupShortcutKeys') && window.rmPopupShortcuts) { rmPopupShortcuts(); } | ||
| Строка 612: | Строка 579: | ||
@fileoverview | @fileoverview | ||
The {@link Drag} object, which enables objects to be dragged around. | The {@link Drag} object, which enables objects to be dragged around. | ||
<pre> | <pre> | ||
************************************************* | ************************************************* | ||
| Строка 623: | Строка 590: | ||
************************************************* | ************************************************* | ||
Pared down, some hooks added by [[User:Lupin]] | Pared down, some hooks added by [[User:Lupin]] | ||
Copyright Aaron Boodman. | Copyright Aaron Boodman. | ||
Saying stupid things daily since March 2001. | Saying stupid things daily since March 2001. | ||
</pre> | </pre> | ||
*/ | */ | ||
/** | /** | ||
Creates a new Drag object. This is used to make various DOM elements draggable. | Creates a new Drag object. This is used to make various DOM elements draggable. | ||
| Строка 647: | Строка 614: | ||
this.endHook = null; | this.endHook = null; | ||
} | } | ||
/** | /** | ||
Gets an event in a cross-browser manner. | Gets an event in a cross-browser manner. | ||
| Строка 669: | Строка 636: | ||
o.onmousedown = function(e) { dragObj.start.apply( dragObj, [e]); }; | o.onmousedown = function(e) { dragObj.start.apply( dragObj, [e]); }; | ||
o.dragging = false; | o.dragging = false; | ||
o. | o.draggable = true; | ||
o.hmode = true; | o.hmode = true; | ||
o.vmode = true; | o.vmode = true; | ||
o.root = oRoot && oRoot !== null ? oRoot : o ; | o.root = oRoot && oRoot !== null ? oRoot : o ; | ||
if (isNaN(parseInt(o.root.style.left, 10))) { o.root.style.left = "0px"; } | if (isNaN(parseInt(o.root.style.left, 10))) { o.root.style.left = "0px"; } | ||
if (isNaN(parseInt(o.root.style.top, 10))) { o.root.style.top = "0px"; } | if (isNaN(parseInt(o.root.style.top, 10))) { o.root.style.top = "0px"; } | ||
o.root.onthisStart = function(){}; | o.root.onthisStart = function(){}; | ||
o.root.onthisEnd = function(){}; | o.root.onthisEnd = function(){}; | ||
o.root.onthis = function(){}; | o.root.onthis = function(){}; | ||
}; | }; | ||
/** | /** | ||
Starts the drag. | Starts the drag. | ||
| Строка 695: | Строка 662: | ||
var x = parseInt(o.hmode ? o.root.style.left : o.root.style.right, 10); | var x = parseInt(o.hmode ? o.root.style.left : o.root.style.right, 10); | ||
o.root.onthisStart(x, y); | o.root.onthisStart(x, y); | ||
o.lastMouseX = e.clientX; | o.lastMouseX = e.clientX; | ||
o.lastMouseY = e.clientY; | o.lastMouseY = e.clientY; | ||
var dragObj = this; | var dragObj = this; | ||
o.onmousemoveDefault = document.onmousemove; | o.onmousemoveDefault = document.onmousemove; | ||
| Строка 714: | Строка 681: | ||
e = this.fixE(e); | e = this.fixE(e); | ||
var o = this.obj; | var o = this.obj; | ||
var ey = e.clientY; | var ey = e.clientY; | ||
var ex = e.clientX; | var ex = e.clientX; | ||
| Строка 720: | Строка 687: | ||
var x = parseInt(o.hmode ? o.root.style.left : o.root.style.right, 10 ); | var x = parseInt(o.hmode ? o.root.style.left : o.root.style.right, 10 ); | ||
var nx, ny; | var nx, ny; | ||
nx = x + ((ex - o.lastMouseX) * (o.hmode ? 1 : -1)); | nx = x + ((ex - o.lastMouseX) * (o.hmode ? 1 : -1)); | ||
ny = y + ((ey - o.lastMouseY) * (o.vmode ? 1 : -1)); | ny = y + ((ey - o.lastMouseY) * (o.vmode ? 1 : -1)); | ||
this.obj.root.style[o.hmode ? "left" : "right"] = nx + "px"; | this.obj.root.style[o.hmode ? "left" : "right"] = nx + "px"; | ||
this.obj.root.style[o.vmode ? "top" : "bottom"] = ny + "px"; | this.obj.root.style[o.vmode ? "top" : "bottom"] = ny + "px"; | ||
this.obj.lastMouseX = ex; | this.obj.lastMouseX = ex; | ||
this.obj.lastMouseY = ey; | this.obj.lastMouseY = ey; | ||
this.obj.root.onthis(nx, ny); | this.obj.root.onthis(nx, ny); | ||
return false; | return false; | ||
}; | }; | ||
/** | /** | ||
Ends the drag. | Ends the drag. | ||
| Строка 780: | Строка 747: | ||
pg.structures.original.popupRedirTitle=pg.structures.original.popupTitle; | pg.structures.original.popupRedirTitle=pg.structures.original.popupTitle; | ||
pg.structures.original.popupRedirTopLinks=pg.structures.original.popupTopLinks; | pg.structures.original.popupRedirTopLinks=pg.structures.original.popupTopLinks; | ||
function copyStructure(oldStructure, newStructure) { | function copyStructure(oldStructure, newStructure) { | ||
pg.structures[newStructure]={}; | pg.structures[newStructure]={}; | ||
| Строка 788: | Строка 755: | ||
} | } | ||
} | } | ||
copyStructure('original', 'nostalgia'); | copyStructure('original', 'nostalgia'); | ||
pg.structures.nostalgia.popupTopLinks=function(x) { | pg.structures.nostalgia.popupTopLinks=function(x) { | ||
var str=''; | var str=''; | ||
str += '<b><<mainlink|shortcut= >></b>'; | str += '<b><<mainlink|shortcut= >></b>'; | ||
// user links | // user links | ||
// contribs - log - count - email - block | // contribs - log - count - email - block | ||
| Строка 800: | Строка 767: | ||
str+='if(wikimedia){*<<count|shortcut=#>>}'; | str+='if(wikimedia){*<<count|shortcut=#>>}'; | ||
str+='if(ipuser){}else{*<<email|shortcut=E>>}if(admin){*<<block|shortcut=b>>}}'; | str+='if(ipuser){}else{*<<email|shortcut=E>>}if(admin){*<<block|shortcut=b>>}}'; | ||
// editing links | // editing links | ||
// talkpage -> edit|new - history - un|watch - article|edit | // talkpage -> edit|new - history - un|watch - article|edit | ||
| Строка 809: | Строка 776: | ||
var historystr='<<history|shortcut=h>>'; | var historystr='<<history|shortcut=h>>'; | ||
var watchstr='<<unwatch|unwatchShort>>|<<watch|shortcut=w|watchThingy>>'; | var watchstr='<<unwatch|unwatchShort>>|<<watch|shortcut=w|watchThingy>>'; | ||
str+='<br>if(talk){' + | str+='<br>if(talk){' + | ||
editOldidStr+'|<<new|shortcut=+>>' + '*' + historystr+'*'+watchstr + '*' + | editOldidStr+'|<<new|shortcut=+>>' + '*' + historystr+'*'+watchstr + '*' + | ||
| Строка 817: | Строка 784: | ||
'<b><<talk|shortcut=t>></b>|<<editTalk|edit>>|<<newTalk|shortcut=+|new>>' | '<b><<talk|shortcut=t>></b>|<<editTalk|edit>>|<<newTalk|shortcut=+|new>>' | ||
+ '}'; | + '}'; | ||
// misc links | // misc links | ||
str += '<br><<whatLinksHere|shortcut=l>>*<<relatedChanges|shortcut=r>>'; | str += '<br><<whatLinksHere|shortcut=l>>*<<relatedChanges|shortcut=r>>'; | ||
str += 'if(admin){<br>}else{*}<<move|shortcut=m>>'; | str += 'if(admin){<br>}else{*}<<move|shortcut=m>>'; | ||
// admin links | // admin links | ||
str += 'if(admin){*<<unprotect|unprotectShort>>|<<protect|shortcut=p>>*' + | str += 'if(admin){*<<unprotect|unprotectShort>>|<<protect|shortcut=p>>*' + | ||
| Строка 828: | Строка 795: | ||
}; | }; | ||
pg.structures.nostalgia.popupRedirTopLinks=pg.structures.nostalgia.popupTopLinks; | pg.structures.nostalgia.popupRedirTopLinks=pg.structures.nostalgia.popupTopLinks; | ||
/** -- fancy -- **/ | /** -- fancy -- **/ | ||
copyStructure('original', 'fancy'); | copyStructure('original', 'fancy'); | ||
| Строка 850: | Строка 817: | ||
user+='if(ipuser){|<<arin>>}else{*<<email|shortcut=E|'+ | user+='if(ipuser){|<<arin>>}else{*<<email|shortcut=E|'+ | ||
popupString('email')+'>>}if(admin){*<<block|shortcut=b>>}'; | popupString('email')+'>>}if(admin){*<<block|shortcut=b>>}'; | ||
var normal='<<whatLinksHere|shortcut=l|links here>>*<<relatedChanges|shortcut=r|related>>'; | var normal='<<whatLinksHere|shortcut=l|links here>>*<<relatedChanges|shortcut=r|related>>'; | ||
return navlinkStringToHTML('<br>if(user){' + user + '*}if(admin){'+admin+'if(user){<br>}else{*}}' + normal, | return navlinkStringToHTML('<br>if(user){' + user + '*}if(admin){'+admin+'if(user){<br>}else{*}}' + normal, | ||
| Строка 858: | Строка 825: | ||
pg.structures.fancy.popupRedirTopLinks=pg.structures.fancy.popupTopLinks; | pg.structures.fancy.popupRedirTopLinks=pg.structures.fancy.popupTopLinks; | ||
pg.structures.fancy.popupRedirOtherLinks=pg.structures.fancy.popupOtherLinks; | pg.structures.fancy.popupRedirOtherLinks=pg.structures.fancy.popupOtherLinks; | ||
/** -- fancy2 -- **/ | /** -- fancy2 -- **/ | ||
// hack for [[User:MacGyverMagic]] | // hack for [[User:MacGyverMagic]] | ||
| Строка 872: | Строка 839: | ||
'popupPrePreviewSep', 'popupPreview', 'popupSecondPreview', 'popupPreviewMore', 'popupPostPreview', 'popupFixDab']; | 'popupPrePreviewSep', 'popupPreview', 'popupSecondPreview', 'popupPreviewMore', 'popupPostPreview', 'popupFixDab']; | ||
}; | }; | ||
/** -- menus -- **/ | /** -- menus -- **/ | ||
copyStructure('original', 'menus'); | copyStructure('original', 'menus'); | ||
| Строка 919: | Строка 886: | ||
var newTopic='if(talk){<<new|shortcut=+|new topic>>}'; | var newTopic='if(talk){<<new|shortcut=+|new topic>>}'; | ||
var protectDelete='if(admin){' + protect + del + '}'; | var protectDelete='if(admin){' + protect + del + '}'; | ||
if (getValueOf('popupActionsMenu')) { | if (getValueOf('popupActionsMenu')) { | ||
s.push( '<<mainlink>>*' + dropdiv + menuTitle('actions')); | s.push( '<<mainlink>>*' + dropdiv + menuTitle('actions')); | ||
| Строка 936: | Строка 903: | ||
'else{<<talk|shortcut=t|talk page>><<editTalk|edit talk>>' + | 'else{<<talk|shortcut=t|talk page>><<editTalk|edit talk>>' + | ||
'<<newTalk|shortcut=+|new topic>>}</menu>' + enddiv); | '<<newTalk|shortcut=+|new topic>>}</menu>' + enddiv); | ||
// user menu starts here | // user menu starts here | ||
var email='<<email|shortcut=E|email user>>'; | var email='<<email|shortcut=E|email user>>'; | ||
var contribs= 'if(wikimedia){<menurow>}<<contribs|shortcut=c|contributions>> | var contribs= 'if(wikimedia){<menurow>}<<contribs|shortcut=c|contributions>>' + | ||
'if( | 'if(wikimedia){|<<contribsTree|tree>></menurow>}'; | ||
s.push('if(user){*' + dropdiv + menuTitle('user')); | s.push('if(user){*' + dropdiv + menuTitle('user')); | ||
s.push('<menu>'); + | s.push('<menu>'); + | ||
| Строка 955: | Строка 921: | ||
s.push('<<blocklog|shortcut=B|block log>>' + getValueOf('popupExtraUserMenu')); | s.push('<<blocklog|shortcut=B|block log>>' + getValueOf('popupExtraUserMenu')); | ||
s.push('</menu>' + enddiv + '}'); | s.push('</menu>' + enddiv + '}'); | ||
// popups menu starts here | // popups menu starts here | ||
if (getValueOf('popupSetupMenu') && !x.navpop.hasPopupMenu /* FIXME: hack */) { | if (getValueOf('popupSetupMenu') && !x.navpop.hasPopupMenu /* FIXME: hack */) { | ||
| Строка 967: | Строка 933: | ||
return navlinkStringToHTML(s.join(''), x.article, x.params); | return navlinkStringToHTML(s.join(''), x.article, x.params); | ||
}; | }; | ||
function menuTitle(s) { | function menuTitle(s) { | ||
return '<a href="#" noPopup=1>' + popupString(s) + '</a>'; | return '<a href="#" noPopup=1>' + popupString(s) + '</a>'; | ||
} | } | ||
pg.structures.menus.popupRedirTitle=pg.structures.menus.popupTitle; | pg.structures.menus.popupRedirTitle=pg.structures.menus.popupTitle; | ||
pg.structures.menus.popupRedirTopLinks=pg.structures.menus.popupTopLinks; | pg.structures.menus.popupRedirTopLinks=pg.structures.menus.popupTopLinks; | ||
copyStructure('menus', 'shortmenus'); | copyStructure('menus', 'shortmenus'); | ||
pg.structures.shortmenus.popupTopLinks=function(x) { | pg.structures.shortmenus.popupTopLinks=function(x) { | ||
| Строка 980: | Строка 946: | ||
}; | }; | ||
pg.structures.shortmenus.popupRedirTopLinks=pg.structures.shortmenus.popupTopLinks; | pg.structures.shortmenus.popupRedirTopLinks=pg.structures.shortmenus.popupTopLinks; | ||
//</NOLITE> | //</NOLITE> | ||
pg.structures.lite={}; | pg.structures.lite={}; | ||
| Строка 1012: | Строка 966: | ||
if (m) { | if (m) { | ||
try { | try { | ||
return | return decodeURI(m[1]); | ||
} catch (someError) {} | } catch (someError) {} | ||
} | } | ||
return null; | return null; | ||
} | } | ||
function substitute(data,cmdBody) { | function substitute(data,cmdBody) { | ||
// alert('sub\nfrom: '+cmdBody.from+'\nto: '+cmdBody.to+'\nflags: '+cmdBody.flags); | // alert('sub\nfrom: '+cmdBody.from+'\nto: '+cmdBody.to+'\nflags: '+cmdBody.flags); | ||
| Строка 1023: | Строка 977: | ||
return data.replace(fromRe, cmdBody.to); | return data.replace(fromRe, cmdBody.to); | ||
} | } | ||
function execCmds(data, cmdList) { | function execCmds(data, cmdList) { | ||
for (var i=0; i<cmdList.length; ++i) { | for (var i=0; i<cmdList.length; ++i) { | ||
| Строка 1030: | Строка 984: | ||
return data; | return data; | ||
} | } | ||
function parseCmd(str) { | function parseCmd(str) { | ||
// returns a list of commands | // returns a list of commands | ||
| Строка 1045: | Строка 999: | ||
return false; | return false; | ||
} | } | ||
function unEscape(str, sep) { | function unEscape(str, sep) { | ||
return str.split('\\\\').join('\\').split('\\'+sep).join(sep).split('\\n').join('\n'); | return str.split('\\\\').join('\\').split('\\'+sep).join(sep).split('\\n').join('\n'); | ||
} | } | ||
function parseSubstitute(str) { | function parseSubstitute(str) { | ||
// takes a string like s/a/b/flags;othercmds and parses it | // takes a string like s/a/b/flags;othercmds and parses it | ||
var from,to,flags,tmp; | var from,to,flags,tmp; | ||
if (str.length<4) { return false; } | if (str.length<4) { return false; } | ||
var sep=str.charAt(1); | var sep=str.charAt(1); | ||
str=str.substring(2); | str=str.substring(2); | ||
tmp=skipOver(str,sep); | tmp=skipOver(str,sep); | ||
if (tmp) { from=tmp.segment; str=tmp.remainder; } | if (tmp) { from=tmp.segment; str=tmp.remainder; } | ||
else { return false; } | else { return false; } | ||
tmp=skipOver(str,sep); | tmp=skipOver(str,sep); | ||
if (tmp) { to=tmp.segment; str=tmp.remainder; } | if (tmp) { to=tmp.segment; str=tmp.remainder; } | ||
else { return false; } | else { return false; } | ||
flags=''; | flags=''; | ||
if (str.length) { | if (str.length) { | ||
| Строка 1073: | Строка 1027: | ||
if (tmp) {flags=tmp.segment; str=tmp.remainder; } | if (tmp) {flags=tmp.segment; str=tmp.remainder; } | ||
} | } | ||
return {action: substitute, from: from, to: to, flags: flags, remainder: str}; | return {action: substitute, from: from, to: to, flags: flags, remainder: str}; | ||
} | } | ||
function skipOver(str,sep) { | function skipOver(str,sep) { | ||
var endSegment=findNext(str,sep); | var endSegment=findNext(str,sep); | ||
| Строка 1084: | Строка 1038: | ||
return {segment: segment, remainder: str.substring(endSegment+1)}; | return {segment: segment, remainder: str.substring(endSegment+1)}; | ||
} | } | ||
function skipToEnd(str,sep) { | function skipToEnd(str,sep) { | ||
return {segment: str, remainder: ''}; | return {segment: str, remainder: ''}; | ||
} | } | ||
function findNext(str, ch) { | function findNext(str, ch) { | ||
for (var i=0; i<str.length; ++i) { | for (var i=0; i<str.length; ++i) { | ||
| Строка 1096: | Строка 1050: | ||
return -1; | return -1; | ||
} | } | ||
function setCheckbox(param, box) { | function setCheckbox(param, box) { | ||
var val=getParamValue(param); | var val=getParamValue(param); | ||
| Строка 1109: | Строка 1063: | ||
} | } | ||
} | } | ||
function autoEdit() { | function autoEdit() { | ||
if (!setupPopups.completed) { setupPopups(); } | if (!setupPopups.completed) { setupPopups(); } | ||
if (!document.editform | if (!document.editform) { return false; } | ||
if (window.autoEdit.alreadyRan) { return false; } | if (window.autoEdit.alreadyRan) { return false; } | ||
window.autoEdit.alreadyRan=true; | window.autoEdit.alreadyRan=true; | ||
| Строка 1124: | Строка 1078: | ||
var output=execCmds(input, cmdList); | var output=execCmds(input, cmdList); | ||
editbox.value=output; | editbox.value=output; | ||
} | } | ||
setCheckbox('autominor', document.editform.wpMinoredit); | setCheckbox('autominor', document.editform.wpMinoredit); | ||
setCheckbox('autowatch', document.editform.wpWatchthis); | setCheckbox('autowatch', document.editform.wpWatchthis); | ||
var rvid = getParamValue('autorv'); | var rvid = getParamValue('autorv'); | ||
if ( | if (getValueOf('popupUseQueryInterface') && getParamValue('autorv')) { | ||
var url=pg.wiki.wikibase + '/ | var url=pg.wiki.wikibase + '/query.php?format=json&what=revisions&revids='+rvid; | ||
startDownload(url, null, autoEdit2); | startDownload(url, null, autoEdit2); | ||
} else { autoEdit2(); } | } else { autoEdit2(); } | ||
} | } | ||
function autoEdit2(d) { | function autoEdit2(d) { | ||
var summary=getParamValue('autosummary'); | var summary=getParamValue('autosummary'); | ||
| Строка 1165: | Строка 1113: | ||
setTimeout(autoEdit3, 100); | setTimeout(autoEdit3, 100); | ||
} | } | ||
function autoEdit3() { | function autoEdit3() { | ||
var btn=getParamValue('autoclick'); | var btn=getParamValue('autoclick'); | ||
if (btn) { | if (btn) { | ||
| Строка 1188: | Строка 1130: | ||
} | } | ||
} | } | ||
function bannerMessage(s) { | function bannerMessage(s) { | ||
var headings=document.getElementsByTagName('h1'); | var headings=document.getElementsByTagName('h1'); | ||
| Строка 1197: | Строка 1139: | ||
} | } | ||
} | } | ||
function getRvSummary(template, json) { | function getRvSummary(template, json) { | ||
var o=getJsObj(json); | |||
try { | try { | ||
var edit = anyChild(o.pages).revisions[0]; | |||
} catch (badness) {return false;} | } catch (badness) {return false;} | ||
var timestamp = edit.timestamp.split(/[A-Z]/g).join(' ').replace(/^ *| *$/g, ''); | var timestamp = edit.timestamp.split(/[A-Z]/g).join(' ').replace(/^ *| *$/g, ''); | ||
return simplePrintf(template, [edit.revid, timestamp, edit.user]); | return simplePrintf(template, [edit.revid, timestamp, edit.user]); | ||
} | } | ||
hookEvent('load', autoEdit); | |||
//</NOLITE> | //</NOLITE> | ||
// ENDFILE: autoedit.js | // ENDFILE: autoedit.js | ||
| Строка 1214: | Строка 1158: | ||
{@link Downloader}, a xmlhttprequest wrapper, and helper functions. | {@link Downloader}, a xmlhttprequest wrapper, and helper functions. | ||
*/ | */ | ||
/** | /** | ||
Creates a new Downloader | Creates a new Downloader | ||
| Строка 1225: | Строка 1169: | ||
/** xmlhttprequest object which we're wrapping */ | /** xmlhttprequest object which we're wrapping */ | ||
this.http = false; | this.http = false; | ||
/*@cc_on @*/ | /*@cc_on @*/ | ||
/*@if (@_jscript_version >= 5) | /*@if (@_jscript_version >= 5) | ||
| Строка 1241: | Строка 1185: | ||
} | } | ||
@end @*/ | @end @*/ | ||
if (! this.http && typeof XMLHttpRequest!='undefined') { this.http = new XMLHttpRequest(); } | if (! this.http && typeof XMLHttpRequest!='undefined') { this.http = new XMLHttpRequest(); } | ||
/** | /** | ||
| Строка 1287: | Строка 1231: | ||
this.async=true; | this.async=true; | ||
} | } | ||
new Downloader(); | new Downloader(); | ||
/** Submits the http request. */ | /** Submits the http request. */ | ||
Downloader.prototype.send = function (x) { | Downloader.prototype.send = function (x) { | ||
| Строка 1310: | Строка 1254: | ||
/** Gets the state of the download. */ | /** Gets the state of the download. */ | ||
Downloader.prototype.getReadyState=function () {if (!this.http) { return null; } return this.http.readyState;}; | Downloader.prototype.getReadyState=function () {if (!this.http) { return null; } return this.http.readyState;}; | ||
pg.misc.downloadsInProgress = { }; | pg.misc.downloadsInProgress = { }; | ||
/** Starts the download. | /** Starts the download. | ||
Note that setTarget {@link Downloader#setTarget} must be run first | Note that setTarget {@link Downloader#setTarget} must be run first | ||
| Строка 1321: | Строка 1265: | ||
this.http.send(null); | this.http.send(null); | ||
}; | }; | ||
/** Gets the 'Last-Modified' date from the download headers. | /** Gets the 'Last-Modified' date from the download headers. | ||
Should be run after the download completes. | Should be run after the download completes. | ||
| Строка 1336: | Строка 1280: | ||
return null; | return null; | ||
}; | }; | ||
/** Sets the callback function. | /** Sets the callback function. | ||
@param {Function} f callback function, called as <code>f(this)</code> on success | @param {Function} f callback function, called as <code>f(this)</code> on success | ||
| Строка 1344: | Строка 1288: | ||
this.http.onreadystatechange = f; | this.http.onreadystatechange = f; | ||
}; | }; | ||
Downloader.prototype.getStatus = function() { if (!this.http) { return null; } return this.http.status; }; | Downloader.prototype.getStatus = function() { if (!this.http) { return null; } return this.http.status; }; | ||
////////////////////////////////////////////////// | ////////////////////////////////////////////////// | ||
// helper functions | // helper functions | ||
/** Creates a new {@link Downloader} and prepares it for action. | /** Creates a new {@link Downloader} and prepares it for action. | ||
@param {String} url The url to download | @param {String} url The url to download | ||
| Строка 1402: | Строка 1346: | ||
return callback(d); | return callback(d); | ||
} | } | ||
/** | /** | ||
Starts a download. | Starts a download. | ||
| Строка 1416: | Строка 1360: | ||
return d; | return d; | ||
} | } | ||
/** | /** | ||
Aborts all downloads which have been started. | Aborts all downloads which have been started. | ||
| Строка 1432: | Строка 1376: | ||
// STARTFILE: livepreview.js | // STARTFILE: livepreview.js | ||
// TODO: location is often not correct (eg relative links in previews) | // TODO: location is often not correct (eg relative links in previews) | ||
/** | /** | ||
* InstaView - a Mediawiki to HTML converter in JavaScript | * InstaView - a Mediawiki to HTML converter in JavaScript | ||
| Строка 1464: | Строка 1408: | ||
* - Support for coloured links (AJAX) | * - Support for coloured links (AJAX) | ||
*/ | */ | ||
var Insta = {} | var Insta = {} | ||
function setupLivePreview() { | function setupLivePreview() { | ||
// options | // options | ||
Insta.conf = | Insta.conf = | ||
{ | { | ||
baseUrl: '', | baseUrl: '', | ||
user: {}, | user: {}, | ||
wiki: { | wiki: { | ||
lang: pg.wiki.lang, | lang: pg.wiki.lang, | ||
| Строка 1482: | Строка 1426: | ||
default_thumb_width: 180 | default_thumb_width: 180 | ||
}, | }, | ||
paths: { | paths: { | ||
articles: '/' + joinPath([pg.wiki.prePath, pg.wiki.articlePath]) + '/', | articles: '/' + joinPath([pg.wiki.prePath, pg.wiki.articlePath]) + '/', | ||
| Строка 1490: | Строка 1434: | ||
magnify_icon: 'skins/common/images/magnify-clip.png' | magnify_icon: 'skins/common/images/magnify-clip.png' | ||
}, | }, | ||
locale: { | locale: { | ||
user: pg.ns.user, | user: pg.ns.user, | ||
| Строка 1499: | Строка 1443: | ||
} | } | ||
} | } | ||
// options with default values or backreferences | // options with default values or backreferences | ||
with (Insta.conf) { | with (Insta.conf) { | ||
user.name = user.name || ' | user.name = user.name || 'Wikipedian' | ||
user.signature = '[['+locale.user+':'+user.name+'|'+user.name+']]' | user.signature = '[['+locale.user+':'+user.name+'|'+user.name+']]' | ||
//paths.images = 'http://upload.wikimedia.org/wikipedia/' + wiki.lang + '/' | //paths.images = 'http://upload.wikimedia.org/wikipedia/' + wiki.lang + '/' | ||
} | } | ||
// define constants | // define constants | ||
Insta.BLOCK_IMAGE = new RegExp('^\\[\\[(?: | Insta.BLOCK_IMAGE = new RegExp('^\\[\\[(?:Image|'+Insta.conf.locale.image+ | ||
'):.*?\\|.*?(?:frame|thumbnail|thumb|none|right|left|center)', 'i'); | '):.*?\\|.*?(?:frame|thumbnail|thumb|none|right|left|center)', 'i'); | ||
} | } | ||
Insta.dump = function(from, to) | Insta.dump = function(from, to) | ||
{ | { | ||
| Строка 1520: | Строка 1464: | ||
to.innerHTML = this.convert(from.value) | to.innerHTML = this.convert(from.value) | ||
} | } | ||
Insta.convert = function(wiki) | Insta.convert = function(wiki) | ||
{ | { | ||
| Строка 1527: | Строка 1471: | ||
p=0, // para flag | p=0, // para flag | ||
$r // result of passing a regexp to $() | $r // result of passing a regexp to $() | ||
// some shorthands | // some shorthands | ||
function remain() { return ll.length } | function remain() { return ll.length } | ||
function sh() { return ll.shift() } // shift | function sh() { return ll.shift() } // shift | ||
function ps(s) { o+=s } // push | function ps(s) { o+=s } // push | ||
function f() // similar to C's printf, uses ? as placeholders, ?? to escape question marks | function f() // similar to C's printf, uses ? as placeholders, ?? to escape question marks | ||
{ | { | ||
| Строка 1544: | Строка 1488: | ||
return o+f | return o+f | ||
} | } | ||
function html_entities(s) { return s.replace(/&/g,"&").replace(/</g,"<").replace(/>/g,">") } | function html_entities(s) { return s.replace(/&/g,"&").replace(/</g,"<").replace(/>/g,">") } | ||
function max(a,b) { return (a>b)?a:b } | function max(a,b) { return (a>b)?a:b } | ||
function min(a,b) { return (a<b)?a:b } | function min(a,b) { return (a<b)?a:b } | ||
// return the first non matching character position between two strings | // return the first non matching character position between two strings | ||
function str_imatch(a, b) | function str_imatch(a, b) | ||
| Строка 1556: | Строка 1500: | ||
return i | return i | ||
} | } | ||
// compare current line against a string or regexp | // compare current line against a string or regexp | ||
// if passed a string it will compare only the first string.length characters | // if passed a string it will compare only the first string.length characters | ||
// if passed a regexp the result is stored in $r | // if passed a regexp the result is stored in $r | ||
function $(c) { return (typeof c == 'string') ? (ll[0].substr(0,c.length)==c) : ($r = ll[0].match(c)) } | function $(c) { return (typeof c == 'string') ? (ll[0].substr(0,c.length)==c) : ($r = ll[0].match(c)) } | ||
function $$(c) { return ll[0]==c } // compare current line against a string | function $$(c) { return ll[0]==c } // compare current line against a string | ||
function _(p) { return ll[0].charAt(p) } // return char at pos p | function _(p) { return ll[0].charAt(p) } // return char at pos p | ||
function endl(s) { ps(s); sh() } | function endl(s) { ps(s); sh() } | ||
function parse_list() | function parse_list() | ||
{ | { | ||
var prev=''; | var prev=''; | ||
while (remain() && $(/^([*#:;]+)(.*)$/)) { | while (remain() && $(/^([*#:;]+)(.*)$/)) { | ||
var l_match = $r | var l_match = $r | ||
sh() | sh() | ||
var ipos = str_imatch(prev, l_match[1]) | var ipos = str_imatch(prev, l_match[1]) | ||
// close uncontinued lists | // close uncontinued lists | ||
for (var i=prev.length-1; i >= ipos; i--) { | for (var i=prev.length-1; i >= ipos; i--) { | ||
var pi = prev.charAt(i) | var pi = prev.charAt(i) | ||
if (pi=='*') ps('</ul>') | if (pi=='*') ps('</ul>') | ||
else if (pi=='#') ps('</ol>') | else if (pi=='#') ps('</ol>') | ||
| Строка 1589: | Строка 1533: | ||
else switch (l_match[1].charAt(i)) { case'':case'*':case'#': ps('</dl>') } | else switch (l_match[1].charAt(i)) { case'':case'*':case'#': ps('</dl>') } | ||
} | } | ||
// open new lists | // open new lists | ||
for (var i=ipos; i<l_match[1].length; i++) { | for (var i=ipos; i<l_match[1].length; i++) { | ||
var li = l_match[1].charAt(i) | var li = l_match[1].charAt(i) | ||
if (li=='*') ps('<ul>') | if (li=='*') ps('<ul>') | ||
else if (li=='#') ps('<ol>') | else if (li=='#') ps('<ol>') | ||
| Строка 1600: | Строка 1544: | ||
else switch(prev.charAt(i)) { case'':case'*':case'#': ps('<dl>') } | else switch(prev.charAt(i)) { case'':case'*':case'#': ps('<dl>') } | ||
} | } | ||
switch (l_match[1].charAt(l_match[1].length-1)) { | switch (l_match[1].charAt(l_match[1].length-1)) { | ||
case '*': case '#': | case '*': case '#': | ||
ps('<li>' + parse_inline_nowiki(l_match[2])); break | ps('<li>' + parse_inline_nowiki(l_match[2])); break | ||
case ';': | case ';': | ||
ps('<dt>') | ps('<dt>') | ||
var dt_match | var dt_match | ||
// handle ;dt :dd format | // handle ;dt :dd format | ||
if (dt_match = l_match[2].match(/(.*?)(:.*?)$/)) { | if (dt_match = l_match[2].match(/(.*?)(:.*?)$/)) { | ||
ps(parse_inline_nowiki(dt_match[1])) | ps(parse_inline_nowiki(dt_match[1])) | ||
ll.unshift(dt_match[2]) | ll.unshift(dt_match[2]) | ||
} else ps(parse_inline_nowiki(l_match[2])) | } else ps(parse_inline_nowiki(l_match[2])) | ||
break | break | ||
case ':': | case ':': | ||
ps('<dd>' + parse_inline_nowiki(l_match[2])) | ps('<dd>' + parse_inline_nowiki(l_match[2])) | ||
} | } | ||
prev=l_match[1] | prev=l_match[1] | ||
} | } | ||
// close remaining lists | // close remaining lists | ||
for (var i=prev.length-1; i>=0; i--) | for (var i=prev.length-1; i>=0; i--) | ||
ps(f('</?>', (prev.charAt(i)=='*')? 'ul': ((prev.charAt(i)=='#')? 'ol': 'dl'))) | ps(f('</?>', (prev.charAt(i)=='*')? 'ul': ((prev.charAt(i)=='#')? 'ol': 'dl'))) | ||
} | } | ||
function parse_table() | function parse_table() | ||
{ | { | ||
endl(f('<table?>', $(/^\{\|( .*)$/)? $r[1]: '')) | endl(f('<table?>', $(/^\{\|( .*)$/)? $r[1]: '')) | ||
for (;remain();) if ($('|')) switch (_(1)) { | for (;remain();) if ($('|')) switch (_(1)) { | ||
case '}': endl('</table>'); return | case '}': endl('</table>'); return | ||
| Строка 1645: | Строка 1589: | ||
else sh() | else sh() | ||
} | } | ||
function parse_table_data() | function parse_table_data() | ||
{ | { | ||
var td_line, match_i | var td_line, match_i | ||
// 1: "|+", '|' or '+' | // 1: "|+", '|' or '+' | ||
// 2: ?? | // 2: ?? | ||
| Строка 1655: | Строка 1599: | ||
// TODO: finish commenting this regexp | // TODO: finish commenting this regexp | ||
var td_match = sh().match(/^(\|\+|\||!)((?:([^[|]*?)\|(?!\|))?(.*))$/) | var td_match = sh().match(/^(\|\+|\||!)((?:([^[|]*?)\|(?!\|))?(.*))$/) | ||
if (td_match[1] == '|+') ps('<caption'); | if (td_match[1] == '|+') ps('<caption'); | ||
else ps('<t' + ((td_match[1]=='|')?'d':'h')) | else ps('<t' + ((td_match[1]=='|')?'d':'h')) | ||
if (typeof td_match[3] != 'undefined') { | if (typeof td_match[3] != 'undefined') { | ||
ps(' ' + td_match[3]) | ps(' ' + td_match[3]) | ||
match_i = 4 | match_i = 4 | ||
} else match_i = 2 | } else match_i = 2 | ||
ps('>') | ps('>') | ||
if (td_match[1] != '|+') { | if (td_match[1] != '|+') { | ||
// use || or !! as a cell separator depending on context | // use || or !! as a cell separator depending on context | ||
// NOTE: when split() is passed a regexp make sure to use non-capturing brackets | // NOTE: when split() is passed a regexp make sure to use non-capturing brackets | ||
td_line = td_match[match_i].split((td_match[1] == '|')? '||': /(?:\|\||!!)/) | td_line = td_match[match_i].split((td_match[1] == '|')? '||': /(?:\|\||!!)/) | ||
ps(parse_inline_nowiki(td_line.shift())) | ps(parse_inline_nowiki(td_line.shift())) | ||
while (td_line.length) ll.unshift(td_match[1] + td_line.pop()) | while (td_line.length) ll.unshift(td_match[1] + td_line.pop()) | ||
} else ps(td_match[match_i]) | } else ps(td_match[match_i]) | ||
var tc = 0, td = [] | var tc = 0, td = [] | ||
for (;remain(); td.push(sh())) | for (;remain(); td.push(sh())) | ||
if ($('|')) { | if ($('|')) { | ||
| Строка 1689: | Строка 1633: | ||
else if (!tc && $('!')) break | else if (!tc && $('!')) break | ||
else if ($('{|')) tc++ | else if ($('{|')) tc++ | ||
if (td.length) ps(Insta.convert(td)) | if (td.length) ps(Insta.convert(td)) | ||
} | } | ||
function parse_pre() | function parse_pre() | ||
{ | { | ||
| Строка 1699: | Строка 1643: | ||
ps('</pre>') | ps('</pre>') | ||
} | } | ||
function parse_block_image() | function parse_block_image() | ||
{ | { | ||
ps(parse_image(sh())) | ps(parse_image(sh())) | ||
} | } | ||
function parse_image(str) | function parse_image(str) | ||
{ | { | ||
//<NOLITE> | //<NOLITE> | ||
// get what's in between "[[Image:" and "]]" | // get what's in between "[[Image:" and "]]" | ||
var tag = str.substring( | var tag = str.substring(Insta.conf.locale.image.length + 3, str.length - 2); | ||
var width; | var width; | ||
var attr = [], filename, caption = ''; | var attr = [], filename, caption = ''; | ||
var thumb=0, frame=0, center=0; | var thumb=0, frame=0, center=0; | ||
var align=''; | var align=''; | ||
if (tag.match(/\|/)) { | if (tag.match(/\|/)) { | ||
// manage nested links | // manage nested links | ||
| Строка 1735: | Строка 1679: | ||
} | } | ||
} | } | ||
attr = tag.split(/\s*\|\s*/); | attr = tag.split(/\s*\|\s*/); | ||
attr.push(last_attr); | attr.push(last_attr); | ||
filename = attr.shift(); | filename = attr.shift(); | ||
var w_match; | var w_match; | ||
for (;attr.length; attr.shift()) | for (;attr.length; attr.shift()) | ||
if (w_match = attr[0].match(/^(\d*)(?:[px]*\d*)?px$/)) width = w_match[1] | if (w_match = attr[0].match(/^(\d*)(?:[px]*\d*)?px$/)) width = w_match[1] | ||
| Строка 1764: | Строка 1708: | ||
if (attr.length == 1) caption = attr[0]; | if (attr.length == 1) caption = attr[0]; | ||
} | } | ||
} else filename = tag; | } else filename = tag; | ||
var o=''; | var o=''; | ||
if (frame) { | if (frame) { | ||
if (align=='') align = 'right'; | if (align=='') align = 'right'; | ||
o += f("<div class='thumb t?'>", align); | o += f("<div class='thumb t?'>", align); | ||
if (thumb) { | if (thumb) { | ||
if (!width) width = Insta.conf.wiki.default_thumb_width; | if (!width) width = Insta.conf.wiki.default_thumb_width; | ||
o += f("<div style='width:?px;'>?", 2+width*1, make_image(filename, caption, width)) + | o += f("<div style='width:?px;'>?", 2+width*1, make_image(filename, caption, width)) + | ||
f("<div class='thumbcaption'><div class='magnify' style='float:right'><a href='?' class='internal' title='Enlarge'><img src='?'></a></div>?</div>", | f("<div class='thumbcaption'><div class='magnify' style='float:right'><a href='?' class='internal' title='Enlarge'><img src='?'></a></div>?</div>", | ||
| Строка 1788: | Строка 1732: | ||
o += '<div>' + make_image(filename, caption) + f("<div class='thumbcaption'>?</div>", parse_inline_nowiki(caption)) | o += '<div>' + make_image(filename, caption) + f("<div class='thumbcaption'>?</div>", parse_inline_nowiki(caption)) | ||
} | } | ||
o += '</div></div>'; | o += '</div></div>'; | ||
} else if (align != '') { | } else if (align != '') { | ||
o += f("<div class='float?'><span>?</span></div>", align, make_image(filename, caption, width)); | o += f("<div class='float?'><span>?</span></div>", align, make_image(filename, caption, width)); | ||
| Строка 1796: | Строка 1740: | ||
return make_image(filename, caption, width); | return make_image(filename, caption, width); | ||
} | } | ||
return center? f("<div class='center'>?</div>", o): o; | return center? f("<div class='center'>?</div>", o): o; | ||
//</NOLITE> | //</NOLITE> | ||
} | } | ||
function parse_inline_nowiki(str) | function parse_inline_nowiki(str) | ||
{ | { | ||
| Строка 1806: | Строка 1750: | ||
var substart=0, nestlev=0, open, close, subloop; | var substart=0, nestlev=0, open, close, subloop; | ||
var html=''; | var html=''; | ||
while (-1 != (start = str.indexOf('<nowiki>', substart))) { | while (-1 != (start = str.indexOf('<nowiki>', substart))) { | ||
html += parse_inline_wiki(str.substring(lastend, start)); | html += parse_inline_wiki(str.substring(lastend, start)); | ||
| Строка 1833: | Строка 1777: | ||
} while (subloop) | } while (subloop) | ||
} | } | ||
return html + parse_inline_wiki(str.substr(lastend)); | return html + parse_inline_wiki(str.substr(lastend)); | ||
} | } | ||
function make_image(filename, caption, width) | function make_image(filename, caption, width) | ||
{ | { | ||
| Строка 1844: | Строка 1788: | ||
// replace spaces with underscores | // replace spaces with underscores | ||
filename = filename.replace(/ /g, '_'); | filename = filename.replace(/ /g, '_'); | ||
caption = strip_inline_wiki(caption); | caption = strip_inline_wiki(caption); | ||
var md5 = hex_md5(filename); | var md5 = hex_md5(filename); | ||
var source = md5.charAt(0) + '/' + md5.substr(0,2) + '/' + filename; | var source = md5.charAt(0) + '/' + md5.substr(0,2) + '/' + filename; | ||
if (width) width = "width='" + width + "px'"; | if (width) width = "width='" + width + "px'"; | ||
var img = f("<img onerror=\"this.onerror=null;this.src='?'\" src='?' ? ?>", Insta.conf.paths.images_fallback + source, Insta.conf.paths.images + source, (caption!='')? "alt='" + caption + "'" : '', width); | var img = f("<img onerror=\"this.onerror=null;this.src='?'\" src='?' ? ?>", Insta.conf.paths.images_fallback + source, Insta.conf.paths.images + source, (caption!='')? "alt='" + caption + "'" : '', width); | ||
return f("<a class='image' ? href='?'>?</a>", (caption!='')? "title='" + caption + "'" : '', Insta.conf.paths.articles + Insta.conf.locale.image + ':' + filename, img); | return f("<a class='image' ? href='?'>?</a>", (caption!='')? "title='" + caption + "'" : '', Insta.conf.paths.articles + Insta.conf.locale.image + ':' + filename, img); | ||
//</NOLITE> | //</NOLITE> | ||
} | } | ||
function parse_inline_images(str) | function parse_inline_images(str) | ||
{ | { | ||
| Строка 1864: | Строка 1808: | ||
var start, substart=0, nestlev=0; | var start, substart=0, nestlev=0; | ||
var loop, close, open, wiki, html; | var loop, close, open, wiki, html; | ||
while (-1 != (start=str.indexOf('[[', substart))) { | while (-1 != (start=str.indexOf('[[', substart))) { | ||
if(str.substr(start+2).match(RegExp('^ | if(str.substr(start+2).match(RegExp('^' + Insta.conf.locale.image + ':','i'))) { | ||
loop=true; | loop=true; | ||
substart=start; | substart=start; | ||
| Строка 1890: | Строка 1834: | ||
} | } | ||
} while (loop) | } while (loop) | ||
} else break; | } else break; | ||
} | } | ||
//</NOLITE> | //</NOLITE> | ||
return str; | return str; | ||
} | } | ||
// the output of this function doesn't respect the FILO structure of HTML | // the output of this function doesn't respect the FILO structure of HTML | ||
// but since most browsers can handle it I'll save myself the hassle | // but since most browsers can handle it I'll save myself the hassle | ||
| Строка 1917: | Строка 1861: | ||
return o+str.substr(li); | return o+str.substr(li); | ||
} | } | ||
function parse_inline_wiki(str) | function parse_inline_wiki(str) | ||
{ | { | ||
var aux_match; | var aux_match; | ||
str = parse_inline_images(str); | str = parse_inline_images(str); | ||
str = parse_inline_formatting(str); | str = parse_inline_formatting(str); | ||
// math | // math | ||
while (aux_match = str.match(/<(?:)math>(.*?)<\/math>/i)) { | while (aux_match = str.match(/<(?:)math>(.*?)<\/math>/i)) { | ||
| Строка 1930: | Строка 1874: | ||
str = str.replace(aux_match[0], f("<img src='?.png'>", Insta.conf.paths.math+math_md5)); | str = str.replace(aux_match[0], f("<img src='?.png'>", Insta.conf.paths.math+math_md5)); | ||
} | } | ||
// Build a Mediawiki-formatted date string | // Build a Mediawiki-formatted date string | ||
var date = new Date; | var date = new Date; | ||
| Строка 1936: | Строка 1880: | ||
if (minutes < 10) minutes = '0' + minutes; | if (minutes < 10) minutes = '0' + minutes; | ||
var date = f("?:?, ? ? ? (UTC)", date.getUTCHours(), minutes, date.getUTCDate(), Insta.conf.locale.months[date.getUTCMonth()], date.getUTCFullYear()); | var date = f("?:?, ? ? ? (UTC)", date.getUTCHours(), minutes, date.getUTCDate(), Insta.conf.locale.months[date.getUTCMonth()], date.getUTCFullYear()); | ||
// text formatting | // text formatting | ||
return str. | return str. | ||
| Строка 1943: | Строка 1887: | ||
replace(/~{4}(?!~)/g, Insta.conf.user.name+' '+date). | replace(/~{4}(?!~)/g, Insta.conf.user.name+' '+date). | ||
replace(/~{3}(?!~)/g, Insta.conf.user.name). | replace(/~{3}(?!~)/g, Insta.conf.user.name). | ||
// [[:Category:...]], [[:Image:...]], etc... | // [[:Category:...]], [[:Image:...]], etc... | ||
replace(RegExp('\\[\\[:((?:'+Insta.conf.locale.category+' | replace(RegExp('\\[\\[:((?:'+Insta.conf.locale.category+'|'+Insta.conf.locale.image+'|'+Insta.conf.wiki.interwiki+'):[^|]*?)\\]\\](\w*)','gi'), "<a href='"+Insta.conf.paths.articles+"$1'>$1$2</a>"). | ||
// remove straight category and interwiki tags | // remove straight category and interwiki tags | ||
replace(RegExp('\\[\\[(?:'+Insta.conf.locale.category+'|'+Insta.conf.wiki.interwiki+'):.*?\\]\\]','gi'),''). | replace(RegExp('\\[\\[(?:'+Insta.conf.locale.category+'|'+Insta.conf.wiki.interwiki+'):.*?\\]\\]','gi'),''). | ||
// [[:Category:...|Links]], [[:Image:...|Links]], etc... | // [[:Category:...|Links]], [[:Image:...|Links]], etc... | ||
replace(RegExp('\\[\\[:((?:'+Insta.conf.locale.category+' | replace(RegExp('\\[\\[:((?:'+Insta.conf.locale.category+'|'+Insta.conf.locale.image+'|'+Insta.conf.wiki.interwiki+'):.*?)\\|([^\\]]+?)\\]\\](\\w*)','gi'), "<a href='"+Insta.conf.paths.articles+"$1'>$2$3</a>"). | ||
// [[/Relative links]] | // [[/Relative links]] | ||
replace(/\[\[(\/[^|]*?)\]\]/g, f("<a href='?$1'>$1</a>", Insta.conf.baseUrl)). | replace(/\[\[(\/[^|]*?)\]\]/g, f("<a href='?$1'>$1</a>", Insta.conf.baseUrl)). | ||
// [[/Replaced|Relative links]] | // [[/Replaced|Relative links]] | ||
replace(/\[\[(\/.*?)\|(.+?)\]\]/g, f("<a href='?$1'>$2</a>", Insta.conf.baseUrl)). | replace(/\[\[(\/.*?)\|(.+?)\]\]/g, f("<a href='?$1'>$2</a>", Insta.conf.baseUrl)). | ||
// [[Common links]] | // [[Common links]] | ||
replace(/\[\[([^|]*?)\]\](\w*)/g, f("<a href='?$1'>$1$2</a>", Insta.conf.paths.articles)). | replace(/\[\[([^|]*?)\]\](\w*)/g, f("<a href='?$1'>$1$2</a>", Insta.conf.paths.articles)). | ||
// [[Replaced|Links]] | // [[Replaced|Links]] | ||
replace(/\[\[(.*?)\|([^\]]+?)\]\](\w*)/g, f("<a href='?$1'>$2$3</a>", Insta.conf.paths.articles)). | replace(/\[\[(.*?)\|([^\]]+?)\]\](\w*)/g, f("<a href='?$1'>$2$3</a>", Insta.conf.paths.articles)). | ||
// [[Stripped:Namespace|Namespace]] | // [[Stripped:Namespace|Namespace]] | ||
replace(/\[\[([^\]]*?:)?(.*?)( *\(.*?\))?\|\]\]/g, f("<a href='?$1$2$3'>$2</a>", Insta.conf.paths.articles)). | replace(/\[\[([^\]]*?:)?(.*?)( *\(.*?\))?\|\]\]/g, f("<a href='?$1$2$3'>$2</a>", Insta.conf.paths.articles)). | ||
// External links | // External links | ||
replace(/\[(https?|news|ftp|mailto|gopher|irc):(\/*)([^\]]*?) (.*?)\]/g, "<a class='external' href='$1:$2$3'>$4</a>"). | replace(/\[(https?|news|ftp|mailto|gopher|irc):(\/*)([^\]]*?) (.*?)\]/g, "<a class='external' href='$1:$2$3'>$4</a>"). | ||
| Строка 1972: | Строка 1916: | ||
replace(/\[(news|ftp|mailto|gopher|irc):(\/*)(.*?)\]/g, "<a class='external' href='$1:$2$3'>$1:$2$3</a>"). | replace(/\[(news|ftp|mailto|gopher|irc):(\/*)(.*?)\]/g, "<a class='external' href='$1:$2$3'>$1:$2$3</a>"). | ||
replace(/(^| )(https?|news|ftp|mailto|gopher|irc):(\/*)([^ $]*[^.,!?;: $])/g, "$1<a class='external' href='$2:$3$4'>$2:$3$4</a>"). | replace(/(^| )(https?|news|ftp|mailto|gopher|irc):(\/*)([^ $]*[^.,!?;: $])/g, "$1<a class='external' href='$2:$3$4'>$2:$3$4</a>"). | ||
replace('__NOTOC__',''). | replace('__NOTOC__',''). | ||
replace('__NOEDITSECTION__',''); | replace('__NOEDITSECTION__',''); | ||
} | } | ||
function strip_inline_wiki(str) | function strip_inline_wiki(str) | ||
{ | { | ||
| Строка 1985: | Строка 1928: | ||
.replace(/''(.*?)''/g,'$1'); | .replace(/''(.*?)''/g,'$1'); | ||
} | } | ||
// begin parsing | // begin parsing | ||
for (;remain();) if ($(/^(={1,6})(.*)\1(.*)$/)) { | for (;remain();) if ($(/^(={1,6})(.*)\1(.*)$/)) { | ||
p=0 | p=0 | ||
endl(f('<h?>?</h?>?', $r[1].length, parse_inline_nowiki($r[2]), $r[1].length, $r[3])) | endl(f('<h?>?</h?>?', $r[1].length, parse_inline_nowiki($r[2]), $r[1].length, $r[3])) | ||
} else if ($(/^[*#:;]/)) { | } else if ($(/^[*#:;]/)) { | ||
p=0 | p=0 | ||
parse_list() | parse_list() | ||
} else if ($(' ')) { | } else if ($(' ')) { | ||
p=0 | p=0 | ||
parse_pre() | parse_pre() | ||
} else if ($('{|')) { | } else if ($('{|')) { | ||
p=0 | p=0 | ||
parse_table() | parse_table() | ||
} else if ($(/^----+$/)) { | } else if ($(/^----+$/)) { | ||
p=0 | p=0 | ||
endl('<hr>') | endl('<hr>') | ||
} else if ($(Insta.BLOCK_IMAGE)) { | } else if ($(Insta.BLOCK_IMAGE)) { | ||
p=0 | p=0 | ||
parse_block_image() | parse_block_image() | ||
} else { | } else { | ||
// handle paragraphs | // handle paragraphs | ||
if ($$('')) { | if ($$('')) { | ||
| Строка 2023: | Строка 1966: | ||
ps(parse_inline_nowiki(ll[0]) + ' ') | ps(parse_inline_nowiki(ll[0]) + ' ') | ||
} | } | ||
sh(); | sh(); | ||
} | } | ||
return o | return o | ||
}; | }; | ||
window.wiki2html=function(txt,baseurl) { | window.wiki2html=function(txt,baseurl) { | ||
Insta.conf.baseUrl=baseurl; | Insta.conf.baseUrl=baseurl; | ||
| Строка 2040: | Строка 1983: | ||
return formatBytes(data.length); | return formatBytes(data.length); | ||
} | } | ||
function popupFilterCountLinks(data) { | function popupFilterCountLinks(data) { | ||
var num=countLinks(data); | var num=countLinks(data); | ||
return String(num) + ' ' + ((num!=1)?popupString('wikiLinks'):popupString('wikiLink')); | return String(num) + ' ' + ((num!=1)?popupString('wikiLinks'):popupString('wikiLink')); | ||
} | } | ||
function popupFilterCountImages(data) { | function popupFilterCountImages(data) { | ||
var num=countImages(data); | var num=countImages(data); | ||
return String(num) + ' ' + ((num!=1)?popupString('images'):popupString('image')); | return String(num) + ' ' + ((num!=1)?popupString('images'):popupString('image')); | ||
} | } | ||
function popupFilterCountCategories(data) { | function popupFilterCountCategories(data) { | ||
var num=countCategories(data); | var num=countCategories(data); | ||
return String(num) + ' ' + ((num!=1)?popupString('categories'):popupString('category')); | return String(num) + ' ' + ((num!=1)?popupString('categories'):popupString('category')); | ||
} | } | ||
function popupFilterLastModified(data,download) { | function popupFilterLastModified(data,download) { | ||
var lastmod=download.lastModified; | var lastmod=download.lastModified; | ||
| Строка 2066: | Строка 2009: | ||
return ''; | return ''; | ||
} | } | ||
function formatAge(age) { | function formatAge(age) { | ||
// coerce into a number | // coerce into a number | ||
var a=0+age, aa=a; | var a=0+age, aa=a; | ||
var seclen = 1000; | var seclen = 1000; | ||
var minlen = 60*seclen; | var minlen = 60*seclen; | ||
| Строка 2076: | Строка 2019: | ||
var daylen = 24*hourlen; | var daylen = 24*hourlen; | ||
var weeklen = 7*daylen; | var weeklen = 7*daylen; | ||
var numweeks = (a-a%weeklen)/weeklen; a = a-numweeks*weeklen; var sweeks = addunit(numweeks, 'week'); | var numweeks = (a-a%weeklen)/weeklen; a = a-numweeks*weeklen; var sweeks = addunit(numweeks, 'week'); | ||
var numdays = (a-a%daylen)/daylen; a = a-numdays*daylen; var sdays = addunit(numdays, 'day'); | var numdays = (a-a%daylen)/daylen; a = a-numdays*daylen; var sdays = addunit(numdays, 'day'); | ||
| Строка 2082: | Строка 2025: | ||
var nummins = (a-a%minlen)/minlen; a = a-nummins*minlen; var smins = addunit(nummins, 'minute'); | var nummins = (a-a%minlen)/minlen; a = a-nummins*minlen; var smins = addunit(nummins, 'minute'); | ||
var numsecs = (a-a%seclen)/seclen; a = a-numsecs*seclen; var ssecs = addunit(numsecs, 'second'); | var numsecs = (a-a%seclen)/seclen; a = a-numsecs*seclen; var ssecs = addunit(numsecs, 'second'); | ||
if (aa > 4*weeklen) { return sweeks; } | if (aa > 4*weeklen) { return sweeks; } | ||
if (aa > weeklen) { return sweeks + ' ' + sdays; } | if (aa > weeklen) { return sweeks + ' ' + sdays; } | ||
| Строка 2092: | Строка 2035: | ||
return ssecs; | return ssecs; | ||
} | } | ||
function addunit(num,str) { return '' + num + ' ' + ((num!=1) ? popupString(str+'s') : popupString(str)) ;} | function addunit(num,str) { return '' + num + ' ' + ((num!=1) ? popupString(str+'s') : popupString(str)) ;} | ||
function runPopupFilters(list, data, download) { | function runPopupFilters(list, data, download) { | ||
var ret=[]; | var ret=[]; | ||
| Строка 2105: | Строка 2048: | ||
return ret; | return ret; | ||
} | } | ||
function getPageInfo(data, download) { | function getPageInfo(data, download) { | ||
if (!data || data.length === 0) { return popupString('Empty page'); } | if (!data || data.length === 0) { return popupString('Empty page'); } | ||
var popupFilters=getValueOf('popupFilters') || []; | var popupFilters=getValueOf('popupFilters') || []; | ||
var extraPopupFilters = getValueOf('extraPopupFilters') || []; | var extraPopupFilters = getValueOf('extraPopupFilters') || []; | ||
var pageInfoArray = runPopupFilters(popupFilters.concat(extraPopupFilters), data, download); | var pageInfoArray = runPopupFilters(popupFilters.concat(extraPopupFilters), data, download); | ||
var pageInfo=pageInfoArray.join(', '); | var pageInfo=pageInfoArray.join(', '); | ||
if (pageInfo !== '' ) { pageInfo = upcaseFirst(pageInfo); } | if (pageInfo !== '' ) { pageInfo = upcaseFirst(pageInfo); } | ||
return pageInfo; | return pageInfo; | ||
} | } | ||
// this could be improved! | // this could be improved! | ||
function countLinks(wikiText) { return wikiText.split('[[').length - 1; } | function countLinks(wikiText) { return wikiText.split('[[').length - 1; } | ||
// if N = # matches, n = # brackets, then | // if N = # matches, n = # brackets, then | ||
// String.parenSplit(regex) intersperses the N+1 split elements | // String.parenSplit(regex) intersperses the N+1 split elements | ||
// with Nn other elements. So total length is | // with Nn other elements. So total length is | ||
// L= N+1 + Nn = N(n+1)+1. So N=(L-1)/(n+1). | // L= N+1 + Nn = N(n+1)+1. So N=(L-1)/(n+1). | ||
function countImages(wikiText) { | function countImages(wikiText) { | ||
return (wikiText.parenSplit(pg.re.image).length - 1) / (pg.re.imageBracketCount + 1); | return (wikiText.parenSplit(pg.re.image).length - 1) / (pg.re.imageBracketCount + 1); | ||
} | } | ||
function countCategories(wikiText) { | function countCategories(wikiText) { | ||
return (wikiText.parenSplit(pg.re.category).length - 1) / (pg.re.categoryBracketCount + 1); | return (wikiText.parenSplit(pg.re.category).length - 1) / (pg.re.categoryBracketCount + 1); | ||
} | } | ||
function popupFilterStubDetect(data, download, article) { | function popupFilterStubDetect(data, download, article) { | ||
var counts=stubCount(data, article); | var counts=stubCount(data, article); | ||
| Строка 2141: | Строка 2084: | ||
return ''; | return ''; | ||
} | } | ||
function popupFilterDisambigDetect(data, download, article) { | function popupFilterDisambigDetect(data, download, article) { | ||
if (getValueOf('popupOnlyArticleDabStub') && article.namespace()) { return ''; } | if (getValueOf('popupOnlyArticleDabStub') && article.namespace()) { return ''; } | ||
return (isDisambig(data, article)) ? popupString('disambig') : ''; | return (isDisambig(data, article)) ? popupString('disambig') : ''; | ||
} | } | ||
function formatBytes(num) { | function formatBytes(num) { | ||
return (num > 949) ? (Math.round(num/100)/10+popupString('kB')) : (num +' ' + popupString('bytes')) ; | return (num > 949) ? (Math.round(num/100)/10+popupString('kB')) : (num +' ' + popupString('bytes')) ; | ||
| Строка 2155: | Строка 2098: | ||
/** | /** | ||
@fileoverview Defines the {@link Title} class, and associated crufty functions. | @fileoverview Defines the {@link Title} class, and associated crufty functions. | ||
<code>Title</code> deals with article titles and their various | <code>Title</code> deals with article titles and their various | ||
forms. {@link Stringwrapper} is the parent class of | forms. {@link Stringwrapper} is the parent class of | ||
<code>Title</code>, which exists simply to make things a little | <code>Title</code>, which exists simply to make things a little | ||
neater. | neater. | ||
*/ | */ | ||
/** | /** | ||
Creates a new Stringwrapper. | Creates a new Stringwrapper. | ||
@constructor | @constructor | ||
@class the Stringwrapper class. This base class is not really | @class the Stringwrapper class. This base class is not really | ||
useful on its own; it just wraps various common string operations. | useful on its own; it just wraps various common string operations. | ||
| Строка 2212: | Строка 2155: | ||
this.replace=function(x,y){ return this.toString().replace(x,y); }; | this.replace=function(x,y){ return this.toString().replace(x,y); }; | ||
} | } | ||
/** | /** | ||
Creates a new <code>Title</code>. | Creates a new <code>Title</code>. | ||
@constructor | @constructor | ||
@class The Title class. Holds article titles and converts them into | @class The Title class. Holds article titles and converts them into | ||
various forms. Also deals with anchors, by which we mean the bits | various forms. Also deals with anchors, by which we mean the bits | ||
of the article URL after a # character, representing locations | of the article URL after a # character, representing locations | ||
within an article. | within an article. | ||
@param {String} value The initial value to assign to the | @param {String} value The initial value to assign to the | ||
article. This must be the canonical title (see {@link | article. This must be the canonical title (see {@link | ||
| Строка 2243: | Строка 2186: | ||
*/ | */ | ||
this.anchor=''; | this.anchor=''; | ||
this.setUtf(val); | this.setUtf(val); | ||
} | } | ||
| Строка 2275: | Строка 2218: | ||
}; | }; | ||
Title.prototype.anchorFromUtf=function(str) { | Title.prototype.anchorFromUtf=function(str) { | ||
this.anchor=encodeURIComponent(str | this.anchor=encodeURIComponent(str).split('.').join('%2E').split('%').join('.'); | ||
}; | }; | ||
Title.fromURL=function(h) { | Title.fromURL=function(h) { | ||
| Строка 2286: | Строка 2228: | ||
return this; | return this; | ||
} | } | ||
// NOTE : playing with decodeURI, encodeURI, escape, unescape, | // NOTE : playing with decodeURI, encodeURI, escape, unescape, | ||
// we seem to be able to replicate the IE borked encoding | // we seem to be able to replicate the IE borked encoding | ||
// IE doesn't do this new-fangled utf-8 thing. | // IE doesn't do this new-fangled utf-8 thing. | ||
// and it's worse than that. | // and it's worse than that. | ||
// IE seems to treat the query string differently to the rest of the url | // IE seems to treat the query string differently to the rest of the url | ||
// the query is treated as bona-fide utf8, but the first bit of the url is pissed around with | // the query is treated as bona-fide utf8, but the first bit of the url is pissed around with | ||
// we fix up & for all browsers, just in case. | // we fix up & for all browsers, just in case. | ||
var splitted=h.split('?'); | var splitted=h.split('?'); | ||
splitted[0]=splitted[0].split('&').join('%26'); | splitted[0]=splitted[0].split('&').join('%26'); | ||
if (pg.flag.linksLikeIE6) { | if (pg.flag.linksLikeIE6) { | ||
splitted[0]=encodeURI(decode_utf8(splitted[0])); | splitted[0]=encodeURI(decode_utf8(splitted[0])); | ||
} | } | ||
h=splitted.join('?'); | h=splitted.join('?'); | ||
var contribs=pg.re.contribs.exec(h); | var contribs=pg.re.contribs.exec(h); | ||
if (contribs !== null) { | if (contribs !== null) { | ||
| Строка 2312: | Строка 2254: | ||
return this; | return this; | ||
} | } | ||
var email=pg.re.email.exec(h); | var email=pg.re.email.exec(h); | ||
if (email !== null) { | if (email !== null) { | ||
| Строка 2318: | Строка 2260: | ||
return this; | return this; | ||
} | } | ||
var backlinks=pg.re.backlinks.exec(h); | var backlinks=pg.re.backlinks.exec(h); | ||
if (backlinks) { | if (backlinks) { | ||
| Строка 2324: | Строка 2266: | ||
return this; | return this; | ||
} | } | ||
// no more special cases to check -- | // no more special cases to check -- | ||
// hopefully it's not a disguised user-related or specially treated special page | // hopefully it's not a disguised user-related or specially treated special page | ||
| Строка 2330: | Строка 2272: | ||
if(m===null) { this.value=null; } | if(m===null) { this.value=null; } | ||
else { | else { | ||
var fromBotInterface = /[?](.+[&])?title=/.test(h); | |||
if (fromBotInterface) { | |||
m[2]=m[2].split('+').join('_'); | |||
} | |||
var extracted = m[2] + (m[3] ? '#' + m[3] : ''); | |||
this.setUtf(this.decodeNasties(extracted)); | |||
} | |||
return this; | return this; | ||
}; | }; | ||
| Строка 2400: | Строка 2336: | ||
var talkRegex=namespaceListToRegex(pg.ns.talkList); | var talkRegex=namespaceListToRegex(pg.ns.talkList); | ||
if (talkRegex.exec(this.value)) { this.value=null; return null;} | if (talkRegex.exec(this.value)) { this.value=null; return null;} | ||
var nsReg=namespaceListToRegex(pg.ns.withTalkList); | var nsReg=namespaceListToRegex(pg.ns.withTalkList); | ||
var splitted=this.value.parenSplit(nsReg); | var splitted=this.value.parenSplit(nsReg); | ||
| Строка 2473: | Строка 2409: | ||
//</NOLITE> | //</NOLITE> | ||
Title.prototype.stripNamespace=function(){ // returns a string, not a Title | Title.prototype.stripNamespace=function(){ // returns a string, not a Title | ||
// this isn't very sophisticated | |||
// it just removes everything up to the final : | |||
// BUG: probably does silly things for images with colons in the name - check it out | |||
var list = this.value.split(':'); | |||
return list[list.length-1]; | |||
}; | |||
return | Title.prototype.setUtf=function(value){ | ||
}; | |||
Title.prototype.setUtf=function(value){ | |||
if (!value) { this.value=''; return; } | if (!value) { this.value=''; return; } | ||
var anch=value.indexOf('#'); | var anch=value.indexOf('#'); | ||
| Строка 2510: | Строка 2444: | ||
return pg.wiki.titlebase + this.urlString(); | return pg.wiki.titlebase + this.urlString(); | ||
}; | }; | ||
function paramValue(param, url) { | function paramValue(param, url) { | ||
var s=url.parenSplit(RegExp('[?&]' + literalizeRegex(param) + '=([^?&]*)')); | var s=url.parenSplit(RegExp('[?&]' + literalizeRegex(param) + '=([^?&]*)')); | ||
| Строка 2517: | Строка 2451: | ||
return s[1] || null; | return s[1] || null; | ||
} | } | ||
function parseParams(url) { | function parseParams(url) { | ||
var ret={}; | var ret={}; | ||
| Строка 2530: | Строка 2464: | ||
return ret; | return ret; | ||
} | } | ||
// all sorts of stuff here | // all sorts of stuff here | ||
// FIXME almost everything needs to be rewritten | // FIXME almost everything needs to be rewritten | ||
function oldidFromAnchor(a) { return paramValue('oldid', a.href); } | function oldidFromAnchor(a) { return paramValue('oldid', a.href); } | ||
//function diffFromAnchor(a) { return paramValue('diff', a.href); } | //function diffFromAnchor(a) { return paramValue('diff', a.href); } | ||
function wikiMarkupToAddressFragment (str) { // for images | function wikiMarkupToAddressFragment (str) { // for images | ||
var ret = safeDecodeURI(str); | var ret = safeDecodeURI(str); | ||
| Строка 2544: | Строка 2478: | ||
return ret; | return ret; | ||
} | } | ||
// (a) myDecodeURI (first standard decodeURI, then pg.re.urlNoPopup) | // (a) myDecodeURI (first standard decodeURI, then pg.re.urlNoPopup) | ||
// (b) change spaces to underscores | // (b) change spaces to underscores | ||
// (c) encodeURI (just the straight one, no pg.re.urlNoPopup) | // (c) encodeURI (just the straight one, no pg.re.urlNoPopup) | ||
function myDecodeURI (str) { | function myDecodeURI (str) { | ||
var ret; | var ret; | ||
| Строка 2561: | Строка 2495: | ||
return ret; | return ret; | ||
} | } | ||
function safeDecodeURI(str) { var ret=myDecodeURI(str); return ret || str; } | function safeDecodeURI(str) { var ret=myDecodeURI(str); return ret || str; } | ||
/////////// | /////////// | ||
// TESTS // | // TESTS // | ||
/////////// | /////////// | ||
//<NOLITE> | //<NOLITE> | ||
function isIpUser(user) {return pg.re.ipUser.test(user);} | function isIpUser(user) {return pg.re.ipUser.test(user);} | ||
function isDisambig(data, article) { | function isDisambig(data, article) { | ||
if (!getValueOf('popupAllDabsStubs') && article.namespace()) { return false; } | if (!getValueOf('popupAllDabsStubs') && article.namespace()) { return false; } | ||
return ! article.isTalkPage() && pg.re.disambig.test(data); | return ! article.isTalkPage() && pg.re.disambig.test(data); | ||
} | } | ||
function stubCount(data, article) { | function stubCount(data, article) { | ||
if (!getValueOf('popupAllDabsStubs') && article.namespace()) { return false; } | if (!getValueOf('popupAllDabsStubs') && article.namespace()) { return false; } | ||
| Строка 2589: | Строка 2523: | ||
return { real: realStub, sect: sectStub }; | return { real: realStub, sect: sectStub }; | ||
} | } | ||
function isValidImageName(str){ // extend as needed... | function isValidImageName(str){ // extend as needed... | ||
return ( str.indexOf('{') == -1 ); | return ( str.indexOf('{') == -1 ); | ||
} | } | ||
function isInStrippableNamespace(article) { | function isInStrippableNamespace(article) { | ||
return ( findInArray( pg.ns.nonArticleList, article.namespace() ) > -1 ); | return ( findInArray( pg.ns.nonArticleList, article.namespace() ) > -1 ); | ||
} | } | ||
function isInMainNamespace(article) { return !isInStrippableNamespace(article); } | function isInMainNamespace(article) { return !isInStrippableNamespace(article); } | ||
function anchorContainsImage(a) { | function anchorContainsImage(a) { | ||
// iterate over children of anchor a | // iterate over children of anchor a | ||
| Строка 2612: | Строка 2546: | ||
// NB for performance reasons, TOC links generally return true | // NB for performance reasons, TOC links generally return true | ||
// they should be stripped out later | // they should be stripped out later | ||
if (!markNopopupSpanLinks.done) { markNopopupSpanLinks(); } | if (!markNopopupSpanLinks.done) { markNopopupSpanLinks(); } | ||
if (a.inNopopupSpan || a.className=='sortheader') { return false; } | if (a.inNopopupSpan || a.className=='sortheader') { return false; } | ||
// FIXME is this faster inline? | // FIXME is this faster inline? | ||
if (a.onmousedown || a.getAttribute('nopopup')) { return false; } | if (a.onmousedown || a.getAttribute('nopopup')) { return false; } | ||
| Строка 2625: | Строка 2559: | ||
h.indexOf('&limit=') == -1 ); | h.indexOf('&limit=') == -1 ); | ||
} | } | ||
function markNopopupSpanLinks() { | function markNopopupSpanLinks() { | ||
var s=document.getElementsByTagName('span'); | |||
var s= | |||
for (var i=0; i<s.length; ++i) { | for (var i=0; i<s.length; ++i) { | ||
var as=s[i].getElementsByTagName('a'); | if (s[i].className && s[i].className.toLowerCase()=='nopopups') { | ||
var as=s[i].getElementsByTagName('a'); | |||
for (var j=0; j<as.length; ++j) { | |||
as[j].inNopopupSpan=true; | |||
} | |||
} | } | ||
} | } | ||
markNopopupSpanLinks.done=true; | markNopopupSpanLinks.done=true; | ||
} | } | ||
// ENDFILE: titles.js | // ENDFILE: titles.js | ||
| Строка 2655: | Строка 2578: | ||
// Cookie handling | // Cookie handling | ||
// from http://www.quirksmode.org/js/cookies.html | // from http://www.quirksmode.org/js/cookies.html | ||
var Cookie= { | var Cookie= { | ||
create: function(name,value,days) | create: function(name,value,days) | ||
| Строка 2669: | Строка 2592: | ||
document.cookie = name+"="+value+expires+"; path=/"; | document.cookie = name+"="+value+expires+"; path=/"; | ||
}, | }, | ||
read: function(name) | read: function(name) | ||
{ | { | ||
| Строка 2682: | Строка 2605: | ||
return null; | return null; | ||
}, | }, | ||
erase: function(name) | erase: function(name) | ||
{ | { | ||
| Строка 2694: | Строка 2617: | ||
// Wiki-specific downloading | // Wiki-specific downloading | ||
// | // | ||
// Schematic for a getWiki call | // Schematic for a getWiki call | ||
// | // | ||
| Строка 2703: | Строка 2626: | ||
// \. | // \. | ||
// (async)->addPageToCache(download)->-onComplete(download) | // (async)->addPageToCache(download)->-onComplete(download) | ||
/** @todo {document} | /** @todo {document} | ||
@param {Title} article | @param {Title} article | ||
| Строка 2717: | Строка 2640: | ||
if (oldid || oldid===0 || oldid==='0') { url += '&oldid='+oldid; } | if (oldid || oldid===0 || oldid==='0') { url += '&oldid='+oldid; } | ||
url += '&maxage=0&smaxage=0'; | url += '&maxage=0&smaxage=0'; | ||
getPageWithCaching(url, onComplete, owner); | getPageWithCaching(url, onComplete, owner); | ||
} | } | ||
// check cache to see if page exists | // check cache to see if page exists | ||
function getPageWithCaching(url, onComplete, owner) { | function getPageWithCaching(url, onComplete, owner) { | ||
log('getPageWithCaching, url='+url); | log('getPageWithCaching, url='+url); | ||
| Строка 2738: | Строка 2661: | ||
} | } | ||
} | } | ||
function getPage(url, onComplete, owner) { | function getPage(url, onComplete, owner) { | ||
log('getPage'); | log('getPage'); | ||
| Строка 2744: | Строка 2667: | ||
return startDownload(url, owner.idNumber, callback); | return startDownload(url, owner.idNumber, callback); | ||
} | } | ||
function findInPageCache(url) { | function findInPageCache(url) { | ||
for (var i=0; i<pg.cache.pages.length; ++i) { | for (var i=0; i<pg.cache.pages.length; ++i) { | ||
| Строка 2751: | Строка 2674: | ||
return -1; | return -1; | ||
} | } | ||
function addPageToCache(download) { | function addPageToCache(download) { | ||
log('addPageToCache '+download.url); | log('addPageToCache '+download.url); | ||
| Строка 2768: | Строка 2691: | ||
* See http://pajhome.org.uk/crypt/md5 for more info. | * See http://pajhome.org.uk/crypt/md5 for more info. | ||
*/ | */ | ||
/* | /* | ||
* Configurable variables. You may need to tweak these to be compatible with | * Configurable variables. You may need to tweak these to be compatible with | ||
| Строка 2775: | Строка 2698: | ||
var hexcase = 0; /* hex output format. 0 - lowercase; 1 - uppercase */ | var hexcase = 0; /* hex output format. 0 - lowercase; 1 - uppercase */ | ||
var b64pad = ""; /* base-64 pad character. "=" for strict RFC compliance */ | var b64pad = ""; /* base-64 pad character. "=" for strict RFC compliance */ | ||
/* | /* | ||
* These are the functions you'll usually want to call | * These are the functions you'll usually want to call | ||
| Строка 2789: | Строка 2712: | ||
function any_hmac_md5(k, d, e) | function any_hmac_md5(k, d, e) | ||
{ return rstr2any(rstr_hmac_md5(str2rstr_utf8(k), str2rstr_utf8(d)), e); } | { return rstr2any(rstr_hmac_md5(str2rstr_utf8(k), str2rstr_utf8(d)), e); } | ||
/* | /* | ||
* Perform a simple self-test to see if the VM is working | * Perform a simple self-test to see if the VM is working | ||
| Строка 2797: | Строка 2720: | ||
return hex_md5("abc") == "900150983cd24fb0d6963f7d28e17f72"; | return hex_md5("abc") == "900150983cd24fb0d6963f7d28e17f72"; | ||
} | } | ||
/* | /* | ||
* Calculate the MD5 of a raw string | * Calculate the MD5 of a raw string | ||
| Строка 2805: | Строка 2728: | ||
return binl2rstr(binl_md5(rstr2binl(s), s.length * 8)); | return binl2rstr(binl_md5(rstr2binl(s), s.length * 8)); | ||
} | } | ||
/* | /* | ||
* Calculate the HMAC-MD5, of a key and some data (raw strings) | * Calculate the HMAC-MD5, of a key and some data (raw strings) | ||
| Строка 2813: | Строка 2736: | ||
var bkey = rstr2binl(key); | var bkey = rstr2binl(key); | ||
if(bkey.length > 16) bkey = binl_md5(bkey, key.length * 8); | if(bkey.length > 16) bkey = binl_md5(bkey, key.length * 8); | ||
var ipad = Array(16), opad = Array(16); | var ipad = Array(16), opad = Array(16); | ||
for(var i = 0; i < 16; i++) | for(var i = 0; i < 16; i++) | ||
| Строка 2820: | Строка 2743: | ||
opad[i] = bkey[i] ^ 0x5C5C5C5C; | opad[i] = bkey[i] ^ 0x5C5C5C5C; | ||
} | } | ||
var hash = binl_md5(ipad.concat(rstr2binl(data)), 512 + data.length * 8); | var hash = binl_md5(ipad.concat(rstr2binl(data)), 512 + data.length * 8); | ||
return binl2rstr(binl_md5(opad.concat(hash), 512 + 128)); | return binl2rstr(binl_md5(opad.concat(hash), 512 + 128)); | ||
} | } | ||
/* | /* | ||
* Convert a raw string to a hex string | * Convert a raw string to a hex string | ||
| Строка 2841: | Строка 2764: | ||
return output; | return output; | ||
} | } | ||
/* | /* | ||
* Convert a raw string to a base-64 string | * Convert a raw string to a base-64 string | ||
| Строка 2863: | Строка 2786: | ||
return output; | return output; | ||
} | } | ||
/* | /* | ||
* Convert a raw string to an arbitrary string encoding | * Convert a raw string to an arbitrary string encoding | ||
| Строка 2872: | Строка 2795: | ||
var remainders = Array(); | var remainders = Array(); | ||
var i, q, x, quotient; | var i, q, x, quotient; | ||
/* Convert to an array of 16-bit big-endian values, forming the dividend */ | /* Convert to an array of 16-bit big-endian values, forming the dividend */ | ||
var dividend = Array(input.length / 2); | var dividend = Array(input.length / 2); | ||
| Строка 2879: | Строка 2802: | ||
dividend[i] = (input.charCodeAt(i * 2) << 8) | input.charCodeAt(i * 2 + 1); | dividend[i] = (input.charCodeAt(i * 2) << 8) | input.charCodeAt(i * 2 + 1); | ||
} | } | ||
/* | /* | ||
* Repeatedly perform a long division. The binary array forms the dividend, | * Repeatedly perform a long division. The binary array forms the dividend, | ||
| Строка 2901: | Строка 2824: | ||
dividend = quotient; | dividend = quotient; | ||
} | } | ||
/* Convert the remainders to the output string */ | /* Convert the remainders to the output string */ | ||
var output = ""; | var output = ""; | ||
for(i = remainders.length - 1; i >= 0; i--) | for(i = remainders.length - 1; i >= 0; i--) | ||
output += encoding.charAt(remainders[i]); | output += encoding.charAt(remainders[i]); | ||
return output; | return output; | ||
} | } | ||
/* | /* | ||
* Encode a string as utf-8. | * Encode a string as utf-8. | ||
| Строка 2919: | Строка 2842: | ||
var i = -1; | var i = -1; | ||
var x, y; | var x, y; | ||
while(++i < input.length) | while(++i < input.length) | ||
{ | { | ||
| Строка 2930: | Строка 2853: | ||
i++; | i++; | ||
} | } | ||
/* Encode output as utf-8 */ | /* Encode output as utf-8 */ | ||
if(x <= 0x7F) | if(x <= 0x7F) | ||
| Строка 2949: | Строка 2872: | ||
return output; | return output; | ||
} | } | ||
/* | /* | ||
* Encode a string as utf-16 | * Encode a string as utf-16 | ||
| Строка 2961: | Строка 2884: | ||
return output; | return output; | ||
} | } | ||
function str2rstr_utf16be(input) | function str2rstr_utf16be(input) | ||
{ | { | ||
| Строка 2970: | Строка 2893: | ||
return output; | return output; | ||
} | } | ||
/* | /* | ||
* Convert a raw string to an array of little-endian words | * Convert a raw string to an array of little-endian words | ||
| Строка 2984: | Строка 2907: | ||
return output; | return output; | ||
} | } | ||
/* | /* | ||
* Convert an array of little-endian words to a string | * Convert an array of little-endian words to a string | ||
| Строка 2995: | Строка 2918: | ||
return output; | return output; | ||
} | } | ||
/* | /* | ||
* Calculate the MD5 of an array of little-endian words, and a bit length. | * Calculate the MD5 of an array of little-endian words, and a bit length. | ||
| Строка 3004: | Строка 2927: | ||
x[len >> 5] |= 0x80 << ((len) % 32); | x[len >> 5] |= 0x80 << ((len) % 32); | ||
x[(((len + 64) >>> 9) << 4) + 14] = len; | x[(((len + 64) >>> 9) << 4) + 14] = len; | ||
var a = 1732584193; | var a = 1732584193; | ||
var b = -271733879; | var b = -271733879; | ||
var c = -1732584194; | var c = -1732584194; | ||
var d = 271733878; | var d = 271733878; | ||
for(var i = 0; i < x.length; i += 16) | for(var i = 0; i < x.length; i += 16) | ||
{ | { | ||
| Строка 3016: | Строка 2939: | ||
var oldc = c; | var oldc = c; | ||
var oldd = d; | var oldd = d; | ||
a = md5_ff(a, b, c, d, x[i+ 0], 7 , -680876936); | a = md5_ff(a, b, c, d, x[i+ 0], 7 , -680876936); | ||
d = md5_ff(d, a, b, c, x[i+ 1], 12, -389564586); | d = md5_ff(d, a, b, c, x[i+ 1], 12, -389564586); | ||
| Строка 3033: | Строка 2956: | ||
c = md5_ff(c, d, a, b, x[i+14], 17, -1502002290); | c = md5_ff(c, d, a, b, x[i+14], 17, -1502002290); | ||
b = md5_ff(b, c, d, a, x[i+15], 22, 1236535329); | b = md5_ff(b, c, d, a, x[i+15], 22, 1236535329); | ||
a = md5_gg(a, b, c, d, x[i+ 1], 5 , -165796510); | a = md5_gg(a, b, c, d, x[i+ 1], 5 , -165796510); | ||
d = md5_gg(d, a, b, c, x[i+ 6], 9 , -1069501632); | d = md5_gg(d, a, b, c, x[i+ 6], 9 , -1069501632); | ||
| Строка 3050: | Строка 2973: | ||
c = md5_gg(c, d, a, b, x[i+ 7], 14, 1735328473); | c = md5_gg(c, d, a, b, x[i+ 7], 14, 1735328473); | ||
b = md5_gg(b, c, d, a, x[i+12], 20, -1926607734); | b = md5_gg(b, c, d, a, x[i+12], 20, -1926607734); | ||
a = md5_hh(a, b, c, d, x[i+ 5], 4 , -378558); | a = md5_hh(a, b, c, d, x[i+ 5], 4 , -378558); | ||
d = md5_hh(d, a, b, c, x[i+ 8], 11, -2022574463); | d = md5_hh(d, a, b, c, x[i+ 8], 11, -2022574463); | ||
| Строка 3067: | Строка 2990: | ||
c = md5_hh(c, d, a, b, x[i+15], 16, 530742520); | c = md5_hh(c, d, a, b, x[i+15], 16, 530742520); | ||
b = md5_hh(b, c, d, a, x[i+ 2], 23, -995338651); | b = md5_hh(b, c, d, a, x[i+ 2], 23, -995338651); | ||
a = md5_ii(a, b, c, d, x[i+ 0], 6 , -198630844); | a = md5_ii(a, b, c, d, x[i+ 0], 6 , -198630844); | ||
d = md5_ii(d, a, b, c, x[i+ 7], 10, 1126891415); | d = md5_ii(d, a, b, c, x[i+ 7], 10, 1126891415); | ||
| Строка 3084: | Строка 3007: | ||
c = md5_ii(c, d, a, b, x[i+ 2], 15, 718787259); | c = md5_ii(c, d, a, b, x[i+ 2], 15, 718787259); | ||
b = md5_ii(b, c, d, a, x[i+ 9], 21, -343485551); | b = md5_ii(b, c, d, a, x[i+ 9], 21, -343485551); | ||
a = safe_add(a, olda); | a = safe_add(a, olda); | ||
b = safe_add(b, oldb); | b = safe_add(b, oldb); | ||
| Строка 3092: | Строка 3015: | ||
return Array(a, b, c, d); | return Array(a, b, c, d); | ||
} | } | ||
/* | /* | ||
* These functions implement the four basic operations the algorithm uses. | * These functions implement the four basic operations the algorithm uses. | ||
| Строка 3116: | Строка 3039: | ||
return md5_cmn(c ^ (b | (~d)), a, b, x, s, t); | return md5_cmn(c ^ (b | (~d)), a, b, x, s, t); | ||
} | } | ||
/* | /* | ||
* Add integers, wrapping at 2^32. This uses 16-bit operations internally | * Add integers, wrapping at 2^32. This uses 16-bit operations internally | ||
| Строка 3127: | Строка 3050: | ||
return (msw << 16) | (lsw & 0xFFFF); | return (msw << 16) | (lsw & 0xFFFF); | ||
} | } | ||
/* | /* | ||
* Bitwise rotate a 32-bit number to the left. | * Bitwise rotate a 32-bit number to the left. | ||
| Строка 3140: | Строка 3063: | ||
////////////////////////////////////////////////// | ////////////////////////////////////////////////// | ||
// parenSplit | // parenSplit | ||
// String.prototype.parenSplit should do what ECMAscript says | // String.prototype.parenSplit should do what ECMAscript says | ||
// String.prototype.split does, interspersing paren matches between | // String.prototype.split does, interspersing paren matches between | ||
// the split elements | // the split elements | ||
if (String('abc'.split(/(b)/))!='a,b,c') { | if (String('abc'.split(/(b)/))!='a,b,c') { | ||
// broken String.split, e.g. konq, IE | // broken String.split, e.g. konq, IE | ||
| Строка 3170: | Строка 3093: | ||
String.prototype.parenSplit.isNative=true; | String.prototype.parenSplit.isNative=true; | ||
} | } | ||
function nonGlobalRegex(re) { | function nonGlobalRegex(re) { | ||
var s=re.toString(); | var s=re.toString(); | ||
| Строка 3201: | Строка 3124: | ||
// | // | ||
// summat else | // summat else | ||
// Source: http://aktuell.de.selfhtml.org/artikel/javascript/utf8b64/utf8.htm | // Source: http://aktuell.de.selfhtml.org/artikel/javascript/utf8b64/utf8.htm | ||
//<NOLITE> | //<NOLITE> | ||
function encode_utf8(rohtext) { | function encode_utf8(rohtext) { | ||
| Строка 3228: | Строка 3151: | ||
return utftext; | return utftext; | ||
} | } | ||
function getJsObj(json) { | function getJsObj(json) { | ||
var jsobj; | |||
try { | try { | ||
eval('jsobj='+json); | |||
return jsobj; | |||
} catch (someError) { | } catch (someError) { | ||
log('Something went wrong with getJsobj, json='+json); | |||
return 1; | return 1; | ||
} | } | ||
} | } | ||
function anyChild(obj) { | function anyChild(obj) { | ||
for (var p in obj) { | for (var p in obj) { | ||
| Строка 3252: | Строка 3170: | ||
return null; | return null; | ||
} | } | ||
//</NOLITE> | //</NOLITE> | ||
function decode_utf8(utftext) { | function decode_utf8(utftext) { | ||
var plaintext = ""; var i=0, c=0, c1=0, c2=0; | var plaintext = ""; var i=0, c=0, c1=0, c2=0; | ||
| Строка 3275: | Строка 3193: | ||
return plaintext; | return plaintext; | ||
} | } | ||
function upcaseFirst(str) { | function upcaseFirst(str) { | ||
if (typeof str != typeof '' || str=='') return ''; | if (typeof str != typeof '' || str=='') return ''; | ||
return str.charAt(0).toUpperCase() + str.substring(1); | return str.charAt(0).toUpperCase() + str.substring(1); | ||
} | } | ||
function findInArray(arr, foo) { | function findInArray(arr, foo) { | ||
if (!arr || !arr.length) { return -1; } | if (!arr || !arr.length) { return -1; } | ||
| Строка 3289: | Строка 3207: | ||
return -1; | return -1; | ||
} | } | ||
function nextOne (array, value) { | function nextOne (array, value) { | ||
// NB if the array has two consecutive entries equal | // NB if the array has two consecutive entries equal | ||
| Строка 3297: | Строка 3215: | ||
return array[i+1]; | return array[i+1]; | ||
} | } | ||
function literalizeRegex(str){ | function literalizeRegex(str){ | ||
return str.replace(RegExp('([-.|()\\+?*^${}\\[\\]])', 'g'), '\\$1'); | return str.replace(RegExp('([-.|()\\+?*^${}\\[\\]])', 'g'), '\\$1'); | ||
} | } | ||
String.prototype.entify=function() { | String.prototype.entify=function() { | ||
//var shy='­'; | //var shy='­'; | ||
return this.split('&').join('&').split('<').join('<').split('>').join('>'/*+shy*/).split('"').join('"'); | return this.split('&').join('&').split('<').join('<').split('>').join('>'/*+shy*/).split('"').join('"'); | ||
}; | }; | ||
function findThis(array, value) { | function findThis(array, value) { | ||
if (typeof array.length == 'undefined') { return null; } | if (typeof array.length == 'undefined') { return null; } | ||
| Строка 3314: | Строка 3232: | ||
return null; | return null; | ||
} | } | ||
function removeNulls(list) { | function removeNulls(list) { | ||
var ret=[]; | var ret=[]; | ||
| Строка 3327: | Строка 3245: | ||
return removeNulls(list).join('/'); | return removeNulls(list).join('/'); | ||
} | } | ||
function simplePrintf(str, subs) { | function simplePrintf(str, subs) { | ||
if (!str || !subs) { return str; } | if (!str || !subs) { return str; } | ||
| Строка 3348: | Строка 3266: | ||
return ret.join(''); | return ret.join(''); | ||
} | } | ||
function max(a,b){return a<b ? b : a;} | function max(a,b){return a<b ? b : a;} | ||
function min(a,b){return a>b ? b : a;} | function min(a,b){return a>b ? b : a;} | ||
function isString(x) { return (typeof x === 'string' || x instanceof String); } | function isString(x) { return (typeof x === 'string' || x instanceof String); } | ||
//function isNumber(x) { return (typeof x === 'number' || x instanceof Number); } | //function isNumber(x) { return (typeof x === 'number' || x instanceof Number); } | ||
| Строка 3360: | Строка 3278: | ||
return !isRegExp(x) && (typeof x === 'function' || x instanceof Function); | return !isRegExp(x) && (typeof x === 'function' || x instanceof Function); | ||
} | } | ||
function repeatString(s,mult) { | function repeatString(s,mult) { | ||
var ret=''; | var ret=''; | ||
| Строка 3366: | Строка 3284: | ||
return ret; | return ret; | ||
} | } | ||
function zeroFill(s, min) { | function zeroFill(s, min) { | ||
min = min || 2; | min = min || 2; | ||
| Строка 3372: | Строка 3290: | ||
return repeatString('0', min - t.length) + t; | return repeatString('0', min - t.length) + t; | ||
} | } | ||
function map(f, o) { | function map(f, o) { | ||
if (isArray(o)) { return map_array(f,o); } | if (isArray(o)) { return map_array(f,o); } | ||
| Строка 3395: | Строка 3313: | ||
// Dab-fixing code | // Dab-fixing code | ||
// | // | ||
function retargetDab(newTarget, oldTarget, friendlyCurrentArticleName, titleToEdit) { | function retargetDab(newTarget, oldTarget, friendlyCurrentArticleName, titleToEdit) { | ||
log('retargetDab: newTarget='+newTarget + ' oldTarget=' + oldTarget); | log('retargetDab: newTarget='+newTarget + ' oldTarget=' + oldTarget); | ||
| Строка 3409: | Строка 3327: | ||
title: titleToEdit}); | title: titleToEdit}); | ||
} | } | ||
function listLinks(wikitext, oldTarget, titleToEdit) { | function listLinks(wikitext, oldTarget, titleToEdit) { | ||
// mediawiki strips trailing spaces, so we do the same | // mediawiki strips trailing spaces, so we do the same | ||
| Строка 3420: | Строка 3338: | ||
var omitRegex=RegExp('^[a-z]*:|^[Ss]pecial:|^[Ii]mage|^[Cc]ategory'); | var omitRegex=RegExp('^[a-z]*:|^[Ss]pecial:|^[Ii]mage|^[Cc]ategory'); | ||
var friendlyCurrentArticleName= oldTarget.toString(); | var friendlyCurrentArticleName= oldTarget.toString(); | ||
for (var i=1; i<splitted.length; i=i+3) { | for (var i=1; i<splitted.length; i=i+3) { | ||
if (typeof splitted[i] == typeof 'string' && splitted[i].length>0 && !omitRegex.test(splitted[i])) { | if (typeof splitted[i] == typeof 'string' && splitted[i].length>0 && !omitRegex.test(splitted[i])) { | ||
| Строка 3427: | Строка 3344: | ||
} /* if */ | } /* if */ | ||
} /* for loop */ | } /* for loop */ | ||
ret = rmDupesFromSortedList(ret.sort()); | ret = rmDupesFromSortedList(ret.sort()); | ||
var wikTarget='wiktionary:' + friendlyCurrentArticleName.replace( RegExp('^(.+)\\s+[(][^)]+[)]\\s*$'), '$1' ); | |||
ret.push( retargetDab(wikTarget, oldTarget, friendlyCurrentArticleName, titleToEdit) ); | |||
ret.push(changeLinkTargetLink( | ret.push(changeLinkTargetLink( | ||
{ newTarget: null, | { newTarget: null, | ||
| Строка 3452: | Строка 3361: | ||
return ret; | return ret; | ||
} | } | ||
function rmDupesFromSortedList(list) { | function rmDupesFromSortedList(list) { | ||
var ret=[]; | var ret=[]; | ||
| Строка 3460: | Строка 3369: | ||
return ret; | return ret; | ||
} | } | ||
function makeFixDab(data, navpop) { | function makeFixDab(data, navpop) { | ||
// grab title from parent popup if there is one; default exists in changeLinkTargetLink | // grab title from parent popup if there is one; default exists in changeLinkTargetLink | ||
var titleToEdit=(navpop.parentPopup && navpop.parentPopup.article.toString()); | var titleToEdit=(navpop.parentPopup && navpop.parentPopup.article.toString()); | ||
var list=listLinks(data, navpop.originalArticle, titleToEdit); | var list=listLinks(data, navpop.originalArticle, titleToEdit); | ||
if (list.length===0) { log('listLinks returned empty list'); return null; } | if (list.length===0) { log('listLinks returned empty list'); return null; } | ||
| Строка 3470: | Строка 3379: | ||
return html; | return html; | ||
} | } | ||
function makeFixDabs(wikiText, navpop) { | function makeFixDabs(wikiText, navpop) { | ||
if (getValueOf('popupFixDabs') && isDisambig(wikiText, navpop.article) && | if (getValueOf('popupFixDabs') && isDisambig(wikiText, navpop.article) && | ||
| Строка 3479: | Строка 3388: | ||
} | } | ||
} | } | ||
function popupRedlinkHTML(article) { | function popupRedlinkHTML(article) { | ||
return changeLinkTargetLink( | return changeLinkTargetLink( | ||
| Строка 3491: | Строка 3400: | ||
// ENDFILE: dab.js | // ENDFILE: dab.js | ||
// STARTFILE: htmloutput.js | // STARTFILE: htmloutput.js | ||
function appendPopupContent(obj, elementId, popupId, onSuccess) { | function appendPopupContent(obj, elementId, popupId, onSuccess) { | ||
return setPopupHTML(obj, elementId, popupId, onSuccess, true); | return setPopupHTML(obj, elementId, popupId, onSuccess, true); | ||
} | } | ||
// this has to use a timer loop as we don't know if the DOM element exists when we want to set the text | // this has to use a timer loop as we don't know if the DOM element exists when we want to set the text | ||
function setPopupHTML (str, elementId, popupId, onSuccess, append) { | function setPopupHTML (str, elementId, popupId, onSuccess, append) { | ||
| Строка 3504: | Строка 3413: | ||
popupId = pg.idNumber; | popupId = pg.idNumber; | ||
} | } | ||
var popupElement=document.getElementById(elementId+popupId); | var popupElement=document.getElementById(elementId+popupId); | ||
if (popupElement) { | if (popupElement) { | ||
| Строка 3524: | Строка 3433: | ||
return null; | return null; | ||
} | } | ||
//<NOLITE> | //<NOLITE> | ||
function setImageStatus(str, id) {return; } // setPopupHTML(str, 'popupImageStatus', id);} | function setImageStatus(str, id) {return; } // setPopupHTML(str, 'popupImageStatus', id);} | ||
function setPopupTrailer(str,id) {return setPopupHTML(str, 'popupData', id);} | function setPopupTrailer(str,id) {return setPopupHTML(str, 'popupData', id);} | ||
//</NOLITE> | //</NOLITE> | ||
function fillEmptySpans(args) { return fillEmptySpans2(args); } | function fillEmptySpans(args) { return fillEmptySpans2(args); } | ||
// args.navpopup is mandatory | // args.navpopup is mandatory | ||
// optional: args.redir, args.redirTarget | // optional: args.redir, args.redirTarget | ||
| Строка 3540: | Строка 3449: | ||
if (typeof args != 'object' || typeof args.redir == 'undefined' || !args.redir) { redir=false; } | if (typeof args != 'object' || typeof args.redir == 'undefined' || !args.redir) { redir=false; } | ||
var a=args.navpopup.parentAnchor; | var a=args.navpopup.parentAnchor; | ||
var article, hint=null, oldid=null, params={}; | var article, hint=null, oldid=null, params={}; | ||
if (redir && typeof args.redirTarget == typeof {}) { | if (redir && typeof args.redirTarget == typeof {}) { | ||
| Строка 3553: | Строка 3462: | ||
} | } | ||
var x={ article:article, hint: hint, oldid: oldid, rcid: rcid, navpop:args.navpopup, params:params }; | var x={ article:article, hint: hint, oldid: oldid, rcid: rcid, navpop:args.navpopup, params:params }; | ||
var structure=pg.structures[getValueOf('popupStructure')]; | var structure=pg.structures[getValueOf('popupStructure')]; | ||
if (typeof structure != 'object') { | if (typeof structure != 'object') { | ||
| Строка 3563: | Строка 3472: | ||
var numspans = spans.length; | var numspans = spans.length; | ||
var redirs=pg.misc.redirSpans; | var redirs=pg.misc.redirSpans; | ||
for (var i=0; i<numspans; ++i) { | for (var i=0; i<numspans; ++i) { | ||
var f=findThis(redirs, spans[i]); | var f=findThis(redirs, spans[i]); | ||
| Строка 3573: | Строка 3482: | ||
var structurefn=structure[spans[i]]; | var structurefn=structure[spans[i]]; | ||
var setfn = setPopupHTML; | var setfn = setPopupHTML; | ||
if (getValueOf('popupActiveNavlinks') && | if (getValueOf('popupActiveNavlinks') && spans[i].indexOf('popupTopLinks')==0) { | ||
setfn = setPopupTipsAndHTML; | setfn = setPopupTipsAndHTML; | ||
} | } | ||
| Строка 3592: | Строка 3499: | ||
} | } | ||
} | } | ||
// flatten an array | // flatten an array | ||
function flatten(list, start) { | function flatten(list, start) { | ||
| Строка 3605: | Строка 3512: | ||
return ret; | return ret; | ||
} | } | ||
// Generate html for whole popup | // Generate html for whole popup | ||
function popupHTML (a) { | function popupHTML (a) { | ||
| Строка 3622: | Строка 3529: | ||
return makeEmptySpans(pg.misc.layout, a.navpopup); | return makeEmptySpans(pg.misc.layout, a.navpopup); | ||
} | } | ||
function makeEmptySpans (list, navpop) { | function makeEmptySpans (list, navpop) { | ||
var ret=''; | var ret=''; | ||
| Строка 3636: | Строка 3543: | ||
return ret; | return ret; | ||
} | } | ||
function emptySpanHTML(name, id, tag, classname) { | function emptySpanHTML(name, id, tag, classname) { | ||
tag = tag || 'span'; | tag = tag || 'span'; | ||
| Строка 3646: | Строка 3553: | ||
} | } | ||
emptySpanHTML.classAliases={ 'popupSecondPreview': 'popupPreview' }; | emptySpanHTML.classAliases={ 'popupSecondPreview': 'popupPreview' }; | ||
// generate html for popup image | // generate html for popup image | ||
// <a id="popupImageLinkn"><img id="popupImagen"> | // <a id="popupImageLinkn"><img id="popupImagen"> | ||
| Строка 3655: | Строка 3562: | ||
'</a>', [ idNumber ]); | '</a>', [ idNumber ]); | ||
} | } | ||
function popTipsSoonFn(id, when, popData) { | function popTipsSoonFn(id, when, popData) { | ||
when || ( when=250 ); | when || ( when=250 ); | ||
| Строка 3661: | Строка 3568: | ||
return function() { setTimeout( popTips, when, popData ); }; | return function() { setTimeout( popTips, when, popData ); }; | ||
} | } | ||
function setPopupTipsAndHTML(html, divname, idnumber, popData) { | function setPopupTipsAndHTML(html, divname, idnumber, popData) { | ||
setPopupHTML(html, divname, idnumber, | setPopupHTML(html, divname, idnumber, | ||
| Строка 3672: | Строка 3579: | ||
////////////////////////////////////////////////// | ////////////////////////////////////////////////// | ||
// fuzzy checks | // fuzzy checks | ||
function fuzzyCursorOffMenus(x,y, fuzz, parent) { | function fuzzyCursorOffMenus(x,y, fuzz, parent) { | ||
if (!parent) { return null; } | if (!parent) { return null; } | ||
| Строка 3683: | Строка 3590: | ||
return true; | return true; | ||
} | } | ||
function checkPopupPosition () { // stop the popup running off the right of the screen | function checkPopupPosition () { // stop the popup running off the right of the screen | ||
// FIXME avoid pg.current.link | // FIXME avoid pg.current.link | ||
| Строка 3689: | Строка 3596: | ||
pg.current.link.navpopup.limitHorizontalPosition(); | pg.current.link.navpopup.limitHorizontalPosition(); | ||
} | } | ||
function mouseOutWikiLink () { | function mouseOutWikiLink () { | ||
if (!window.popupsReady || !window.popupsReady()) { return; } | if (!window.popupsReady || !window.popupsReady()) { return; } | ||
| Строка 3701: | Строка 3608: | ||
Navpopup.tracker.addHook(posCheckerHook(a.navpopup)); | Navpopup.tracker.addHook(posCheckerHook(a.navpopup)); | ||
} | } | ||
function posCheckerHook(navpop) { | function posCheckerHook(navpop) { | ||
return function() { | return function() { | ||
| Строка 3711: | Строка 3618: | ||
var mouseOverNavpop = navpop.isWithin(x,y,navpop.fuzz, navpop.mainDiv) || | var mouseOverNavpop = navpop.isWithin(x,y,navpop.fuzz, navpop.mainDiv) || | ||
!fuzzyCursorOffMenus(x,y,navpop.fuzz, navpop.mainDiv); | !fuzzyCursorOffMenus(x,y,navpop.fuzz, navpop.mainDiv); | ||
// FIXME it'd be prettier to do this internal to the Navpopup objects | // FIXME it'd be prettier to do this internal to the Navpopup objects | ||
var t=getValueOf('popupHideDelay'); | var t=getValueOf('popupHideDelay'); | ||
| Строка 3739: | Строка 3646: | ||
}; | }; | ||
} | } | ||
function runStopPopupTimer(navpop) { | function runStopPopupTimer(navpop) { | ||
// at this point, we should have left the link but remain within the popup | // at this point, we should have left the link but remain within the popup | ||
| Строка 3755: | Строка 3662: | ||
Defines the {@link Previewmaker} object, which generates short previews from wiki markup. | Defines the {@link Previewmaker} object, which generates short previews from wiki markup. | ||
*/ | */ | ||
/** | /** | ||
Creates a new Previewmaker | Creates a new Previewmaker | ||
| Строка 3868: | Строка 3775: | ||
log ('makeRegexp failed'); | log ('makeRegexp failed'); | ||
} | } | ||
log ('makeRegexp: got reStr=' + reStr + ', flags=' + flags); | log ('makeRegexp: got reStr=' + reStr + ', flags=' + flags); | ||
return RegExp(reStr, flags); | return RegExp(reStr, flags); | ||
| Строка 3876: | Строка 3783: | ||
*/ | */ | ||
Previewmaker.prototype.killBoxTemplates = function () { | Previewmaker.prototype.killBoxTemplates = function () { | ||
// taxobox removal... in fact, there's a saudiprincebox_begin, so let's be more general | // taxobox removal... in fact, there's a saudiprincebox_begin, so let's be more general | ||
// also, have float_begin, ... float_end | // also, have float_begin, ... float_end | ||
this.kill(RegExp('[{][{][^{}\\s|]*?(float|box)[_ ](begin|start)', 'i'), /[}][}]\s*/, '{{'); | this.kill(RegExp('[{][{][^{}\\s|]*?(float|box)[_ ](begin|start)', 'i'), /[}][}]\s*/, '{{'); | ||
// infoboxes etc | // infoboxes etc | ||
// from [[User:Zyxw/popups.js]]: kill frames too | // from [[User:Zyxw/popups.js]]: kill frames too | ||
this.kill(RegExp('[{][{][^{}\\s|]*?(infobox|elementbox|frame)[_ ]', 'i'), /[}][}]\s*/, '{{'); | this.kill(RegExp('[{][{][^{}\\s|]*?(infobox|elementbox|frame)[_ ]', 'i'), /[}][}]\s*/, '{{'); | ||
}; | }; | ||
/** | /** | ||
| Строка 3909: | Строка 3816: | ||
Previewmaker.prototype.killImages = function () { | Previewmaker.prototype.killImages = function () { | ||
// images and categories are a nono | // images and categories are a nono | ||
this.kill(RegExp('[[][[]\\s*( | this.kill(RegExp('[[][[]\\s*(' + pg.ns.image + '|' + pg.ns.category + ')\\s*:', 'i'), | ||
/\]\]\s*/, '[', ']'); | /\]\]\s*/, '[', ']'); | ||
}; | }; | ||
| Строка 3918: | Строка 3825: | ||
// kill <ref ...>...</ref> | // kill <ref ...>...</ref> | ||
this.kill(/<ref\b.*?>/i, /<\/ref>/i); | this.kill(/<ref\b.*?>/i, /<\/ref>/i); | ||
// let's also delete entire lines starting with <. it's worth a try. | // let's also delete entire lines starting with <. it's worth a try. | ||
this.data=this.data.replace(RegExp('(^|\\n) *<.*', 'g'), '\n'); | this.data=this.data.replace(RegExp('(^|\\n) *<.*', 'g'), '\n'); | ||
// and those pesky html tags, but not <nowiki> or <blockquote> | // and those pesky html tags, but not <nowiki> or <blockquote> | ||
var splitted=this.data.parenSplit(/(<.*?>)/); | var splitted=this.data.parenSplit(/(<.*?>)/); | ||
| Строка 3954: | Строка 3861: | ||
// we simply *can't* be doing with horizontal rules right now | // we simply *can't* be doing with horizontal rules right now | ||
this.data=this.data.replace(RegExp('^-{4,}','mg'),''); | this.data=this.data.replace(RegExp('^-{4,}','mg'),''); | ||
// no indented lines | // no indented lines | ||
this.data=this.data.replace(RegExp('(^|\\n) *:[^\\n]*','g'), ''); | this.data=this.data.replace(RegExp('(^|\\n) *:[^\\n]*','g'), ''); | ||
// replace __TOC__, __NOTOC__ and whatever else there is | // replace __TOC__, __NOTOC__ and whatever else there is | ||
// this'll probably do | // this'll probably do | ||
| Строка 3969: | Строка 3876: | ||
/// first we "normalize" section headings, removing whitespace after, adding before | /// first we "normalize" section headings, removing whitespace after, adding before | ||
var d=this.data; | var d=this.data; | ||
if (getValueOf('popupPreviewCutHeadings')) { | if (getValueOf('popupPreviewCutHeadings')) { | ||
this.data=this.data.replace(RegExp('\\s*(==+[^=]*==+)\\s*', 'g'), '\n\n$1 '); | this.data=this.data.replace(RegExp('\\s*(==+[^=]*==+)\\s*', 'g'), '\n\n$1 '); | ||
/// then we want to get rid of paragraph breaks whose text ends badly | /// then we want to get rid of paragraph breaks whose text ends badly | ||
this.data=this.data.replace(RegExp('([:;]) *\\n{2,}', 'g'), '$1\n'); | this.data=this.data.replace(RegExp('([:;]) *\\n{2,}', 'g'), '$1\n'); | ||
this.data=this.data.replace(RegExp('^[\\s\\n]*'), ''); | this.data=this.data.replace(RegExp('^[\\s\\n]*'), ''); | ||
stuff=(RegExp('^([^\\n]|\\n[^\\n\\s])*')).exec(this.data); | stuff=(RegExp('^([^\\n]|\\n[^\\n\\s])*')).exec(this.data); | ||
if (stuff) { d = stuff[0]; } | if (stuff) { d = stuff[0]; } | ||
if (!getValueOf('popupPreviewFirstParOnly')) { d = this.data; } | if (!getValueOf('popupPreviewFirstParOnly')) { d = this.data; } | ||
/// now put \n\n after sections so that bullets and numbered lists work | /// now put \n\n after sections so that bullets and numbered lists work | ||
d=d.replace(RegExp('(==+[^=]*==+)\\s*', 'g'), '$1\n\n'); | d=d.replace(RegExp('(==+[^=]*==+)\\s*', 'g'), '$1\n\n'); | ||
} | } | ||
// superfluous sentences are RIGHT OUT. | // superfluous sentences are RIGHT OUT. | ||
// note: exactly 1 set of parens here needed to make the slice work | // note: exactly 1 set of parens here needed to make the slice work | ||
| Строка 3990: | Строка 3897: | ||
// leading space is bad, mmkay? | // leading space is bad, mmkay? | ||
d[0]=d[0].replace(RegExp('^\\s*'), ''); | d[0]=d[0].replace(RegExp('^\\s*'), ''); | ||
var notSentenceEnds=RegExp('([^.][a-z][.] *[a-z]|etc|sic|Dr|Mr|Mrs|Ms|St|no|op|cit|\\[[^\\]]*|\\s[A-Zvclm])$', 'i'); | var notSentenceEnds=RegExp('([^.][a-z][.] *[a-z]|etc|sic|Dr|Mr|Mrs|Ms|St|no|op|cit|\\[[^\\]]*|\\s[A-Zvclm])$', 'i'); | ||
d = this.fixSentenceEnds(d, notSentenceEnds); | d = this.fixSentenceEnds(d, notSentenceEnds); | ||
this.fullLength=d.join('').length; | this.fullLength=d.join('').length; | ||
var maxChars=getValueOf('popupMaxPreviewCharacters') + this.extraCharacters; | var maxChars=getValueOf('popupMaxPreviewCharacters') + this.extraCharacters; | ||
var n=this.maxSentences; | var n=this.maxSentences; | ||
var dd=this.firstSentences(d,n); | var dd=this.firstSentences(d,n); | ||
do { | do { | ||
dd=this.firstSentences(d,n); --n; | dd=this.firstSentences(d,n); --n; | ||
} while ( dd.length > this.maxCharacters && n != 0 ); | } while ( dd.length > this.maxCharacters && n != 0 ); | ||
this.data = dd; | this.data = dd; | ||
}; | }; | ||
| Строка 4011: | Строка 3918: | ||
// take an array of strings, strs | // take an array of strings, strs | ||
// join strs[i] to strs[i+1] & strs[i+2] if strs[i] matches regex reg | // join strs[i] to strs[i+1] & strs[i+2] if strs[i] matches regex reg | ||
var abbrevRe=/\b[a-z][^a-z]*$/i; | var abbrevRe=/\b[a-z][^a-z]*$/i; | ||
for (var i=0; i<strs.length-2; ++i) { | for (var i=0; i<strs.length-2; ++i) { | ||
if (reg.test(strs[i])) { | if (reg.test(strs[i])) { | ||
| Строка 4058: | Строка 3965: | ||
*/ | */ | ||
Previewmaker.prototype.makePreview = function() { | Previewmaker.prototype.makePreview = function() { | ||
if (this.owner.article.namespace()!=pg.ns.template | if (this.owner.article.namespace()!=pg.ns.template) { | ||
this.killComments(); | this.killComments(); | ||
this.killDivs(); | this.killDivs(); | ||
this.killGalleries(); | this.killGalleries(); | ||
this.killBoxTemplates(); | this.killBoxTemplates(); | ||
if (getValueOf('popupPreviewKillTemplates')) { | if (getValueOf('popupPreviewKillTemplates')) { | ||
this.killTemplates(); | this.killTemplates(); | ||
| Строка 4075: | Строка 3981: | ||
this.killChunks(); | this.killChunks(); | ||
this.mopup(); | this.mopup(); | ||
this.firstBit(); | this.firstBit(); | ||
this.killBadWhitespace(); | this.killBadWhitespace(); | ||
} | } | ||
this.html=wiki2html(this.data, this.baseUrl); // needs livepreview | this.html=wiki2html(this.data, this.baseUrl); // needs livepreview | ||
| Строка 4087: | Строка 3989: | ||
this.stripLongTemplates(); | this.stripLongTemplates(); | ||
}; | }; | ||
Previewmaker.prototype.editSummaryPreview=function() { | Previewmaker.prototype.editSummaryPreview=function() { | ||
var | var c=this.data; | ||
var re=/^\/[*] +(.*?) +[*]\/(.*)/; | |||
if (re.test(c)) { | |||
var section=c.replace(re, '$1'); | |||
if ( | |||
var section = | |||
var t=new Title().fromURL(this.baseUrl); | var t=new Title().fromURL(this.baseUrl); | ||
t.anchorFromUtf(section); | t.anchorFromUtf(section); | ||
// work around livepreview brokenness with anchors: | |||
// pass .-escaped anchor instead of literal value | |||
c=c.replace(re, '[[' + t.toString(true).split("'").join('%27') + | |||
'#' + t.anchor.split("'").join('%27') + '|→]]' + | |||
'<span class=autocomment>$1</span>$2'); | |||
} | } | ||
this.html=wiki2html(c, this.baseUrl); | |||
return this.html; | |||
return this. | |||
}; | }; | ||
//<NOLITE> | //<NOLITE> | ||
/** Test function for debugging preview problems one step at a time. | /** Test function for debugging preview problems one step at a time. | ||
| Строка 4160: | Строка 4028: | ||
p.killGalleries(); if (!confirm('done killGalleries(). Continue?\n---\n' + p.data)) { return; } | p.killGalleries(); if (!confirm('done killGalleries(). Continue?\n---\n' + p.data)) { return; } | ||
p.killBoxTemplates(); if (!confirm('done killBoxTemplates(). Continue?\n---\n' + p.data)) { return; } | p.killBoxTemplates(); if (!confirm('done killBoxTemplates(). Continue?\n---\n' + p.data)) { return; } | ||
if (getValueOf('popupPreviewKillTemplates')) { | if (getValueOf('popupPreviewKillTemplates')) { | ||
p.killTemplates(); if (!confirm('done killTemplates(). Continue?\n---\n' + p.data)) { return; } | p.killTemplates(); if (!confirm('done killTemplates(). Continue?\n---\n' + p.data)) { return; } | ||
| Строка 4166: | Строка 4034: | ||
p.killMultilineTemplates(); if (!confirm('done killMultilineTemplates(). Continue?\n---\n' + p.data)) { return; } | p.killMultilineTemplates(); if (!confirm('done killMultilineTemplates(). Continue?\n---\n' + p.data)) { return; } | ||
} | } | ||
p.killTables(); if (!confirm('done killTables(). Continue?\n---\n' + p.data)) { return; } | p.killTables(); if (!confirm('done killTables(). Continue?\n---\n' + p.data)) { return; } | ||
p.killImages(); if (!confirm('done killImages(). Continue?\n---\n' + p.data)) { return; } | p.killImages(); if (!confirm('done killImages(). Continue?\n---\n' + p.data)) { return; } | ||
| Строка 4172: | Строка 4040: | ||
p.killChunks(); if (!confirm('done killChunks(). Continue?\n---\n' + p.data)) { return; } | p.killChunks(); if (!confirm('done killChunks(). Continue?\n---\n' + p.data)) { return; } | ||
p.mopup(); if (!confirm('done mopup(). Continue?\n---\n' + p.data)) { return; } | p.mopup(); if (!confirm('done mopup(). Continue?\n---\n' + p.data)) { return; } | ||
p.firstBit(); if (!confirm('done firstBit(). Continue?\n---\n' + p.data)) { return; } | p.firstBit(); if (!confirm('done firstBit(). Continue?\n---\n' + p.data)) { return; } | ||
p.killBadWhitespace(); if (!confirm('done killBadWhitespace(). Continue?\n---\n' + p.data)) { return; } | p.killBadWhitespace(); if (!confirm('done killBadWhitespace(). Continue?\n---\n' + p.data)) { return; } | ||
} | } | ||
p.html=wiki2html(p.data, base); // needs livepreview | p.html=wiki2html(p.data, base); // needs livepreview | ||
p.fixHTML(); if (!confirm('done fixHTML(). Continue?\n---\n' + p.html)) { return; } | p.fixHTML(); if (!confirm('done fixHTML(). Continue?\n---\n' + p.html)) { return; } | ||
| Строка 4183: | Строка 4051: | ||
} | } | ||
//</NOLITE> | //</NOLITE> | ||
/** | /** | ||
Works around a quoting bug in livepreview. | Works around a quoting bug in livepreview. | ||
| Строка 4207: | Строка 4075: | ||
/** | /** | ||
Generates the preview and displays it in the current popup. | Generates the preview and displays it in the current popup. | ||
Does nothing if the generated preview is invalid or consists of whitespace only. | Does nothing if the generated preview is invalid or consists of whitespace only. | ||
Also activates wikilinks in the preview for subpopups if the popupSubpopups option is true. | Also activates wikilinks in the preview for subpopups if the popupSubpopups option is true. | ||
| Строка 4236: | Строка 4104: | ||
return a; | return a; | ||
} | } | ||
/** | /** | ||
@private | @private | ||
| Строка 4255: | Строка 4123: | ||
// ENDFILE: previewmaker.js | // ENDFILE: previewmaker.js | ||
// STARTFILE: querypreview.js | // STARTFILE: querypreview.js | ||
function | //<NOLITE> | ||
function loadQueryPreview(queryType, article, navpop) { | |||
var art=new Title(article).urlString(); | var art=new Title(article).urlString(); | ||
var url=pg.wiki.wikibase + '/ | var url=pg.wiki.wikibase + '/query.php?format=json&'; | ||
var htmlGenerator=function(a,d){alert('invalid html generator');}; | var htmlGenerator=function(a,d){alert('invalid html generator');}; | ||
switch (queryType) { | switch (queryType) { | ||
case 'history': | case 'history': | ||
url += ' | url += 'titles=' + art + '&what=revisions|userinfo&uioptions=timecorrection&rvcomments&rvlimit=' + | ||
getValueOf('popupHistoryPreviewLimit'); | getValueOf('popupHistoryPreviewLimit'); | ||
htmlGenerator= | htmlGenerator=historyPreviewHTML; | ||
break; | |||
case 'imagelinks': | |||
// redundant case | |||
url += 'titles=' + art + '&what=imagelinks&ilfilter=all'; | |||
htmlGenerator=imagelinksPreviewHTML; | |||
break; | break; | ||
case 'category': | case 'category': | ||
url += ' | url += 'what=category&cptitle=' + art; | ||
htmlGenerator= | htmlGenerator=categoryPreviewHTML; | ||
break; | break; | ||
case 'contribs': | case 'contribs': | ||
url += 'what=usercontribs|userinfo&uioptions=timecorrection&titles=' + art + '&uccomments' + | |||
url += ' | |||
'&uclimit=' + getValueOf('popupContribsPreviewLimit'); | '&uclimit=' + getValueOf('popupContribsPreviewLimit'); | ||
htmlGenerator= | htmlGenerator=contribsPreviewHTML; | ||
break; | break; | ||
case 'imagepagepreview': | case 'imagepagepreview': | ||
var trail=''; | var trail='&what=imageinfo|content|imagelinks&ilfilter=all'; | ||
if (getValueOf('popupImageLinks')) { trail = '& | if (!getValueOf('popupImageLinks')) { trail = '&what=imageinfo|content'; } | ||
url += 'titles=' + art + '& | if (pg.wiki.commons) { trail += '&iishared'; } | ||
htmlGenerator= | url += 'titles=' + art + trail; | ||
htmlGenerator=imagepagePreviewHTML; | |||
break; | |||
case 'sharedimagepage': | |||
url += 'titles=' + art + '&what=content&proxylang=' + pg.wiki.commonslang; | |||
htmlGenerator=sharedImagePagePreviewHTML; | |||
break; | break; | ||
case 'backlinks': | case 'backlinks': | ||
url += ' | url += 'what=backlinks&titles=' + art; | ||
htmlGenerator= | htmlGenerator=backlinksPreviewHTML; | ||
break; | break; | ||
} | } | ||
pendingNavpopTask(navpop); | pendingNavpopTask(navpop); | ||
var callback=function(d){ | var callback=function(d){ | ||
showQueryPreview(queryType, htmlGenerator(article,d,navpop), navpop.idNumber, navpop, d); | |||
}; | }; | ||
var go = function(){ | var go = function(){ | ||
getPageWithCaching(url, callback, navpop); | |||
return true; | return true; | ||
} | } | ||
| Строка 4309: | Строка 4175: | ||
else { navpop.addHook(go, 'unhide', 'before', 'DOWNLOAD_'+queryType+'_QUERY_DATA'); } | else { navpop.addHook(go, 'unhide', 'before', 'DOWNLOAD_'+queryType+'_QUERY_DATA'); } | ||
} | } | ||
function | function showQueryPreview(queryType, html, id, navpop, download) { | ||
var target='popupPreview'; | |||
var | switch (queryType) { | ||
case 'imagelinks': | |||
case 'category': | |||
target='popupPostPreview'; break; | |||
case 'sharedimagepage': | |||
target='popupSecondPreview'; break; | |||
} | } | ||
setPopupTipsAndHTML(html, target, id); | |||
completedNavpopTask(navpop); | |||
} | } | ||
function | function backlinksPreviewHTML(article, download, navpop) { | ||
var jsObj=getJsObj(download.data); | |||
try { | |||
var page=anyChild(jsObj.pages); | |||
var list=page.backlinks; | |||
} catch (someError) { return 'backlinksPreviewHTML went wonky'; } | |||
var html=[]; | |||
if (!list) { return popupString('No backlinks found'); } | |||
for (var i=0; i<list.length; ++i) { | |||
var t=new Title(list[i]['*']); | |||
html.push('<a href="' + pg.wiki.titlebase + t.urlString() + '">' + t + '</a>'); | |||
} | } | ||
return | html=html.join(', '); | ||
if (jsObj.query && jsObj.query.backlinks && jsObj.query.backlinks.next) { | |||
html += popupString(' and more'); | |||
} | |||
return html; | |||
} | |||
function sharedImagePagePreviewHTML(article, download, navpop) { | |||
var jsObj=getJsObj(download.data); | |||
try { | |||
var page=anyChild(jsObj.pages); | |||
var content=(page && page.content) ? page.content['*'] : null; | |||
} catch (someError) { return 'sharedimagepage preview failed :( is the query.php extension installed?'; } | |||
var ret=''; | |||
if (content) { | |||
var p=prepPreviewmaker(content, article, navpop); | |||
p.makePreview(); | |||
if (p.html) { ret += '<hr>' + p.html; } | |||
} | |||
return ret; | |||
} | |||
function imagepagePreviewHTML(article, download, navpop) { | |||
var jsObj=getJsObj(download.data); | |||
try { | |||
var page=anyChild(jsObj['pages']); | |||
var content=(page && page.content) ? page.content['*'] : null; | |||
var a=page.image; | |||
var b=page.sharedimage; | |||
} catch (someError) { return 'imagepage preview failed :( is the query.php extension installed?'; } | |||
var ret=''; | |||
if (content) { | |||
var p=prepPreviewmaker(content, article, navpop); | |||
p.makePreview(); | |||
if (p.html) { ret += '<hr>' + p.html; } | |||
} | |||
var sharingInfo=getSharingInfo(a,b); | |||
if (sharingInfo) { ret += '<hr>' + sharingInfo; } | |||
if (content!==null && getValueOf('popupSummaryData')) { | |||
var info=getPageInfo(content, download); | |||
log(info); | |||
setPopupTrailer(info, navpop.idNumber); | |||
} | |||
if (!a && b) { | |||
loadQueryPreview('sharedimagepage', article, navpop); | |||
} | |||
showQueryPreview('imagelinks', imagelinksPreviewHTML(article,download), navpop.idNumber, download); | |||
return ret; | |||
} | } | ||
function | function getSharingInfo(a,b) { | ||
if (!pg.wiki.commons) { return ''; } | |||
var | var sharingInfo=''; | ||
if (a && b) { | |||
if (checkSameImage(a,b)) { | |||
if ( | sharingInfo = popupString('commons dupe'); | ||
} else { | |||
sharingInfo = popupString('commons conflict'); | |||
} | } | ||
} else if (a && !b) { | |||
// nothing interesting | |||
if (getValueOf('popupShowNonCommonsImages')) { | |||
sharingInfo = popupString('not commons'); | |||
} | } | ||
html.push('<tr class="popup_history_row_' + ( (i%2) ? 'odd' : 'even') + '">'); | } else if (!a && b) { | ||
html.push('<td>(<a href="' + pg.wiki.titlebase + new Title(curart).urlString() + | sharingInfo = popupString('commons only'); | ||
'&diff=prev&oldid=' + h[i]['revid'] + '">' + popupString('last') + '</a>)</td>'); | } else { | ||
html.push('<td>' + | sharingInfo = popupString('No image found'); | ||
'<a href="' + pg.wiki.titlebase + new Title(curart).urlString() + | } | ||
'&oldid=' + h[i]['revid'] + '">' + thisTime + '</a></td>'); | return sharingInfo; | ||
} | |||
function checkSameImage(a,b){ | |||
return (a['size']==b['size'] && a['width']==b['width'] && a['bits']==b['bits'] && | |||
a['media']==b['media'] && a['mime']==b['mime']); | |||
} | |||
function imagelinksPreviewHTML(article, download) { | |||
var jsobj=getJsObj(download.data); | |||
try { | |||
var list=anyChild(jsobj['pages'])['imagelinks']; | |||
if (!list) { return popupString('No image links found'); } | |||
} catch(someError) { return 'Image links preview generation failed :( Is the query.php extension installed?'; } | |||
var ret=[]; | |||
for (var i=0; i<list.length; ++i) { ret.push(list[i]['*']); } | |||
if (ret.length === 0) { return popupString('No image links found'); } | |||
return '<h2>' + popupString('File links') + '</h2>' + linkList(ret); | |||
} | |||
function categoryPreviewHTML(article, download) { | |||
var jsobj=getJsObj(download.data); | |||
try{ var list=jsobj['pages']; } | |||
catch(someError) { return 'Category preview failed :( Is the query.php extension installed?'; } | |||
var ret=[]; | |||
for (var p in list) { ret.push(list[p]['title']); } | |||
if (ret.length === 0) { return popupString('Empty category'); } | |||
return '<h2>' + tprintf('Category members (%s shown)', [ret.length]) + '</h2>' +linkList(ret); | |||
} | |||
function linkList(list) { | |||
list.sort(function(x,y) { return (x==y ? 0 : (x<y ? -1 : 1)); }); | |||
var buf=[]; | |||
for (var i=0; i<list.length; ++i) { | |||
buf.push(wikiLink({article: new Title(list[i]), | |||
text: list[i].split(' ').join(' '), | |||
action: 'view'})); | |||
} | |||
return buf.join(', '); | |||
} | |||
function contribsPreviewHTML(article, download, navpop) { | |||
return historyPreviewHTML(article, download, navpop, true); | |||
} | |||
function historyPreviewHTML(article, download, navpop, reallyContribs) { | |||
var jsobj=getJsObj(download.data); | |||
try { | |||
var tz=jsobj.meta.user.timecorrection; | |||
var edits=anyChild(jsobj.pages)[reallyContribs ? 'contributions' : 'revisions']; | |||
} catch (someError) { | |||
return 'Preview failed :-( Is the query.php extension installed?'; | |||
} | |||
var timeOffset = getTimeOffset(tz); | |||
Cookie.create('popTz', timeOffset, 1); | |||
var ret=editPreviewTable(article, edits, reallyContribs, timeOffset); | |||
return ret; | |||
} | |||
function getTimeOffset(tz) { | |||
return ( tz && tz.indexOf(':') > -1 ) ? ( parseInt(tz,10)*60 + parseInt(tz.split(':')[1],10) ) : 0; | |||
} | |||
function editPreviewTable(article, h, reallyContribs, timeOffset) { | |||
var html=['<table>']; | |||
var day=null; | |||
var curart=article; | |||
for (var i=0; i<h.length; ++i) { | |||
if (reallyContribs) { var page=h[i]['*']; curart = new Title(page); } | |||
var minor=typeof h[i]['minor']=='undefined' ? '' : '<b>m </b>'; | |||
var editDate=adjustDate(getDateFromTimestamp(h[i].timestamp), timeOffset); | |||
var thisDay = dayFormat(editDate); | |||
var thisTime = timeFormat(editDate); | |||
if (thisDay==day) { thisDay=''; } | |||
else { day=thisDay; } | |||
if (thisDay) { | |||
html.push( '<tr><td colspan=3><span class="popup_history_date">' + | |||
thisDay+'</span></td></tr>' ); | |||
} | |||
html.push('<tr class="popup_history_row_' + ( (i%2) ? 'odd' : 'even') + '">'); | |||
html.push('<td>(<a href="' + pg.wiki.titlebase + new Title(curart).urlString() + | |||
'&diff=prev&oldid=' + h[i]['revid'] + '">' + popupString('last') + '</a>)</td>'); | |||
html.push('<td>' + | |||
'<a href="' + pg.wiki.titlebase + new Title(curart).urlString() + | |||
'&oldid=' + h[i]['revid'] + '">' + thisTime + '</a></td>'); | |||
var col3url='', col3txt=''; | var col3url='', col3txt=''; | ||
if (!reallyContribs) { | if (!reallyContribs) { | ||
var user=h[i]['user']; | var user=h[i]['user']; | ||
col3url=pg.wiki.titlebase + pg.ns.user + ':' + new Title(user).urlString(); | col3url=pg.wiki.titlebase + pg.ns.user + ':' + new Title(user).urlString(); | ||
col3txt= | col3txt=user; | ||
} else { | } else { | ||
col3url=pg.wiki.titlebase + curart.urlString(); | col3url=pg.wiki.titlebase + curart.urlString(); | ||
col3txt= | col3txt=page; // FIXME do we have to escape this? | ||
} | } | ||
html.push('<td>' + (reallyContribs ? minor : '') + | html.push('<td>' + (reallyContribs ? minor : '') + | ||
| Строка 4381: | Строка 4380: | ||
return html.join(''); | return html.join(''); | ||
} | } | ||
function getDateFromTimestamp(t) { | function getDateFromTimestamp(t) { | ||
var s=t.split(/[^0-9]/); | var s=t.split(/[^0-9]/); | ||
| Строка 4395: | Строка 4394: | ||
} | } | ||
} | } | ||
function adjustDate(d, offset) { | function adjustDate(d, offset) { | ||
// offset is in minutes | // offset is in minutes | ||
| Строка 4401: | Строка 4400: | ||
return new Date( +d + o); | return new Date( +d + o); | ||
} | } | ||
function dayFormat(editDate, utc) { | function dayFormat(editDate, utc) { | ||
if (utc) { return map(zeroFill, [editDate.getUTCFullYear(), editDate.getUTCMonth()+1, editDate.getUTCDate()]).join('-'); } | if (utc) { return map(zeroFill, [editDate.getUTCFullYear(), editDate.getUTCMonth()+1, editDate.getUTCDate()]).join('-'); } | ||
return map(zeroFill, [editDate.getFullYear(), editDate.getMonth()+1, editDate.getDate()]).join('-'); | return map(zeroFill, [editDate.getFullYear(), editDate.getMonth()+1, editDate.getDate()]).join('-'); | ||
} | } | ||
function timeFormat(editDate, utc) { | function timeFormat(editDate, utc) { | ||
if (utc) { return map(zeroFill, [editDate.getUTCHours(), editDate.getUTCMinutes(), editDate.getUTCSeconds()]).join(':'); } | if (utc) { return map(zeroFill, [editDate.getUTCHours(), editDate.getUTCMinutes(), editDate.getUTCSeconds()]).join(':'); } | ||
return map(zeroFill, [editDate.getHours(), editDate.getMinutes(), editDate.getSeconds()]).join(':'); | return map(zeroFill, [editDate.getHours(), editDate.getMinutes(), editDate.getSeconds()]).join(':'); | ||
} | } | ||
//</NOLITE> | |||
// ENDFILE: querypreview.js | |||
// STARTFILE: debug.js | |||
//////////////////////////////////////////////////////////////////// | |||
// Debugging functions | |||
//////////////////////////////////////////////////////////////////// | |||
function log(){}; // dummy to stop errors | |||
function setupDebugging() { | |||
//<NOLITE> | |||
// debugging - change DEBUG to NONE to switch off | |||
if (window.popupDebug) { // popupDebug is set from .version | |||
window.log=function(x) { //if(gMsg!='')gMsg += '\n'; gMsg+=time() + ' ' + x; }; | |||
if (pg.debugLevel != log.None) { window.logger.debug(x); } | |||
} | |||
window.errlog=function(x) { | |||
if (pg.debugLevel != log.None) { window.logger.error(x); } | |||
} | |||
function | |||
} | } | ||
pg.debugLevel=Log.DEBUG; | |||
window.logger = new Log(pg.debugLevel, Log.popupLogger); | |||
log('Initializing logger'); | |||
} else { | |||
//</NOLITE> | |||
window.log = function(x) {}; | |||
window.errlog = function(x) {}; | |||
//<NOLITE> | |||
} | } | ||
//</NOLITE> | |||
} | } | ||
// ENDFILE: debug.js | |||
// STARTFILE: images.js | |||
//<NOLITE> | |||
// FIXME rewrite ALL of this | |||
// How the URLs for images in the popup come about | |||
// loadPreview | |||
// | | |||
// getWiki | |||
var | // |<----------------see other schematic for details | ||
if ( | // insertPreview (insertPreview = onComplete) | ||
// | | |||
// | insertPreview gets a wikiText fragment from | |||
// | the wikiText downloaded by getWiki | |||
// | | |||
// [wikiMarkupToAddressFragment] | |||
// | | |||
// | mouseOverWikiLink (gets an "address fragment", | |||
// | | no processing needed) | |||
// \->-*loadThisImage---<----loadImages | |||
// | | |||
var | // [image(Thumb)URL]-->--hopefully valid image urls | ||
// FIXME get rid of pg.idNumber | |||
function sequentialLoadThisImage (image) { | |||
if (!getValueOf('popupImages')) { return false; } | |||
if (!isValidImageName(image)) { return false; } | |||
var imageUrls=getImageUrls(image); | |||
if (!imageUrls) { return null; } | |||
} | var img=new Image(); | ||
img.isNew=true; | |||
img.pg.idNumber=pg.idNumber; | |||
img.counter=1; | |||
img.onload = function () { | |||
// clear status thingy | |||
} | setImageStatus(''); | ||
var i=findThis(imageUrls, this.src); | |||
var goodSrc=this.src; | |||
} | |||
var setPopupImage=function () { | |||
var popupImage=document.getElementById("popupImage"+this.pg.idNumber); | |||
if (popupImage && typeof popupImage.src != 'undefined') { | |||
clearInterval(pg.timer.image); | |||
function | popupImage.src=goodSrc; | ||
popupImage.width=getValueOf('popupImageSize'); | |||
popupImage.style.display='inline'; | |||
setPopupImageLink(image, pg.wiki.imageSources[i].wiki); | |||
return true; | |||
} else { return false; } | |||
}; | |||
pg.timer.image=setInterval(setPopupImage, 250); | |||
pg.cache.images.push(goodSrc); | |||
}; | |||
img.onerror = function () { | |||
pg.cache.badImageUrls.push(this.src); | |||
}; | |||
img.setNext = function () { | |||
var currentSrc=null; | |||
var newSrc; | |||
if (!this.isNew) { currentSrc=this.src; } | |||
this.isNew=false; | |||
newSrc= (currentSrc) ? nextOne(imageUrls, currentSrc) : imageUrls[0]; | |||
while (findThis(pg.cache.badImageUrls, newSrc)) { | |||
newSrc=nextOne(imageUrls, newSrc); | |||
if (!newSrc) { | |||
setImageStatus (' :-('); | |||
return; | |||
} | |||
} | |||
setImageStatus(' '+findThis(imageUrls, newSrc)); | |||
this.src=newSrc; | |||
}; | |||
// start the ball rolling | |||
img.setNext(); | |||
} | } | ||
function | function loadThisImageAtThisUrl(image, url) { | ||
log('loading "best" image:\n'+url); | |||
pg.misc.gImage=new Title(image.toString()); | |||
pg.misc.imageArray = []; | |||
pg.misc.imageArray[0] = new Image(); | |||
pg.misc.imageArray[0].src=url; | |||
if (pg.timer.image || pg.timer.image===0) { | |||
clearInterval(pg.timer.image); | |||
pg.counter.checkImages=0; | |||
if ( | |||
} | } | ||
pg.timer.image=setInterval(checkImages, 250); | |||
return; | |||
} | } | ||
// methinks this is unbelievably silly | |||
// it dovetails with the parallel image loader function | |||
// | function checkImages() { | ||
// | //log('checkImages: pg.counter.loop='+pg.counter.loop+'; pg.counter.checkImages='+pg.counter.checkImages); | ||
if (pg.timer.checkImages || pg.timer.checkImages===0) { | |||
clearInterval(pg.timer.checkImages); | |||
pg.timer.checkImages=null; | |||
if (pg.counter.loop > 10) {pg.counter.loop=0; log('too many iterations of checkImages'); return;} | |||
pg.counter.loop++; | |||
// | } else pg.counter.checkImages++; | ||
var status = ( pg.counter.checkImages % 2 ) ? ':' : '.' ; | |||
setImageStatus(status); | |||
if (pg.counter.checkImages > 100) { | |||
pg.counter.checkImages = 0; | |||
log ('pg.counter.checkImages too big in checkImages; returning'); | |||
clearInterval(pg.timer.image); | |||
} | |||
var popupImage=null; | |||
popupImage=document.getElementById("popupImg"+pg.idNumber); | |||
if (popupImage == null) { | |||
// this doesn't seem to happen any more in practise for some reason | |||
// still, I'll leave it in | |||
log('checkImages: document.getElementById("popupImg'+pg.idNumber+'") is null! retrying in 333ms...'); | |||
pg.timer.checkImages=setInterval("checkImages()",333); | |||
return; | |||
var | } | ||
log('checkImages: found element popupImg'+pg.idNumber+', and src='+popupImage.src); | |||
// get the first image to successfully load | |||
// and put it in the popupImage | |||
for(var i = 0; i < pg.misc.imageArray.length; ++i) { | |||
if(isImageOk(pg.misc.imageArray[i])) { | |||
// stop all the gubbins, assign the image and return | |||
// | |||
log('checkImages: got at pos '+i+', src='+pg.misc.imageArray[i].src); | |||
clearInterval(pg.timer.image); | |||
if(pg.misc.gImage && pg.misc.gImage.namespace() == pg.ns.image) { | |||
popupImage.src=pg.misc.imageArray[i].src; | |||
popupImage.width=getValueOf('popupImageSize'); | |||
popupImage.style.display='inline'; | |||
if ( | // should we check to see if it's already there? maybe... | ||
pg.cache.images.push(pg.misc.imageArray[i].src); | |||
popupImage.src= | |||
popupImage.width=getValueOf('popupImageSize'); | setPopupImageLink(pg.misc.gImage, pg.wiki.imageSources[i].wiki); | ||
popupImage.style.display='inline'; | stopImagesDownloading(); | ||
} | } | ||
setImageStatus(''); | |||
// reset evil nonconstant globals | |||
delete pg.misc.imageArray; pg.misc.imageArray=[]; | |||
pg.timer.image=null; | |||
pg.counter.checkImages=0; | |||
pg.counter.loop=0; | |||
return popupImage.src; | |||
} | } | ||
} | |||
log('checkImages: no good image found. retrying in a tic...'); | |||
pg.timer.checkImages=setInterval("checkImages()",333); | |||
} | } | ||
function | function stopImagesDownloading() { | ||
pg.misc.gImage=null; | |||
if (pg.misc.imageArray == null) { return null; } | |||
for (var i=0; i<pg.misc.imageArray.length; ++i) { | |||
//pg.misc.imageArray[i].src=''; // this is a REALLY BAD IDEA | |||
delete pg.misc.imageArray[i]; | |||
//pg.misc.imageArray[i] = new Image(); | |||
} | |||
pg.misc.imageArray = []; | pg.misc.imageArray = []; | ||
} | |||
pg. | |||
if (pg. | function toggleSize() { | ||
var imgContainer=this; | |||
if (!imgContainer) { alert('imgContainer is null :/'); return;} | |||
img=imgContainer.firstChild; | |||
if (!img) { alert('img is null :/'); return;} | |||
if (!img.style.width || img.style.width=='') { img.style.width='100%'; } | |||
else { img.style.width=''; } | |||
} | |||
function setPopupImageLink (img, wiki) { | |||
if( wiki === null || img === null ) { return null; } | |||
var a=document.getElementById("popupImageLink"+pg.idNumber); | |||
if (a === null) { return null; } | |||
switch (getValueOf('popupThumbAction')) { | |||
case 'imagepage': | |||
if (pg.current.article.namespace()!=pg.ns.image) { | |||
a.href=pg.wiki.titlebase + img.urlString(); | |||
// FIXME: unreliable pg.idNumber | |||
popTipsSoonFn('popupImage' + pg.idNumber)(); | |||
break; | |||
} // else fall through | |||
case 'sizetoggle': | |||
a.onclick=toggleSize; | |||
a.title=popupString('Toggle image size'); | |||
return; | |||
case 'linkfull': | |||
var linkURL = imageURL(img, wiki); | |||
if (linkURL) { | |||
a.href = linkURL; | |||
a.title=popupString('Open full-size image'); | |||
} | |||
return; | |||
} | } | ||
} | } | ||
function isImageOk(img) { | |||
// | // IE test | ||
if (!img.complete) { return false; } | |||
// | |||
if ( | // gecko test | ||
if (typeof img.naturalWidth != "undefined" && img.naturalWidth == 0) { return false; } | |||
// test for konqueror and opera | |||
// note that img.width must not be defined in the html with a width="..." | |||
// for this to work. | |||
// konq seems to give "broken images" width 16, presumably an icon width | |||
// this test would probably work in gecko too, *except for very small images* | |||
if (typeof img.width == 'undefined' || img.width <= 16) { return false; } | |||
// No other way of checking: assume it's ok. | |||
return true; | |||
} | |||
// those odd a/a5/ bits of image urls | |||
function imagePathComponent(article) { // article is string, no namespace | |||
// FIXME needs testing with odd characters | |||
var forhash=article.split(' ').join('_'); | |||
var hash=hex_md5(forhash); | |||
return hash.substring(0,1) + '/' + hash.substring(0,2) + '/'; | |||
} | |||
function getImageUrlStart(wiki) { // this returns a trailing slash | |||
switch (wiki) { | |||
case 'en.wikipedia.org': return 'http://upload.wikimedia.org/wikipedia/en/'; | |||
case pg.wiki.commons: return 'http://upload.wikimedia.org/wikipedia/commons/'; | |||
case 'en.wiktionary.org': return 'http://en.wiktionary.org/upload/en/'; | |||
case 'secure.wikimedia.org': | |||
return joinPath(['http://upload.wikimedia.org', pg.wiki.prePath]) + '/'; break; | |||
default: // unsupported - take a guess | |||
if (pg.wiki.wikimedia) { | |||
return 'http://upload.wikimedia.org/wikipedia/' + pg.wiki.lang +'/'; | |||
} | |||
/* this should work for wikicities */ | |||
return 'http://' + wiki + '/images/'; | |||
} | } | ||
} | } | ||
function | function imageURL(img, wiki) { | ||
pg. | if (getValueOf('popupImagesFromThisWikiOnly') && wiki != pg.wiki.hostname) return null; | ||
if (pg. | var imgurl=null; | ||
for (var i=0; i<pg. | var pathcpt = imagePathComponent(img.stripNamespace()); | ||
imgurl=getImageUrlStart(wiki) + pathcpt + img.stripNamespace().split(' ').join('_'); | |||
return imgurl; | |||
} | |||
function imageThumbURL(img, wiki, width) { | |||
// | |||
// eg http://upload.wikimedia.org/wikipedia/en/thumb/6/61/ | |||
// Rubiks_cube_solved.jpg/120px-Rubiks_cube_solved.jpg | |||
// ^^^^^^^^^^^^^^^^^^^^^^^ | |||
// wikicities omits this bit | |||
// AND wikicities needs a new pathcpt for each filename including thumbs | |||
if (getValueOf('popupImagesFromThisWikiOnly') && wiki != pg.wiki.hostname) return null; | |||
if (getValueOf('popupNeverGetThumbs')) return null; | |||
var imgurl=null; | |||
var stripped=img.stripNamespace(); | |||
var pathcpt; | |||
if (pg.wiki.wikimedia) pathcpt = imagePathComponent(stripped); | |||
else pathcpt = imagePathComponent(width+'px-'+stripped); | |||
imgurl=getImageUrlStart(wiki) + "thumb/" + pathcpt; | |||
if (pg.wiki.wikimedia) imgurl += stripped + '/'; | |||
imgurl += width +"px-" + stripped; | |||
return imgurl; | |||
} | |||
function loadImages(image) { | |||
if (typeof image.stripNamespace != 'function') { alert('loadImages bad'); } | |||
if (getValueOf('popupLoadImagesSequentially')) { return sequentialLoadThisImage(image); } | |||
return parallelLoadThisImage(image); | |||
} | |||
function getImageUrls(image) { | |||
if (typeof image.stripNamespace != 'function') { alert('getImageUrls bad'); } | |||
var imageUrls=[]; | |||
for (var i=0; i<pg.wiki.imageSources.length; ++i) { | |||
var url; | |||
if (pg.wiki.imageSources[i].thumb) { | |||
url=imageThumbURL(image, pg.wiki.imageSources[i].wiki, pg.wiki.imageSources[i].width); | |||
} else { url=imageURL(image, pg.wiki.imageSources[i].wiki); } | |||
for (var j=0; j<pg.cache.images.length; ++j) { | |||
if (url == pg.cache.images[j]) { | |||
loadThisImageAtThisUrl(image, url); | |||
return null; | |||
} | |||
} | |||
if (url!=null) imageUrls.push(url); | |||
} | } | ||
return imageUrls; | |||
} | } | ||
function | |||
// this is probably very wasteful indeed of bandwidth | |||
if (! | // hey ho | ||
if (! | function parallelLoadThisImage (image) { | ||
if (! | if (typeof image.stripNamespace != 'function') { alert('parallelLoadThisImage bad'); } | ||
if (!getValueOf('popupImages')) return; | |||
if (!isValidImageName(image)) return false; | |||
var imageUrls=getImageUrls(image); | |||
if (!imageUrls) return null; | |||
var | for (var i=0; i<imageUrls.length; ++i) { | ||
if ( | var url = imageUrls[i]; | ||
pg.misc.imageArray[i]=new Image(); | |||
pg.misc.imageArray[i].src=url; | |||
} | |||
if (pg.timer.image != null) { | |||
clearInterval(pg.timer.image); | |||
pg.counter.checkImages=0; | |||
} | } | ||
pg.misc.gImage=new Title(image.toString()); | |||
pg.timer.image=setInterval("checkImages()", 250); | |||
return true; | return true; | ||
} | } | ||
function getValidImageFromWikiText(wikiText) { | |||
function | var imagePage=null; | ||
// | // nb in pg.re.image we're interested in the second bracketed expression | ||
var | // this may change if the regex changes :-( | ||
var | //var match=pg.re.image.exec(wikiText); | ||
var matched=null; | |||
var match; | |||
// strip html comments, used by evil bots :-( | |||
var t = removeMatchesUnless(wikiText, RegExp('(<!--[\\s\\S]*?-->)'), 1, | |||
RegExp('^<!--[^[]*popup', 'i')); | |||
while ( match = pg.re.image.exec(t) ) { | |||
// now find a sane image name - exclude templates by seeking { | |||
var m = match[2] || match[6]; | |||
var pxWidth=match[4]; | |||
if ( isValidImageName(m) && | |||
(!pxWidth || parseInt(pxWidth,10) >= getValueOf('popupMinImageWidth')) ) { | |||
matched=m; | |||
break; | |||
} | } | ||
} | } | ||
pg.re.image.lastIndex=0; | |||
if (!matched) { return null; } | |||
return pg.ns.image+':'+upcaseFirst(matched); | |||
} | } | ||
function | function removeMatchesUnless(str, re1, parencount, re2) { | ||
var split=str.parenSplit(re1); | |||
var c=parencount + 1; | |||
for (var i=0; i<split.length; ++i) { | |||
if ( i%c === 0 || re2.test(split[i]) ) { continue; } | |||
split[i]=''; | |||
} | |||
return split.join(''); | |||
} | } | ||
//</NOLITE> | |||
// ENDFILE: images.js | |||
// STARTFILE: namespaces.js | |||
// Set up namespaces and other non-strings.js localization | |||
// (currently that means redirs too) | |||
// Put the right namespace list into pg.ns.list, based on pg.wiki.lang | |||
// Default to english if nothing seems to fit | |||
function setNamespaceList() { | |||
var m="Media"; | |||
var list = [m, "Special", "Talk", "User", "User talk", "Wikipedia", "Wikipedia talk", "Image", "Image talk", "MediaWiki", "MediaWiki talk", "Template", "Template talk", "Help", "Help talk", "Category", "Category talk", "Portal", "Portal talk"]; | |||
var | var nsIndex = { '': 0, 'Special': 1, | ||
var | 'Talk': 2, 'User': 3, 'User talk': 4, 'Wikipedia': 5, | ||
'Wikipedia talk': 6, 'Image': 7, 'Image talk': 8, 'MediaWiki': 9, | |||
'MediaWiki talk': 10, 'Template': 11, 'Template talk': 12, | |||
'Help': 13, 'Help talk': 14, 'Category': 15, 'Category talk':16, | |||
'Portal': 17, 'Portal talk': 18}; | |||
var nsLists = { | |||
//<NOLITE> | |||
"af": [m, "Spesiaal", "Bespreking", "Gebruiker", "Gebruikerbespreking", "Wikipedia", "Wikipediabespreking", "Beeld", "Beeldbespreking", "MediaWiki", "MediaWikibespreking", "Sjabloon", "Sjabloonbespreking", "Hulp", "Hulpbespreking", "Kategorie", "Kategoriebespreking"], | |||
"als": [m, "Spezial", "Diskussion", "Benutzer", "Benutzer Diskussion", "Wikipedia", "Wikipedia Diskussion", "Bild", "Bild Diskussion", "MediaWiki", "MediaWiki Diskussion", "Vorlage", "Vorlage Diskussion", "Hilfe", "Hilfe Diskussion", "Kategorie", "Kategorie Diskussion"], | |||
"ar": ["ملف", "خاص", "نقاش", "مستخدم", "نقاش المستخدم", "ويكيبيديا", "نقاش ويكيبيديا", "صورة", "نقاش الصورة", "ميدياويكي", "نقاش ميدياويكي", "Template", "نقاش Template", "مساعدة", "نقاش المساعدة", "تصنيف", "نقاش التصنيف"], | |||
"ast": [m, "Especial", "Discusión", "Usuariu", "Usuariu discusión", "Uiquipedia", "Uiquipedia discusión", "Imaxen", "Imaxen discusión", "MediaWiki", "MediaWiki discusión", "Plantilla", "Plantilla discusión", "Ayuda", "Ayuda discusión", "Categoría", "Categoría discusión"], | |||
"be": ["Мэдыя", "Спэцыяльныя", "Абмеркаваньне", "Удзельнік", "Гутаркі ўдзельніка", "Вікіпэдыя", "Абмеркаваньне Вікіпэдыя", "Выява", "Абмеркаваньне выявы", "MediaWiki", "Абмеркаваньне MediaWiki", "Шаблён", "Абмеркаваньне шаблёну", "Дапамога", "Абмеркаваньне дапамогі", "Катэгорыя", "Абмеркаваньне катэгорыі"], | |||
"bg": ["Медия", "Специални", "Беседа", "Потребител", "Потребител беседа", "Уикипедия", "Уикипедия беседа", "Картинка", "Картинка беседа", "МедияУики", "МедияУики беседа", "Шаблон", "Шаблон беседа", "Помощ", "Помощ беседа", "Категория", "Категория беседа"], | |||
"bm": [m, "Special", "Discuter", "Utilisateur", "Discussion Utilisateur", "Wikipedia", "Discussion Wikipedia", "Image", "Discussion Image", "MediaWiki", "Discussion MediaWiki", "Modèle", "Discussion Modèle", "Aide", "Discussion Aide", "Catégorie", "Discussion Catégorie"], | |||
"bn": ["বিশেষ", "আলাপ", "ব্যবহারকারী", "ব্যবহারকারী আলাপ", "উইকিপেডিয়া", "উইকিপেডিয়া আলাপ", "চিত্র", "চিত্র আলাপ", "MediaWik i আলাপ", m, "MediaWiki", "Template", "Template talk", "Help", "Help talk", "Category", "Category talk"], | |||
"br": [m, "Dibar", "Kaozeal", "Implijer", "Kaozeadenn Implijer", "Wikipedia", "Kaozeadenn Wikipedia", "Skeudenn", "Kaozeadenn Skeudenn", "MediaWiki", "Kaozeadenn MediaWiki", "Patrom", "Kaozeadenn Patrom", "Skoazell", "Kaozeadenn Skoazell", "Rummad", "Kaozeadenn Rummad"], | |||
"ca": [m, "Especial", "Discussió", "Usuari", "Usuari Discussió", "Viquipèdia", "Viquipèdia Discussió", "Imatge", "Imatge Discussió", "MediaWiki", "MediaWiki Discussió", "Template", "Template Discussió", "Ajuda", "Ajuda Discussió", "Categoria", "Categoria Discussió"], | |||
"cs": ["Média", "Speciální", "Diskuse", "Wikipedista", "Wikipedista diskuse", "Wikipedie", "Wikipedie diskuse", "Soubor", "Soubor diskuse", "MediaWiki", "MediaWiki diskuse", "Šablona", "Šablona diskuse", "Nápověda", "Nápověda diskuse", "Kategorie", "Kategorie diskuse"], | |||
"csb": [m, "Specjalnô", "Diskùsëjô", "Brëkòwnik", "Diskùsëjô brëkòwnika", "Wiki", "Diskùsëjô Wiki", "Òbrôzk", "Diskùsëjô òbrôzków", "MediaWiki", "Diskùsëjô MediaWiki", "Szablóna", "Diskùsëjô Szablónë", "Pòmòc", "Diskùsëjô Pòmòcë", "Kategòrëjô", "Diskùsëjô Kategòrëji"], | |||
"cv": ["Медиа", "Ятарлă", "Сӳтсе явасси", "Хутшăнакан", "Хутшăнаканăн канашлу страници", "Wikipedia", "0", "Ӳкерчĕк", "Ӳкерчĕке сӳтсе явмалли", "MediaWiki", "MediaWiki сӳтсе явмалли", "Шаблон", "Шаблона сӳтсе явмалли", "Пулăшу", "Пулăшăва сӳтсе явмалли", "Категори", "Категорине сӳтсе явмалли"], | |||
"cy": [m, "Arbennig", "Sgwrs", "Defnyddiwr", "Sgwrs Defnyddiwr", "Wicipedia", "Sgwrs Wicipedia", "Delwedd", "Sgwrs Delwedd", "MediaWiki", "Sgwrs MediaWiki", "Nodyn", "Sgwrs Nodyn", "Help", "Help talk", "Category", "Category talk"], | |||
"da": [m, "Speciel", "Diskussion", "Bruger", "Brugerdiskussion", "Wikipedia", "Wikipedia-diskussion", "Billede", "Billeddiskussion", "MediaWiki", "MediaWiki-diskussion", "Skabelon", "Skabelondiskussion", "Hjælp", "Hjælpdiskussion", "Kategori", "Kategoridiskussion", "Portal", "Portaldiskussion"], | |||
"de": [m, "Spezial", "Diskussion", "Benutzer", "Benutzer Diskussion", "Wikipedia", "Wikipedia Diskussion", "Bild", "Bild Diskussion", "MediaWiki", "MediaWiki Diskussion", "Vorlage", "Vorlage Diskussion", "Hilfe", "Hilfe Diskussion", "Kategorie", "Kategorie Diskussion", "Portal", "Portal Diskussion"], | |||
"el": ["Μέσον", "Ειδικό", "Συζήτηση", "Χρήστης", "Συζήτηση χρήστη", "Βικιπαίδεια", "Βικιπαίδεια συζήτηση", "Εικόνα", "Συζήτηση εικόνας", "MediaWiki", "MediaWiki talk", "Πρότυπο", "Συζήτηση προτύπου", "Βοήθεια", "Συζήτηση βοήθειας", "Κατηγορία", "Συζήτηση κατηγορίας"], | |||
"eo": [m, "Speciala", "Diskuto", "Vikipediisto", "Vikipediista diskuto", "Vikipedio", "Vikipedio diskuto", "Dosiero", "Dosiera diskuto", "MediaWiki", "MediaWiki diskuto", "Ŝablono", "Ŝablona diskuto", "Helpo", "Helpa diskuto", "Kategorio", "Kategoria diskuto"], | |||
"es": [m, "Especial", "Discusión", "Usuario", "Usuario Discusión", "Wikipedia", "Wikipedia Discusión", "Imagen", "Imagen Discusión", "MediaWiki", "MediaWiki Discusión", "Plantilla", "Plantilla Discusión", "Ayuda", "Ayuda Discusión", "Categoría", "Categoría Discusión"], | |||
"et": ["Meedia", "Eri", "Arutelu", "Kasutaja", "Kasutaja arutelu", "Vikipeedia", "Vikipeedia arutelu", "Pilt", "Pildi arutelu", "MediaWiki", "MediaWiki arutelu", "Mall", "Malli arutelu", "Juhend", "Juhendi arutelu", "Kategooria", "Kategooria arutelu"], | |||
"eu": [m, "Aparteko", "Eztabaida", "Lankide", "Lankide eztabaida", "Wikipedia", "Wikipedia eztabaida", "Irudi", "Irudi eztabaida", "MediaWiki", "MediaWiki eztabaida", "Template", "Template talk", "Help", "Help talk", "Category", "Category talk"], | |||
"fa": ["مدیا", "ویژه", "بحث", "کاربر", "بحث کاربر", "ویکیپدیا", "بحث ویکیپدیا", "تصویر", "بحث تصویر", "مدیاویکی", "بحث مدیاویکی", "الگو", "بحث الگو", "راهنما", "بحث راهنما", "رده", "بحث رده"], | |||
"fi": [m, "Toiminnot", "Keskustelu", "Käyttäjä", "Keskustelu käyttäjästä", "Wikipedia", "Keskustelu Wikipediasta", "Kuva", "Keskustelu kuvasta", "MediaWiki", "MediaWiki talk", "Malline", "Keskustelu mallineesta", "Ohje", "Keskustelu ohjeesta", "Luokka", "Keskustelu luokasta"], | |||
"fo": ["Miðil", "Serstakur", "Kjak", "Brúkari", "Brúkari kjak", "Wikipedia", "Wikipedia kjak", "Mynd", "Mynd kjak", "MidiaWiki", "MidiaWiki kjak", "Fyrimynd", "Fyrimynd kjak", "Hjálp", "Hjálp kjak", "Bólkur", "Bólkur kjak"], | |||
"fr": [m, "Special", "Discuter", "Utilisateur", "Discussion Utilisateur", "Wikipédia", "Discussion Wikipédia", "Image", "Discussion Image", "MediaWiki", "Discussion MediaWiki", "Modèle", "Discussion Modèle", "Aide", "Discussion Aide", "Catégorie", "Discussion Catégorie", "Portail", "Discussion Portail"], | |||
"fur": [m, "Speciâl", "Discussion", "Utent", "Discussion utent", "Vichipedie", "Discussion Vichipedie", "Figure", "Discussion figure", "MediaWiki", "Discussion MediaWiki", "Model", "Discussion model", "Jutori", "Discussion jutori", "Categorie", "Discussion categorie"], | |||
"fy": [m, "Wiki", "Oerlis", "Meidogger", "Meidogger oerlis", "Wikipedy", "Wikipedy oerlis", "Ofbyld", "Ofbyld oerlis", "MediaWiki", "MediaWiki oerlis", "Berjocht", "Berjocht oerlis", "Hulp", "Hulp oerlis", "Kategory", "Kategory oerlis"], | |||
"ga": ["Meán", "Speisialta", "Plé", "Úsáideoir", "Plé úsáideora", "Vicipéid", "Plé Vicipéide", "Íomhá", "Plé íomhá", "MediaWiki", "Plé MediaWiki", "Teimpléad", "Plé teimpléid", "Cabhair", "Plé cabhrach", "Catagóir", "Plé catagóire"], | |||
"gu": [m, "Special", "Talk", "User", "User talk", "વિકિપીડિયા", "વિકિપીડિયા talk", "Image", "Image talk", "MediaWiki", "MediaWiki talk", "Template", "Template talk", "Help", "Help talk", "Category", "Category talk"], | |||
"he": [m, "מיוחד", "שיחה", "משתמש", "שיחת משתמש", "ויקיפדיה", "שיחת ויקיפדיה", "תמונה", "שיחת תמונה", "MediaWiki", "שיחת MediaWiki", "תבנית", "שיחת תבנית", "עזרה", "שיחת עזרה", "קטגוריה", "שיחת קטגוריה"], | |||
"hi": [m, "विशेष", "वार्ता", "सदस्य", "सदस्य वार्ता", "विकिपीडिया", "विकिपीडिया वार्ता", "चित्र", "चित्र वार्ता", "MediaWiki", "MediaWiki talk", "Template", "Template talk", "श्रेणी", "श्रेणी वार्ता", "Help", "Help talk"], | |||
"hr": ["Mediji", "Posebno", "Razgovor", "Suradnik", "Razgovor sa suradnikom", "Wikipedia", "Razgovor Wikipedia", "Slika", "Razgovor o slici", "MediaWiki", "MediaWiki razgovor", "Predložak", "Razgovor o predlošku", "Pomoć", "Razgovor o pomoći", "Kategorija", "Razgovor o kategoriji"], | |||
"hu": ["Média", "Speciális", "Vita", "User", "User vita", "Wikipédia", "Wikipédia vita", "Kép", "Kép vita", "MediaWiki", "MediaWiki vita", "Sablon", "Sablon vita", "Segítség", "Segítség vita", "Kategória", "Kategória vita"], | |||
"ia": [m, "Special", "Discussion", "Usator", "Discussion Usator", "Wikipedia", "Discussion Wikipedia", "Imagine", "Discussion Imagine", "MediaWiki", "Discussion MediaWiki", "Template", "Template talk", "Help", "Help talk", "Category", "Category talk"], | |||
"id": [m, "Istimewa", "Bicara", "Pengguna", "Bicara Pengguna", "Wikipedia", "Pembicaraan Wikipedia", "Gambar", "Pembicaraan Gambar", "MediaWiki", "Pembicaraan MediaWiki", "Templat", "Pembicaraan Templat", "Bantuan", "Pembicaraan Bantuan", "Kategori", "Pembicaraan Kategori"], | |||
"is": ["Miðill", "Kerfissíða", "Spjall", "Notandi", "Notandaspjall", "Wikipedia", "Wikipediaspjall", "Mynd", "Myndaspjall", "Melding", "Meldingarspjall", "Snið", "Sniðaspjall", "Hjálp", "Hjálparspjall", "Flokkur", "Flokkaspjall"], | |||
"it": [m, "Speciale", "Discussione", "Utente", "Discussioni utente", "Wikipedia", "Discussioni Wikipedia", "Immagine", "Discussioni immagine", "MediaWiki", "Discussioni MediaWiki", "Template", "Discussioni template", "Aiuto", "Discussioni aiuto", "Categoria", "Discussioni categoria"], | |||
"ja": [m, "特別", "ノート", "利用者", "利用者‐会話", "Wikipedia", "Wikipedia‐ノート", "画像", "画像‐ノート", "MediaWiki", "MediaWiki‐ノート", "Template", "Template‐ノート", "Help", "Help‐ノート", "Category", "Category‐ノート"], | |||
"ka": ["მედია", "სპეციალური", "განხილვა", "მომხმარებელი", "მომხმარებელი განხილვა", "ვიკიპედია", "ვიკიპედია განხილვა", "სურათი", "სურათი განხილვა", "მედიავიკი", "მედიავიკი განხილვა", "თარგი", "თარგი განხილვა", "დახმარება", "დახმარება განხილვა", "კატეგორია", "კატეგორია განხილვა"], | |||
"ko": [m, "특수기능", "토론", "사용자", "사용자토론", "위키백과", "위키백과토론", "그림", "그림토론", "분류", "분류토론", "MediaWiki", "MediaWiki talk", "Template", "Template talk", "Help", "Help talk"], | |||
"ku": ["Medya", "Taybet", "Nîqaş", "Bikarhêner", "Bikarhêner nîqaş", "Wîkîpediya", "Wîkîpediya nîqaş", "Wêne", "Wêne nîqaş", "MediaWiki", "MediaWiki nîqaş", "Şablon", "Şablon nîqaş", "Alîkarî", "Alîkarî nîqaş", "Kategorî", "Kategorî nîqaş"], | |||
"la": ["Specialis", "Disputatio", "Usor", "Disputatio Usoris", "Vicipaedia", "Disputatio Vicipaediae", "Imago", "Disputatio Imaginis", "MediaWiki", "Disputatio MediaWiki", "Formula", "Disputatio Formulae", "Auxilium", "Disputatio Auxilii", "Categoria", "Disputatio Categoriae", m], | |||
"li": [m, "Speciaal", "Euverlik", "Gebroeker", "Euverlik gebroeker", "Wikipedia", "Euverlik Wikipedia", "Aafbeilding", "Euverlik afbeelding", "MediaWiki", "Euverlik MediaWiki", "Sjabloon", "Euverlik sjabloon", "Help", "Euverlik help", "Kategorie", "Euverlik kategorie"], | |||
"lt": ["Medija", "Specialus", "Aptarimas", "Naudotojas", "Naudotojo aptarimas", "Wikipedia", "Wikipedia aptarimas", "Vaizdas", "Vaizdo aptarimas", "MediaWiki", "MediaWiki aptarimas", "Šablonas", "Šablono aptarimas", "Pagalba", "Pagalbos aptarimas", "Kategorija", "Kategorijos aptarimas"], | |||
"mk": ["Медија", "Специјални", "Разговор", "Корисник", "Корисник разговор", "Wikipedia", "Wikipedia разговор", "Слика", "Слика разговор", "МедијаВики", "МедијаВики разговор", "Шаблон", "Шаблон разговор", "Помош", "Помош разговор", "Категорија", "Категорија разговор"], | |||
"ms": [m, "Istimewa", "Perbualan", "Pengguna", "Perbualan Pengguna", "Wikipedia", "Perbualan Wikipedia", "Imej", "Imej Perbualan", "MediaWiki", "MediaWiki Perbualan", "Template", "Template talk", "Help", "Help talk", "Category", "Category talk"], | |||
"mt": [m, "Special", "Talk", "User", "User talk", "Wikipedija", "Wikipedija talk", "Image", "Image talk", "MediaWiki", "MediaWiki talk", "Template", "Template talk", "Help", "Help talk", "Category", "Category talk"], | |||
"nap": [m, "Speciale", "Discussione", "Utente", "Discussioni utente", "Wikipedia", "Discussioni Wikipedia", "Immagine", "Discussioni immagine", "MediaWiki", "Discussioni MediaWiki", "Template", "Discussioni template", "Aiuto", "Discussioni aiuto", "Categoria", "Discussioni categoria"], | |||
"nds": [m, "Spezial", "Diskuschoon", "Bruker", "Bruker Diskuschoon", "Wikipedia", "Wikipedia Diskuschoon", "Bild", "Bild Diskuschoon", "MediaWiki", "MediaWiki Diskuschoon", "Vörlaag", "Vörlaag Diskuschoon", "Hülp", "Hülp Diskuschoon", "Kategorie", "Kategorie Diskuschoon"], | |||
"nl": [m, "Speciaal", "Overleg", "Gebruiker", "Overleg gebruiker", "Wikipedia", "Overleg Wikipedia", "Afbeelding", "Overleg afbeelding", "MediaWiki", "Overleg MediaWiki", "Sjabloon", "Overleg sjabloon", "Help", "Overleg help", "Categorie", "Overleg categorie"], | |||
pg. | "nn": ["Filpeikar", "Spesial", "Diskusjon", "Brukar", "Brukardiskusjon", "Wikipedia", "Wikipedia-diskusjon", "Fil", "Fildiskusjon", "MediaWiki", "MediaWiki-diskusjon", "Mal", "Maldiskusjon", "Hjelp", "Hjelpdiskusjon", "Kategori", "Kategoridiskusjon"], | ||
"no": ["Medium", "Spesial", "Diskusjon", "Bruker", "Brukerdiskusjon", "Wikipedia", "Wikipedia-diskusjon", "Bilde", "Bildediskusjon", "MediaWiki", "MediaWiki-diskusjon", "Mal", "Maldiskusjon", "Hjelp", "Hjelpdiskusjon", "Kategori", "Kategoridiskusjon"], | |||
"nv": [m, "Special", "Naaltsoos baa yinísht'į́", "Choinish'įįhí", "Choinish'įįhí baa yinísht'į́", "Wikiibíídiiya", "Wikiibíídiiya baa yinísht'į́", "E'elyaaígíí", "E'elyaaígíí baa yinísht'į́", "MediaWiki", "MediaWiki baa yinísht'į́", "Template", "Template talk", "Aná'álwo'", "Aná'álwo' baa yinísht'į́", "T'ááłáhági át'éego", "T'ááłáhági át'éego baa yinísht'į́"], | |||
"oc": ["Especial", "Discutir", "Utilisator", "Discutida Utilisator", "Oiquipedià", "Discutida Oiquipedià", "Image", "Discutida Image", "MediaWiki", "MediaWiki talk", "Template", "Template talk", m, "Help", "Help talk", "Category", "Category talk"], | |||
"os": [m, "Сæрмагонд", "Дискусси", "Архайæг", "Архайæджы дискусси", "Wikipedia", "0", "Ныв", "Нывы тыххæй дискусси", "MediaWiki", "Дискусси MediaWiki", "Шаблон", "Шаблоны тыххæй дискусси", "Æххуыс", "Æххуысы тыххæй дискусси", "Категори", "Категорийы тыххæй дискусси"], | |||
"pa": ["ਮੀਡੀਆ", "ਖਾਸ", "ਚਰਚਾ", "ਮੈਂਬਰ", "ਮੈਂਬਰ ਚਰਚਾ", "Wikipedia", "Wikipedia ਚਰਚਾ", "ਤਸਵੀਰ", "ਤਸਵੀਰ ਚਰਚਾ", "ਮੀਡੀਆਵਿਕਿ", "ਮੀਡੀਆਵਿਕਿ ਚਰਚਾ", "ਨਮੂਨਾ", "ਨਮੂਨਾ ਚਰਚਾ", "ਮਦਦ", "ਮਦਦ ਚਰਚਾ", "ਸ਼੍ਰੇਣੀ", "ਸ਼੍ਰੇਣੀ ਚਰਚਾ"], | |||
"pl": [m, "Specjalna", "Dyskusja", "Wikipedysta", "Dyskusja Wikipedysty", "Wikipedia", "Dyskusja Wikipedii", "Grafika", "Dyskusja grafiki", "MediaWiki", "Dyskusja MediaWiki", "Szablon", "Dyskusja szablonu", "Pomoc", "Dyskusja pomocy", "Kategoria", "Dyskusja kategorii", "Portal", "Dyskusja portalu"], | |||
"pt": [m, "Especial", "Discussão", "Usuário", "Usuário Discussão", "Wikipedia", "Wikipedia Discussão", "Imagem", "Imagem Discussão", "MediaWiki", "MediaWiki Discussão", "Predefinição", "Predefinição Discussão", "Ajuda", "Ajuda Discussão", "Categoria", "Categoria Discussão"], | |||
"ro": [m, "Special", "Discuţie", "Utilizator", "Discuţie Utilizator", "Wikipedia", "Discuţie Wikipedia", "Imagine", "Discuţie Imagine", "MediaWiki", "Discuţie MediaWiki", "Format", "Discuţie Format", "Ajutor", "Discuţie Ajutor", "Categorie", "Discuţie Categorie"], | |||
"ru": ["Медиа", "Служебная", "Обсуждение", "Участник", "Обсуждение участника", "Википедия", "Обсуждение Википедии", "Изображение", "Обсуждение изображения", "MediaWiki", "Обсуждение MediaWiki", "Шаблон", "Обсуждение шаблона", "Справка", "Обсуждение справки", "Категория", "Обсуждение категории"], | |||
"sc": ["Speciale", "Contièndha", "Utente", "Utente discussioni", "Wikipedia", "Wikipedia discussioni", "Immàgini", "Immàgini contièndha", m, "MediaWiki", "MediaWiki talk", "Template", "Template talk", "Help", "Help talk", "Category", "Category talk"], | |||
"sk": ["Médiá", "Špeciálne", "Diskusia", "Redaktor", "Diskusia s redaktorom", "Wikipédia", "Diskusia k Wikipédii", "Obrázok", "Diskusia k obrázku", "MediaWiki", "Diskusia k MediaWiki", "Šablóna", "Diskusia k šablóne", "Pomoc", "Diskusia k pomoci", "Kategória", "Diskusia ku kategórii"], | |||
"sl": [m, "Posebno", "Pogovor", "Uporabnik", "Uporabniški pogovor", "Wikipedija", "Pogovor k Wikipediji", "Slika", "Pogovor k sliki", "MediaWiki", "MediaWiki talk", "Template", "Template talk", "Help", "Help talk", "Category", "Category talk"], | |||
"sq": [m, "Speciale", "Diskutim", "Përdoruesi", "Përdoruesi diskutim", "Wikipedia", "Wikipedia diskutim", "Figura", "Figura diskutim", "MediaWiki", "MediaWiki diskutim", "Stampa", "Stampa diskutim", "Ndihmë", "Ndihmë diskutim", "Category", "Category talk"], | |||
"sr": [m, "Посебно", "Разговор", "Корисник", "Разговор са корисником", "Википедија", "Разговор о Википедији", "Слика", "Разговор о слици", "МедијаВики", "Разговор о МедијаВикију", "Шаблон", "Разговор о шаблону", "Помоћ", "Разговор о помоћи", "Категорија", "Разговор о категорији", "Портал", "Разговор о порталу"], | |||
"sv": [m, "Special", "Diskussion", "Användare", "Användardiskussion", "Wikipedia", "Wikipediadiskussion", "Bild", "Bilddiskussion", "MediaWiki", "MediaWiki diskussion", "Mall", "Malldiskussion", "Hjälp", "Hjälp diskussion", "Kategori", "Kategoridiskussion"], | |||
"ta": ["ஊடகம்", "சிறப்பு", "பேச்சு", "பயனர்", "பயனர் பேச்சு", "Wikipedia", "Wikipedia பேச்சு", "படிமம்", "படிமப் பேச்சு", "மீடியாவிக்கி", "மீடியாவிக்கி பேச்சு", "வார்ப்புரு", "வார்ப்புரு பேச்சு", "உதவி", "உதவி பேச்சு", "பகுப்பு", "பகுப்பு பேச்சு"], | |||
"th": [m, "พิเศษ", "พูดคุย", "ผู้ใช้", "คุยเกี่ยวกับผู้ใช้", "Wikipedia", "Wikipedia talk", "ภาพ", "คุยเกี่ยวกับภาพ", "MediaWiki", "คุยเกี่ยวกับ MediaWiki", "Template", "Template talk", "Help", "Help talk", "Category", "Category talk"], | |||
"tlh": ["Doch", "le'", "ja'chuq", "lo'wI'", "lo'wI' ja'chuq", "wIqIpe'DIya", "wIqIpe'DIya ja'chuq", "nagh beQ", "nagh beQ ja'chuq", "MediaWiki", "MediaWiki ja'chuq", "chen'ay'", "chen'ay' ja'chuq", "QaH", "QaH ja'chuq", "Segh", "Segh ja'chuq"], | |||
"tr": [m, "Özel", "Tartışma", "Kullanıcı", "Kullanıcı mesaj", "Vikipedi", "Vikipedi tartışma", "Resim", "Resim tartışma", "MedyaViki", "MedyaViki tartışma", "Şablon", "Şablon tartışma", "Yardım", "Yardım tartışma", "Kategori", "Kategori tartışma"], | |||
"tt": [m, "Maxsus", "Bäxäs", "Äğzä", "Äğzä bäxäse", "Wikipedia", "Wikipedia bäxäse", "Räsem", "Räsem bäxäse", "MediaWiki", "MediaWiki bäxäse", "Ürnäk", "Ürnäk bäxäse", "Yärdäm", "Yärdäm bäxäse", "Törkem", "Törkem bäxäse"], | |||
"uk": ["Медіа", "Спеціальні", "Обговорення", "Користувач", "Обговорення користувача", "Wikipedia", "Обговорення Wikipedia", "Зображення", "Обговорення зображення", "MediaWiki", "Обговорення MediaWiki", "Шаблон", "Обговорення шаблону", "Довідка", "Обговорення довідки", "Категорія", "Обговорення категорії"], | |||
"vi": ["Phương tiện", "Đặc biệt", "Thảo luận", "Thành viên", "Thảo luận Thành viên", "Wikipedia", "Thảo luận Wikipedia", "Hình", "Thảo luận Hình", "MediaWiki", "Thảo luận MediaWiki", "Tiêu bản", "Thảo luận Tiêu bản", "Trợ giúp", "Thảo luận Trợ giúp", "Thể loại", "Thảo luận Thể loại"], | |||
"wa": [m, "Sipeciås", "Copene", "Uzeu", "Uzeu copene", "Wikipedia", "Wikipedia copene", "Imådje", "Imådje copene", "MediaWiki", "MediaWiki copene", "Modele", "Modele copene", "Aidance", "Aidance copene", "Categoreye", "Categoreye copene"] | |||
//</NOLITE> | |||
}; | |||
pg.ns.list = nsLists[pg.wiki.lang] || list; | |||
pg.ns.index = nsIndex; | |||
} | } | ||
function | function namespaceListToRegex(list) {return RegExp('^('+list.join('|').split(' ').join('[ _]')+'):');}; | ||
// function setNamespaceList is ugly as sin, moved to later in the code | |||
function setNamespaces() { | |||
setNamespaceList(); | |||
pg.ns.withTalkList=[null]; // NB root (article) corresponds with this entry, null | |||
pg.ns.talkList=[pg.ns.list[2]]; | |||
// | |||
var | // if the number of namespaces changes then this will have to be changed | ||
// maybe the easiest way is to specify the arrays by hand as in the comments following the loop | |||
for (var i=3; i+1<pg.ns.list.length; i=i+2) { | |||
pg.ns.withTalkList.push(pg.ns.list[i]); | |||
pg.ns.talkList.push(pg.ns.list[i+1]); | |||
} | } | ||
pg. | |||
// ALERT! SILLY HARDCODED VALUES FOLLOW! | |||
pg.ns.special = pg.ns.list[pg.ns.index.Special]; | |||
pg.ns.image = pg.ns.list[pg.ns.index.Image]; | |||
pg.ns.user = pg.ns.list[pg.ns.index.User]; | |||
pg.ns.usertalk = pg.ns.list[pg.ns.index['User talk']]; | |||
pg.ns.category = pg.ns.list[pg.ns.index.Category]; | |||
pg.ns.template = pg.ns.list[pg.ns.index.Template]; | |||
pg.ns.nonArticleList=pg.ns.list.slice(0,2).concat(pg.ns.list.slice(2)); | |||
} | } | ||
function | |||
function setRedirs() { | |||
var r='redirect'; | |||
var R='REDIRECT'; | |||
var redirLists={ | |||
//<NOLITE> | |||
'ar': [ R, 'تحويل' ], | |||
'be': [ r, 'перанакіраваньне' ], | |||
'bg': [ r, 'пренасочване', 'виж' ], | |||
'bs': [ r, 'Preusmjeri', 'preusmjeri', 'PREUSMJERI' ], | |||
//< | 'cs': [ R, 'PŘESMĚRUJ' ], | ||
'cy': [ r, 'ail-cyfeirio' ], | |||
'et': [ r, 'suuna' ], | |||
'ga': [ r, 'athsheoladh' ], | |||
'he': [ R, 'הפניה' ], | |||
'is': [ r, 'tilvísun', 'TILVÍSUN' ], | |||
'mk': [ r, 'пренасочување', 'види' ], | |||
'nds': [ r, 'wiederleiden' ], | |||
'nn': [ r, 'omdiriger' ], | |||
'pt': [ R, 'redir' ], | |||
'ru': [ R, 'ПЕРЕНАПРАВЛЕНИЕ', 'ПЕРЕНАПР' ], | |||
'sk': [ r, 'presmeruj' ], | |||
'sr': [ r, 'Преусмери', 'преусмери', 'ПРЕУСМЕРИ', 'Preusmeri', 'preusmeri', 'PREUSMERI' ], | |||
'tt': [ 'yünältü' ], | |||
'vi': [ r, 'đổi' ] // no comma | |||
//</NOLITE> | |||
}; | |||
var | var redirList=redirLists[ pg.wiki.lang ] || [r, R]; | ||
// Mediawiki is very tolerant about what comes after the #redirect at the start | |||
pg.re.redirect=RegExp('^\\s*[#](' + redirList.join('|') + ').*?\\[{2}([^\\|\\]]*)(|[^\\]]*)?\\]{2}\\s*(.*)', 'i'); | |||
} | |||
function setInterwiki() { | |||
if (pg.wiki.wikimedia) { | |||
pg.wiki.interwiki='aa|ab|af|ak|als|am|an|ang|ar|arc|as|ast|av|ay|az|ba|be|ber|bg|bh|bi|bm|bn|bdf|bo|br|bs|ca|ce|ceb|ch|cho|chr|chy|co|commons|cr|cs|csb|cu|cv|cy|da|de|dv|dz|el|en|eo|es|et|eu|fa|ff|fi|fiu-vro|fj|fo|fr|fur|fy|ga|gd|gil|gl|gn|got|gu|gv|ha|haw|he|hi|ho|hr|ht|hu|hy|hz|ia|id|ie|ig|ii|ik|io|is|it|iu|ja|jbo|jv|ka|kg|ki|kj|kk|kl|km|kn|ko|kr|ks|ku|kv|kw|ky|la|lad|lan|lb|lg|li|ln|lo|lt|lu|lv|mg|mh|mi|mk|ml|mn|mo|mr|ms|mt|mus|my|na|nah|nap|nb|nd|nds|ne|ng|nl|nn|no|nr|nv|ny|oc|oj|om|or|os|pa|pam|pi|pl|ps|pt|qu|rm|rn|ro|roa-rup|ru|rw|sa|sc|scn|sco|sd|se|sg|sh|si|simple|sk|sl|sm|smg|sn|so|sq|sr|ss|st|su|sv|sw|ta|te|tg|th|ti|tk|tl|tlh|tn|to|tpi|tr|ts|tt|tum|tw|ty|ug|uk|ur|uz|ve|vi|vk|vo|wa|war|wen|wo|xh|yi|yo|za|zh|zh-min-nan|zu'; | |||
pg.re.interwiki=RegExp('^'+pg.wiki.interwiki+':'); | |||
} else { | |||
pg.wiki.interwiki=null; | |||
pg.re.interwiki=RegExp('^$'); | |||
} | |||
} | |||
function nsRe(label) { | |||
var l=upcaseFirst(label); | |||
return nsRegexString(pg.ns.list[pg.ns.index[l]], l); | |||
} | |||
function nsRegexString(str, extra) { | |||
return '(?:' + str + '|' + encodeURI(str) + (extra ? '|' + extra : '') + ')'; | |||
} | |||
function nsRegex(str, extra) { | |||
return RegExp(nsRegexString(str, extra)); | |||
} | |||
// ENDFILE: namespaces.js | |||
// STARTFILE: selpop.js | |||
//<NOLITE> | //<NOLITE> | ||
function getEditboxSelection() { | |||
// see http://www.webgurusforum.com/8/12/0 | |||
try { | |||
var editbox=document.editform.wpTextbox1; | |||
} catch (dang) { return; } | |||
// IE, Opera | |||
if (document.selection) { return document.selection.createRange().text; } | |||
// Mozilla | |||
var selStart = editbox.selectionStart; | |||
var selEnd = editbox.selectionEnd; | |||
return (editbox.value).substring(selStart, selEnd); | |||
} | |||
function doSelectionPopup() { | |||
// popup if the selection looks like [[foo|anything afterwards at all | |||
// or [[foo|bar]]text without ']]' | |||
// or [[foo|bar]] | |||
var sel=getEditboxSelection(); | |||
var open=sel.indexOf('[['); | |||
var pipe=sel.indexOf('|'); | |||
var close=sel.indexOf(']]'); | |||
if (open == -1 || ( pipe == -1 && close == -1) ) { return; } | |||
if (pipe != -1 && open > pipe || close != -1 && open > close) { return; } | |||
if (getValueOf('popupOnEditSelection')=='boxpreview') { | |||
return doSeparateSelectionPopup(sel); | |||
} | |||
var article=new Title(sel.substring(open+2, (pipe < 0) ? close : pipe)).urlString(); | |||
if (close > 0 && sel.substring(close+2).indexOf('[[') >= 0) { | |||
return; | |||
} | |||
var a=document.createElement('a'); | |||
a.href=pg.wiki.titlebase + article; | |||
mouseOverWikiLink2(a); | |||
if (a.navpopup) { | |||
a.navpopup.addHook(function(){runStopPopupTimer(a.navpopup);}, 'unhide', 'after'); | |||
} | |||
} | } | ||
function | function doSeparateSelectionPopup(str) { | ||
var div=document.getElementById('selectionPreview'); | |||
if (!div) { | |||
div = document.createElement('div'); | |||
div.id='selectionPreview'; | |||
try { var box=document.editform.wpTextbox1; } | |||
catch (oopsie) { return; } | |||
box.parentNode.insertBefore(div, box); | |||
} | } | ||
div.innerHTML=wiki2html(str); | |||
div.ranSetupTooltipsAlready = false; | |||
popTipsSoonFn('selectionPreview')(); | |||
} | } | ||
//</NOLITE> | |||
// ENDFILE: selpop.js | |||
// STARTFILE: navpopup.js | |||
/** | |||
@fileoverview Defines two classes: {@link Navpopup} and {@link Mousetracker}. | |||
//<NOLITE> | <code>Navpopup</code> describes popups: when they appear, where, what | ||
they look like and so on. | |||
<code>Mousetracker</code> "captures" the mouse using | |||
<code>document.onmousemove</code>. | |||
*/ | |||
/** | |||
Creates a new Mousetracker. | |||
@constructor | |||
@class The Mousetracker class. This monitors mouse movements and manages associated hooks. | |||
*/ | |||
function Mousetracker() { | |||
/** | |||
Interval to regularly run the hooks anyway, in milliseconds. | |||
@type Integer | |||
*/ | |||
this.loopDelay=400; | |||
/** | |||
Timer for the loop. | |||
@type Timer | |||
/ | */ | ||
this.timer=null; | |||
// | /** | ||
Flag - are we switched on? | |||
@type Boolean | |||
*/ | |||
this.active=false; | |||
/** | |||
Flag - are we probably inaccurate, i.e. not reflecting the actual mouse position? | |||
*/ | |||
this.dirty=true; | |||
/** | |||
Array of hook functions. | |||
@private | |||
@type Array | |||
*/ | |||
this.hooks=[]; | |||
} | } | ||
function | /** | ||
Adds a hook, to be called when we get events. | |||
@param {Function} f A function which is called as | |||
<code>f(x,y)</code>. It should return <code>true</code> when it | |||
wants to be removed, and <code>false</code> otherwise. | |||
*/ | |||
Mousetracker.prototype.addHook = function (f) { | |||
this.hooks.push(f); | |||
}; | |||
/** | |||
Runs hooks, passing them the x | |||
and y coords of the mouse. Hook functions that return true are | |||
passed to {@link Mousetracker#removeHooks} for removal. | |||
@private | |||
*/ | |||
Mousetracker.prototype.runHooks = function () { | |||
if (!this.hooks || !this.hooks.length) { return; } | |||
//log('Mousetracker.runHooks; we got some hooks to run'); | |||
var remove=false; | |||
var removeObj={}; | |||
// this method gets called a LOT - | |||
// pre-cache some variables | |||
var x=this.x, y=this.y, len = this.hooks.length; | |||
for (var i=0; i<len; ++i) { | |||
//~ run the hook function, and remove it if it returns true | |||
if (this.hooks[i](x, y)===true) { | |||
remove=true; | |||
removeObj[i]=true; | |||
} | |||
} | } | ||
if (remove) { this.removeHooks(removeObj); } | |||
}; | |||
/** | |||
Removes hooks. | |||
@private | |||
@param {Object} removeObj An object whose keys are the index | |||
numbers of functions for removal, with values that evaluate to true | |||
*/ | |||
Mousetracker.prototype.removeHooks = function(removeObj) { | |||
} | var newHooks=[]; | ||
var len = this.hooks.length; | |||
for (var i=0; i<len; ++i) { | |||
if (! removeObj[i]) { newHooks.push(this.hooks[i]); } | |||
} | |||
/ | |||
function | |||
var | |||
var | |||
} | } | ||
this.hooks=newHooks; | |||
if ( | }; | ||
/** | |||
Event handler for mouse wiggles. | |||
We simply grab the event, set x and y and run the hooks. | |||
This makes the cpu all hot and bothered :-( | |||
@private | |||
@param {Event} e Mousemove event | |||
*/ | |||
Mousetracker.prototype.track=function (e) { | |||
//~ Apparently this is needed in IE. | |||
e = e || window.event; | |||
var x, y; | |||
if (e) { | |||
if (e.pageX) { x=e.pageX; y=e.pageY; } | |||
else if (typeof e.clientX!='undefined') { | |||
var left, top, docElt = window.document.documentElement; | |||
if (docElt) { left=docElt.scrollLeft; } | |||
left = left || window.document.body.scrollLeft || window.document.scrollLeft || 0; | |||
if (docElt) { top=docElt.scrollTop; } | |||
top = top || window.document.body.scrollTop || window.document.scrollTop || 0; | |||
x=e.clientX + left; | |||
y=e.clientY + top; | |||
} else { return; } | |||
this.setPosition(x,y); | |||
} | } | ||
} | }; | ||
function | /** | ||
Sets the x and y coordinates stored and takes appropriate action, | |||
if (! | running hooks as appropriate. | ||
@param {Integer} x, y Screen coordinates to set | |||
*/ | |||
Mousetracker.prototype.setPosition=function(x,y) { | |||
this.x = x; | |||
this.y = y; | |||
if (this.dirty || this.hooks.length === 0) { this.dirty=false; return; } | |||
if (typeof this.lastHook_x != 'number') { this.lastHook_x = -100; this.lastHook_y=-100; } | |||
var diff = (this.lastHook_x - x)*(this.lastHook_y - y); | |||
diff = (diff >= 0) ? diff : -diff; | |||
if ( diff > 1 ) { | |||
this.lastHook_x=x; | |||
this.lastHook_y=y; | |||
if (this.dirty) { this.dirty = false; } | |||
else { this.runHooks(); } | |||
} | } | ||
} | } | ||
/** | /** | ||
Sets things in motion, unless they are already that is, registering an event handler on <code>document.onmousemove</code>. | |||
A half-hearted attempt is made to preserve the old event handler if there is one. | |||
*/ | */ | ||
Mousetracker.prototype.enable = function () { | |||
if (this.active) { return; } | |||
this.active=true; | |||
//~ Save the current handler for mousemove events. This isn't too | |||
//~ robust, of course. | |||
this.savedHandler=document.onmousemove; | |||
//~ Gotta save @tt{this} again for the closure, and use apply for | |||
//~ the member function. | |||
var savedThis=this; | |||
document.onmousemove=function (e) {savedThis.track.apply(savedThis, [e]);}; | |||
if (this.loopDelay) { this.timer = setInterval(function() { //log('loop delay in mousetracker is working'); | |||
savedThis.runHooks();}, this.loopDelay); } | |||
}; | |||
/** | /** | ||
Creates a new | Disables the tracker, removing the event handler. | ||
*/ | |||
Mousetracker.prototype.disable = function () { | |||
if (!this.active) { return; } | |||
if (typeof this.savedHandler=='function') { | |||
document.onmousemove=this.savedHandler; | |||
} else { delete document.onmousemove; } | |||
if (this.timer) { clearInterval(this.timer); } | |||
this.active=false; | |||
}; | |||
/** | |||
Creates a new Navpopup. | |||
Gets a UID for the popup and | |||
@param init Contructor object. If <code>init.draggable</code> is true or absent, the popup becomes draggable. | |||
@constructor | @constructor | ||
@class The | @class The Navpopup class. This generates popup hints, and does some management of them. | ||
*/ | */ | ||
function | function Navpopup(init) { | ||
/** | //alert('new Navpopup(init)'); | ||
/** UID for each Navpopup instance. | |||
Read-only. | |||
@type integer | |||
*/ | */ | ||
this. | this.uid=Navpopup.uid++; | ||
/** | /** | ||
Read-only flag for current visibility of the popup. | |||
@type | @type boolean | ||
@private | |||
*/ | */ | ||
this. | this.visible=false; | ||
/** Flag to be set when we want to cancel a previous request to | |||
/** | show the popup in a little while. | ||
@private | |||
@type boolean | |||
*/ | |||
this.noshow=false; | |||
/** Categorised list of hooks. | |||
@see #runHooks | |||
@see #addHook | |||
@private | |||
@type Object | |||
*/ | |||
this.hooks={ | |||
'create': [], | |||
'unhide': [], | |||
'hide': [] | |||
}; | |||
/** list of unique IDs of hook functions, to avoid duplicates | |||
@private | |||
*/ | |||
this.hookIds={}; | |||
/** List of downloads associated with the popup. | |||
@private | |||
@type Array | |||
*/ | */ | ||
this. | this.downloads=[]; | ||
/** | /** Number of uncompleted downloads. | ||
@type integer | |||
*/ | */ | ||
this. | this.pending=null; | ||
/** | /** Tolerance in pixels when detecting whether the mouse has left the popup. | ||
@type integer | |||
*/ | */ | ||
this. | this.fuzz=5; | ||
} | /** Flag to toggle running {@link #limitHorizontalPosition} to regulate the popup's position. | ||
@type boolean | |||
/** | */ | ||
this.constrained=true; | |||
/** The popup width in pixels. | |||
@private | |||
@type integer | |||
*/ | */ | ||
this.width=0; | |||
this. | /** The popup width in pixels. | ||
} | @private | ||
@type integer | |||
/** | */ | ||
this.height=0; | |||
/** The main content DIV element. | |||
@type HTMLDivElement | |||
*/ | |||
this.mainDiv=null; | |||
this.createMainDiv(); | |||
// if (!init || typeof init.draggable=='undefined' || init.draggable) { | |||
// this.makeDraggable(true); | |||
// } | |||
} | |||
/** | |||
A UID for each Navpopup. This constructor property is just a counter. | |||
@type integer | |||
@private | @private | ||
*/ | */ | ||
Navpopup.uid=0; | |||
/** | |||
Retrieves the {@link #visible} attribute, indicating whether the popup is currently visible. | |||
@type boolean | |||
*/ | |||
Navpopup.prototype.isVisible=function() { | |||
return this.visible; | |||
}; | }; | ||
/** | /** | ||
Repositions popup using CSS style. | |||
@private | @private | ||
@param { | @param {integer} x x-coordinate (px) | ||
@param {integer} y y-coordinate (px) | |||
@param {boolean} noLimitHor Don't call {@link #limitHorizontalPosition} | |||
*/ | */ | ||
Navpopup.prototype.reposition= function (x,y, noLimitHor) { | |||
log ('reposition('+x+','+y+','+noLimitHor+')'); | |||
if (typeof x != 'undefined' && x!==null) { this.left=x; } | |||
if (typeof y != 'undefined' && y!==null) { this.top=y; } | |||
if (typeof this.left != 'undefined' && typeof this.top != 'undefined') { | |||
this.mainDiv.style.left=this.left + 'px'; | |||
this.mainDiv.style.top=this.top + 'px'; | |||
} | } | ||
this. | if (!noLimitHor) { this.limitHorizontalPosition(); } | ||
//console.log('navpop'+this.uid+' - (left,top)=(' + this.left + ',' + this.top + '), css=(' | |||
//+ this.mainDiv.style.left + ',' + this.mainDiv.style.top + ')'); | |||
}; | }; | ||
/** | /** | ||
Prevents popups from being in silly locations. Hopefully. | |||
Should not be run if {@link #constrained} is true. | |||
@private | @private | ||
*/ | */ | ||
Navpopup.prototype.limitHorizontalPosition=function() { | |||
if (!this.constrained || this.tooWide) { return; } | |||
this.updateDimensions(); | |||
var x | var x=this.left; | ||
var w=this.width; | |||
var cWidth=document.body.clientWidth; | |||
// log('limitHorizontalPosition: x='+x+ | |||
// ', this.left=' + this.left + | |||
// ', this.width=' + this.width + | |||
// ', cWidth=' + cWidth); | |||
if ( (x+w) >= cWidth || | |||
( x > 0 && this.maxWidth && this.width < this.maxWidth && this.height > this.width | |||
&& x > cWidth - this.maxWidth ) ) { | |||
// This is a very nasty hack. There has to be a better way! | |||
this. | // We find the "natural" width of the div by positioning it at the far left | ||
// then reset it so that it should be flush right (well, nearly) | |||
this.mainDiv.style.left='-10000px'; | |||
this.mainDiv.style.width = this.maxWidth + 'px'; | |||
var naturalWidth=parseInt(this.mainDiv.offsetWidth, 10); | |||
var newLeft=cWidth - naturalWidth - 1; | |||
if (newLeft < 0) { newLeft = 0; this.tooWide=true; } // still unstable for really wide popups? | |||
log ('limitHorizontalPosition: moving to ('+newLeft + ','+ this.top+');' + ' naturalWidth=' + naturalWidth + ', clientWidth=' + cWidth); | |||
this.reposition(newLeft, null, true); | |||
} | } | ||
}; | }; | ||
/** | /** | ||
Counter indicating the z-order of the "highest" popup. | |||
We start the z-index at 1000 so that popups are above everything | |||
@ | else on the screen. | ||
@private | |||
@type integer | |||
*/ | */ | ||
Navpopup.highest=1000; | |||
/** | /** | ||
Brings popup to the top of the z-order. | |||
We increment the {@link #highest} property of the contructor here. | |||
@private | |||
*/ | */ | ||
Navpopup.prototype.raise = function () { | |||
this.mainDiv.style.zIndex=Navpopup.highest + 1; | |||
++Navpopup.highest; | |||
}; | |||
/** | |||
Shows the popup provided {@link #noshow} is not true. | |||
Updates the position, brings the popup to the top of the z-order and unhides it. | |||
*/ | |||
Navpopup.prototype.show = function () { | |||
if (this. | //document.title+='s'; | ||
if (this.noshow) { return; } | |||
//document.title+='t'; | |||
this.reposition(); | |||
this.raise(); | |||
this.unhide(); | |||
}; | }; | ||
/** | /** | ||
Runs the {@link #show} method in a little while, unless we're | |||
already visible. | |||
@param {integer} time Delay in milliseconds | |||
@see #showSoonIfStable | |||
*/ | */ | ||
Navpopup.prototype.showSoon = function (time) { | |||
if ( | if (this.visible) { return; } | ||
this.noshow=false; | |||
//~ We have to save the value of @tt{this} so that the closure below | |||
//~ works. | |||
if ( | var savedThis=this; | ||
//this.start_x = Navpopup.tracker.x; | |||
//this.start_y = Navpopup.tracker.y; | |||
setTimeout(function () { | |||
if (Navpopup.tracker.active) { | |||
savedThis.reposition.apply(savedThis, [Navpopup.tracker.x + 2, Navpopup.tracker.y + 2]); | |||
} | |||
//~ Have to use apply to invoke his member function here | |||
savedThis.show.apply(savedThis, []); | |||
}, time); | |||
}; | }; | ||
/** | /** | ||
Checks to see if the mouse pointer has | |||
stabilised (checking every <code>time</code>/2 milliseconds) and runs the | |||
{@link #show} method if it has. This method makes {@link #showSoon} redundant. | |||
@ | @param {integer} time The minimum time (ms) before the popup may be shown. | ||
@ | |||
*/ | */ | ||
function | Navpopup.prototype.showSoonIfStable = function (time) { | ||
log ('showSoonIfStable, time='+time); | |||
if (this.visible) { return; } | |||
this.noshow = false; | |||
//~ initialize these variables so that we never run @tt{show} after | |||
this. | //~ just half the time | ||
this.stable_x = -10000; this.stable_y = -10000; | |||
var stableShow = function() { | |||
log('stableShow called'); | |||
var new_x = Navpopup.tracker.x, new_y = Navpopup.tracker.y; | |||
this. | var dx = savedThis.stable_x - new_x, dy = savedThis.stable_y - new_y; | ||
var fuzz2 = 0; // savedThis.fuzz * savedThis.fuzz; | |||
//document.title += '[' + [savedThis.stable_x,new_x, savedThis.stable_y,new_y, dx, dy, fuzz2].join(',') + '] '; | |||
if ( dx * dx <= fuzz2 && dy * dy <= fuzz2 ) { | |||
log ('mouse is stable'); | |||
clearInterval(savedThis.showSoonStableTimer); | |||
savedThis.reposition.apply(savedThis, [new_x + 2, new_y + 2]); | |||
savedThis.show.apply(savedThis, []); | |||
return; | |||
} | |||
savedThis.stable_x = new_x; savedThis.stable_y = new_y; | |||
}; | |||
var savedThis = this; | |||
this.showSoonStableTimer = setInterval(stableShow, time/2); | |||
}; | |||
/** | |||
Makes the popup unhidable until we call {@link #unstick}. | |||
*/ | |||
Navpopup.prototype.stick=function() { | |||
this.noshow=false; | this.noshow=false; | ||
this.sticky=true; | |||
}; | |||
this. | |||
/** | /** | ||
Allows the popup to be hidden. | |||
*/ | */ | ||
Navpopup. | Navpopup.prototype.unstick=function() { | ||
this.sticky=false; | |||
}; | |||
/** | /** | ||
Sets the {@link #noshow} flag and hides the popup. This should be called | |||
when the mouse leaves the link before | |||
(or after) it's actually been displayed. | |||
*/ | */ | ||
Navpopup.prototype. | Navpopup.prototype.banish = function () { | ||
log ('banish called'); | |||
// hide and prevent showing with showSoon in the future | |||
this.noshow=true; | |||
if (this.showSoonStableTimer) { | |||
log('clearing showSoonStableTimer'); | |||
clearInterval(this.showSoonStableTimer); | |||
} | |||
this.hide(); | |||
}; | }; | ||
/** | /** | ||
Runs hooks added with {@link #addHook}. | |||
@private | @private | ||
@param { | @param {String} key Key name of the {@link #hooks} array - one of 'create', 'unhide', 'hide' | ||
@param {String} when Controls exactly when the hook is run: either 'before' or 'after' | |||
@param { | |||
*/ | */ | ||
Navpopup.prototype. | Navpopup.prototype.runHooks = function (key, when) { | ||
if (!this.hooks[key]) { return; } | |||
var keyHooks=this.hooks[key]; | |||
if ( | var len=keyHooks.length; | ||
for (var i=0; i< len; ++i) { | |||
if (keyHooks[i] && keyHooks[i].when == when) { | |||
if (keyHooks[i].hook.apply(this, [])) { | |||
// remove the hook | |||
if (keyHooks[i].hookId) { | |||
delete this.hookIds[keyHooks[i].hookId]; | |||
} | |||
keyHooks[i]=null; | |||
} | |||
} | |||
} | } | ||
}; | }; | ||
/** | /** | ||
Adds a hook to the popup. Hook functions are run with <code>this</code> set to refer to the Navpopup instance, and no arguments. | |||
@param {Function} hook The hook function. Functions that return true are deleted. | |||
@ | @param {String} key Key name of the {@link #hooks} array - one of 'create', 'unhide', 'hide' | ||
@param {String} when Controls exactly when the hook is run: either 'before' or 'after' | |||
@param {String} uid A truthy string identifying the hook function; if it matches another hook in this position, it won't be added again. | |||
*/ | */ | ||
Navpopup.prototype. | Navpopup.prototype.addHook = function ( hook, key, when, uid ) { | ||
if (!this. | when = when || 'after'; | ||
if (!this.hooks[key]) { return; } | |||
// if uid is specified, don't add duplicates | |||
var hookId=null; | |||
if (uid) { | |||
hookId=[key,when,uid].join('|'); | |||
if (this.hookIds[hookId]) { | |||
// | return; | ||
} | |||
this.hookIds[hookId]=true; | |||
if ( | |||
} | } | ||
this.hooks[key].push( {hook: hook, when: when, hookId: hookId} ); | |||
}; | }; | ||
/** | /** | ||
Creates the main DIV element, which contains all the actual popup content. | |||
Runs hooks with key 'create'. | |||
@private | @private | ||
*/ | */ | ||
Navpopup. | Navpopup.prototype.createMainDiv = function () { | ||
if (this.mainDiv) { return; } | |||
this.runHooks('create', 'before'); | |||
var mainDiv=document.createElement('div'); | |||
var savedThis=this; | |||
mainDiv.onclick=function(e) {savedThis.onclickHandler(e);}; | |||
mainDiv.className=(this.className) ? this.className : 'navpopup_maindiv'; | |||
this.mainDiv.style. | mainDiv.id=mainDiv.className + this.uid; | ||
mainDiv.style.position='absolute'; | |||
mainDiv.style.display='none'; | |||
mainDiv.className='navpopup'; | |||
// easy access to javascript object through DOM functions | |||
mainDiv.navpopup=this; | |||
this.mainDiv=mainDiv; | |||
document.body.appendChild(mainDiv); | |||
this.runHooks('create', 'after'); | |||
}; | }; | ||
/** | /** | ||
Calls the {@link #raise} method. | |||
@private | |||
*/ | */ | ||
Navpopup.prototype. | Navpopup.prototype.onclickHandler=function(e) { | ||
this.raise(); | this.raise(); | ||
}; | }; | ||
/** | /** | ||
Makes the popup draggable, using a {@link Drag} object. | |||
@private | |||
@ | |||
*/ | */ | ||
Navpopup.prototype. | Navpopup.prototype.makeDraggable=function(handleName) { | ||
if (this. | if (!this.mainDiv) { this.createMainDiv(); } | ||
var drag=new Drag(); | |||
if (!handleName) { | |||
drag.startCondition=function(e) { | |||
var | try { if (!e.shiftKey) { return false; } } catch (err) { return false; } | ||
return true; | |||
/ | }; | ||
} | |||
var dragHandle = document.getElementById(handleName) || this.mainDiv; | |||
var np=this; | |||
drag.endHook=function(x,y) { | |||
Navpopup.tracker.dirty=true; | |||
np.reposition(x,y); | |||
}, | }; | ||
drag.init(dragHandle,this.mainDiv); | |||
}; | |||
/** Hides the popup using CSS. Runs hooks with key 'hide'. | |||
Sets {@link #visible} appropriately. {@link #banish} should be called externally instead of this method. | |||
@private | |||
*/ | |||
Navpopup.prototype.hide = function () { | |||
this.runHooks('hide', 'before'); | |||
this.abortDownloads(); | |||
if (this.sticky) { return; } | |||
if (typeof this.visible != 'undefined' && this.visible) { | |||
this.mainDiv.style.display='none'; | |||
this.visible=false; | |||
} | |||
this.runHooks('hide', 'after'); | |||
}; | |||
/** Shows the popup using CSS. Runs hooks with key 'unhide'. | |||
Sets {@link #visible} appropriately. {@link #show} should be called externally instead of this method. | |||
@private | |||
*/ | |||
Navpopup.prototype.unhide = function () { | |||
this.runHooks('unhide', 'before'); | |||
if (typeof this.visible != 'undefined' && !this.visible) { | |||
this.mainDiv.style.display='inline'; | |||
this.visible=true; | |||
} | |||
this.runHooks('unhide', 'after'); | |||
}; | }; | ||
/** | /** | ||
Sets the <code>innerHTML</code> attribute of the main div containing the popup content. | |||
@param {String} html The HTML to set. | |||
@param { | |||
*/ | */ | ||
Navpopup.prototype. | Navpopup.prototype.setInnerHTML = function (html) { | ||
this.mainDiv.innerHTML = html; | |||
}; | }; | ||
/** | /** | ||
Updates the {@link #width} and {@link #height} attributes with the CSS properties. | |||
@private | |||
*/ | */ | ||
Navpopup.prototype. | Navpopup.prototype.updateDimensions = function () { | ||
this. | this.width=parseInt(this.mainDiv.offsetWidth, 10); | ||
this. | this.height=parseInt(this.mainDiv.offsetHeight, 10); | ||
}; | }; | ||
/** | /** | ||
Checks if the point (x,y) is within {@link #fuzz} of the | |||
{@link #mainDiv}. | |||
@param {integer} x x-coordinate (px) | |||
@param {integer} y y-coordinate (px) | |||
@type boolean | |||
*/ | */ | ||
Navpopup.prototype. | Navpopup.prototype.isWithin = function(x,y) { | ||
this. | //~ If we're not even visible, no point should be considered as | ||
//~ being within the popup. | |||
if (!this.visible) { return false; } | |||
this.updateDimensions(); | |||
var fuzz=this.fuzz || 0; | |||
//~ Use a simple box metric here. | |||
return (x+fuzz >= this.left && x-fuzz <= this.left + this.width && | |||
y+fuzz >= this.top && y-fuzz <= this.top + this.height); | |||
}; | }; | ||
/** | /** | ||
Adds a download to {@link #downloads}. | |||
@param {Downloader} download | |||
*/ | */ | ||
Navpopup.prototype. | Navpopup.prototype.addDownload=function(download) { | ||
if (!download) { return; } | |||
this.downloads.push(download); | |||
if ( | |||
this. | |||
}; | }; | ||
/** | /** | ||
Aborts the downloads listed in {@link #downloads}. | |||
@ | @see Downloader#abort | ||
*/ | */ | ||
Navpopup.prototype. | Navpopup.prototype.abortDownloads=function() { | ||
for(var i=0; i<this.downloads.length; ++i) { | |||
var d=this.downloads[i]; | |||
if (d && d.abort) { d.abort(); } | |||
for (var i=0; i< | |||
} | } | ||
this.downloads=[]; | |||
}; | }; | ||
/** | /** | ||
A {@link Mousetracker} instance which is a property of the constructor (pseudo-global). | |||
*/ | */ | ||
Navpopup. | Navpopup.tracker=new Mousetracker(); | ||
// ENDFILE: navpopup.js | |||
if (! | // STARTFILE: diff.js | ||
// if | //<NOLITE> | ||
var | /* | ||
* Javascript Diff Algorithm | |||
* By John Resig (http://ejohn.org/) and [[:en:User:Lupin]] | |||
if ( | * | ||
return; | * More Info: | ||
* http://ejohn.org/projects/javascript-diff-algorithm/ | |||
*/ | |||
function delFmt(x) { | |||
if (!x.length) { return ''; } | |||
return "<del class='popupDiff'>" + x.join('').split('\n').join('¶\n') +"</del>"; | |||
} | |||
function insFmt(x) { | |||
if (!x.length) { return ''; } | |||
return "<ins class='popupDiff'>" + x.join('').split('\n').join('¶\n') +"</ins>"; | |||
} | |||
function countCrossings(a, b, i, eject) { | |||
// count the crossings on the edge starting at b[i] | |||
if (!b[i].row && b[i].row !== 0) { return -1; } | |||
var count=0; | |||
for (var j=0; j<a.length; ++j) { | |||
if (!a[j].row && a[j].row !== 0) { continue; } | |||
if ( (j-b[i].row)*(i-a[j].row) > 0) { | |||
if(eject) { return true; } | |||
count++; | |||
} | } | ||
} | } | ||
return count; | |||
} | } | ||
function shortenDiffString(str, context) { | |||
var re=RegExp('(<del[\\s\\S]*?</del>|<ins[\\s\\S]*?</ins>)'); | |||
var splitted=str.parenSplit(re); | |||
var ret=['']; | |||
for (var i=0; i<splitted.length; i+=2) { | |||
if (splitted[i].length < 2*context) { | |||
ret[ret.length-1] += splitted[i]; | |||
if (i+1<splitted.length) { ret[ret.length-1] += splitted[i+1]; } | |||
var | continue; | ||
} | |||
var | else { | ||
if (i > 0) { ret[ret.length-1] += splitted[i].substring(0,context); } | |||
if (i+1 < splitted.length) { | |||
ret.push(splitted[i].substring(splitted[i].length-context) + | |||
splitted[i+1]); | |||
} | |||
} | |||
} | } | ||
while (ret.length > 0 && !ret[0]) { ret = ret.slice(1); } | |||
return ret; | |||
} | |||
function diffString( o, n, simpleSplit ) { | |||
var splitRe=RegExp('([[]{2}|[\]]{2}|[{]{2,3}|[}]{2,3}|[|]|=|[*:]+|\\s|\\b)'); | |||
} | |||
o=o.entify(); n=n.entify(); | |||
var out, i; | |||
if (simpleSplit) { out = diff( o.split(/\b/), n.split(/\b/) ); } | |||
else { out = diff( o.parenSplit(splitRe), n.parenSplit(splitRe) ); } | |||
var str = ""; | |||
var acc=[]; // accumulator for prettier output | |||
// crossing pairings -- eg 'A B' vs 'B A' -- cause problems, so let's iron them out | |||
// this doesn't always do things optimally but it should be fast enough | |||
var maxOutputPair=0; | |||
for (i=0; i<out.n.length; ++i) { | |||
if ( out.n[i].paired ) { | |||
if( maxOutputPair > out.n[i].row ) { | |||
// tangle - delete pairing | |||
out.o[ out.n[i].row ]=out.o[ out.n[i].row ].text; | |||
out.n[i]=out.n[i].text; | |||
} | |||
if (maxOutputPair < out.n[i].row) { maxOutputPair = out.n[i].row; } | |||
} | |||
} | } | ||
// output the stuff preceding the first paired old line | |||
for (i=0; i<out.o.length && !out.o[i].paired; ++i) { acc.push( out.o[i] ); } | |||
/ | str += delFmt(acc); acc=[]; | ||
// main loop | |||
for ( i = 0; i < out.n.length; ++i ) { | |||
// output unpaired new "lines" | |||
while ( i < out.n.length && !out.n[i].paired ) { acc.push( out.n[i++] ); } | |||
str += insFmt(acc); acc=[]; | |||
if ( i < out.n.length ) { // this new "line" is paired with the (out.n[i].row)th old "line" | |||
str += out.n[i].text; | |||
// output unpaired old rows starting after this new line's partner | |||
var m = out.n[i].row + 1; | |||
while ( m < out.o.length && !out.o[m].paired ) { acc.push ( out.o[m++] ); } | |||
str += delFmt(acc); acc=[]; | |||
} | |||
} | |||
return str; | |||
} | |||
// see http://developer.mozilla.org/en/docs/Core_JavaScript_1.5_Reference:Global_Objects:Object | |||
// FIXME: use obj.hasOwnProperty instead of this kludge! | |||
window.jsReservedProperties=RegExp('^(constructor|prototype|__((define|lookup)[GS]etter)__' + | |||
/ | '|eval|hasOwnProperty|propertyIsEnumerable' + | ||
'|to(Source|String|LocaleString)|(un)?watch|valueOf)$'); | |||
function diffBugAlert(word) { | |||
if (!diffBugAlert.list[word]) { | |||
diffBugAlert.list[word]=1; | |||
alert('Bad word: '+word+'\n\nPlease report this bug.'); | |||
} | |||
} | |||
diffBugAlert.list={}; | |||
function makeDiffHashtable(src) { | |||
var ret={}; | |||
for ( var i = 0; i < src.length; i++ ) { | |||
if ( jsReservedProperties.test(src[i]) ) { src[i] += '<!-- -->'; } | |||
if ( !ret[ src[i] ] ) { ret[ src[i] ] = []; } | |||
try { ret[ src[i] ].push( i ); } catch (err) { diffBugAlert(src[i]); } | |||
} | |||
return ret; | |||
} | |||
function diff( o, n ) { | |||
// pass 1: make hashtable ns with new rows as keys | |||
var ns = makeDiffHashtable(n); | |||
}; | // pass 2: make hashtable os with old rows as keys | ||
var os = makeDiffHashtable(o); | |||
// pass 3: pair unique new rows and matching unique old rows | |||
var i; | |||
for ( i in ns ) { | |||
if ( ns[i].length == 1 && os[i] && os[i].length == 1 ) { | |||
n[ ns[i][0] ] = { text: n[ ns[i][0] ], row: os[i][0], paired: true }; | |||
o[ os[i][0] ] = { text: o[ os[i][0] ], row: ns[i][0], paired: true }; | |||
}; | } | ||
} | } | ||
// pass 4: pair matching rows immediately following paired rows (not necessarily unique) | |||
for ( i = 0; i < n.length - 1; i++ ) { | |||
if ( n[i].paired && ! n[i+1].paired && n[i].row + 1 < o.length && ! o[ n[i].row + 1 ].paired && | |||
/ | n[i+1] == o[ n[i].row + 1 ] ) { | ||
n[i+1] = { text: n[i+1], row: n[i].row + 1, paired: true }; | |||
o[n[i].row+1] = { text: o[n[i].row+1], row: i + 1, paired: true }; | |||
} | } | ||
} | } | ||
// pass 5: pair matching rows immediately preceding paired rows (not necessarily unique) | |||
for ( i = n.length - 1; i > 0; i-- ) { | |||
if ( n[i].paired && ! n[i-1].paired && n[i].row > 0 && ! o[ n[i].row - 1 ].paired && | |||
n[i-1] == o[ n[i].row - 1 ] ) { | |||
n[i-1] = { text: n[i-1], row: n[i].row - 1, paired: true }; | |||
o[n[i].row-1] = { text: o[n[i].row-1], row: i - 1, paired: true }; | |||
for ( | |||
if ( | |||
} | } | ||
} | } | ||
return { o: o, n: n }; | |||
} | } | ||
//</NOLITE> | |||
// ENDFILE: diff.js | |||
// STARTFILE: init.js | |||
function setSiteInfo() { | |||
if (window.popupLocalDebug) { | |||
pg.wiki.hostname = 'en.wikipedia.org'; | |||
} else { | |||
pg.wiki.hostname = location.hostname; // use in preference to location.hostname for flexibility (?) | |||
} | } | ||
pg.wiki.wikimedia=RegExp('(wiki([pm]edia|source|books|news|quote|versity)|wiktionary)[.]org').test(pg.wiki.hostname); | |||
pg.wiki.wikia=RegExp('[.]wikia[.]com$', 'i').test(pg.wiki.hostname); | |||
pg.wiki.isLocal=RegExp('^localhost').test(pg.wiki.hostname); | |||
pg.wiki.commons=( pg.wiki.wikimedia && pg.wiki.hostname != 'commons.wikimedia.org') ? 'commons.wikimedia.org' : null; | |||
pg.wiki.commonslang = pg.wiki.commons ? pg.wiki.commons.split('.')[0] : null; | |||
pg.wiki.lang = pg.wiki.hostname.split('.')[0]; | |||
// toolDbName needs pg.wiki.lang and pg.wiki.hostname | |||
window.toolDbName && (pg.wiki.userNameCookie=toolDbName(true) + 'UserName'); | |||
pg.wiki.prePath=''; | |||
if (pg.wiki.hostname == 'secure.wikimedia.org') { | |||
var s=document.location.href.split('/'); | |||
pg.wiki.prePath=s.slice(3,5).join('/'); | |||
pg.wiki.lang=s[4]; | |||
} | } | ||
var port = location.port ? ':' + location.port : ''; | |||
pg.wiki.sitebase = joinPath([pg.wiki.hostname + port, pg.wiki.prePath]); | |||
} | } | ||
function getArticlePath() { | |||
if (isFunction(window.siteArticlePath)) { | |||
return siteArticlePath(); | |||
function | |||
if ( | |||
} | } | ||
return 'wiki'; | |||
} | } | ||
function getBotInterfacePath() { | |||
function | if (isFunction(window.siteBotInterfacePath)) { | ||
return siteBotInterfacePath(); | |||
} | } | ||
return | var botInterfacePath = pg.wiki.articlePath.replace(/\/index[.]php$/, ''); | ||
if (pg.wiki.wikimedia) { botInterfacePath = 'w'; } // as in http://some.thing.com/w/index.php?title=foo | |||
else if (pg.wiki.wikia) { botInterfacePath = ''; } | |||
return botInterfacePath; | |||
} | } | ||
function | function setTitleBase() { | ||
var protocol = ( window.popupLocalDebug ? 'http:' : location.protocol ); | |||
pg.wiki.articlePath = getArticlePath(); // as in http://some.thing.com/wiki/Article | |||
pg.wiki.botInterfacePath = getBotInterfacePath(); | |||
// default mediawiki setting is paths like http://some.thing.com/articlePath/index.php?title=foo | |||
var titletail = joinPath([pg.wiki.botInterfacePath, 'index.php?title=']); | |||
var titletail2 = joinPath([pg.wiki.botInterfacePath, 'wiki.phtml?title=']); | |||
// | |||
var | // other sites may need to add code here to set titletail depending on how their urls work | ||
pg.wiki.titlebase = protocol + '//' + joinPath([pg.wiki.sitebase, titletail]); | |||
pg.wiki.titlebase2 = protocol + '//' + joinPath([pg.wiki.sitebase, titletail2]); | |||
pg.wiki.wikibase = protocol + '//' + joinPath([pg.wiki.sitebase, pg.wiki.botInterfacePath]); | |||
pg.wiki.articlebase = protocol + '//' + joinPath([pg.wiki.sitebase, pg.wiki.articlePath]); | |||
pg.re.basenames = RegExp( '^(' + | |||
map( literalizeRegex, [ pg.wiki.titlebase, pg.wiki.titlebase2, | |||
pg.wiki.articlebase ]).join('|') + ')' ); | |||
} | |||
////////////////////////////////////////////////// | |||
// Global regexps | |||
function setMainRegex() { | |||
var reStart='[^:]*://'; | |||
var preTitles = joinPath([literalizeRegex(pg.wiki.botInterfacePath), '(?:index[.]php|wiki[.]phtml)[?]title=']); | |||
// slightly ugly hack when pg.wiki.articlePath is empty | |||
preTitles += '|' + literalizeRegex( ( pg.wiki.articlePath ? pg.wiki.articlePath + '/' : '')); | |||
var reEnd='/(' + preTitles + ')([^&?#]*)[^#]*(?:#(.+))?'; | |||
pg.re.main = RegExp(reStart + literalizeRegex(pg.wiki.sitebase) + reEnd); | |||
} | } | ||
function setRegexps() { | |||
setMainRegex(); | |||
function | var sp=nsRe('Special'); | ||
pg.re.urlNoPopup=RegExp('((title=|/)' + sp + '(?:%3A|:)|section=[0-9])') ; | |||
pg.re.contribs =RegExp('(title=|/)' + sp + '(?:%3A|:)Contributions' + '(&target=|/|/' + pg.ns.user+':)(.*)') ; | |||
pg.re.email =RegExp('(title=|/)' + sp + '(?:%3A|:)Emailuser' + '(&target=|/|/(?:' + pg.ns.user+':)?)(.*)') ; | |||
pg.re.backlinks =RegExp('(title=|/)' + sp + '(?:%3A|:)Whatlinkshere' + '(&target=|/)([^&]*)'); | |||
//<NOLITE> | |||
pg. | var im=nsRe('Image'); | ||
pg. | // note: tries to get images in infobox templates too, e.g. movie pages, album pages etc | ||
// (^|\[\[)image: *([^|\]]*[^|\] ]) * | |||
// (^|\[\[)image: *([^|\]]*[^|\] ])([^0-9\]]*([0-9]+) *px)? | |||
pg. | // $4 = 120 as in 120px | ||
pg.re.image = RegExp('(^|\\[\\[)' + im + ': *([^|\\]]*[^|\\] ])' + | |||
pg. | '([^0-9\\]]*([0-9]+) *px)?|(?:\\n *[|]?|[|]) *' + | ||
'(' + getValueOf('popupImageVarsRegexp') + ')' + | |||
' *= *(?:\\[\\[ *)?(?:' + im + ':)?' + | |||
'([^|]*?)(?:\\]\\])? *[|]? *\\n', 'img') ; | |||
pg.re.imageBracketCount = 6; | |||
pg.re.category = RegExp('\\[\\[' +nsRe('Category') + | |||
pg. | ': *([^|\\]]*[^|\\] ]) *', 'i'); | ||
pg.re.categoryBracketCount = 1; | |||
pg.re.ipUser=RegExp('('+nsRe('User')+':)?' + | |||
'((25[0-5]|2[0-4][0-9]|1[0-9][0-9]|[1-9][0-9]|[0-9])\\.){3}' + | |||
'(25[0-5]|2[0-4][0-9]|1[0-9][0-9]|[1-9][0-9]|[0-9])'); | |||
pg.re.stub= RegExp(getValueOf('popupStubRegexp'), 'im'); | |||
pg.re.disambig=RegExp(getValueOf('popupDabRegexp'), 'im'); | |||
//</NOLITE> | |||
// FIXME replace with general parameter parsing function, this is daft | |||
pg.re.oldid=RegExp('[?&]oldid=([^&]*)'); | |||
pg.re.diff=RegExp('[?&]diff=([^&]*)'); | |||
} | } | ||
function | |||
if ( | //<NOLITE> | ||
////////////////////////////////////////////////// | |||
} | // Image sources | ||
} | function setImageSources() { | ||
pg.wiki.imageSources=[]; | |||
if ( | // frequently seen thumbs | ||
pg.wiki.imageSources.push( | |||
{wiki: pg.wiki.hostname, thumb: true, width: 180}, // default | |||
{wiki: pg.wiki.hostname, thumb: true, width: 120} // gallery | |||
); | |||
// frequently seen thumbs on commons | |||
if (pg.wiki.commons) { | |||
pg.wiki.imageSources.push( | |||
{wiki: pg.wiki.commons, thumb: true, width: 180}, | |||
{wiki: pg.wiki.commons, thumb: true, width: 120} | |||
); | |||
} | |||
// unusual thumb sizes and full-size | |||
pg.wiki.imageSources.push( | |||
{wiki: pg.wiki.hostname, thumb: true, width: 200}, // common? | |||
{wiki: pg.wiki.hostname, thumb: true, width: 250}, // common? | |||
{wiki: pg.wiki.hostname, thumb: true, width: 300}, | |||
{wiki: pg.wiki.hostname, thumb: true, width: 210}, | |||
{wiki: pg.wiki.hostname, thumb: true, width: 230}, | |||
{wiki: pg.wiki.hostname, thumb: false, width: 0} // no comma | |||
); | |||
// full-size on commons | |||
if (pg.wiki.commons) { | |||
pg.wiki.imageSources.push({wiki: pg.wiki.commons, thumb: false, width: 0}); | |||
} | } | ||
} | } | ||
//</NOLITE> | |||
////////////////////////////////////////////////// | ////////////////////////////////////////////////// | ||
// | // miscellany | ||
function | function setupCache() { | ||
// page caching | |||
pg.cache.pages = []; | |||
pg.cache.images = []; | |||
// global array for 404'ed image urls | |||
pg.cache.badImageUrls=[]; | |||
pg. | |||
} | } | ||
function | function setMisc() { | ||
pg.current.link=null; | |||
pg.current.links=[]; | |||
pg. | pg.current.linksHash={}; | ||
pg. | |||
// downloading images are put here | |||
pg. | pg.misc.imageArray=[]; | ||
setupCache(); | |||
// FIXME what is this for? | |||
// | pg.misc.gImage=null; // global for image | ||
// check to see if images are done with this timer | |||
// | pg.timer.image=null; | ||
pg. | |||
// These are for checkImages() | |||
pg.counter.checkImages=0; | |||
pg.timer.checkImages=null; | |||
pg.timer.checkPopupPosition=null; | |||
pg. | pg.counter.loop=0; | ||
pg. | // ids change with each popup: popupImage0, popupImage1 etc | ||
pg.idNumber=0; | |||
pg. | |||
// for myDecodeURI | |||
pg. | pg.misc.decodeExtras = [ | ||
{from: '%2C', to: ',' }, | |||
{from: '_', to: ' ' }, | |||
{from: '%24', to: '$'}, | |||
{from: '%26', to: '&' } // no , | |||
]; | |||
} | } | ||
function leadingInteger(s){ | |||
var n=s.match(/^(\d*)/)[1]; | |||
if (n) { return +n; } | |||
return null; | |||
function | |||
if ( | |||
} | } | ||
function setBrowserHacks() { | |||
var useOriginal=false; | |||
// browser-specific hacks | |||
if (typeof window.opera != 'undefined') { | |||
//if (leadingInteger(opera.version()) < 9) | |||
{ useOriginal=true; } // v9 beta still seems to have buggy css | |||
setDefault('popupNavLinkSeparator', ' · '); | |||
} else if (navigator.appName=='Konqueror') { | |||
function setBrowserHacks() { | |||
var useOriginal=false; | |||
// browser-specific hacks | |||
if (typeof window.opera != 'undefined') { | |||
//if (leadingInteger(opera.version()) < 9) | |||
{ useOriginal=true; } // v9 beta still seems to have buggy css | |||
setDefault('popupNavLinkSeparator', ' · '); | |||
} else if (navigator.appName=='Konqueror') { | |||
setDefault('popupNavLinkSeparator', ' • '); | setDefault('popupNavLinkSeparator', ' • '); | ||
pg.flag.isKonq=true; | pg.flag.isKonq=true; | ||
| Строка 6243: | Строка 6079: | ||
pg.flag.IEVersion=ver; | pg.flag.IEVersion=ver; | ||
} | } | ||
if | if (pg.flag.isIE && pg.flag.IEVersion < 7 || pg.flag.isKonq || pg.flag.isSafari) { | ||
pg.flag.linksLikeIE6=true; | pg.flag.linksLikeIE6=true; | ||
} | } | ||
| Строка 6250: | Строка 6086: | ||
} | } | ||
} | } | ||
function setupPopups() { | function setupPopups() { | ||
// NB translatable strings should be set up first (strings.js) | // NB translatable strings should be set up first (strings.js) | ||
// basics | // basics | ||
setupDebugging(); | setupDebugging(); | ||
| Строка 6258: | Строка 6095: | ||
setTitleBase(); | setTitleBase(); | ||
setOptions(); // see options.js | setOptions(); // see options.js | ||
// namespaces etc | // namespaces etc | ||
setNamespaces(); | setNamespaces(); | ||
setInterwiki(); | setInterwiki(); | ||
// regexps | // regexps | ||
setRegexps(); | setRegexps(); | ||
setRedirs(); | setRedirs(); | ||
// other stuff | // other stuff | ||
window.setImageSources && setImageSources(); | window.setImageSources && setImageSources(); | ||
| Строка 6272: | Строка 6109: | ||
setMisc(); | setMisc(); | ||
setupLivePreview(); | setupLivePreview(); | ||
// main deal here | // main deal here | ||
setupTooltips(); | setupTooltips(); | ||
Navpopup.tracker.enable(); | Navpopup.tracker.enable(); | ||
setupPopups.completed = true; | setupPopups.completed = true; | ||
} | } | ||
| Строка 6285: | Строка 6122: | ||
// navlinks... let the fun begin | // navlinks... let the fun begin | ||
// | // | ||
function defaultNavlinkSpec() { | function defaultNavlinkSpec() { | ||
var str=''; | var str=''; | ||
| Строка 6292: | Строка 6129: | ||
str += '*<<lastEdit|shortcut=/>>|<<lastContrib>>|<<sinceMe>>if(oldid){|<<oldEdit>>|<<diffCur>>}'; | str += '*<<lastEdit|shortcut=/>>|<<lastContrib>>|<<sinceMe>>if(oldid){|<<oldEdit>>|<<diffCur>>}'; | ||
} | } | ||
// user links | // user links | ||
// contribs - log - count - email - block | // contribs - log - count - email - block | ||
| Строка 6299: | Строка 6136: | ||
str+='if(ipuser){*<<arin>>}if(wikimedia){*<<count|shortcut=#>>}'; | str+='if(ipuser){*<<arin>>}if(wikimedia){*<<count|shortcut=#>>}'; | ||
str+='if(ipuser){}else{*<<email|shortcut=E>>}if(admin){*<<block|shortcut=b>>|<<blocklog|log>>}}'; | str+='if(ipuser){}else{*<<email|shortcut=E>>}if(admin){*<<block|shortcut=b>>|<<blocklog|log>>}}'; | ||
// editing links | // editing links | ||
// talkpage -> edit|new - history - un|watch - article|edit | // talkpage -> edit|new - history - un|watch - article|edit | ||
| Строка 6307: | Строка 6144: | ||
var historystr='<<history|shortcut=h>>if(mainspace_en){|<<editors|shortcut=E|>>}'; | var historystr='<<history|shortcut=h>>if(mainspace_en){|<<editors|shortcut=E|>>}'; | ||
var watchstr='<<unwatch|unwatchShort>>|<<watch|shortcut=w|watchThingy>>'; | var watchstr='<<unwatch|unwatchShort>>|<<watch|shortcut=w|watchThingy>>'; | ||
str+='<br>if(talk){' + | str+='<br>if(talk){' + | ||
editOldidStr+'|<<new|shortcut=+>>' + '*' + historystr+'*'+watchstr + '*' + | editOldidStr+'|<<new|shortcut=+>>' + '*' + historystr+'*'+watchstr + '*' + | ||
| Строка 6315: | Строка 6152: | ||
'<b><<talk|shortcut=t>></b>|<<editTalk|edit>>|<<newTalk|shortcut=+|new>>' | '<b><<talk|shortcut=t>></b>|<<editTalk|edit>>|<<newTalk|shortcut=+|new>>' | ||
+ '}'; | + '}'; | ||
// misc links | // misc links | ||
str += '<br><<whatLinksHere|shortcut=l>>*<<relatedChanges|shortcut=r>>*<<move|shortcut=m>>'; | str += '<br><<whatLinksHere|shortcut=l>>*<<relatedChanges|shortcut=r>>*<<move|shortcut=m>>'; | ||
// admin links | // admin links | ||
str += 'if(admin){<br><<unprotect|unprotectShort>>|<<protect|shortcut=p>>|<<protectlog|log>>*' + | str += 'if(admin){<br><<unprotect|unprotectShort>>|<<protect|shortcut=p>>|<<protectlog|log>>*' + | ||
| Строка 6324: | Строка 6161: | ||
return str; | return str; | ||
} | } | ||
function navLinksHTML (article, hint, params) { //oldid, rcid) { | function navLinksHTML (article, hint, params) { //oldid, rcid) { | ||
var str = '<span class="popupNavLinks">' + defaultNavlinkSpec() + '</span>'; | var str = '<span class="popupNavLinks">' + defaultNavlinkSpec() + '</span>'; | ||
| Строка 6330: | Строка 6167: | ||
return navlinkStringToHTML(str, article, params); | return navlinkStringToHTML(str, article, params); | ||
} | } | ||
function expandConditionalNavlinkString(s,article,z,recursionCount) { | function expandConditionalNavlinkString(s,article,z,recursionCount) { | ||
var oldid=z.oldid, rcid=z.rcid, diff=z.diff; | var oldid=z.oldid, rcid=z.rcid, diff=z.diff; | ||
| Строка 6347: | Строка 6184: | ||
var ret = splitted[0]; | var ret = splitted[0]; | ||
for (var i=1; i<splitted.length; i=i+numParens+1) { | for (var i=1; i<splitted.length; i=i+numParens+1) { | ||
var testString=splitted[i+2-1]; | var testString=splitted[i+2-1]; | ||
var trueString=splitted[i+3-1]; | var trueString=splitted[i+3-1]; | ||
| Строка 6353: | Строка 6190: | ||
if (typeof falseString=='undefined' || !falseString) { falseString=''; } | if (typeof falseString=='undefined' || !falseString) { falseString=''; } | ||
var testResult=null; | var testResult=null; | ||
switch (testString) { | switch (testString) { | ||
case 'user': | case 'user': | ||
| Строка 6384: | Строка 6221: | ||
break; | break; | ||
} | } | ||
switch(testResult) { | switch(testResult) { | ||
case null: ret+=splitted[i]; break; | case null: ret+=splitted[i]; break; | ||
| Строка 6390: | Строка 6227: | ||
case false: ret+=falseString; break; | case false: ret+=falseString; break; | ||
} | } | ||
// append non-conditional string | // append non-conditional string | ||
ret += splitted[i+numParens]; | ret += splitted[i+numParens]; | ||
| Строка 6399: | Строка 6236: | ||
return ret; | return ret; | ||
} | } | ||
function navlinkStringToArray(s, article, params) { | function navlinkStringToArray(s, article, params) { | ||
s=expandConditionalNavlinkString(s,article,params); | s=expandConditionalNavlinkString(s,article,params); | ||
| Строка 6432: | Строка 6269: | ||
return ret; | return ret; | ||
} | } | ||
function navlinkSubstituteHTML(s) { | function navlinkSubstituteHTML(s) { | ||
return s.split('*').join(getValueOf('popupNavLinkSeparator')) | return s.split('*').join(getValueOf('popupNavLinkSeparator')) | ||
| Строка 6440: | Строка 6277: | ||
.split('<menu>').join('<ul class="popup_menu">') | .split('<menu>').join('<ul class="popup_menu">') | ||
.split('</menu>').join('</ul>'); | .split('</menu>').join('</ul>'); | ||
} | } | ||
function navlinkDepth(magic,s) { | function navlinkDepth(magic,s) { | ||
return s.split('<' + magic + '>').length - s.split('</' + magic + '>').length; | return s.split('<' + magic + '>').length - s.split('</' + magic + '>').length; | ||
} | } | ||
// navlinkString: * becomes the separator | // navlinkString: * becomes the separator | ||
// <<foo|bar=baz|fubar>> becomes a foo-link with attribute bar='baz' | // <<foo|bar=baz|fubar>> becomes a foo-link with attribute bar='baz' | ||
// and visible text 'fubar' | // and visible text 'fubar' | ||
// if(test){...} and if(test){...}else{...} work too (nested ok) | // if(test){...} and if(test){...}else{...} work too (nested ok) | ||
function navlinkStringToHTML(s,article,params) { | function navlinkStringToHTML(s,article,params) { | ||
//limitAlert(navlinkStringToHTML, 5, 'navlinkStringToHTML\n' + article + '\n' + (typeof article)); | //limitAlert(navlinkStringToHTML, 5, 'navlinkStringToHTML\n' + article + '\n' + (typeof article)); | ||
| Строка 6482: | Строка 6319: | ||
return html; | return html; | ||
} | } | ||
function navlinkTag() { | function navlinkTag() { | ||
this.type='navlinkTag'; | this.type='navlinkTag'; | ||
} | } | ||
navlinkTag.prototype.html=function () { | navlinkTag.prototype.html=function () { | ||
this.getNewWin(); | this.getNewWin(); | ||
| Строка 6508: | Строка 6345: | ||
return opening + html + closing; | return opening + html + closing; | ||
}; | }; | ||
navlinkTag.prototype.getNewWin=function() { | navlinkTag.prototype.getNewWin=function() { | ||
getValueOf('popupLinksNewWindow'); | getValueOf('popupLinksNewWindow'); | ||
| Строка 6514: | Строка 6351: | ||
this.newWin=pg.option.popupLinksNewWindow[this.id]; | this.newWin=pg.option.popupLinksNewWindow[this.id]; | ||
} | } | ||
navlinkTag.prototype.getPrintFunction=function() { //think about this some more | navlinkTag.prototype.getPrintFunction=function() { //think about this some more | ||
// this.id and this.article should already be defined | // this.id and this.article should already be defined | ||
| Строка 6520: | Строка 6357: | ||
var html=''; | var html=''; | ||
var a,t; | var a,t; | ||
this.noPopup=1; | this.noPopup=1; | ||
switch (this.id) { | switch (this.id) { | ||
case 'contribs': case 'history': case 'whatLinksHere': | case 'contribs': case 'history': case 'whatLinksHere': | ||
if (!getValueOf('popupUseQueryInterface')) { break; } | |||
case 'userPage': case 'monobook': case 'userTalk': | case 'userPage': case 'monobook': case 'userTalk': | ||
case 'talk': case 'article': case 'lastEdit': | case 'talk': case 'article': case 'lastEdit': | ||
| Строка 6530: | Строка 6368: | ||
switch (this.id) { | switch (this.id) { | ||
case 'email': case 'contribs': case 'block': case 'unblock': | case 'email': case 'contribs': case 'block': case 'unblock': | ||
case 'userlog': case 'userSpace | case 'userlog': case 'userSpace': | ||
this.article=this.article.userName(); | this.article=this.article.userName(); | ||
} | } | ||
switch (this.id) { | switch (this.id) { | ||
case 'userTalk': case 'newUserTalk': case 'editUserTalk': | case 'userTalk': case 'newUserTalk': case 'editUserTalk': | ||
| Строка 6542: | Строка 6380: | ||
delete this.oldid; | delete this.oldid; | ||
} | } | ||
if (this.id=='editMonobook' || this.id=='monobook') { this.article.append('/monobook.js'); } | if (this.id=='editMonobook' || this.id=='monobook') { this.article.append('/monobook.js'); } | ||
if (this.id != 'mainlink') { | if (this.id != 'mainlink') { | ||
// FIXME anchor handling should be done differently with Title object | // FIXME anchor handling should be done differently with Title object | ||
| Строка 6550: | Строка 6388: | ||
// if (typeof this.text=='undefined') this.text=popupString(this.id); | // if (typeof this.text=='undefined') this.text=popupString(this.id); | ||
} | } | ||
switch (this.id) { | switch (this.id) { | ||
case 'undelete': this.print=specialLink; this.specialpage='Undelete'; this.sep='/'; break; | case 'undelete': this.print=specialLink; this.specialpage='Undelete'; this.sep='/'; break; | ||
| Строка 6557: | Строка 6395: | ||
case 'move': this.print=specialLink; this.specialpage='Movepage'; break; | case 'move': this.print=specialLink; this.specialpage='Movepage'; break; | ||
case 'contribs': this.print=specialLink; this.specialpage='Contributions'; break; | case 'contribs': this.print=specialLink; this.specialpage='Contributions'; break; | ||
case 'email': this.print=specialLink; this.specialpage='Emailuser'; break; | case 'email': this.print=specialLink; this.specialpage='Emailuser'; break; | ||
case 'block': this.print=specialLink; this.specialpage='Blockip'; this.sep='&ip='; break; | case 'block': this.print=specialLink; this.specialpage='Blockip'; this.sep='&ip='; break; | ||
| Строка 6566: | Строка 6403: | ||
case 'protectlog': this.print=specialLink; this.specialpage='Log'; this.sep='&type=protect&page='; break; | case 'protectlog': this.print=specialLink; this.specialpage='Log'; this.sep='&type=protect&page='; break; | ||
case 'deletelog': this.print=specialLink; this.specialpage='Log'; this.sep='&type=delete&page='; break; | case 'deletelog': this.print=specialLink; this.specialpage='Log'; this.sep='&type=delete&page='; break; | ||
case 'userSpace': this.print=specialLink; this.specialpage='Prefixindex'; this.sep='&namespace=2& | case 'userSpace': this.print=specialLink; this.specialpage='Prefixindex'; this.sep='&namespace=2&from='; break; | ||
case 'search': this.print=specialLink; this.specialpage='Search'; this.sep='&fulltext=Search&search='; break; | case 'search': this.print=specialLink; this.specialpage='Search'; this.sep='&fulltext=Search&search='; break; | ||
case 'history': case 'historyfeed': case 'unwatch': case 'watch': | case 'history': case 'historyfeed': case 'unwatch': case 'watch': | ||
case 'unprotect': case 'protect': | case 'unprotect': case 'protect': | ||
this.print=wikiLink; this.action=this.id; break; | this.print=wikiLink; this.action=this.id; break; | ||
case 'delete': | case 'delete': | ||
this.print=wikiLink; this.action='delete'; | this.print=wikiLink; this.action='delete'; | ||
| Строка 6579: | Строка 6416: | ||
} | } | ||
break; | break; | ||
case 'markpatrolled': | case 'markpatrolled': | ||
case 'edit': // editOld should keep the oldid, but edit should not. | case 'edit': // editOld should keep the oldid, but edit should not. | ||
| Строка 6627: | Строка 6464: | ||
this.print=arinLink; break; | this.print=arinLink; break; | ||
case 'count': | case 'count': | ||
this.print= | this.print=kateLink; break; | ||
case 'google': | case 'google': | ||
this.print=googleLink; break; | this.print=googleLink; break; | ||
case 'contribsTree': | |||
this.print=contribsTreeLink; break; | |||
case 'editors': | case 'editors': | ||
this.print=editorListLink; break; | this.print=editorListLink; break; | ||
| Строка 6692: | Строка 6531: | ||
return false; // swallow keypress | return false; // swallow keypress | ||
} | } | ||
var letter=String.fromCharCode(keyCode); | var letter=String.fromCharCode(keyCode); | ||
var links=pg.current.link.navpopup.mainDiv.getElementsByTagName('A'); | var links=pg.current.link.navpopup.mainDiv.getElementsByTagName('A'); | ||
var startLink=0; | var startLink=0; | ||
var i,j; | var i,j; | ||
if (popupHandleKeypress.lastPopupLinkSelected) { | if (popupHandleKeypress.lastPopupLinkSelected) { | ||
for (i=0; i<links.length; ++i) { | for (i=0; i<links.length; ++i) { | ||
| Строка 6712: | Строка 6551: | ||
} | } | ||
} | } | ||
// pass keypress on | // pass keypress on | ||
if (document.oldPopupOnkeypress) { return document.oldPopupOnkeypress(evt); } | if (document.oldPopupOnkeypress) { return document.oldPopupOnkeypress(evt); } | ||
return true; | return true; | ||
} | } | ||
function addPopupShortcuts() { | function addPopupShortcuts() { | ||
if (document.onkeypress!=popupHandleKeypress) { | if (document.onkeypress!=popupHandleKeypress) { | ||
| Строка 6724: | Строка 6563: | ||
document.onkeypress=popupHandleKeypress; | document.onkeypress=popupHandleKeypress; | ||
} | } | ||
function rmPopupShortcuts() { | function rmPopupShortcuts() { | ||
popupHandleKeypress.lastPopupLinkSelected=null; | popupHandleKeypress.lastPopupLinkSelected=null; | ||
| Строка 6736: | Строка 6575: | ||
} catch (nasties) { /* IE goes here */ } | } catch (nasties) { /* IE goes here */ } | ||
} | } | ||
function addLinkProperty(html, property) { | function addLinkProperty(html, property) { | ||
// take "<a href=...>...</a> and add a property | // take "<a href=...>...</a> and add a property | ||
| Строка 6745: | Строка 6584: | ||
return html.substring(0,i) + ' ' + property + html.substring(i); | return html.substring(0,i) + ' ' + property + html.substring(i); | ||
} | } | ||
function addPopupShortcut(html, key) { | function addPopupShortcut(html, key) { | ||
if (!getValueOf('popupShortcutKeys')) { return html; } | if (!getValueOf('popupShortcutKeys')) { return html; } | ||
| Строка 6784: | Строка 6623: | ||
oldRev = oldRev || 0; | oldRev = oldRev || 0; | ||
newRev = newRev || 0; | newRev = newRev || 0; | ||
var go = function() { | var go = function() { | ||
pendingNavpopTask(navpop); | pendingNavpopTask(navpop); | ||
getWiki(article, doneDiffNew, newRev, navpop); | getWiki(article, doneDiffNew, newRev, navpop); | ||
pendingNavpopTask(navpop); | pendingNavpopTask(navpop); | ||
getWiki(article, doneDiffOld, oldRev, navpop); | getWiki(article, doneDiffOld, oldRev, navpop); | ||
var tz = Cookie.read('popTz'); | var tz = Cookie.read('popTz'); | ||
if ( ( | if (getValueOf('popupUseQueryInterface') && getValueOf('popupAdjustDiffDates') && tz===null) { | ||
pendingNavpopTask(navpop); | pendingNavpopTask(navpop); | ||
getPageWithCaching(pg.wiki.wikibase + '/ | getPageWithCaching(pg.wiki.wikibase + '/query.php?format=json&what=userinfo&uioptions=timecorrection', | ||
function(d) { | function(d) { | ||
completedNavpopTask(navpop); | completedNavpopTask(navpop); | ||
| Строка 6807: | Строка 6646: | ||
else { navpop.addHook(go, 'unhide', 'before', 'DOWNLOAD_DIFFS'); } | else { navpop.addHook(go, 'unhide', 'before', 'DOWNLOAD_DIFFS'); } | ||
} | } | ||
function setTimecorrectionCookie(d) { | function setTimecorrectionCookie(d) { | ||
Cookie.create('popTz', getTimeOffset(getJsObj(d.data).meta.user.timecorrection), 1); | |||
} | } | ||
function doneDiff(download, isOld) { | function doneDiff(download, isOld) { | ||
if (!download.owner || !download.owner.diffData) { return; } | if (!download.owner || !download.owner.diffData) { return; } | ||
| Строка 6828: | Строка 6660: | ||
if (diffDownloadsComplete(navpop)) { insertDiff(navpop); } | if (diffDownloadsComplete(navpop)) { insertDiff(navpop); } | ||
} | } | ||
function diffDownloadsComplete(navpop) { | function diffDownloadsComplete(navpop) { | ||
if ( Cookie.read('popTz')===null) { return false; } | if (getValueOf('popupUseQueryInterface') && Cookie.read('popTz')===null) { return false; } | ||
return navpop.diffData.Old && navpop.diffData.New; | return navpop.diffData.Old && navpop.diffData.New; | ||
} | } | ||
function doneDiffNew(download) { doneDiff(download, false); } | function doneDiffNew(download) { doneDiff(download, false); } | ||
function doneDiffOld(download) { doneDiff(download, true); } | function doneDiffOld(download) { doneDiff(download, true); } | ||
function rmBoringLines(a,b,context) { | function rmBoringLines(a,b,context) { | ||
if (typeof context == 'undefined') { context=2; } | if (typeof context == 'undefined') { context=2; } | ||
// this is fairly slow... i think it's quicker than doing a word-based diff from the off, though | // this is fairly slow... i think it's quicker than doing a word-based diff from the off, though | ||
| Строка 6844: | Строка 6676: | ||
var bb=[], bbb=[]; | var bb=[], bbb=[]; | ||
var i, j; | var i, j; | ||
// first, gather all disconnected nodes in a and all crossing nodes in a and b | // first, gather all disconnected nodes in a and all crossing nodes in a and b | ||
for (i=0; i<a.length; ++i ) { | for (i=0; i<a.length; ++i ) { | ||
| Строка 6853: | Строка 6685: | ||
} | } | ||
} | } | ||
// pick up remaining disconnected nodes in b | // pick up remaining disconnected nodes in b | ||
for (i=0; i<b.length; ++i ) { | for (i=0; i<b.length; ++i ) { | ||
| Строка 6859: | Строка 6691: | ||
if(!b[i].paired) { bb[i]=1; } | if(!b[i].paired) { bb[i]=1; } | ||
} | } | ||
// another pass to gather context: we want the neighbours of included nodes which are not yet included | // another pass to gather context: we want the neighbours of included nodes which are not yet included | ||
// we have to add in partners of these nodes, but we don't want to add context for *those* nodes in the next pass | // we have to add in partners of these nodes, but we don't want to add context for *those* nodes in the next pass | ||
| Строка 6869: | Строка 6701: | ||
} | } | ||
} | } | ||
for (i=0; i<a.length; ++i) { | for (i=0; i<a.length; ++i) { | ||
if ( aa[i] == 1 ) { | if ( aa[i] == 1 ) { | ||
| Строка 6877: | Строка 6709: | ||
} | } | ||
} | } | ||
for (i=0; i<bb.length; ++i) { | for (i=0; i<bb.length; ++i) { | ||
if (bb[i] > 0) { // it's a row we need | if (bb[i] > 0) { // it's a row we need | ||
| Строка 6894: | Строка 6726: | ||
} | } | ||
} | } | ||
return { a: aaa, b: bbb}; | return { a: aaa, b: bbb}; | ||
} | } | ||
function stripOuterCommonLines(a,b,context) { | function stripOuterCommonLines(a,b,context) { | ||
var i=0; | var i=0; | ||
| Строка 6903: | Строка 6735: | ||
var j=a.length-1; var k=b.length-1; | var j=a.length-1; var k=b.length-1; | ||
while ( j>=0 && k>=0 && a[j]==b[k] ) { --j; --k; } | while ( j>=0 && k>=0 && a[j]==b[k] ) { --j; --k; } | ||
return { a: a.slice(max(0,i - 1 - context), min(a.length+1, j + context+1)), | return { a: a.slice(max(0,i - 1 - context), min(a.length+1, j + context+1)), | ||
b: b.slice(max(0,i - 1 - context), min(b.length+1, k + context+1)) }; | b: b.slice(max(0,i - 1 - context), min(b.length+1, k + context+1)) }; | ||
} | } | ||
function insertDiff(navpop) { | function insertDiff(navpop) { | ||
// for speed reasons, we first do a line-based diff, discard stuff that seems boring, then do a word-based diff | // for speed reasons, we first do a line-based diff, discard stuff that seems boring, then do a word-based diff | ||
| Строка 6925: | Строка 6757: | ||
oldlines=inner.a; newlines=inner.b; | oldlines=inner.a; newlines=inner.b; | ||
} | } | ||
var lineDiff=diff(oldlines, newlines); | var lineDiff=diff(oldlines, newlines); | ||
var lines2=rmBoringLines(lineDiff.o, lineDiff.n); | var lines2=rmBoringLines(lineDiff.o, lineDiff.n); | ||
var oldlines2=lines2.a; var newlines2=lines2.b; | var oldlines2=lines2.a; var newlines2=lines2.b; | ||
var simpleSplit = !String.prototype.parenSplit.isNative; | var simpleSplit = !String.prototype.parenSplit.isNative; | ||
var html='<hr>'; | var html='<hr>'; | ||
| Строка 6943: | Строка 6775: | ||
'popupPreview', navpop.idNumber); | 'popupPreview', navpop.idNumber); | ||
} | } | ||
function diffDatesTable( oldDl, newDl ) { | function diffDatesTable( oldDl, newDl ) { | ||
var html='<table class="popup_diff_dates">'; | var html='<table class="popup_diff_dates">'; | ||
| Строка 6985: | Строка 6817: | ||
// LINK GENERATION // | // LINK GENERATION // | ||
///////////////////// | ///////////////////// | ||
// titledDiffLink --> titledWikiLink --> generalLink | // titledDiffLink --> titledWikiLink --> generalLink | ||
// wikiLink --> titledWikiLink --> generalLink | // wikiLink --> titledWikiLink --> generalLink | ||
// | // kateLink --> generalLink | ||
function titledDiffLink(l) { // article, text, title, from, to) { | function titledDiffLink(l) { // article, text, title, from, to) { | ||
return titledWikiLink({article: l.article, action: l.to + '&oldid=' + l.from, | return titledWikiLink({article: l.article, action: l.to + '&oldid=' + l.from, | ||
| Строка 6998: | Строка 6830: | ||
actionName: 'diff'}); | actionName: 'diff'}); | ||
} | } | ||
function wikiLink(l) { | function wikiLink(l) { | ||
//{article:article, action:action, text:text, oldid, newid}) { | //{article:article, action:action, text:text, oldid, newid}) { | ||
if (! (typeof l.article == typeof {} | if (! (typeof l.article == typeof {} | ||
&& typeof l.action == typeof '' && typeof l.text==typeof '')) return null; | && typeof l.action == typeof '' && typeof l.text==typeof '')) return null; | ||
if (typeof l.oldid == 'undefined') | if (typeof l.oldid == 'undefined') l.oldid=null; | ||
if (!/^((edit|view|revert|render)$|(raw))/.test(l.action)) { l.oldid=null; } | |||
if (!/^(edit|view|revert|render)$| | |||
var hint=popupString(l.action + 'Hint'); // revertHint etc etc etc | var hint=popupString(l.action + 'Hint'); // revertHint etc etc etc | ||
var oldidData=[l.oldid, safeDecodeURI(l.article)]; | var oldidData=[l.oldid, safeDecodeURI(l.article)]; | ||
| Строка 7014: | Строка 6845: | ||
case 'edit§ion=new': hint = popupString('newSectionHint'); break; | case 'edit§ion=new': hint = popupString('newSectionHint'); break; | ||
case 'edit&undo=': | case 'edit&undo=': | ||
l.action += l.diff; hint = popupString('undoHint'); | |||
break; | break; | ||
case 'raw&ctype=text/css': hint=popupString('rawHint'); break; | case 'raw&ctype=text/css': hint=popupString('rawHint'); break; | ||
case 'revert': | case 'revert': | ||
var p=parseParams(pg.current.link.href); | |||
l.action='edit&autoclick=wpSave&autosummary=' + revertSummary(l.oldid, p.diff); | |||
var p=parseParams(pg.current.link.href); | |||
l.action='edit&autoclick=wpSave | |||
if (p.diff=='prev') { | if (p.diff=='prev') { | ||
l.action += '&direction=prev'; | l.action += '&direction=prev'; | ||
| Строка 7039: | Строка 6860: | ||
break; | break; | ||
case 'nullEdit': | case 'nullEdit': | ||
l.action='edit&autoclick=wpSave | l.action='edit&autoclick=wpSave&autosummary=null'; | ||
break; | break; | ||
case 'historyfeed': | case 'historyfeed': | ||
| Строка 7047: | Строка 6868: | ||
l.action='markpatrolled&rcid='+l.rcid; | l.action='markpatrolled&rcid='+l.rcid; | ||
} | } | ||
if (hint) { | if (hint) { | ||
if (l.oldid) { | if (l.oldid) { | ||
| Строка 7059: | Строка 6880: | ||
hint = safeDecodeURI(l.article + '&action=' + l.action) + (l.oldid) ? '&oldid='+l.oldid : ''; | hint = safeDecodeURI(l.article + '&action=' + l.action) + (l.oldid) ? '&oldid='+l.oldid : ''; | ||
} | } | ||
return titledWikiLink({article: l.article, action: l.action, text: l.text, newWin:l.newWin, | return titledWikiLink({article: l.article, action: l.action, text: l.text, newWin:l.newWin, | ||
title: hint, oldid: l.oldid, noPopup: l.noPopup}); | title: hint, oldid: l.oldid, noPopup: l.noPopup}); | ||
} | } | ||
function revertSummary(oldid, diff) { | function revertSummary(oldid, diff) { | ||
if (getValueOf('popupUseQueryInterface')) { return revertSummaryQueried(oldid, diff); } | |||
if (typeof getValueOf('popupTimeOffset') == 'number' && /[?&]action=history/.test(document.location.href)) { | |||
var links=document.links; | |||
var numlinks=links.length; | |||
var date=null, editor=null; | |||
var dateRe = RegExp('^([0-9]{2}:[0-9]{2}),\s*(.*[1-3][0-9]{3})$'); | |||
for (var i=0; i<numlinks-1; ++i) { | |||
if (RegExp('oldid='+oldid).test(links[i].href) && dateRe.test(links[i].innerHTML)) { | |||
// help konqueror out by putting the time at the end | |||
var ds = links[i].innerHTML.replace(dateRe, '$2 $1'); | |||
// d is parsed according to current locale, in FF at least | |||
// this is only OK if the user has set the time offset in prefs! | |||
var d=new Date(+(new Date(ds)) - 1000*3600*getValueOf('popupTimeOffset')); | |||
// strip out zero seconds and timezone in date, since they're prolly bogus | |||
date=d.toString().replace(/([0-9]{2}:[0-9]{2}):00.*/, '$1'); | |||
editor=Title.fromURL(links[i+1].href).userName(); | |||
break; | |||
} | |||
} | |||
if (date && editor && diff != 'prev') { | |||
return simplePrintf(getValueOf('popupExtendedRevertSummary'), [date, editor, oldid]); | |||
} | |||
} | |||
if (diff != 'prev') { | |||
return simplePrintf(getValueOf('popupRevertSummary'), [ oldid ]); | |||
} | |||
return simplePrintf(getValueOf('popupRevertToPreviousSummary'), [ oldid ]); | |||
} | |||
function revertSummaryQueried(oldid, diff) { | |||
var ret=''; | var ret=''; | ||
if (diff == 'prev') { | if (diff == 'prev') { | ||
| Строка 7071: | Строка 6922: | ||
return ret + '&autorv=' + oldid; | return ret + '&autorv=' + oldid; | ||
} | } | ||
function titledWikiLink(l) { | function titledWikiLink(l) { | ||
// possible properties of argument: | // possible properties of argument: | ||
// article, action, text, title, oldid, actionName, className, noPopup | // article, action, text, title, oldid, actionName, className, noPopup | ||
// oldid = null is fine here | // oldid = null is fine here | ||
// article and action are mandatory args | // article and action are mandatory args | ||
if (typeof l.article == 'undefined' || typeof l.action=='undefined') { | if (typeof l.article == 'undefined' || typeof l.action=='undefined') { | ||
errlog('got undefined article or action in titledWikiLink'); | errlog('got undefined article or action in titledWikiLink'); | ||
return null; | return null; | ||
} | } | ||
var base = pg.wiki.titlebase + l.article.urlString(); | var base = pg.wiki.titlebase + l.article.urlString(); | ||
var url=base; | var url=base; | ||
if (typeof l.actionName=='undefined' || !l.actionName) { l.actionName='action'; } | if (typeof l.actionName=='undefined' || !l.actionName) { l.actionName='action'; } | ||
// no need to add &action=view, and this confuses anchors | // no need to add &action=view, and this confuses anchors | ||
if (l.action != 'view') { url = base + '&' + l.actionName + '=' + l.action; } | if (l.action != 'view') { url = base + '&' + l.actionName + '=' + l.action; } | ||
if (typeof l.oldid!='undefined' && l.oldid) { url+='&oldid='+l.oldid; } | if (typeof l.oldid!='undefined' && l.oldid) { url+='&oldid='+l.oldid; } | ||
var cssClass=pg.misc.defaultNavlinkClassname; | var cssClass=pg.misc.defaultNavlinkClassname; | ||
if (typeof l.className!='undefined' && l.className) { cssClass=l.className; } | if (typeof l.className!='undefined' && l.className) { cssClass=l.className; } | ||
return generalNavLink({url: url, newWin: l.newWin, | return generalNavLink({url: url, newWin: l.newWin, | ||
title: (typeof l.title != 'undefined') ? l.title : null, | title: (typeof l.title != 'undefined') ? l.title : null, | ||
| Строка 7102: | Строка 6953: | ||
className: cssClass, noPopup:l.noPopup}); | className: cssClass, noPopup:l.noPopup}); | ||
} | } | ||
function getLastContrib(wikipage, newWin) { | function getLastContrib(wikipage, newWin) { | ||
getHistoryInfo(wikipage, function(x){processLastContribInfo(x,{page: wikipage, newWin: newWin})}); | getHistoryInfo(wikipage, function(x){processLastContribInfo(x,{page: wikipage, newWin: newWin})}); | ||
| Строка 7137: | Строка 6988: | ||
else { document.location=url; } | else { document.location=url; } | ||
} | } | ||
function purgePopups() { | function purgePopups() { | ||
processAllPopups(true); | processAllPopups(true); | ||
| Строка 7144: | Строка 6995: | ||
abortAllDownloads(); | abortAllDownloads(); | ||
} | } | ||
function processAllPopups(nullify, banish) { | function processAllPopups(nullify, banish) { | ||
for (var i=0; i<pg.current.links.length; ++i) { | for (var i=0; i<pg.current.links.length; ++i) { | ||
if (!pg.current.links[i].navpopup) { continue; } | if (!pg.current.links[i].navpopup) { continue; } | ||
(nullify || banish) && pg.current.links[i].navpopup.banish(); | (nullify || banish) && pg.current.links[i].navpopup.banish(); | ||
nullify && (pg.current.links[i].navpopup=null); | nullify && (pg.current.links[i].navpopup=null); | ||
} | } | ||
} | } | ||
function disablePopups(){ | function disablePopups(){ | ||
processAllPopups(false, true); | processAllPopups(false, true); | ||
setupTooltips(null, true); | setupTooltips(null, true); | ||
} | } | ||
function togglePreviews() { | function togglePreviews() { | ||
processAllPopups(true, true); | processAllPopups(true, true); | ||
| Строка 7164: | Строка 7014: | ||
abortAllDownloads(); | abortAllDownloads(); | ||
} | } | ||
function magicHistoryLink(l) { | function magicHistoryLink(l) { | ||
// FIXME use onclick change href trick to sort this out instead of window.open | // FIXME use onclick change href trick to sort this out instead of window.open | ||
var jsUrl='', title=''; | var jsUrl='', title=''; | ||
switch(l.id) { | switch(l.id) { | ||
| Строка 7181: | Строка 7031: | ||
break; | break; | ||
} | } | ||
return generalNavLink({url: jsUrl, newWin: false, // can't have new windows with JS links, I think | return generalNavLink({url: jsUrl, newWin: false, // can't have new windows with JS links, I think | ||
title: title, text: l.text, noPopup: l.noPopup}); | title: title, text: l.text, noPopup: l.noPopup}); | ||
} | } | ||
function popupMenuLink(l) { | function popupMenuLink(l) { | ||
var jsUrl=simplePrintf('javascript:%s()', [l.id]); | var jsUrl=simplePrintf('javascript:%s()', [l.id]); | ||
| Строка 7191: | Строка 7041: | ||
return generalNavLink({url: jsUrl, newWin:false, title:title, text:l.text, noPopup:l.noPopup}); | return generalNavLink({url: jsUrl, newWin:false, title:title, text:l.text, noPopup:l.noPopup}); | ||
} | } | ||
function specialLink(l) { | function specialLink(l) { | ||
// properties: article, specialpage, text, sep | // properties: article, specialpage, text, sep | ||
| Строка 7214: | Строка 7064: | ||
if (hint) hint = simplePrintf(hint, [safeDecodeURI(l.article)]); | if (hint) hint = simplePrintf(hint, [safeDecodeURI(l.article)]); | ||
else hint = safeDecodeURI(l.specialpage+':'+l.article) ; | else hint = safeDecodeURI(l.specialpage+':'+l.article) ; | ||
var url = base + l.sep + article; | var url = base + l.sep + article; | ||
return generalNavLink({url: url, title: hint, text: l.text, newWin:l.newWin, noPopup:l.noPopup}); | return generalNavLink({url: url, title: hint, text: l.text, newWin:l.newWin, noPopup:l.noPopup}); | ||
} | } | ||
function generalLink(l) { | function generalLink(l) { | ||
// l.url, l.text, l.title, l.newWin, l.className, l.noPopup | // l.url, l.text, l.title, l.newWin, l.className, l.noPopup | ||
if (typeof l.url=='undefined') return null; | if (typeof l.url=='undefined') return null; | ||
// only quotation marks in the url can screw us up now... I think | // only quotation marks in the url can screw us up now... I think | ||
var url=l.url.split('"').join('%22'); | var url=l.url.split('"').join('%22'); | ||
var ret='<a href="' + url + '"'; | var ret='<a href="' + url + '"'; | ||
if (typeof l.title!='undefined' && l.title) { ret += ' title="' + l.title + '"'; } | if (typeof l.title!='undefined' && l.title) { ret += ' title="' + l.title + '"'; } | ||
| Строка 7239: | Строка 7089: | ||
return ret; | return ret; | ||
} | } | ||
function appendParamsToLink(linkstr, params) { | function appendParamsToLink(linkstr, params) { | ||
var sp=linkstr.parenSplit(RegExp('(href="[^"]+?)"', 'i')); | var sp=linkstr.parenSplit(RegExp('(href="[^"]+?)"', 'i')); | ||
| Строка 7248: | Строка 7098: | ||
return ret; | return ret; | ||
} | } | ||
function changeLinkTargetLink(x) { // newTarget, text, hint, summary, clickButton, minor, title (optional) { | function changeLinkTargetLink(x) { // newTarget, text, hint, summary, clickButton, minor, title (optional) { | ||
if (x.newTarget) { | if (x.newTarget) { | ||
| Строка 7255: | Строка 7105: | ||
// optional: oldTarget (in wikitext) | // optional: oldTarget (in wikitext) | ||
// if x.newTarget omitted or null, remove the link | // if x.newTarget omitted or null, remove the link | ||
//x.text=encodeURI(x.text); // this buggers things up on zh.wikipedia.org and doesn't seem necessary | //x.text=encodeURI(x.text); // this buggers things up on zh.wikipedia.org and doesn't seem necessary | ||
x.clickButton=encodeURI(x.clickButton); | x.clickButton=encodeURI(x.clickButton); | ||
// FIXME: first character of page title as well as namespace should be case insensitive | // FIXME: first character of page title as well as namespace should be case insensitive | ||
// eg [[category:foo]] and [[Category:Foo]] are equivalent | // eg [[category:foo]] and [[Category:Foo]] are equivalent | ||
| Строка 7265: | Строка 7115: | ||
var chs=cA.charAt(0).toUpperCase(); | var chs=cA.charAt(0).toUpperCase(); | ||
chs='['+chs + chs.toLowerCase()+']'; | chs='['+chs + chs.toLowerCase()+']'; | ||
var currentArticleRegexBit= | var currentArticleRegexBit=chs+cA.substring(1); | ||
currentArticleRegexBit=currentArticleRegexBit | currentArticleRegexBit=currentArticleRegexBit | ||
.split(RegExp('[_ ]+', 'g')).join('[_ ]+') | .split(RegExp('[_ ]+', 'g')).join('[_ ]+') | ||
| Строка 7273: | Строка 7123: | ||
currentArticleRegexBit = '\\s*(' + currentArticleRegexBit + '(?:#[^\\[\\|]*)?)\\s*'; | currentArticleRegexBit = '\\s*(' + currentArticleRegexBit + '(?:#[^\\[\\|]*)?)\\s*'; | ||
// e.g. Computer (archaic) -> \s*([Cc]omputer[_ ](?:%2528|\()archaic(?:%2528|\)))\s* | // e.g. Computer (archaic) -> \s*([Cc]omputer[_ ](?:%2528|\()archaic(?:%2528|\)))\s* | ||
// autoedit=s~\[\[([Cc]ad)\]\]~[[Computer-aided%20design|$1]]~g;s~\[\[([Cc]AD)[|]~[[Computer-aided%20design|~g | // autoedit=s~\[\[([Cc]ad)\]\]~[[Computer-aided%20design|$1]]~g;s~\[\[([Cc]AD)[|]~[[Computer-aided%20design|~g | ||
var title=x.title || wgPageName.split('_').join(' '); | var title=x.title || wgPageName.split('_').join(' '); | ||
var lk=titledWikiLink({article: new Title(title), newWin:x.newWin, | var lk=titledWikiLink({article: new Title(title), newWin:x.newWin, | ||
| Строка 7286: | Строка 7136: | ||
if (x.newTarget) { | if (x.newTarget) { | ||
// escape '&' and other nasties | // escape '&' and other nasties | ||
var t= | var t=encodeURI(x.newTarget); | ||
var s= | var s=encodeURI(literalizeRegex(x.newTarget)); | ||
cmd += 's~\\[\\['+currentArticleRegexBit+'\\]\\]~[['+t+'|$1]]~g;'; | cmd += 's~\\[\\['+currentArticleRegexBit+'\\]\\]~[['+t+'|$1]]~g;'; | ||
cmd += 's~\\[\\['+currentArticleRegexBit+'[|]~[['+t+'|~g;'; | cmd += 's~\\[\\['+currentArticleRegexBit+'[|]~[['+t+'|~g;'; | ||
| Строка 7295: | Строка 7145: | ||
cmd += 's~\\[\\['+currentArticleRegexBit+'[|](.*?)\\]\\]~$2~g'; | cmd += 's~\\[\\['+currentArticleRegexBit+'[|](.*?)\\]\\]~$2~g'; | ||
} | } | ||
cmd += '&autoclick='+x.clickButton | cmd += '&autoclick='+x.clickButton; | ||
cmd += ( x.minor == null ) ? '' : '&autominor='+x.minor; | cmd += ( x.minor == null ) ? '' : '&autominor='+x.minor; | ||
cmd += ( x.watch == null ) ? '' : '&autowatch='+x.watch; | cmd += ( x.watch == null ) ? '' : '&autowatch='+x.watch; | ||
cmd += '&autosummary='+ | cmd += '&autosummary='+x.summary; | ||
return appendParamsToLink(lk, 'autoedit='+cmd); | return appendParamsToLink(lk, 'autoedit='+cmd); | ||
} | } | ||
function redirLink(redirMatch, article) { | function redirLink(redirMatch, article) { | ||
// NB redirMatch is in wikiText | // NB redirMatch is in wikiText | ||
var ret=''; | var ret=''; | ||
if (getValueOf('popupAppendRedirNavLinks') && getValueOf('popupNavLinks')) { | if (getValueOf('popupAppendRedirNavLinks') && getValueOf('popupNavLinks')) { | ||
ret += '<hr>'; | ret += '<hr>'; | ||
| Строка 7315: | Строка 7165: | ||
{newTarget: redirMatch, text: popupString('Redirects'), | {newTarget: redirMatch, text: popupString('Redirects'), | ||
hint: popupString('Fix this redirect'), | hint: popupString('Fix this redirect'), | ||
summary: simplePrintf(getValueOf('popupFixRedirsSummary'), | summary: simplePrintf(getValueOf('popupFixRedirsSummary'), | ||
[article.toString(), redirMatch ]), | [article.toString(), redirMatch ]), | ||
oldTarget: article.toString(), | oldTarget: article.toString(), | ||
clickButton: getValueOf('popupRedirAutoClick'), minor: true, | clickButton: getValueOf('popupRedirAutoClick'), minor: true, | ||
watch: getValueOf('popupWatchRedirredPages')}) | watch: getValueOf('popupWatchRedirredPages')}) | ||
, 'R'); | , 'R'); | ||
ret += popupString(' to '); | ret += popupString(' to '); | ||
} | } | ||
else ret += popupString('Redirects') + popupString(' to '); | else ret += popupString('Redirects') + popupString(' to '); | ||
return ret; | return ret; | ||
} | } | ||
else return '<br> ' + popupString('Redirects') + popupString(' to ') + | else return '<br> ' + popupString('Redirects') + popupString(' to ') + | ||
titledWikiLink({article: new Title().fromWikiText(redirMatch), action: 'view', /* FIXME: newWin */ | titledWikiLink({article: new Title().fromWikiText(redirMatch), action: 'view', /* FIXME: newWin */ | ||
text: safeDecodeURI(redirMatch), title: popupString('Bypass redirect')}); | text: safeDecodeURI(redirMatch), title: popupString('Bypass redirect')}); | ||
} | } | ||
function arinLink(l) { | function arinLink(l) { | ||
if (!saneLinkCheck(l)) { return null; } | if (!saneLinkCheck(l)) { return null; } | ||
if ( ! l.article.isIpUser() || ! pg.wiki.wikimedia) return null; | if ( ! l.article.isIpUser() || ! pg.wiki.wikimedia) return null; | ||
var uN=l.article.userName(); | var uN=l.article.userName(); | ||
return generalNavLink({url:'http://ws.arin.net/cgi-bin/whois.pl?queryinput=' + | return generalNavLink({url:'http://ws.arin.net/cgi-bin/whois.pl?queryinput=' + escape(uN), newWin:l.newWin, | ||
title: tprintf('Look up %s in ARIN whois database', [uN]), | title: tprintf('Look up %s in ARIN whois database', [uN]), | ||
text: l.text, noPopup:1}); | text: l.text, noPopup:1}); | ||
} | } | ||
function toolDbName(cookieStyle) { | function toolDbName(cookieStyle) { | ||
var ret=null; | var ret=null; | ||
var theWiki=pg.wiki.hostname.split('.')[1]; | var theWiki=pg.wiki.hostname.split('.')[1]; | ||
if (pg.wiki.hostname==pg.wiki.commons) { | if (pg.wiki.hostname==pg.wiki.commons) { | ||
ret = 'commonswiki'; | ret = 'commonswiki'; | ||
} else { | } else { | ||
switch(theWiki) { | switch(theWiki) { | ||
case 'wikipedia': | case 'wikipedia': | ||
case 'wikimedia': | case 'wikimedia': | ||
ret = pg.wiki.lang + 'wiki'; | ret = pg.wiki.lang + 'wiki'; | ||
break; | break; | ||
default: | default: | ||
ret = pg.wiki.lang + theWiki; | ret = pg.wiki.lang + theWiki; | ||
break; | break; | ||
} | |||
} | |||
if (!cookieStyle) { ret+= '_p'; } | |||
return ret; | |||
} | |||
function saneLinkCheck(l) { | |||
if (typeof l.article != typeof {} || typeof l.text != typeof '') { return false; } | |||
return true; | |||
} | |||
function kateLink(l) { | |||
if(!saneLinkCheck(l)) return null; | |||
if (! pg.wiki.wikimedia) return null; | |||
var uN=l.article.userName(); | |||
var tool=getValueOf('popupEditCounterTool'); | |||
var url; | |||
var defaultToolUrl='http://tools.wikimedia.de/~$3/cgi-bin/count_edits?dbname=$2&user=$1'; | |||
switch(tool) { | |||
case 'custom': | |||
url=simplePrintf(getValueOf('popupEditCounterUrl'), [ escape(uN), toolDbName() ]); | |||
break; | |||
default: | |||
url=simplePrintf(defaultToolUrl, [ escape(uN), toolDbName(), tool ]); | |||
} | |||
return generalNavLink({url:url, title: tprintf('katelinkHint', [uN]), | |||
newWin:l.newWin, text: l.text, noPopup:1}); | |||
} | |||
function contribsTreeLink(l) { | |||
if(!saneLinkCheck(l)) return null; | |||
if (! pg.wiki.wikimedia) return null; | |||
var uN=l.article.userName(); | |||
var url='http://tools.wikimedia.de/~interiot/cgi-bin/contribution_tree?dbname='; | |||
url += toolDbName() + '&user='+ escape(uN); | |||
return generalNavLink({url:url, title: tprintf('contribsTreeHint', [uN]), newWin:l.newWin, text: l.text, | |||
noPopup:1}); | |||
} | |||
function globalSearchLink(l) { | |||
if(!saneLinkCheck(l)) return null; | |||
var base='http://vs.aka-online.de/cgi-bin/globalwpsearch.pl?timeout=120&search='; | |||
var article=l.article.urlString({keepSpaces:true}); | |||
return generalNavLink({url:base + article, newWin:l.newWin, | |||
title: tprintf('globalSearchHint', [article]), | |||
text: l.text, noPopup:1}); | |||
} | |||
function googleLink(l) { | |||
if(!saneLinkCheck(l)) return null; | |||
var base='http://www.google.com/search?q='; | |||
var article=l.article.urlString({keepSpaces:true}); | |||
return generalNavLink({url:base + '%22' + article + '%22', newWin:l.newWin, | |||
title: tprintf('googleSearchHint', [article]), | |||
text: l.text, noPopup:1}); | |||
} | |||
function editorListLink(l) { | |||
if(!saneLinkCheck(l)) return null; | |||
var article= l.article.articleFromTalkPage() || l.article; | |||
var base='http://tools.wikimedia.de/~tim/counter/?page='; | |||
return generalNavLink({url:base+article.urlString(), | |||
title: tprintf('editorListHint', [article]), | |||
newWin:l.newWin, text: l.text, noPopup:1}); | |||
} | |||
function generalNavLink(l) { | |||
l.className = (l.className==null) ? 'popupNavLink' : l.className; | |||
return generalLink(l); | |||
} | |||
////////////////////////////////////////////////// | |||
// magic history links | |||
// | |||
function getHistoryInfo(wikipage, whatNext) { | |||
log('getHistoryInfo'); | |||
getHistory(wikipage, whatNext ? function(d){whatNext(processHistory(d));} : processHistory); | |||
} | |||
// FIXME eliminate pg.idNumber ... how? :-( | |||
function getHistory(wikipage, onComplete) { | |||
log('getHistory'); | |||
var url; | |||
if (getValueOf('popupUseQueryInterface')) { | |||
url = pg.wiki.wikibase + '/query.php?format=json&what=revisions&titles=' + | |||
new Title(wikipage).urlString() + '&rvlimit=' + getValueOf('popupHistoryLimit'); | |||
} else { | |||
url = pg.wiki.titlebase + new Title(wikipage).urlString() + | |||
'&action=history' + '&limit=' + getValueOf('popupHistoryLimit'); | |||
} | |||
log('getHistory: url='+url); | |||
return startDownload(url, pg.idNumber+'history', onComplete); | |||
} | |||
function processHistory(download) { | |||
if (getValueOf('popupUseQueryInterface')) { | |||
return processHistoryQuery(download); | |||
} | |||
return processHistoryScreenScrape(download); | |||
} | |||
function processHistoryScreenScrape(download) { | |||
// screen scrape alert | |||
var d=download.data; | |||
// pg.misc.data=d; // for debugging | |||
var edits=[]; | |||
var split=d.split('<li>'); | |||
for (var i=0; i<split.length; ++i) { | |||
var histRe=RegExp( | |||
'^[(].*?type="radio" value="([0-9]*)".*?class=\'history-user\'>' + | |||
'<a href="(/wiki/User:|/w/index.php[?]title=(Special:Contributions&target=|User:))([^&"]*)'); | |||
var match=histRe.exec(split[i]); | |||
if (match) { | |||
edits.push({ oldid: match[1], editor: match[4] }); | |||
} | } | ||
} | } | ||
var userName=getValueOf('popupUserName') || | |||
Cookie.read(pg.wiki.userNameCookie).split('+').join('_'); | |||
return finishProcessHistory(edits, userName); | |||
var | |||
return | |||
} | } | ||
function | function processHistoryQuery(download) { | ||
var | log ('processHistoryQuery'); | ||
var d=download.data; | |||
log('d='+d); | |||
var jsobj; | |||
try { | try { | ||
log('trying to parse JSON'); | |||
log('jsobj=' + d); | |||
eval('jsobj=' + d); | |||
log('done eval; jsobj='+jsobj); | |||
window.x=jsobj; | window.x=jsobj; | ||
var p=jsobj[' | var p=jsobj['pages']; | ||
log('got p'); | |||
for (var pageid in p) { | for (var pageid in p) { | ||
var revisions=p[pageid]['revisions']; | var revisions=p[pageid]['revisions']; | ||
| Строка 7463: | Строка 7358: | ||
break; | break; | ||
} | } | ||
log('got revisions'); | |||
log(revisions.length +' of them'); | |||
} catch (someError) { | } catch (someError) { | ||
log('Something went wrong with JSON business'); | log('Something went wrong with JSON business'); | ||
| Строка 7472: | Строка 7369: | ||
} | } | ||
log('processed ' + edits.length + ' edits'); | log('processed ' + edits.length + ' edits'); | ||
return finishProcessHistory(edits, | var userName=getValueOf('popupUserName') || | ||
unescape(Cookie.read(pg.wiki.userNameCookie).split('+').join(' ')); | |||
return finishProcessHistory(edits, userName); | |||
} | } | ||
function finishProcessHistory(edits, userName) { | function finishProcessHistory(edits, userName) { | ||
var histInfo={}; | var histInfo={}; | ||
histInfo.edits=edits; | histInfo.edits=edits; | ||
histInfo.userName=userName; | histInfo.userName=userName; | ||
for (var i=0; i<edits.length; ++i) { | for (var i=0; i<edits.length; ++i) { | ||
if (typeof histInfo.myLastEdit == 'undefined' && userName && edits[i].editor==userName) { | if (typeof histInfo.myLastEdit == 'undefined' && userName && edits[i].editor==userName) { | ||
| Строка 7498: | Строка 7397: | ||
////////////////////////////////////////////////// | ////////////////////////////////////////////////// | ||
// options | // options | ||
// check for cookies and existing value, else use default | // check for cookies and existing value, else use default | ||
function defaultize(x) { | function defaultize(x) { | ||
| Строка 7514: | Строка 7413: | ||
} | } | ||
} | } | ||
function newOption(x, def) { | function newOption(x, def) { | ||
pg.optionDefault[x]=def; | pg.optionDefault[x]=def; | ||
} | } | ||
function setDefault(x, def) { | function setDefault(x, def) { | ||
return newOption(x, def); | return newOption(x, def); | ||
} | } | ||
function getValueOf(varName) { | function getValueOf(varName) { | ||
defaultize(varName); | defaultize(varName); | ||
return pg.option[varName]; | return pg.option[varName]; | ||
} | } | ||
function useDefaultOptions() { // for testing | function useDefaultOptions() { // for testing | ||
for (var p in pg.optionDefault) { | for (var p in pg.optionDefault) { | ||
| Строка 7534: | Строка 7433: | ||
} | } | ||
} | } | ||
function setOptions() { | function setOptions() { | ||
// user-settable parameters and defaults | // user-settable parameters and defaults | ||
// Basic options | // Basic options | ||
newOption('popupDelay', 0.5); | newOption('popupDelay', 0.5); | ||
| Строка 7556: | Строка 7455: | ||
newOption('popupTocLinks', false); | newOption('popupTocLinks', false); | ||
newOption('popupSubpopups', true); | newOption('popupSubpopups', true); | ||
newOption('popupUserName', ''); // should be magically detected with cookies if this isn't set | |||
newOption('popupDragHandle', false /* 'popupTopLinks'*/); | newOption('popupDragHandle', false /* 'popupTopLinks'*/); | ||
newOption('popupLazyPreviews', true); | newOption('popupLazyPreviews', true); | ||
| Строка 7564: | Строка 7464: | ||
newOption('popupActiveNavlinks', true); | newOption('popupActiveNavlinks', true); | ||
newOption('popupModifier', false); // ctrl, shift, alt or meta | newOption('popupModifier', false); // ctrl, shift, alt or meta | ||
//<NOLITE> | //<NOLITE> | ||
// images | // images | ||
| Строка 7578: | Строка 7476: | ||
newOption('popupThumbAction', 'imagepage'); //'sizetoggle'); | newOption('popupThumbAction', 'imagepage'); //'sizetoggle'); | ||
newOption('popupImageSize', 60); | newOption('popupImageSize', 60); | ||
newOption('popupShowNonCommonsImages', false); | |||
// redirs, dabs, reversion | // redirs, dabs, reversion | ||
newOption('popupFixRedirs', false); | newOption('popupFixRedirs', false); | ||
| Строка 7588: | Строка 7487: | ||
newOption('popupWatchDisambiggedPages', null); | newOption('popupWatchDisambiggedPages', null); | ||
newOption('popupWatchRedirredPages', null); | newOption('popupWatchRedirredPages', null); | ||
// navlinks | // navlinks | ||
newOption('popupNavLinks', true); | newOption('popupNavLinks', true); | ||
newOption('popupNavLinkSeparator', ' ⋅ '); | newOption('popupNavLinkSeparator', ' ⋅ '); | ||
newOption('popupLastEditLink', true); | newOption('popupLastEditLink', true); | ||
newOption('popupEditCounterTool', ' | newOption('popupEditCounterTool', 'interiot'); | ||
newOption('popupEditCounterUrl', | newOption('popupEditCounterUrl', ''); | ||
newOption('popupExtraUserMenu', ''); | newOption('popupExtraUserMenu', ''); | ||
//</NOLITE> | //</NOLITE> | ||
// previews etc | // previews etc | ||
newOption('popupPreviews', true); | newOption('popupPreviews', true); | ||
| Строка 7606: | Строка 7504: | ||
newOption('popupLastModified', true); | newOption('popupLastModified', true); | ||
newOption('popupPreviewKillTemplates', true); | newOption('popupPreviewKillTemplates', true); | ||
newOption('popupPreviewRawTemplates', | newOption('popupPreviewRawTemplates', false); | ||
newOption('popupPreviewFirstParOnly', true); | newOption('popupPreviewFirstParOnly', true); | ||
newOption('popupPreviewCutHeadings', true); | newOption('popupPreviewCutHeadings', true); | ||
//<NOLITE> | //<NOLITE> | ||
// diffs | // diffs | ||
| Строка 7620: | Строка 7516: | ||
newOption('popupDiffDates', true); | newOption('popupDiffDates', true); | ||
newOption('popupDiffDatePrinter', 'toLocaleString'); | newOption('popupDiffDatePrinter', 'toLocaleString'); | ||
// edit summaries. God, these are ugly. | // edit summaries. God, these are ugly. | ||
newOption('popupFixDabsSummary', popupString('defaultpopupFixDabsSummary') ); | newOption('popupFixDabsSummary', popupString('defaultpopupFixDabsSummary') ); | ||
| Строка 7642: | Строка 7538: | ||
popupFilterLastModified]); | popupFilterLastModified]); | ||
newOption('extraPopupFilters', []); | newOption('extraPopupFilters', []); | ||
newOption('popupOnEditSelection', 'cursor'); | newOption('popupOnEditSelection', 'cursor'); | ||
newOption('popupUseQueryInterface', true); | |||
newOption('popupPreviewHistory', true); | newOption('popupPreviewHistory', true); | ||
newOption('popupImageLinks', true); | newOption('popupImageLinks', true); | ||
newOption('popupCategoryMembers', true); | newOption('popupCategoryMembers', true); | ||
newOption('popupHistoryPreviewLimit', 25); | newOption('popupHistoryPreviewLimit', 25); | ||
newOption('popupContribsPreviewLimit',25); | newOption('popupContribsPreviewLimit',25); | ||
//</NOLITE> | //</NOLITE> | ||
// new windows | // new windows | ||
newOption('popupNewWindows', false); | newOption('popupNewWindows', false); | ||
newOption('popupLinksNewWindow', {'lastContrib': true, 'sinceMe': true}); | newOption('popupLinksNewWindow', {'lastContrib': true, 'sinceMe': true}); | ||
// regexps | // regexps | ||
newOption('popupDabRegexp', '([{][{]\\s*disambig|disambig\\s*[}][}]|disamb\\s*[}][}]|dab\\s*[}][}])|[{][{]\\s*(((geo|hn|road?|school|number)dis)|[234][lc][acw]|shipindex)(\\s*[|][^}]*)?\\s*[}][}]|is a .*disambiguation.*page'); | newOption('popupDabRegexp', '([{][{]\\s*disambig|disambig\\s*[}][}]|disamb\\s*[}][}]|dab\\s*[}][}])|[{][{]\\s*(((geo|hn|road?|school|number)dis)|[234][lc][acw]|shipindex)(\\s*[|][^}]*)?\\s*[}][}]|is a .*disambiguation.*page'); | ||
| Строка 7669: | Строка 7565: | ||
// See instructions at | // See instructions at | ||
// http://en.wikipedia.org/wiki/Wikipedia:Tools/Navigation_popups/Translation | // http://en.wikipedia.org/wiki/Wikipedia:Tools/Navigation_popups/Translation | ||
pg.string = { | pg.string = { | ||
///////////////////////////////////// | ///////////////////////////////////// | ||
| Строка 7707: | Строка 7603: | ||
'popupsMenu': 'popups', | 'popupsMenu': 'popups', | ||
'togglePreviewsHint': 'Toggle preview generation in popups on this page', | 'togglePreviewsHint': 'Toggle preview generation in popups on this page', | ||
'toggle previews': 'toggle previews', | 'toggle previews': 'toggle previews', | ||
'reset': 'reset', | 'reset': 'reset', | ||
'more...': 'more...', | 'more...': 'more...', | ||
| Строка 7838: | Строка 7731: | ||
'No image links found': 'No image links found', | 'No image links found': 'No image links found', | ||
'File links': 'File links', | 'File links': 'File links', | ||
'not commons': 'There is no file with this name on the Wikimedia Commons.', | |||
'commons only': 'This file is from the Wikimedia Commons.', | |||
'No image found': 'No image found', | 'No image found': 'No image found', | ||
' | 'commons dupe': 'The same file appears to be available on the Wikimedia Commons.', | ||
' | 'commons conflict': 'A different file with the same name is available on the Wikimedia Commons.', | ||
///////////////////////////////////// | ///////////////////////////////////// | ||
// user-related actions and info | // user-related actions and info | ||
| Строка 7854: | Строка 7749: | ||
'space': 'space', // short form for userSpace link | 'space': 'space', // short form for userSpace link | ||
'PrefixindexHint': 'Show pages in the userspace of %s', | 'PrefixindexHint': 'Show pages in the userspace of %s', | ||
'count': 'count', ///// contributions, log | 'count': 'count', ///// contributions, tree, log | ||
'edit counter': 'edit counter', | 'edit counter': 'edit counter', | ||
' | 'katelinkHint': 'Count the countributions made by %s', | ||
'contribs': 'contribs', | 'contribs': 'contribs', | ||
'contributions': 'contributions', | 'contributions': 'contributions', | ||
'ContributionsHint': 'List the contributions made by %s', | 'ContributionsHint': 'List the contributions made by %s', | ||
'tree': 'tree', | |||
'contribsTreeHint': 'Explore %s\'s contributions by namespace and by article', | |||
'log': 'log', | 'log': 'log', | ||
'user log': 'user log', | 'user log': 'user log', | ||
| Строка 7883: | Строка 7778: | ||
'undoHint': 'undo this edit', | 'undoHint': 'undo this edit', | ||
'Download preview data': 'Download preview data', | 'Download preview data': 'Download preview data', | ||
///////////////////////////////////// | ///////////////////////////////////// | ||
// Autoediting | // Autoediting | ||
| Строка 7900: | Строка 7791: | ||
'zxy': 'zxy' | 'zxy': 'zxy' | ||
}; | }; | ||
function popupString(str) { | function popupString(str) { | ||
if (typeof popupStrings != 'undefined' && popupStrings && popupStrings[str]) { return popupStrings[str]; } | if (typeof popupStrings != 'undefined' && popupStrings && popupStrings[str]) { return popupStrings[str]; } | ||
| Строка 7907: | Строка 7798: | ||
return str; | return str; | ||
} | } | ||
function tprintf(str,subs) { | function tprintf(str,subs) { | ||
if (typeof subs != typeof []) { subs = [subs]; } | if (typeof subs != typeof []) { subs = [subs]; } | ||
return simplePrintf(popupString(str), subs); | return simplePrintf(popupString(str), subs); | ||
} | } | ||
//</NOLITE> | //</NOLITE> | ||
// ENDFILE: strings.js | // ENDFILE: strings.js | ||