User talk:MrX/highlight-comments.js
/**
* Highlights specific users' posts to discussion pages using a CSS class. * * Originally written by PleaseStand in 2010, updated for MediaWiki 1.17 in 2011 * Rewrite completed in 2012 * * Released to the public domain; see http://en.wikipedia.org/wiki/Template:PD-self */
( function ( mw, $ ) {
"use strict";
// Default settings var settings = { highlighterFunction: function ( hc ) { // Default highlighter function hc.addColorForUsers( '#ff7', [mw.config.get( 'wgUserName' )] ); hc.wrapComments(); hc.addMenuItem(); } };
/** * Messages displayed by this script (in English). * Any translations (see below) replace these at runtime. */ var msg = { highlightText: 'Highlight', highlightTooltip: 'Enable highlighting of your own comments on this page', unhighlightText: 'Unhighlight', unhighlightTooltip: 'Disable highlighting of your own comments on this page' };
/** * Translations for messages displayed by this script. * To have your translations added, please contact this script's maintainer. */ var translations = { };
// Load translations. $.extend( msg, translations[document.documentElement.lang] );
// Initialize other enclosed variables. var linkMap = Object.create( null ), classNumber = 0, pageRE = null, commentsAreHighlighted = false;
/** * Build pageRE, a regexp for the use of findPageNameFromHref(). */ function buildPageRE() { var articlePathParts = mw.config.get( 'wgArticlePath' ).split( '$1' ); var articlePathStartRE = mw.RegExp.escape( articlePathParts[0] ); var articlePathEndRE = mw.RegExp.escape( articlePathParts[1] ); var indexPathRE = mw.RegExp.escape( mw.util.wikiScript( 'index' ) );
return new RegExp( '^(?:' + articlePathStartRE + '([^?#]+)' + articlePathEndRE + '|' + indexPathRE + '\\?(?:[^&#]*&)*title=([^&#]+))' ); }
/** * Find a linked page's name (with underscores, not spaces) given a relative URL. * This assumes the page is linked using a normal, intra-wiki link. */ function findPageNameFromHref( href ) { var m = pageRE.exec( href ); return m ? decodeURIComponent( ( m[1] || m[2] ).replace( /\+/g, '%20' ) ).replace( / /g, '_' ) : null; }
/** * Give comments linking to any given page a specific CSS class. * @see unwrapComments */ function wrapComments() { wrapElementComments( $( '.mw-highlight-comments' ) ); commentsAreHighlighted = true; addMenuItem( true ); }
/** * Mechanics of wrapComments(), excluding the flag and menu item updates. * * Essentially, we need to find the comment's container and wrap (except where unnecessary) * everything inside except replies to that comment. We can filter the replies out in that * they are inside other element types that have the effect of indenting the text. * * @param content The DOM element(s) containing the content. This may be a jQuery object. */ function wrapElementComments( content ) { // Elements containing comments or indented text (replies to those comments) var commentTags = 'dd, li, p', indentTags = 'dl, ol, ul';
$( 'a', content ).each( function () { var pageName = findPageNameFromHref( this.getAttribute( 'href' ) ); // linkMap is from linked page names to CSS class names. if ( pageName && pageName in linkMap ) { var className = linkMap[pageName]; $( this ).closest( commentTags ).contents().not( indentTags ).each( function () { if ( this.nodeType === 1 ) { var $elem = $( this ); if ( !$elem.hasClass( className ) ) { $elem .addClass( className ) .attr( 'data-mw-highlighted-comment-class', className ); } } else { $( this ).wrap( $( '', { 'class': className, 'data-mw-highlighted-comment-wrapper': } ) ); } } ); } } ); }
/** * Undo the actions performed by wrapComments(). */ function unwrapComments() { // Remove added wrappers $( '[data-mw-highlighted-comment-wrapper]' ).replaceWith( function () { return this.childNodes; } );
// Remove added classes $( '[data-mw-highlighted-comment-class]' ).removeClass( function () { var klass = $( this ).attr( 'data-mw-highlighted-comment-class' ); $( this ).removeAttr( 'data-mw-highlighted-comment-class' ); return klass; } );
commentsAreHighlighted = false; addMenuItem( true ); }
/** * Add a group of users whose comments should be given the same CSS class. * @param className The CSS class name to use * @param users An array of usernames */ function addClassForUsers( className, users ) { var ns = mw.config.get( 'wgFormattedNamespaces' ); for ( var i = 0; i < users.length; ++i ) { var userName = users[i].replace( / /g, '_' ); var userPage = ns[2] + ':' + userName, userTalkPage = ns[3] + ':' + userName; linkMap[userPage] = className; linkMap[userTalkPage] = className; } }
/** * Add a group of users whose comments should be highlighted in the same color. * @param color The CSS background-color to use * @param users An array of usernames * @return The resulting CSSStyleSheet object */ function addColorForUsers( color, users ) { var className = 'highlighted-comment-' + classNumber++; addClassForUsers( className, users ); return mw.util.addCSS( '.' + className + ' { background-color: ' + color + '; }' ); }
/** * Adds or updates a "Highlight" or "Unhighlight" option in the content action menu. * @param updateOnly Do nothing if the menu item does not already exist? */ function addMenuItem( updateOnly ) { var text, tooltip, $oldItem = $( '#ca-highlightcomments' );
if ( updateOnly && !$oldItem.length ) { return; }
if ( commentsAreHighlighted ) { text = msg.unhighlightText; tooltip = msg.unhighlightTooltip; } else { text = msg.highlightText; tooltip = msg.highlightTooltip; }
var link = mw.util.addPortletLink( 'p-cactions', '#', text, 'ca-highlightcomments', tooltip, null, $oldItem[0] ); $oldItem.remove();
$( link ).click(function () { if ( commentsAreHighlighted ) { unwrapComments(); } else { wrapComments(); } }); }
// Members exposed to custom highlighter functions var hc = { addClassForUsers: addClassForUsers, addColorForUsers: addColorForUsers, addMenuItem: addMenuItem, wrapComments: wrapComments };
mw.loader.using( [ 'mediawiki.util', 'mediawiki.RegExp' ], function () { // Cache pageRE for performance. pageRE = buildPageRE();
// Run either the user's highlighter function or the default one. $( function () { $.extend( settings, window.highlightCommentsSettings ); settings.highlighterFunction( hc ); } );
// Now that all settings have been processed, get the elements // in which comments should be highlighted. Of course, actually // highlight them if that is desired. mw.hook( 'wikipage.content' ).add( function ( $content ) { $content.addClass( 'mw-highlight-comments' ); if ( commentsAreHighlighted ) { wrapElementComments( $content ); } } ); } );
}( mediaWiki, jQuery ) );