User:Cacycle/wikiWatch.js
Appearance
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. |
![]() | This user script seems to have a documentation page at User:Cacycle/wikiWatch. |
// <pre><nowiki>
// ==UserScript==
// @name wikiWatch
// @namespace http://en.wikipedia.org/wiki/User:Cacycle/
// @description A universally compatible watchlist sorter for Wikipedia and other MediaWikis
// @include *
// @exclude
//
// @homepage http://en.wikipedia.org/wiki/User:Cacycle/wikiWatch
// @source http://en.wikipedia.org/wiki/User:Cacycle/wikiWatch.js
// @author Cacycle (http://en.wikipedia.org/wiki/User:Cacycle)
// @license Released into the public domain
// @version 0.1.0
// ==/UserScript==
//
// add wrapped wikiWatch code to body in order to access and use page scripts and variables under Greasemonkey
//
// start of global code wrapper
window.WWWrapper = function() {
// watchlist sorter main program
window.WWMain = function() {
WWRemoveEventListener(window, 'load', WWMain, false);
// check if this has already been run, either as a wiki gadget, wiki user script, or a Greasemonkey user script
if (document.getElementById('WWSetupFlag') != null) {
return;
}
// set already run flag
var flag = document.createElement('span');
flag.id = 'WWSetupFlag';
flag.style.display = 'none';
flag.style.visibility = 'hidden';
document.body.appendChild(flag);
// check if this runs under Greasemonkey
window.WWGreasemonkey = false;
if (typeof(GM_getValue) == 'function') {
WWGreasemonkey = true;
}
// get MediaWiki globals in a Greasemonkey compatible way
window.WWGetGlobalNode = window.WWGetGlobalNode || null;
var wgCanonicalNamespace = WWGetGlobal('wgCanonicalNamespace');
var wgCanonicalSpecialPageName = WWGetGlobal('wgCanonicalSpecialPageName');
var wgArticlePath = WWGetGlobal('wgArticlePath');
var wgServer = WWGetGlobal('wgServer');
// check if this is a MediaWiki watchlist
if ( (wgCanonicalNamespace != 'Special') || (wgCanonicalSpecialPageName != 'Watchlist') ) {
return;
}
// customizable definitions
// number of most recent entries in short display
window.WWRecentShort = window.WWRecentShort || 15;
// texts
window.WWText = window.WWText || {
'WWRecentAll': 'All',
'WWRecentAllToggle': '<span class="WWToggle" title="Toggle the display of all entries">(<a onclick="javascript:{document.getElementById(\'WWSectionBlock-1-{day}\').style.display=\'block\';document.getElementById(\'WWSectionBlock-2-{day}\').style.display=\'none\';}">most recent only</a>)</span>',
'WWRecentTop': 'All',
'WWRecentTopToggle': '<span class="WWToggle" title="Toggle the display of all entries">(<a onclick="document.getElementById(\'WWSectionBlock-2-{day}\').style.display=\'block\';document.getElementById(\'WWSectionBlock-1-{day}\').style.display=\'none\';">show all</a>)</span>',
'WWUnwatch': 'unwatch'
};
// css styles
window.WWCss = window.WWCss || {
'.WWToggle': 'font-weight: normal;',
'.WWToggle A': 'cursor: pointer;',
'.WWToggleDiv': 'margin-left: 4em;',
'.WWToggleUi': '',
'.WWSectionFooter': 'margin-left: 0.5em;',
'.WWDayHeading': 'background-color: #c0c0c0; border: grey solid 1px; margin: 1em 0 0.5em 0 !important; padding: 0 2em;',
'.WWSectionHeading': 'margin: 0 0 0.5em 0; padding: 0 0 0.75em 0.5em;',
'.WWSectionBlock': 'margin: 0 0 0.5em 0;',
'.WWSection': 'border: grey solid 1px; padding: 0 0.5em 0.75em 0.5em;',
'.WWSection > H5': 'padding-top: 0.3em; padding-bottom: 0;',
'TD': 'text-indent: -2em; padding-left: 2em;',
'.WWPopup': 'display: block; padding: 0 1em 1.5em 0; position: absolute; left: 17em; right: 1em; border: 1px solid black; border-top: none; border-right: 1px solid grey;',
'.WWPopup TT': 'display: none;',
'.WWSection-1, .WWSection-1 DIV': 'background-color: #f8fcff;',
'.WWSection-2, .WWSection-1 DIV': 'background-color: #f8fcff;',
'.WWSection0, .WWSection0 DIV': 'background-color: #ffffff;',
'.WWSection1, .WWSection1 DIV': 'background-color: #f2f2f2;',
'.WWSection2, .WWSection2 DIV': 'background-color: #e5e5e5;',
'.WWSection3, .WWSection3 DIV': 'background-color: #d0d0d0;',
// colors: HSB 40°-5%-100% (light), 40°-5%-95% (dark), 40° steps
'.WWSection4, .WWSection4 DIV': 'background-color: #fffbf2;',
'.WWSection5, .WWSection5 DIV': 'background-color: #f2eee6;',
'.WWSection6, .WWSection6 DIV': 'background-color: #fbfff2;',
'.WWSection7, .WWSection7 DIV': 'background-color: #eef2e6;',
'.WWSection8, .WWSection8 DIV': 'background-color: #f2fff2;',
'.WWSection9, .WWSection9 DIV': 'background-color: #e6f2e6;',
'.WWSection10, .WWSection10 DIV': 'background-color: #f2fffb;',
'.WWSection11, .WWSection11 DIV': 'background-color: #e6f2ee;',
'.WWSection12, .WWSection12 DIV': 'background-color: #f2fbff;',
'.WWSection13, .WWSection13 DIV': 'background-color: #e6eef2;',
'.WWSection14, .WWSection14 DIV': 'background-color: #f2f2ff;',
'.WWSection15, .WWSection15 DIV': 'background-color: #e6e6f2;',
'.WWSection16, .WWSection16 DIV': 'background-color: #fbf2ff;',
'.WWSection17, .WWSection17 DIV': 'background-color: #eee6f2;',
'.WWSection18, .WWSection18 DIV': 'background-color: #fff2fb;',
'.WWSection19, .WWSection19 DIV': 'background-color: #f2e6ee;',
'.WWSection20, .WWSection20 DIV': 'background-color: #fff2f2;',
'.WWSection21, .WWSection21 DIV': 'background-color: #f2e6e6;',
'.WWSection22, .WWSection22 DIV': 'background-color: #fff2fb;',
'.WWSection23, .WWSection23 DIV': 'background-color: #f2e6ee;'
};
// add stylesheet definitions
var styles = new WWStyleSheet();
var rules = '';
for (var ruleName in WWCss) {
var ruleStyle = WWCss[ruleName];
if (typeof(ruleStyle) != 'string') {
continue;
}
rules += ruleName + ' {' + ruleStyle + '}\n';
}
styles.addRules(rules);
var regExpMatch;
// define regexps
var regExpWatchlist = new RegExp('(<select\\b[^>]*?\\bid="namespace"[^>]*>(.|\\n)*?)(<h4\\b[^>]*>(.|\\n)*?)(<div\\b[^>]*?\\bclass="printfooter"[^>]*>)', '');
// get watchlist block
document.body.innerHTML = document.body.innerHTML.replace(regExpWatchlist,
function (p, p1, p2, p3, p4, p5) {
var namespaceBlock = p1;
var watchlistBlock = p3;
var pageBottom = p5;
// add unwatch link
// 12 link 2 action3 3 4 41
watchlistBlock = watchlistBlock.replace(/((<a href=\"[^\"]*?&action=)history(\b[^\"]*\"[^>]*>)[^<]+(<\/a>))/g, '$1, $2unwatch$3' + WWText['WWUnwatch'] + '$4');
// get namespaces
var namespaceName = [];
var namespaceNumber = [];
var namespaceHash = [];
var ns = 0;
var regExpNamespace = new RegExp('<option\\b[^>]*?\\bvalue="(\\d+)"[^>]*>((.|\\n)*?)</option\\b[^>]*>', 'g');
while ( (regExpMatch = regExpNamespace.exec(namespaceBlock)) != null) {
namespaceNumber[ns] = regExpMatch[1];
namespaceName[ns] = regExpMatch[2];
if (namespaceNumber[ns] == 0) {
namespaceName[ns] = namespaceName[ns].substr(0, 1).toUpperCase() + namespaceName[ns].substr(1);
}
namespaceHash[ 'WW' + namespaceName[ns] ] = ns;
ns ++;
}
var namespaceMax = ns;
namespaceName[-1] = WWText['WWRecentTop'];
namespaceName[-2] = WWText['WWRecentAll'];
var namespaceSection = [];
// get day block
var day = 0;
var sorted = '';
var regExpDays = new RegExp('(<h4\\b[^>]*>\\s*((.|\\n)*?)\\s*</h4>)\\s*((.|\\n)*?)(?=(<h4\\b[^>]*>|$))', 'g');
while ( (regExpMatch = regExpDays.exec(watchlistBlock)) != null) {
var dayHeading = regExpMatch[1];
var dayContainer = regExpMatch[4];
var mostRecent = 0;
// initialize and clear for +=
for (var ns = -2; ns <= namespaceMax; ns ++) {
namespaceSection[ns] = '';
}
namespaceSection[-2] = dayContainer;
// add day heading
sorted += '<div class="WWDayHeading">' + dayHeading + '</div>';
// get article block
var regExpArticles = new RegExp('((<table\\b[^>]*?>\\s*(.|\\s)*?\\s*</table>)\\s*(<div\\b[^>]*>(.|\\s)*?</div>)?)', 'g');
var regExpArticleName = new RegExp('<a\\b[^>]*?\\btitle="([^\\n\\"]*)"[^>]*>\\1</a>', '');
while ( (regExpMatch = regExpArticles.exec(dayContainer)) != null) {
var articleEditsBlock = regExpMatch[1];
var articleBlock = regExpMatch[2];
var editsBlock = regExpMatch[4];
// get article name
if ( (regExpMatch = regExpArticleName.exec(articleBlock)) != null) {
articleName = regExpMatch[1];
// get article namespace
regExpMatch = /^(.*?):/.exec(articleName);
var namespaceIndex = 0;
if (regExpMatch != null) {
namespaceIndex = namespaceHash[ 'WW' + regExpMatch[1] ];
}
// append article block to section
if (namespaceIndex != null) {
namespaceSection[namespaceIndex] += articleEditsBlock;
// add to all section
// add to most recent section
if (mostRecent < WWRecentShort) {
namespaceSection[-1] += articleEditsBlock;
mostRecent ++;
}
}
}
// finish articles
}
// finish sections
for (var ns = -2; ns <= namespaceMax; ns ++) {
// sort the two main namespaces last
if (ns == 0) {
ns = 2;
}
else if (ns == namespaceMax) {
ns = 0;
}
else if (ns == 2) {
break;
}
// skip empty sections
if (namespaceSection[ns] == '') {
continue;
}
// rename all and top section elements
if ( (ns == -2) || (ns == -1) ) {
namespaceSection[ns] = namespaceSection[ns].replace(/(<[^>]*?\bid=\"RC[IML]\d+)(\")/g, '$1.' + ns + '$2');
namespaceSection[ns] = namespaceSection[ns].replace(/(<[^>]*?=\"javascript:toggleVisibility\(\'RC[IML]\d+)(\',\s*\'RC[IML]\d+)(\',\s*\'RC[IML]\d+)(\')/g, '$1.' + ns + '$2.' + ns + '$3.' + ns + '$4');
}
var sectionStyle = '';
var headerToggle = '';
var footerToggle = '';
if (ns == -1) {
var topToggle = WWText['WWRecentTopToggle'].replace(/\{day\}/g, day)
headerToggle += ' ' + topToggle;
footerToggle = '<div class="WWSectionFooter">' + topToggle + '</div>';
}
else if (ns == -2) {
var allToggle = WWText['WWRecentAllToggle'].replace(/\{day\}/g, day)
headerToggle = ' ' + allToggle;
footerToggle = '<div class="WWSectionFooter">' + allToggle + '</div>';
sectionStyle = ' style="display: none;"';
}
// add sections to sorted watchlist
sorted += '<div class="WWSectionBlock"' + sectionStyle + ' id="WWSectionBlock' + ns + '-' + day + '"><div class="WWSection' + ns + '"><div class="WWSection"><h5 class="WWSectionHeading">' + namespaceName[ns] + headerToggle + '</h5>' + namespaceSection[ns] + footerToggle + '</div></div></div>';
}
// finish day
day ++;
}
return(namespaceBlock + '<div id="WWSorted" class="WWSorted">' + sorted + '</div>' + pageBottom);
}
);
// ceate list of expandable entries for closing popups
window.wwEditDivs = [];
var divs = document.getElementsByTagName('div');
for (var i = 0; i < divs.length; i ++) {
if (divs[i].id.match(/^RCI[\d\.\-]+/) != null) {
wwEditDivs.push(divs[i]);
}
}
// regexp to identify article links from link href
var regExpStr = '^' + wgServer + wgArticlePath+ '$';
regExpStr = regExpStr.replace(/\$\d/, '[^\\?]*?');
regExpStr = regExpStr.replace(/\./, '\\.');
var regExpArticleLink = new RegExp(regExpStr);
// get all page links
var bodyContent = document.getElementById('bodyContent');
if (bodyContent == null) {
return;
}
var links = bodyContent.getElementsByTagName('a');
// cycle through all links
var linkNumber = 0;
for (var i = 0; i < links.length; i ++) {
// check if this is an article link
if (links[i].innerHTML.replace(/\"/g, '') != links[i].title) {
continue;
}
if (links[i].href.match(regExpArticleLink) == null) {
continue;
}
// add mouseover event to link
WWAddEventListener(links[i], 'mouseover', WWOpenPopup, false);
// find the container table element
var mainTable = links[i];
while (mainTable != null) {
if (mainTable.nodeName == 'TABLE') {
break;
}
mainTable = mainTable.parentNode;
}
// check if next sibling is an edits div
if (mainTable == null) {
continue;
}
var editsDiv = mainTable.nextSibling;
while (editsDiv != null) {
if (editsDiv.nodeType != 3) {
break;
}
editsDiv = editsDiv.nextSibling;
}
// add link id for easy access of related edits div
if (editsDiv == null) {
continue;
}
if (editsDiv.nodeName != 'DIV') {
continue;
}
var editsDivId = editsDiv.id;
if (editsDivId.match(/^RCI[\d\.\-]+/) != null) {
links[i].id = 'WW' + linkNumber + '-' + editsDivId;
linkNumber ++;
}
}
return;
}
//
// WWToggleVisibility: replacement for toggleVisibility
//
window.WWToggleVisibility = function(levelId, otherId, linkId) {
WWClosePopups();
var thisLevel = document.getElementById(levelId);
var otherLevel = document.getElementById(otherId);
var linkLevel = document.getElementById(linkId);
if (thisLevel.class == 'WWPopup') {
thisLevel.style.display = 'none';
thisLevel.className = '';
}
if (thisLevel.style.display == 'none') {
thisLevel.style.display = 'block';
otherLevel.style.display = 'none';
linkLevel.style.display = 'inline';
}
else {
thisLevel.style.display = 'none';
otherLevel.style.display = 'inline';
linkLevel.style.display = 'none';
}
return;
}
window.toggleVisibility = WWToggleVisibility;
//
// WWOpenPopup: open detailed edits preview
//
window.WWOpenPopup = function(event) {
// MS IE compatibility fix
event = WWEvent(event);
if (event == null) {
return;
}
// get link id with div RCI id
var lnk = event.target
var levelId;
if (lnk == null) {
return;
}
if (lnk.nodeName != 'A') {
return;
}
// only close popups for single-entry links
if (lnk.id == '') {
WWClosePopups();
}
// popup edits
else {
levelId = lnk.id.replace(/^WW\d+-/, '');
if (levelId != '') {
var thisLevel = document.getElementById(levelId);
// show edits div as popup
thisLevel.className = 'WWPopup';
thisLevel.style.display = 'block';
// down arrow back to right arrow
var regExpMatch = /^RCI([\d\.\-]+)/.exec(levelId);
if (regExpMatch != null) {
var idNumber = regExpMatch[1];
var otherLevel = document.getElementById('RCM' + idNumber);
var linkLevel = document.getElementById('RCL' + idNumber);
otherLevel.style.display = 'inline';
otherLevel.blur();
linkLevel.style.display = 'none';
}
WWClosePopups(levelId);
}
}
return;
}
//
// WWClosePopups: close all detailed edit previews
//
window.WWClosePopups = function(levelId) {
for (var i = 0; i < wwEditDivs.length; i ++) {
if (wwEditDivs[i].className == 'WWPopup') {
if (wwEditDivs[i].id != levelId) {
wwEditDivs[i].className = '';
wwEditDivs[i].style.display = 'none';
}
}
}
return;
}
//
// WWEvent: MS IE compatibility fix for event object
//
window.WWEvent = function(event) {
var eventAlt;
if (window.event != null) {
eventAlt = window.event;
}
if (eventAlt != null) {
event = eventAlt;
event.stopPropagation = function() {
event.cancelBubble = true;
};
event.preventDefault = function() {
event.returnValue = false;
};
event.target = event.srcElement;
}
return(event);
}
//
// WWGetGlobal: access values of global variables from Greasemonkey scripts using the 'location hack'
//
window.WWGetGlobal = function(globalName) {
var globalValue;
if (WWGreasemonkey == true) {
if (WWGetGlobalNode == null) {
window.WWGetGlobalNode = document.getElementById('WWGetGlobalNode');
}
if (WWGetGlobalNode == null) {
WWGetGlobalNode = document.createElement('textarea');
WWGetGlobalNode.id = 'WWGetGlobalNode';
WWGetGlobalNode.style.display = 'none';
WWGetGlobalNode.style.visibility = 'hidden';
document.body.appendChild(WWGetGlobalNode);
}
location.href = 'javascript:void(typeof(' + globalName + ')!=\'undefined\'?(' + globalName + '!=null?(document.getElementById(\'WWGetGlobalNode\').value=' + globalName + '.toString()):null):null)';
globalValue = WWGetGlobalNode.value;
}
else {
try {
globalValue = eval(globalName + '.toString();');
}
catch(err) { }
}
return(globalValue);
}
//
// WWAddEventListener: wrapper for addEventListener (http://ejohn.org/projects/flexible-javascript-events/)
//
window.WWAddEventListener = function(domElement, eventType, eventHandler, useCapture) {
if (domElement != null) {
if (domElement.attachEvent != null) {
domElement['WW' + eventType + eventHandler] = eventHandler;
domElement[eventType + eventHandler] = function() {
domElement['WW' + eventType + eventHandler](window.event);
}
domElement.attachEvent('on' + eventType, domElement[eventType + eventHandler] );
}
else {
domElement.addEventListener(eventType, eventHandler, useCapture);
}
}
return;
}
//
// WWRemoveEventListener: wrapper for removeEventListener
//
window.WWRemoveEventListener = function(domElement, eventType, eventHandler, useCapture) {
if (domElement.detachEvent != null) {
domElement.detachEvent('on' + eventType, domElement[eventType + eventHandler]);
domElement[eventType + eventHandler] = null;
}
else {
domElement.removeEventListener(eventType, eventHandler, useCapture);
}
return;
}
//
// WWStyleSheet: create a new style sheet object
//
window.WWStyleSheet = function(contextObj) {
if (contextObj == null) {
contextObj = document;
}
this.styleElement = null;
// MS IE compatibility
if (contextObj.createStyleSheet) {
this.styleElement = contextObj.createStyleSheet();
}
// standards compliant browsers
else {
this.styleElement = contextObj.createElement('style');
this.styleElement.from = 'text/css';
var insert = contextObj.getElementsByTagName('head')[0];
if (insert != null) {
this.styleElement.appendChild(contextObj.createTextNode('')); // Safari 3 fix
insert.appendChild(this.styleElement);
}
}
//
// WWStyleSheet.addRules: add all rules at once, much faster
//
this.addRules = function(rules) {
// MS IE compatibility
if (this.styleElement.innerHTML == null) {
this.styleElement.cssText = rules;
}
// via innerHTML
else {
this.styleElement.innerHTML = rules;
}
return;
}
}
//
// WWDebug: print the value of variables
// use either a single value or a description followed by a value
// popup = true: use alert popup if debug textarea is not yet setup
//
window.WWDebugTextarea = null;
window.WWDebug = function(objectName, object, usePopup, useConsole) {
// create debug textarea and add to debug wrapper
if (WWDebugTextarea == null) {
window.WWDebugTextarea = document.createElement('textarea');
WWDebugTextarea.id = 'WWDebug';
WWDebugTextarea.className = 'WWDebug';
WWDebugTextarea.rows = 20;
WWDebugTextarea.style.display = 'none';
WWDebugTextarea.style.position = 'relative';
WWDebugTextarea.style.margin = '1em';
WWDebugTextarea.style.zIndex = '10000';
WWDebugTextarea = document.body.insertBefore(WWDebugTextarea, document.body.firstChild);
}
WWDebugTextarea.style.display = 'block';
if (objectName == null) {
WWDebugTextarea.value = '';
}
else {
if (object == null) {
WWDebugTextarea.value = objectName + '\n' + WWDebugTextarea.value;
}
else {
WWDebugTextarea.value = objectName + ': ' + object + '\n' + WWDebugTextarea.value;
}
}
// use popup alert
if (usePopup != null) {
if (object == null) {
alert(objectName);
}
else {
alert(objectName + ': ' + object);
}
}
// use error console
if (useConsole != null) {
var msg;
if (object == null) {
msg = objectName + '';
}
else {
msg = objectName + ': ' + object;
}
msg = msg.replace(/\'/g, '\\\'');
setTimeout('throw new Error(\'WWDebug: ' + msg + '\')', 0);
}
return;
}
window.WWD = WWDebug;
//
// add wrapped WW code to body in order to access and use page scripts under Greasemonkey
//
// close global wrapper
}
// append wrapper
window.WWSetup = function() {
var script = document.createElement('script');
script.innerHTML = 'WWWrapper = ' + WWWrapper.toString() + '; WWWrapper(); WWMain();';
document.body.appendChild(script);
return;
}
// schedule the setup routine (currently Mozilla-only)
window.addEventListener('load', WWSetup, false);
// </nowiki></pre>