MediaWiki:Gadget-watchlist.js: различия между версиями
Перейти к навигации
Перейти к поиску
Содержимое удалено Содержимое добавлено
появилась новая возможность побороть скачки здесь — воспользуемся (см. css и Gadgets-definition) |
устанавливаем куки на 90 дней — имхо, оптимально: не слишком коротко, но и не навечно, оформление кода |
||
Строка 1: | Строка 1: | ||
if ( |
if (mw.config.get('wgCanonicalSpecialPageName') === 'Watchlist' && mw.config.get('wgAction') === 'view') { |
||
mw.hook('wikipage.content').add(function () { |
mw.hook('wikipage.content').add(function () { |
||
setTimeout(function () { // лечение для Firefox |
setTimeout(function () { // лечение для Firefox |
||
/* MAIN BLOCK */ |
|||
var whenPageLoaded = +(new Date()) - 20000 //add 20 sec just in case |
|||
var whenPageLoaded = +(new Date()) - 20000; // add 20 seconds just in case |
|||
var |
var hideInterfaceCSS, rvOffCSS; |
||
var sortingDone, allStarsOn, hoverOnTitlesDone |
var sortingDone, allStarsOn, hoverOnTitlesDone; |
||
//ruwiki |
// ruwiki |
||
var mm = { |
var mm = { |
||
sortTip: 'Сортировать страницы по пространствам', |
sortTip: 'Сортировать страницы по пространствам', |
||
Строка 21: | Строка 22: | ||
}; |
}; |
||
// recent changes type in preferences |
|||
var isEnhanced = mw.util.$content.find('ul.special').length == 0; |
|||
// find insertion points for links: after "days all" |
|||
var linksAt = $('#mw-watchlist-options').find('#days').next(); |
|||
//find insertion points for links: after "days all" |
|||
var linksAt = $('#mw-watchlist-options').find('#days').next() |
|||
// UNWATCH LINKS |
|||
// on every line |
|||
//UNWATCH links: |
|||
if (document.cookie.indexOf('wlunw=1') != -1) { |
|||
//on every line |
|||
showAllStars(); |
|||
if( document.cookie.indexOf('wlunw=1') != -1 ) $(showAllStars) |
|||
else |
} else { |
||
bindHoverOnTitles(); // mouseover on title |
|||
} |
|||
// switch for above, saved in a cookie |
// switch for above, saved in a cookie |
||
addLink( |
|||
addLnk('<img alt="x" style="width:1em;" src="/upwiki/wikipedia/commons/' |
|||
'<img alt="x" style="width:1em;" src="/upwiki/wikipedia/commons/a/a4/Vector_skin_-_page_not_in_the_watchlist.png">', |
|||
mm.unwatchTip |
|||
//click on timestamp (enhanced RC) / empty space (non-enhanced) |
|||
).click(showAllStars); // click on timestamp (enhanced recent changes) / empty space (non-enhanced) |
|||
if (document.cookie.indexOf('wlrvoff=1') != -1) switchRevert(); |
if (document.cookie.indexOf('wlrvoff=1') != -1) switchRevert(); |
||
// OTHER LINKS |
|||
// "sort" link |
// "sort" link |
||
addLink('↑↓', mm.sortTip).click(sortWatchlist); |
|||
// "expand all" link |
// "expand all" link |
||
if ($('.mw-enhancedchanges-arrow').length) { |
if ($('.mw-enhancedchanges-arrow').length) { |
||
addLink('±', mm.expandAll).click(expandMultipleEdits); |
|||
} |
} |
||
// "switch revert" link |
|||
if ($('.mw-rollback-link').length) { |
if ($('.mw-rollback-link').length) { |
||
addLink('⎌', mm.switchRevert).click(switchRevert); |
|||
// "switch revert" link |
|||
addLnk('⎌', mm.switchRevert).click(switchRevert); |
|||
} |
} |
||
// "only new" link |
// "only new" link |
||
addLink(mm.onlynew, mm.onlynewTip).mousedown(onlyNewEntries).attr('id', 'listSince'); |
|||
//TABS |
// TABS |
||
if( |
if (window.wlNoTabs) return; |
||
var mainTab = $('#ca-special, #ca-nstab-special').eq(0) //"Special" tab |
var mainTab = $('#ca-special, #ca-nstab-special').eq(0); // "Special" tab |
||
//change main tab into "watchlist Δ" |
// change main tab into "watchlist Δ" |
||
var wl = $.trim( |
var wl = $.trim($('h1#firstHeading').text()); |
||
mainTab.find('a') //replace "Special" tab text with "Watchlist" |
mainTab.find('a') // replace "Special" tab text with "Watchlist" |
||
.text(wl + ' △') //Δ is good but monobook makes is lowercase |
.text(wl + ' △') // Δ is good but monobook makes is lowercase |
||
.attr('title', wl + ' — ' + mm.onlynewTipLowerCase) |
.attr('title', wl + ' — ' + mm.onlynewTipLowerCase) |
||
.on('mousedown keydown', onlyNewEntries) |
.on('mousedown keydown', onlyNewEntries); |
||
//add "hideInterface" tab |
// add "hideInterface" tab |
||
mainTab.clone(true).removeClass('selected') |
mainTab.clone(true).removeClass('selected') |
||
.appendTo(mainTab.parent()) |
.appendTo(mainTab.parent()) |
||
.click(hideInterface) |
.click(hideInterface) |
||
.attr('id','').attr('href','#') |
.attr('id','').attr('href', '#') |
||
.find('a') |
.find('a') |
||
.text('↸').attr('title', mm.fullPage).attr('accesskey','') |
.text('↸').attr('title', mm.fullPage).attr('accesskey', ''); |
||
if |
if (document.cookie.indexOf('wlmax=1') != -1) hideInterface(); |
||
if ($('.mw-changeslist .mw-rollback-link').first().css('visibility') == 'hidden') { |
if ($('.mw-changeslist .mw-rollback-link').first().css('visibility') == 'hidden') { |
||
Строка 82: | Строка 88: | ||
} |
} |
||
return |
return; |
||
/* FUNCTIONS */ |
|||
function addLink(txt, tip) { |
|||
linksAt.before(' '); |
|||
return $('<a href="#" title="' + tip + '">' + txt + '</a>').insertBefore(linksAt); |
|||
function addLnk(txt, tip){ |
|||
linksAt.before(' ') |
|||
return $('<a href=# title="'+tip+'">'+txt+'</a>').insertBefore(linksAt) |
|||
} |
} |
||
function onlyNewEntries(e) { |
function onlyNewEntries(e) { |
||
var url = window.location.href.split('#')[0] |
var url = window.location.href.split('#')[0]; |
||
var days = ( |
var days = (+(new Date()) - whenPageLoaded)/(1000 * 3600 * 24); |
||
if |
if (days < 0) days = 0.01; // negative might happen when adjusting local time |
||
e.target.href = /[?&]days=/.test(url) |
e.target.href = /[?&]days=/.test(url) |
||
? url.replace(/([?&]days=)[^&]*/, '$1' + days) |
|||
: url + (url.indexOf('?') < 0 ? '?':'&') + 'days=' + days; |
|||
return true |
return true; |
||
} |
} |
||
function showAllStars(e) { |
|||
if (e) { |
|||
e.preventDefault(); |
|||
function showAllStars(e){ |
|||
} |
|||
if( !allStarsOn ){ |
|||
if (!allStarsOn) { |
|||
mw.util.$content.find('a[href*="action=history"]') |
|||
mw.util.$content.find('a[href*="action=history"]') |
|||
.each( function(i, lnk){ updateStar( getRow(this) ) } ) |
|||
.each(function(i, lnk) { |
|||
document.cookie = 'wlunw=1; path=/' |
|||
updateStar(getRow(this)); |
|||
allStarsOn = true |
|||
}); |
|||
}else{ //otherwise remove |
|||
if (e) { |
|||
mw.util.$content.find('a.aj-unwatch').not('unwatched').remove() |
|||
var cookieDate = new Date($.now() + 1000 * 60 * 60 * 24 * 90).toGMTString(); |
|||
document.cookie = 'wlunw=1; expires=' + cookieDate + '; path=/'; |
|||
if( !hoverOnTitlesDone ) bindHoverOnTitles() |
|||
} |
|||
allStarsOn = false |
|||
allStarsOn = true; |
|||
} |
|||
} else { // otherwise remove |
|||
return false |
|||
mw.util.$content.find('a.aj-unwatch').not('unwatched').remove(); |
|||
document.cookie = 'wlunw=0; expires=' + (new Date()).toGMTString() + '; path=/'; |
|||
if (!hoverOnTitlesDone) { |
|||
bindHoverOnTitles(); |
|||
} |
|||
allStarsOn = false; |
|||
} |
|||
} |
} |
||
function sortWatchlist(e){ |
function sortWatchlist(e) { |
||
e.preventDefault() |
e.preventDefault(); |
||
if( |
if (sortingDone) { |
||
return alert(mm.sortDone); |
|||
} |
|||
mw.util.$content.find('h4').each(function(){ //sort all days separately |
|||
mw.util.$content.find('h4').each(function() { // sort all days separately |
|||
var container = $(this).next('div, ul') |
|||
var container = $(this).next('div, ul'); |
|||
var rows = container.children('li, table'); |
|||
//create sorting keys |
|||
// create sorting keys |
|||
var key |
|||
var key; |
|||
rows.each( function(i){ |
|||
rows.each(function(i) { |
|||
//use built-in class: either li.watchlist-5-<title> or table.mw-changeslist-ns100-<title> in enhanced RC |
|||
// use built-in class: either li.watchlist-5-<title> or |
|||
key = /(\d+)-(\S+)/.exec( this.className ) || ['', 0, ' '] //logs might not have this class |
|||
// table.mw-changeslist-ns100-<title> in enhanced recent changes |
|||
if( key[1] % 2 ) key[1]-- //sort talk page as if it was a base page |
|||
key = /(\d+)-(\S+)/.exec(this.className) || ['', 0, ' ']; // logs might not have this class |
|||
if( window.watchlistSortNamespaceOnly ) key[2] = zzz(i) //keep timestamp order within each NS block |
|||
if (key[1] % 2) { |
|||
key[1]--; // sort talk page as if it was a base page |
|||
}) |
|||
} |
|||
//sort array and then HTML |
|||
if (window.watchlistSortNamespaceOnly) { |
|||
rows.sort(function(a,b){ return a.skey > b.skey ? 1 : ( a.skey < b.skey ? -1 : 0 ) }) |
|||
key[2] = zzz(i); // keep timestamp order within each NS block |
|||
for( i=0; i<rows.length; i++ ) container.append( rows.eq(i) ) |
|||
} |
|||
}) |
|||
this.skey = zzz(key[1]) + ':' + key[2]; |
|||
sortingDone = true |
|||
}); |
|||
// sort array and then HTML |
|||
rows.sort(function(a, b) { |
|||
return a.skey > b.skey ? 1 : (a.skey < b.skey ? -1 : 0); |
|||
}); |
|||
for (i = 0; i < rows.length; i++) { |
|||
container.append(rows.eq(i)); |
|||
} |
|||
}); |
|||
sortingDone = true; |
|||
} |
} |
||
function expandMultipleEdits(e){ |
function expandMultipleEdits(e) { |
||
e.preventDefault() |
e.preventDefault(); |
||
var i = 0, sp, state = $('.mw-changeslist .mw-collapsible')[0].style.display |
var i = 0, sp, state = $('.mw-changeslist .mw-collapsible')[0].style.display; |
||
while |
while (sp = $('.mw-changeslist .mw-collapsible')[i++]) { |
||
if (sp.style.display == state) { |
|||
$(sp).find('.mw-enhancedchanges-arrow').click(); |
|||
} |
|||
} |
|||
} |
} |
||
function switchRevert(e) { |
function switchRevert(e) { |
||
if (e) |
if (e) e.preventDefault(); |
||
e.preventDefault(); |
|||
} |
|||
if (!rvOffCSS) { |
if (!rvOffCSS) { |
||
rvOffCSS = mw.util.addCSS('.mw-rollback-link { display:none; }') |
rvOffCSS = mw.util.addCSS('.mw-rollback-link { display:none; }'); |
||
} else { |
|||
document.cookie = 'wlrvoff=1; expires=' + (new Date($.now() + 1000 * 60 * 60 * 24 * 365)).toGMTString() + '; path=/'; |
|||
} else { |
|||
rvOffCSS.disabled = !rvOffCSS.disabled; |
rvOffCSS.disabled = !rvOffCSS.disabled; |
||
} |
|||
if (rvOffCSS.disabled) { |
|||
// Поставлено 28 января 2017, чтобы сбросить куки, установленные ранее по путям /wiki/ и /ruwiki/w/, |
|||
// Поставлено 28 января 2017 года, чтобы сбросить куки, установленные ранее по путям |
|||
// которые могут перебивать новую настройку. Через год можно убирать |
|||
// /wiki/ и /ruwiki/w/, которые могут перебивать новую настройку. Через год можно убирать. |
|||
document.cookie = 'wlrvoff=0; expires=' + (new Date()).toGMTString() + ''; |
document.cookie = 'wlrvoff=0; expires=' + (new Date()).toGMTString() + ''; |
||
document.cookie = 'wlrvoff=0; expires=' + (new Date()).toGMTString() + '; path=/'; |
document.cookie = 'wlrvoff=0; expires=' + (new Date()).toGMTString() + '; path=/'; |
||
} else if (e) { |
|||
var cookieDate = (new Date($.now() + 1000 * 60 * 60 * 24 * 90)).toGMTString(); |
|||
document.cookie = 'wlrvoff=1; expires=' + cookieDate + '; path=/'; |
|||
} |
} |
||
} |
} |
||
function bindHoverOnTitles() { // find all "titles" links and assign hover event |
|||
if (hoverOnTitlesDone) return; |
|||
// $('#mw-content-text').find(isEnhanced ? 'table' : 'li'); |
|||
mw.util.$content.find('a[href*="action=history"]') |
|||
.each(function() { |
|||
getRow(this).find('a[href^="/wiki/"]:first').hover(hoverOnTitle); |
|||
}); |
|||
hoverOnTitlesDone = true; |
|||
} |
|||
function |
function hoverOnTitle(e) { // on hover: add "unwatch" star after 1 second |
||
var lnk = $(this); |
|||
if( hoverOnTitlesDone ) return |
|||
if (e.type == 'mouseenter') { |
|||
//$('#mw-content-text').find( isEnhanced ? 'table' : 'li') |
|||
lnk.data('uwTimeout', setTimeout(function() {showStarOnHover(lnk)}, 1000)); |
|||
mw.util.$content.find('a[href*="action=history"]') |
|||
} else { |
|||
.each( function(){ |
|||
clearTimeout(lnk.data('uwTimeout')); |
|||
getRow(this).find('a[href^="/wiki/"]:first').hover( hoverOnTitle ) |
|||
} |
} |
||
hoverOnTitlesDone = true |
|||
} |
} |
||
function showStarOnHover(lnk) { |
|||
var row = getRow(lnk); |
|||
updateStar(row); |
|||
// attach mouseleave to remove the star |
|||
if (row.attr('leaveAssigned')) return; |
|||
row.attr('leaveAssigned', true); |
|||
row.mouseleave(function(e) { |
|||
var uw = $(this).find('.aj-unwatch'); |
|||
if (uw.length |
|||
&& /unwatch/.test(uw.attr('href')) |
|||
&& !/waiting|failure/.test(uw.attr('class')) |
|||
&& !allStarsOn |
|||
) { |
|||
uw.remove(); |
|||
} |
|||
}); |
|||
} |
|||
function updateStar(row) { |
|||
function hoverOnTitle(e){ //on hover: add "unwatch" star after 1s |
|||
var |
var star = row.find('a.aj-unwatch'); |
||
if (!star.length) { // create |
|||
if( e.type == 'mouseenter' ) |
|||
star = $('<a class="aj-unwatch" href="' |
|||
lnk.data( 'uwTimeout', setTimeout( function(){showStarOnHover(lnk)}, 1000 ) ) |
|||
+ row.find('a[href*="action=history"]').attr('href').replace(/&curid=\d+/,'') |
|||
else |
|||
+ '">x</a>') |
|||
clearTimeout( lnk.data( 'uwTimeout' ) ) |
|||
.click(ajaxUnwatch) |
|||
} |
|||
.insertBefore(row.find('a[href^="/wiki/"]:first')) |
|||
.after(' '); |
|||
} |
|||
function showStarOnHover(lnk){ |
|||
// update |
|||
var row = getRow(lnk) |
|||
var isUnwatched = row.hasClass('unwatched'); |
|||
updateStar(row) |
|||
var state = isUnwatched ? 'watch' : 'unwatch'; |
|||
//attach mouseleave to remove the star |
|||
star.attr('title', mw.msg(state)) |
|||
.attr('href', star.attr('href').replace(/&action=\w+/, '&action='+ state)) |
|||
row.attr('leaveAssigned', true) |
|||
.html('<img alt="x" style="width:0.6em;" src="/upwiki/wikipedia/commons/' |
|||
row.mouseleave( function(e){ |
|||
+ (isUnwatched |
|||
var uw = $(this).find('.aj-unwatch') |
|||
? 'a/a4/Vector_skin_-_page_not_in_the_watchlist.png' |
|||
if( uw.length |
|||
: 'f/f2/Vector_skin_-_page_in_the_watchlist.png') |
|||
&& /unwatch/.test( uw.attr('href') ) |
|||
+ '" />'); |
|||
&& !/waiting|failure/.test( uw.attr('class') ) |
|||
&& !allStarsOn |
|||
) |
|||
uw.remove() |
|||
}) |
|||
} |
} |
||
function getRow(el) { |
|||
return $(el).closest(isEnhanced ? 'tr' : 'li'); |
|||
function updateStar(row){ |
|||
var star = row.find('a.aj-unwatch') |
|||
if( !star.length ){ //create |
|||
star = $('<a class=aj-unwatch href="' |
|||
+ row.find('a[href*="action=history"]').attr('href').replace(/&curid=\d+/,'') |
|||
+ '">x</a>') |
|||
.click(ajaxUnwatch) |
|||
.insertBefore( row.find('a[href^="/wiki/"]:first') ) |
|||
.after(' ') |
|||
} |
|||
//update |
|||
var isUnwatched = row.hasClass('unwatched') |
|||
var state = isUnwatched ? 'watch' : 'unwatch' |
|||
star.attr( 'title', mw.msg(state) ) |
|||
.attr( 'href', star.attr('href').replace(/&action=\w+/, '&action='+ state) ) |
|||
.html('<img alt=x style="width:0.6em" ' |
|||
+ 'src="/upwiki/wikipedia/commons/' |
|||
+ ( isUnwatched |
|||
? 'a/a4/Vector_skin_-_page_not_in_the_watchlist.png' |
|||
: 'f/f2/Vector_skin_-_page_in_the_watchlist.png' |
|||
) |
|||
+ '" />') |
|||
} |
} |
||
function getRow(el){ |
|||
return $(el).closest(isEnhanced ? 'tr' : 'li') |
|||
} |
|||
function ajaxUnwatch(e) { |
function ajaxUnwatch(e) { |
||
var xLnk = $(this), errMsg = '' |
var xLnk = $(this), errMsg = ''; |
||
var req = { |
var req = { |
||
token: mw.user.tokens.get('watchToken'), |
|||
title: getLinkTitle(xLnk) |
|||
}; |
|||
if( /&action=unwatch/.test(xLnk.attr('href')) ) req.unwatch = '' |
|||
if (/&action=unwatch/.test(xLnk.attr('href'))) { |
|||
xLnk.addClass('waiting') |
|||
req.unwatch = ''; |
|||
$.ajax({ |
|||
} |
|||
type:'POST', dataType: 'json', |
|||
xLnk.addClass('waiting'); |
|||
url: mw.util.wikiScript('api') + '?action=watch&format=json', |
|||
$.ajax({ |
|||
data: req, |
|||
type:'POST', dataType: 'json', |
|||
timeout: 5000, |
|||
url: mw.util.wikiScript('api') + '?action=watch&format=json', |
|||
success: function(resp){ |
|||
data: req, |
|||
if( resp.error ) errMsg = resp.error.info |
|||
timeout: 5000, |
|||
else if( !resp.watch ) errMsg = 'empty response' |
|||
success: function(resp) { |
|||
else if( typeof resp.watch.unwatched == 'string') unwatchSuccess( req.title, true ) |
|||
if (resp.error) { |
|||
else if( typeof resp.watch.watched == 'string') unwatchSuccess( req.title, false ) |
|||
errMsg = resp.error.info; |
|||
} else if (!resp.watch) { |
|||
}, |
|||
errMsg = 'empty response'; |
|||
error: function(xhr, status, err) { |
|||
} else if (typeof resp.watch.unwatched == 'string') { |
|||
errMsg = status + ':' + err |
|||
unwatchSuccess(req.title, true); |
|||
}, |
|||
} else if (typeof resp.watch.watched == 'string') { |
|||
complete: function(){ //update X link |
|||
unwatchSuccess(req.title, false); |
|||
xLnk.removeClass('waiting') |
|||
} else { |
|||
if( errMsg ) xLnk.attr( 'title', 'API error: ' + errMsg ).addClass('failure') |
|||
errMsg = 'unrecognized response'; |
|||
else xLnk.removeClass('failure') |
|||
} |
|||
}, |
|||
error: function(xhr, status, err) { |
|||
return false |
|||
errMsg = status + ':' + err; |
|||
}, |
|||
complete: function() { // update X link |
|||
xLnk.removeClass('waiting'); |
|||
if (errMsg) xLnk.attr('title', 'API error: ' + errMsg).addClass('failure'); |
|||
else xLnk.removeClass('failure'); |
|||
} |
|||
}); |
|||
return false; |
|||
} |
} |
||
function unwatchSuccess(name, isUnwatched) { |
function unwatchSuccess(name, isUnwatched) { |
||
// find full name of associated talk page (or vice versa) |
|||
var ns = getTitleNamespace(name); |
|||
var name2 = name; |
|||
if (ns > 0) { |
|||
name2 = name2.replace(/^.+?:/,''); // remove old prefix |
|||
} |
|||
if( ns % 2 ) ns--; else ns++ //switch to "other" namespace |
|||
if (ns % 2) { |
|||
if( ns > 0 ) name2 = mw.config.get( 'wgFormattedNamespaces' )[ns] + ':' + name2 //add new prefix |
|||
ns--; |
|||
//mark all rows that are either name or name2 |
|||
} else { |
|||
mw.util.$content.find('a[href*="action=history"]').each(function(){ |
|||
ns++; // switch to "other" namespace |
|||
var ttl = getLinkTitle(this) |
|||
} |
|||
if( ttl != name && ttl != name2 ) return |
|||
if (ns > 0) { |
|||
var row = getRow(this) |
|||
name2 = mw.config.get('wgFormattedNamespaces')[ns] + ':' + name2; // add new prefix |
|||
row.toggleClass('unwatched', isUnwatched || false) |
|||
} |
|||
updateStar(row) |
|||
// mark all rows that are either name or name2 |
|||
if( !isUnwatched && !allStarsOn) row.find('a.aj-unwatch').remove() |
|||
mw.util.$content.find('a[href*="action=history"]').each(function() { |
|||
}) |
|||
var ttl = getLinkTitle(this); |
|||
if (ttl != name && ttl != name2) return; |
|||
var row = getRow(this); |
|||
row.toggleClass('unwatched', isUnwatched || false); |
|||
updateStar(row); |
|||
if (!isUnwatched && !allStarsOn) { |
|||
row.find('a.aj-unwatch').remove(); |
|||
} |
|||
}); |
|||
} |
} |
||
function hideInterface(e) { |
|||
if (e) e.preventDefault(); |
|||
if (!hideInterfaceCSS) { |
|||
hideInterfaceCSS = mw.util.addCSS('\ |
|||
h4 { font-size: 90%; }\ |
|||
\ |
|||
#firstHeading,\ |
|||
div#siteNotice, #contentSub, fieldset#mw-watchlist-options,\ |
|||
div.mw-rc-label-legend, #mw-fr-watchlist-pending-notice { display: none; }'); |
|||
} else { |
|||
hideInterfaceCSS.disabled = !hideInterfaceCSS.disabled; |
|||
} |
|||
if (e) { |
|||
if (!hideInterfaceCSS.disabled) { |
|||
var cookieDate = new Date($.now() + 1000 * 60 * 60 * 24 * 90).toGMTString(); |
|||
document.cookie = 'wlmax=1; expires=' + cookieDate + '; path=/'; |
|||
} else { |
|||
document.cookie = 'wlmax=0; expires=' + (new Date()).toGMTString() + '; path=/'; |
|||
} |
|||
} |
|||
} |
|||
function getTitleNamespace(title) { // returns namespace number |
|||
var prefix = /^(.+?):/.exec(title); |
|||
if (!prefix) return 0; // no prefix means article |
|||
return mw.config.get('wgNamespaceIds')[ prefix[1].toLowerCase().replace(/ /g,'_') ] || 0; |
|||
} |
|||
function getLinkTitle(lnk) { // gets 'title=' part from a link |
|||
return mw.util.getParamValue('title', $(lnk).attr('href')).replace(/_/g,' '); |
|||
// var ma = /(&|\?)title=([^&]+)/.exec($(lnk).attr('href')); |
|||
// if (ma) return decodeURIComponent(ma[2]).replace(/_/g,' '); |
|||
// else return ''; |
|||
function hideInterface(e){ |
|||
if( e ) e.preventDefault() |
|||
if (!hideInterfaceCSS) hideInterfaceCSS = mw.util.addCSS('\ |
|||
h4 {font-size:90%}\ |
|||
#firstHeading,\ |
|||
div#siteNotice, #contentSub, fieldset#mw-watchlist-options,\ |
|||
div.mw-rc-label-legend, #mw-fr-watchlist-pending-notice {display:none}') |
|||
else hideInterfaceCSS.disabled = !hideInterfaceCSS.disabled |
|||
document.cookie = 'wlmax=' + (!hideInterfaceCSS.disabled ? '1; path=/' : '0; expires=' + (new Date()).toGMTString() + '; path=/') |
|||
} |
} |
||
function zzz(s) { // 5 -> 005 |
|||
s = s.toString(); |
|||
if (s.length == 1) { |
|||
function getTitleNamespace(title){ //returns namespace number |
|||
return '00' + s; |
|||
var prefix = /^(.+?):/.exec(title) |
|||
} else if (s.length == 2) { |
|||
if( !prefix ) return 0 //no prefix means article |
|||
return '0' + s; |
|||
return mw.config.get( 'wgNamespaceIds' )[ prefix[1].toLowerCase().replace(/ /g,'_') ] || 0 |
|||
} |
} else { |
||
return s; |
|||
} |
|||
function getLinkTitle (lnk){ //gets 'title=' part from a link |
|||
return mw.util.getParamValue('title', $(lnk).attr('href')).replace(/_/g,' ') |
|||
//var ma = /(&|\?)title=([^&]+)/.exec( $(lnk).attr('href') ) |
|||
//if( ma ) return decodeURIComponent(ma[2]).replace(/_/g,' ') |
|||
//else return '' |
|||
} |
} |
||
}, 0); |
|||
function zzz(s){ // 5 -> 005 |
|||
}); // main |
|||
s = s.toString() |
|||
if( s.length==1 ) return '00'+s |
|||
else if( s.length==2 ) return '0'+s |
|||
else return s |
|||
} |
} |
||
}, 0) |
|||
})//main |
Версия от 16:07, 19 февраля 2017
if (mw.config.get('wgCanonicalSpecialPageName') === 'Watchlist' && mw.config.get('wgAction') === 'view') {
mw.hook('wikipage.content').add(function () {
setTimeout(function () { // лечение для Firefox
/* MAIN BLOCK */
var whenPageLoaded = +(new Date()) - 20000; // add 20 seconds just in case
var hideInterfaceCSS, rvOffCSS;
var sortingDone, allStarsOn, hoverOnTitlesDone;
// ruwiki
var mm = {
sortTip: 'Сортировать страницы по пространствам',
sortDone: 'Изменения уже отсортированы',
unwatchTip: 'Добавить звёздочки для вычёркивания страниц из списка наблюдения',
onlynew: 'Только новые',
onlynewTip: 'Изменения с момента загрузки этой страницы',
onlynewTipLowerCase: 'изменения с момента загрузки этой страницы',
expandAll: 'Показать/спрятать все свёрнутые правки',
switchRevert: 'Спрятать/показать ссылки «откатить»',
fullPage: 'Спрятать/показать элементы интерфейса'
};
// recent changes type in preferences
var isEnhanced = mw.util.$content.find('ul.special').length == 0;
// find insertion points for links: after "days all"
var linksAt = $('#mw-watchlist-options').find('#days').next();
// UNWATCH LINKS
// on every line
if (document.cookie.indexOf('wlunw=1') != -1) {
showAllStars();
} else {
bindHoverOnTitles(); // mouseover on title
}
// switch for above, saved in a cookie
addLink(
'<img alt="x" style="width:1em;" src="/upwiki/wikipedia/commons/a/a4/Vector_skin_-_page_not_in_the_watchlist.png">',
mm.unwatchTip
).click(showAllStars); // click on timestamp (enhanced recent changes) / empty space (non-enhanced)
if (document.cookie.indexOf('wlrvoff=1') != -1) switchRevert();
// OTHER LINKS
// "sort" link
addLink('↑↓', mm.sortTip).click(sortWatchlist);
// "expand all" link
if ($('.mw-enhancedchanges-arrow').length) {
addLink('±', mm.expandAll).click(expandMultipleEdits);
}
// "switch revert" link
if ($('.mw-rollback-link').length) {
addLink('⎌', mm.switchRevert).click(switchRevert);
}
// "only new" link
addLink(mm.onlynew, mm.onlynewTip).mousedown(onlyNewEntries).attr('id', 'listSince');
// TABS
if (window.wlNoTabs) return;
var mainTab = $('#ca-special, #ca-nstab-special').eq(0); // "Special" tab
// change main tab into "watchlist Δ"
var wl = $.trim($('h1#firstHeading').text());
mainTab.find('a') // replace "Special" tab text with "Watchlist"
.text(wl + ' △') // Δ is good but monobook makes is lowercase
.attr('title', wl + ' — ' + mm.onlynewTipLowerCase)
.on('mousedown keydown', onlyNewEntries);
// add "hideInterface" tab
mainTab.clone(true).removeClass('selected')
.appendTo(mainTab.parent())
.click(hideInterface)
.attr('id','').attr('href', '#')
.find('a')
.text('↸').attr('title', mm.fullPage).attr('accesskey', '');
if (document.cookie.indexOf('wlmax=1') != -1) hideInterface();
if ($('.mw-changeslist .mw-rollback-link').first().css('visibility') == 'hidden') {
$('.mw-changeslist .mw-rollback-link').css('visibility', 'visible');
}
return;
/* FUNCTIONS */
function addLink(txt, tip) {
linksAt.before(' ');
return $('<a href="#" title="' + tip + '">' + txt + '</a>').insertBefore(linksAt);
}
function onlyNewEntries(e) {
var url = window.location.href.split('#')[0];
var days = (+(new Date()) - whenPageLoaded)/(1000 * 3600 * 24);
if (days < 0) days = 0.01; // negative might happen when adjusting local time
e.target.href = /[?&]days=/.test(url)
? url.replace(/([?&]days=)[^&]*/, '$1' + days)
: url + (url.indexOf('?') < 0 ? '?':'&') + 'days=' + days;
return true;
}
function showAllStars(e) {
if (e) {
e.preventDefault();
}
if (!allStarsOn) {
mw.util.$content.find('a[href*="action=history"]')
.each(function(i, lnk) {
updateStar(getRow(this));
});
if (e) {
var cookieDate = new Date($.now() + 1000 * 60 * 60 * 24 * 90).toGMTString();
document.cookie = 'wlunw=1; expires=' + cookieDate + '; path=/';
}
allStarsOn = true;
} else { // otherwise remove
mw.util.$content.find('a.aj-unwatch').not('unwatched').remove();
document.cookie = 'wlunw=0; expires=' + (new Date()).toGMTString() + '; path=/';
if (!hoverOnTitlesDone) {
bindHoverOnTitles();
}
allStarsOn = false;
}
}
function sortWatchlist(e) {
e.preventDefault();
if (sortingDone) {
return alert(mm.sortDone);
}
mw.util.$content.find('h4').each(function() { // sort all days separately
var container = $(this).next('div, ul');
var rows = container.children('li, table');
// create sorting keys
var key;
rows.each(function(i) {
// use built-in class: either li.watchlist-5-<title> or
// table.mw-changeslist-ns100-<title> in enhanced recent changes
key = /(\d+)-(\S+)/.exec(this.className) || ['', 0, ' ']; // logs might not have this class
if (key[1] % 2) {
key[1]--; // sort talk page as if it was a base page
}
if (window.watchlistSortNamespaceOnly) {
key[2] = zzz(i); // keep timestamp order within each NS block
}
this.skey = zzz(key[1]) + ':' + key[2];
});
// sort array and then HTML
rows.sort(function(a, b) {
return a.skey > b.skey ? 1 : (a.skey < b.skey ? -1 : 0);
});
for (i = 0; i < rows.length; i++) {
container.append(rows.eq(i));
}
});
sortingDone = true;
}
function expandMultipleEdits(e) {
e.preventDefault();
var i = 0, sp, state = $('.mw-changeslist .mw-collapsible')[0].style.display;
while (sp = $('.mw-changeslist .mw-collapsible')[i++]) {
if (sp.style.display == state) {
$(sp).find('.mw-enhancedchanges-arrow').click();
}
}
}
function switchRevert(e) {
if (e) e.preventDefault();
if (!rvOffCSS) {
rvOffCSS = mw.util.addCSS('.mw-rollback-link { display:none; }');
} else {
rvOffCSS.disabled = !rvOffCSS.disabled;
}
if (rvOffCSS.disabled) {
// Поставлено 28 января 2017 года, чтобы сбросить куки, установленные ранее по путям
// /wiki/ и /ruwiki/w/, которые могут перебивать новую настройку. Через год можно убирать.
document.cookie = 'wlrvoff=0; expires=' + (new Date()).toGMTString() + '';
document.cookie = 'wlrvoff=0; expires=' + (new Date()).toGMTString() + '; path=/';
} else if (e) {
var cookieDate = (new Date($.now() + 1000 * 60 * 60 * 24 * 90)).toGMTString();
document.cookie = 'wlrvoff=1; expires=' + cookieDate + '; path=/';
}
}
function bindHoverOnTitles() { // find all "titles" links and assign hover event
if (hoverOnTitlesDone) return;
// $('#mw-content-text').find(isEnhanced ? 'table' : 'li');
mw.util.$content.find('a[href*="action=history"]')
.each(function() {
getRow(this).find('a[href^="/wiki/"]:first').hover(hoverOnTitle);
});
hoverOnTitlesDone = true;
}
function hoverOnTitle(e) { // on hover: add "unwatch" star after 1 second
var lnk = $(this);
if (e.type == 'mouseenter') {
lnk.data('uwTimeout', setTimeout(function() {showStarOnHover(lnk)}, 1000));
} else {
clearTimeout(lnk.data('uwTimeout'));
}
}
function showStarOnHover(lnk) {
var row = getRow(lnk);
updateStar(row);
// attach mouseleave to remove the star
if (row.attr('leaveAssigned')) return;
row.attr('leaveAssigned', true);
row.mouseleave(function(e) {
var uw = $(this).find('.aj-unwatch');
if (uw.length
&& /unwatch/.test(uw.attr('href'))
&& !/waiting|failure/.test(uw.attr('class'))
&& !allStarsOn
) {
uw.remove();
}
});
}
function updateStar(row) {
var star = row.find('a.aj-unwatch');
if (!star.length) { // create
star = $('<a class="aj-unwatch" href="'
+ row.find('a[href*="action=history"]').attr('href').replace(/&curid=\d+/,'')
+ '">x</a>')
.click(ajaxUnwatch)
.insertBefore(row.find('a[href^="/wiki/"]:first'))
.after(' ');
}
// update
var isUnwatched = row.hasClass('unwatched');
var state = isUnwatched ? 'watch' : 'unwatch';
star.attr('title', mw.msg(state))
.attr('href', star.attr('href').replace(/&action=\w+/, '&action='+ state))
.html('<img alt="x" style="width:0.6em;" src="/upwiki/wikipedia/commons/'
+ (isUnwatched
? 'a/a4/Vector_skin_-_page_not_in_the_watchlist.png'
: 'f/f2/Vector_skin_-_page_in_the_watchlist.png')
+ '" />');
}
function getRow(el) {
return $(el).closest(isEnhanced ? 'tr' : 'li');
}
function ajaxUnwatch(e) {
var xLnk = $(this), errMsg = '';
var req = {
token: mw.user.tokens.get('watchToken'),
title: getLinkTitle(xLnk)
};
if (/&action=unwatch/.test(xLnk.attr('href'))) {
req.unwatch = '';
}
xLnk.addClass('waiting');
$.ajax({
type:'POST', dataType: 'json',
url: mw.util.wikiScript('api') + '?action=watch&format=json',
data: req,
timeout: 5000,
success: function(resp) {
if (resp.error) {
errMsg = resp.error.info;
} else if (!resp.watch) {
errMsg = 'empty response';
} else if (typeof resp.watch.unwatched == 'string') {
unwatchSuccess(req.title, true);
} else if (typeof resp.watch.watched == 'string') {
unwatchSuccess(req.title, false);
} else {
errMsg = 'unrecognized response';
}
},
error: function(xhr, status, err) {
errMsg = status + ':' + err;
},
complete: function() { // update X link
xLnk.removeClass('waiting');
if (errMsg) xLnk.attr('title', 'API error: ' + errMsg).addClass('failure');
else xLnk.removeClass('failure');
}
});
return false;
}
function unwatchSuccess(name, isUnwatched) {
// find full name of associated talk page (or vice versa)
var ns = getTitleNamespace(name);
var name2 = name;
if (ns > 0) {
name2 = name2.replace(/^.+?:/,''); // remove old prefix
}
if (ns % 2) {
ns--;
} else {
ns++; // switch to "other" namespace
}
if (ns > 0) {
name2 = mw.config.get('wgFormattedNamespaces')[ns] + ':' + name2; // add new prefix
}
// mark all rows that are either name or name2
mw.util.$content.find('a[href*="action=history"]').each(function() {
var ttl = getLinkTitle(this);
if (ttl != name && ttl != name2) return;
var row = getRow(this);
row.toggleClass('unwatched', isUnwatched || false);
updateStar(row);
if (!isUnwatched && !allStarsOn) {
row.find('a.aj-unwatch').remove();
}
});
}
function hideInterface(e) {
if (e) e.preventDefault();
if (!hideInterfaceCSS) {
hideInterfaceCSS = mw.util.addCSS('\
h4 { font-size: 90%; }\
\
#firstHeading,\
div#siteNotice, #contentSub, fieldset#mw-watchlist-options,\
div.mw-rc-label-legend, #mw-fr-watchlist-pending-notice { display: none; }');
} else {
hideInterfaceCSS.disabled = !hideInterfaceCSS.disabled;
}
if (e) {
if (!hideInterfaceCSS.disabled) {
var cookieDate = new Date($.now() + 1000 * 60 * 60 * 24 * 90).toGMTString();
document.cookie = 'wlmax=1; expires=' + cookieDate + '; path=/';
} else {
document.cookie = 'wlmax=0; expires=' + (new Date()).toGMTString() + '; path=/';
}
}
}
function getTitleNamespace(title) { // returns namespace number
var prefix = /^(.+?):/.exec(title);
if (!prefix) return 0; // no prefix means article
return mw.config.get('wgNamespaceIds')[ prefix[1].toLowerCase().replace(/ /g,'_') ] || 0;
}
function getLinkTitle(lnk) { // gets 'title=' part from a link
return mw.util.getParamValue('title', $(lnk).attr('href')).replace(/_/g,' ');
// var ma = /(&|\?)title=([^&]+)/.exec($(lnk).attr('href'));
// if (ma) return decodeURIComponent(ma[2]).replace(/_/g,' ');
// else return '';
}
function zzz(s) { // 5 -> 005
s = s.toString();
if (s.length == 1) {
return '00' + s;
} else if (s.length == 2) {
return '0' + s;
} else {
return s;
}
}
}, 0);
}); // main
}