User:Js/watchlist.js - Wikipedia
Article Images
Code that you insert on this page could contain malicious content capable of compromising your account. If you import a script from another page with "importScript", "mw.loader.load", "iusc", or "lusc", take note that this causes you to dynamically load a remote script, which could be changed by others. Editors are responsible for all edits and actions they perform, including by scripts. User scripts are not centrally supported and may malfunction or become inoperable due to software changes. A guide to help you find broken scripts is available. If you are unsure whether code you are adding to this page is safe, you can ask at the appropriate village pump.
This code will be executed when previewing this page.
Note: After saving, you have to bypass your browser's cache to see the changes. Google Chrome, Firefox, Microsoft Edge and Safari: Hold down the ⇧ Shift key and click the Reload toolbar button. For details and instructions about other browsers, see Wikipedia:Bypass your cache.
function WLScript(){ var whenPageLoaded = +(new Date()) - 20000 //add 20 sec just in case var mainTab, hideInterfaceCSS var alreadySorted, alreadyAddedUnwatch mw.util.addCSS('\ a.failure {color:red}\ a.unwatched {text-decoration: line-through}\ ') //enwiki var mm = {sortTip:'Sort rows by even namespace number, then by page title' ,sortDone:'Watchlist changes already sorted' ,unwatchTip:'Add (x) quick unwatch links' ,unwatchDone:'Use (x) links to quickly unwatch pages' ,onlynew:'Only new' ,onlynewTip:'Show changes since this page was last loaded' ,expandAll:'Expand multiple edits' ,fullPage:'Hide/Show interface' } PngFixDisabled = true //enhanced RC: make (x) appear by clicking on timestamp var isEnhanced = $( '#mw-content-text ul.special').length === 0; if( isEnhanced ) $( '#mw-content-text' ).click(toggleXLink) //find insertion points for links: after "days all" var linksAt = $('#mw-watchlist-options').find('#days').eq(0); if( !linksAt.length ) linksAt = $('#mw-watchlist-options').find('hr:last') //find "Special" tab mainTab = $('#ca-special, #ca-nstab-special').eq(0); //"only new" link and tab addLnk(mm.onlynew, mm.onlynewTip).click(onlyNewEntries).attr('id', 'listSince'); addTab(mm.onlynew, mm.onlynewTip).click(onlyNewEntries); //"unwatch" link(s) if( window.unwatchLinksOnLoad ) addXLinks() else addLnk('x' , mm.unwatchTip).click(addXLinks) //"sort" link addLnk('↑↓', mm.sortTip).click(sortWatchlist) //"expand all" link if( $('#mw-rc-openarrow-0').length ) addLnk('±', mm.expandAll).click(expandMultipleEdits) //"hideInterface" tab addTab('↸',mm.fullPage).click(hideInterface).attr('href','#') if( document.cookie.indexOf('wlmax=1') != -1 ) hideInterface() function addLnk(txt, tip){ var link = $('<a href="#" title="'+tip+'" style="font-style:italic">'+txt+'</a>').insertAfter(linksAt); linksAt.after(' | '); return link; } function addTab(txt, tip){ if( window.wlNoTabs ) return var tab = mainTab.clone(true).removeClass('selected').attr('id','') tab.find('a').text(txt).attr('title', tip).attr('accesskey','') return tab.appendTo(mainTab.parent()) } return function onlyNewEntries(e) { var url = window.location.href.split('#')[0] var days = ( +(new Date()) - whenPageLoaded)/(1000 * 3600 * 24) e.target.href = /[?&]days=/.test(url) ? url.replace(/([?&]days=)[^&]*/, '$1'+days) : url + (url.indexOf('?') < 0 ? '?':'&') + 'days=' + days return true } function sortWatchlist(e){ e.preventDefault() if( alreadySorted ) return alert(mm.sortDone) $( '#mw-content-text' ).find('h4').each(function(i, H4){ //sort all days separately sortDay($(H4).next('div, ul')) }) alreadySorted = true } function sortDay(dayDiv){ var i, ns, pgname, rowElem, hiddenDiv, rows = dayDiv.find('a[href*="&action=history"]') for (i = 0; i < rows.length; i++){ pgname = getLinkTitle(rows[i]) ns = getTitleNamespace(pgname) if( ns>0 ) pgname = pgname.replace(/^.+?:/,'') //remove prefix if( ns%2 ) ns-- //sort talk page as if it was a base page rows[i].sortkey = zzz(ns) + ':' + pgname //assign custom tag attribute: namespace+title } //sort rows array rows.sort(function(a,b){ if( a.sortkey > b.sortkey ) return 1 else if( a.sortkey < b.sortkey ) return -1 else return 0 }) //sort rows in HTML, by moving all to the bottom if( isEnhanced ) for (i=0; i<rows.length; i++){ rowElem = rows.eq(i).closest('table') hiddenDiv = rowElem.next('div') dayDiv.append(rowElem, hiddenDiv) } else for (i=0; i<rows.length; i++){ rowElem = rows.eq(i).closest('li') dayDiv.append(rowElem) } } function expandMultipleEdits(e){ e.preventDefault() var i = 0, sp, state = $('#mw-rc-openarrow-0')[0].style.display while( sp=document.getElementById('mw-rc-openarrow-'+(i++).toString()) ) if( sp.style.display == state ) $(sp.firstChild).click() } function addXLinks(e){ if( e ) e.preventDefault() if( alreadyAddedUnwatch ) return alert(mm.unwatchDone) $( '#mw-content-text' ).find('a[href*="&action=history"]') .each( function(i, lnk){ addXLink( $(lnk) ) } ) alreadyAddedUnwatch = true } function addXLink(histLink){ //create and append (x) link to the row with histLink var xLnk = $('<a class="aj-unwatch" style="font-size:smaller" href="' + histLink.attr('href').replace(/&curid=\d+/,'') + '" />') .click(ajaxUnwatch) if( isEnhanced ) histLink.parent().prepend( xLnk.text('(x)'), ' ' ) else histLink.after( ' | ', xLnk.text('x') ) updateXLink(xLnk) } function updateXLink(xLnk, state){ //change title and url of (x) link if( !xLnk.length ) return state = state ? 'watch' : 'unwatch' xLnk.attr( 'title', mw.msg(state) ) .attr( 'href', xLnk.attr('href').replace(/&action=\w+/, '&action='+ state) ) } function toggleXLink(e){ //add (x) when clicking on timestamp if( ! $(e.target).filter('td.mw-enhanced-rc').length ) return var tbl = $(e.target).parents('table.mw-enhanced-rc') var x = tbl.find('a.aj-unwatch') if( x.length ) x.remove() else addXLink(tbl.find('a[href*="&action=history"]')) } function ajaxUnwatch(e) { var xLnk = $(this), errMsg = '' var req = { action: 'watch', format: 'json', title: getLinkTitle(xLnk), token: mw.user.tokens.get('watchToken') } if( /&action=unwatch/.test(xLnk.attr('href')) ) req.unwatch = '' $.ajax({ type:'POST', dataType: 'json', url: mw.util.wikiScript( 'api' ), 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 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-content-text' ).find('a[href*="&action=history"]').each(function(){ var ttl = getLinkTitle(this) if( ttl != name && ttl != name2 ) return var row = $(this).parent() zthis = this row.children('a[href^="/wiki"]:first').toggleClass('unwatched', isUnwatched) updateXLink( row.children('a.aj-unwatch'), isUnwatched ) }) } function hideInterface(e){ if( e ) e.preventDefault() if (!hideInterfaceCSS) hideInterfaceCSS = mw.util.addCSS('\ div#siteNotice, h1#firstHeading, #siteSub, #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' : '0;expires=' + (new Date()).toGMTString() + ';;') var a = mainTab.find('a') //replace "Special" tab text with "Watchlist" if( hideInterfaceCSS.disabled ){ //restore a.text( a.attr('oldtext') ) }else{//set to "watchlist" a.attr('oldtext', a.text()) a.text($('h1#firstHeading').text()) } } 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 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 } } if( mw.config.get( 'wgCanonicalSpecialPageName' ) === 'Watchlist' && mw.config.get( 'wgAction' ) === 'view' ) { $.when( mw.loader.using( [ 'mediawiki.util', 'mediawiki.page.ready'] ), $.ready ).done( WLScript ); }