User:Js/watchlist.js
From Wikipedia, the free encyclopedia
< User:Js
Note: After saving, you have to bypass your browser's cache to see the changes. In Internet Explorer and Firefox, hold down the Ctrl key and click the Refresh or Reload button. Opera users have to clear their caches through Tools→Preferences, see the instructions for Opera. Konqueror and Safari users can just click the Reload button.
var WLScript = new function(){ //wrapper object var whenPageLoaded = +(new Date()) - 30000 //add 30 sec just in case var namespace, content, alreadySorted, alreadyAddedUnwatch, mw, rcm0 mw = { sort:'Sort...', sortTitle:'Sort titles by even namespace number, then by page title', sortDone:'Watchlist changes already sorted', unwatchTitle:'Add (x) quick unwatch links', unwatchDone:'Use (x) links to quickly unwatch pages', onlynew: 'Only new', onlynewTitle: 'Show changes since this page was loaded', expandAll: 'Expand/hide all' } mw.unwatch = (window.wgAjaxWatch ? wgAjaxWatch.unwatchMsg : 'Unwatch' ) mw.watch = (window.wgAjaxWatch ? wgAjaxWatch.watchMsg : 'Watch') this.onLoad = function() { PngFixDisabled = true init() if (!namespace) return //Sort and Unwatch links var insert = namespace.form addLnk('javascript:WLScript.sortWatchlist()', mw.sort, mw.sortTitle) addLnk('javascript:WLScript.addUnwatchLinks()', mw.unwatch+'…', mw.unwatchTitle) if (rcm0=document.getElementById('RCM0')) addLnk('javascript:WLScript.expandWatchlist()', '±', mw.expandAll) //Only new link while (insert.previousSibling && insert.nodeName != 'BR') insert=insert.previousSibling var lnk = addLnk('#', mw.onlynew, mw.onlynewTitle) lnk.id = 'listSince' lnk.onclick = lnk.onmousedown = onlyNewEntries // react to middle clicks too // function adds " | <link>" just before 'insert' element function addLnk(url, text, tooltip){ var lnk = document.createElement('a') lnk.href = url lnk.appendChild(document.createTextNode(text)) lnk.title = tooltip || '' insert.parentNode.insertBefore(document.createTextNode(' | '), insert) insert.parentNode.insertBefore(lnk, insert) return lnk } } function init(){ namespace = document.getElementById('namespace') content = document.getElementById('bodyContent') || document.body } this.init = init function onlyNewEntries() { var url = window.location.href.split('#')[0] var days = ( +(new Date()) - whenPageLoaded)/(1000 * 3600 * 24) if (url.match(/[?&]days=/)) this.href = url.replace(/([?&]days=)[^&]*/, '$1'+days) else this.href = url + (url.indexOf('?') < 0 ? '?':'&') + 'days=' + days return true } this.sortWatchlist = function(){ if (alreadySorted) return alert(mw.sortDone) var H4s = content.getElementsByTagName('h4'), dayDiv, rows, h, i, j, pgname, el, step, last //sort all days separately for (var h=0; h<H4s.length; h++){ //get UL or DIV immediately after H4 dayDiv = H4s[h] while ((dayDiv=dayDiv.nextSibling) && (dayDiv.nodeName != 'DIV') && (dayDiv.nodeName != 'UL')); //get WL rows, find their namespaces, calculate sortkeys rows = getWatchlistRows(dayDiv) if (!rows) return for (i = 0; i < rows.length; i++){ pgname = getTitleFromURL(rows[i].href) ns = getNSFromTitle(pgname) if (ns>0) pgname = pgname.substring(getNamespace(ns).length+1) //title w/o 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 for (i=0; i<rows.length; i++){ //move rows to the dayDiv bottom el = last = rows[i] if (el.parentNode.nodeName == 'LI') //non-enhanced watchlist el.parentNode.parentNode.appendChild(el.parentNode) //move to bottom if (el.parentNode.nodeName == 'TD'){ //new enhanced WL, with tables while ((el=el.parentNode) && el.nodeName != 'TABLE'); if (!el) continue do{ //move table bottom, also taking next (hidden) DIV step = el.nextSibling; el.parentNode.appendChild(el); el = step }while (el && el.nodeName != 'TABLE') }else{ //old enhanced WL, in case new is reverted //find last row element , which is usually BR while ((last=last.nextSibling) && last.nodeName!='BR'); if (!last) continue //just in case, this should not happen //move to next DIV (if present), containing (collapsed) list of changes with "enhanced RC" if ((step=last.nextSibling) && step.nodeName == '#text') last = step //Firefox insists on '\n' being here if ((step=last.nextSibling) && step.nodeName == 'DIV') last = step //now get to the 1st element, stopping just before <br> or <div> while ((step=el.previousSibling) && step.nodeName!='BR' && step.nodeName!='DIV') el = step //move all row elements one by one to the bottom of the day div do { step=el.nextSibling; dayDiv.appendChild(el) } while (el != last && (el=step)) } } }//for alreadySorted = true } this.expandWatchlist = function(){ var i = 0, sp, state = rcm0.style.display while (sp=document.getElementById('RCM'+(i++).toString())) if (sp.style.display == state) eval(sp.firstChild.href) } var uwLinks = [], inProgress = null, timeoutID = null this.addUnwatchLinks = function() { if (alreadyAddedUnwatch) return alert(mw.unwatchDone) var rows = getWatchlistRows(content), x, insAt, el for (var i = 0; i < rows.length; i++){ x = document.createElement('a') x.href = wgServer+wgScript+'?action=unwatch&title='+encodeURIComponent(rows[i].title) //non-Ajax unwatch x.onclick = ajaxUnwatch uwLinks.push(x) insAt = rows[i] if (insAt.parentNode.nodeName == 'LI') insAt = insAt.nextSibling.nextSibling //non-enhanced WL: insert before ) after history else while ((el=insAt.previousSibling) && el.nodeName != 'TT') insAt = el //insert after TT (with time) insAt.parentNode.insertBefore(document.createTextNode(' ('), insAt) insAt.parentNode.insertBefore(x, insAt) insAt.parentNode.insertBefore(document.createTextNode(') '), insAt) setUnwatchLink(x, false) } alreadyAddedUnwatch = true } function ajaxUnwatch(e) { if (inProgress) return false e = e || window.event var targ = e.target || e.srcElement inProgress = getTitleFromURL(targ.href) timeoutID = window.setTimeout( function() {inProgress = null}, 10000 ) //call server var action = (targ.innerHTML == 'x') ? 'u' : 'w' sajax_do_call('wfAjaxWatch', [inProgress, action], showUnwatch) return false } function showUnwatch (request) { if (timeoutID) window.clearTimeout(timeoutID) var response = request.responseText if (window.wlUnwatchShowMsg) jsMsg (response.substr(4), 'watch') var name = inProgress, state, prefix, idx, pg, i, el inProgress = null if (/^<u#>/.test(response)) state = true else if (/^<w#>/.test(response)) state = false else return //unrecognized response //find the full name of "other page" var ns = getNSFromTitle(name) var name2 = name if (ns > 0) name2 = name2.substring(getNamespace(ns).length+1) //remove old prefix if (ns % 2) ns--; else ns++ //switch to "other" namespace if (ns > 0) name2 = getNamespace(ns) + ':' + name2 //add new prefix //now mark all rows that are either name or name2 for (i=0; i<uwLinks.length; i++){ el = uwLinks[i] pg = getTitleFromURL(el.href) if (pg != name && pg != name2) continue setUnwatchLink (el, state) //now mark the whole line while ((el=el.nextSibling) && (el.nodeName!='DIV') && (el.nodeName!='BR')) if (el.style) el.style.textDecoration = state ? 'line-through' : '' } } function setUnwatchLink (unwatchLink, state) { unwatchLink.innerHTML = state ? '+' : 'x' unwatchLink.title = state ? mw.watch : mw.unwatch } //common functions, some need 'namespace' select element function getNSFromTitle(title){ //returns namespace number var i = title.indexOf(':') if (i == -1) return 0 var prefix = title.substring(0,i+1) //including : for (i=2; i < namespace.options.length; i++) if (namespace.options[i].text+':' == prefix) return i-1 return 0 // ':' was simply a part of a title } function getNamespace(ns){ //returns namespace name if (ns==0) return '' else return namespace.options[ns+1].text } function getTitleFromURL (url){ //gets 'title=' part from a link var ma = url.match(/(&|\?)title=([^&]+)/) if (ma) return decodeURIComponent(ma[2]).replace(/_/g,' ') else return '' } function getWatchlistRows(parent){ //returns all 'history' links inside 'parent' var histLinks = [] var allLinks = parent.getElementsByTagName('a') for (var i = 0; i < allLinks.length; i++) if (/[?&]action=history(&|$)/.test(allLinks[i].href)){ histLinks[histLinks.length] = allLinks[i] i += 3 //move counter to speed things up a bit } return histLinks } 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 } }//obj if (wgCanonicalSpecialPageName && wgCanonicalSpecialPageName=='Watchlist') addOnloadHook(WLScript.onLoad)