MediaWiki:FileComments.js
Jump to navigation
Jump to search
Note: After saving, you have to bypass your browser's cache to see the changes. Internet Explorer: press Ctrl-F5, Mozilla: hold down Shift while clicking Reload (or press Ctrl-Shift-R), Opera/Konqueror: press F5, Safari: hold down Shift + Alt while clicking Reload, Chrome: hold down Shift while clicking Reload.
Documentation for this user script can be added at MediaWiki:FileComments. |
/**
* (c) 2011 by Magnus Manske
* Released under GPL V2 or above
*/
$.fn.exists = function() {
return this.length > 0;
};
/**
* Check typeof of variables.
* Note: Do not use for variables that may be undeclared (ie. implied global)
* this only works for local variables and arguments
* (Otherwise a ReferenceError is thrown when the function is called)
*/
function isDef( o ) {
return typeof o !== "undefined";
}
$.fn.tagName = function() {
return this.get(0).tagName;
};
Object.size = function(obj) {
var size = 0, key;
for ( key in obj ) {
if ( obj.hasOwnProperty( key ) ) size++;
}
return size;
};
var filecomments = {
interface_texts : {
'heading' : 'Comments and favourites' ,
'comments' : 'comments' ,
'favourites' : 'favourites' ,
'rem_fav' : 'Remove favourite' ,
'set_fav' : 'Set favourite' ,
'loading_comments' : 'Loading comments from talk page...' ,
'add_comment' : 'Add a comment' ,
'edit_comments' : 'Edit comments' ,
'my_favs' : 'My favourite files' ,
'my_comments' : 'My file comments' ,
'summary_new_fav' : 'New favourite of ' ,
'summary_rem_fav' : 'Removing favourite' ,
'talk_to_user' : 'talk' ,
'add_a_comment' : 'Add a comment, ' ,
'summary_new_comment' : 'New comment : ' ,
'alert_no_edit_token' : 'Could not acquire edit token, operation aborted' ,
'alert_edit_fail' : 'The edit operation has failed' ,
'user_subpage_favourites' : 'My_favourite_files' ,
'user_subpage_comments' : 'My_file_comments'
} ,
it : function ( key ) {
var ret = filecomments.interface_texts[key];
if ( !isDef( ret ) ) ret = "???";
return ret;
} ,
initInterfaceTexts : function () {
// For future use
} ,
init : function () {
if ( !mw.user.isAnon() ) this.user_name = mw.user.getName();
else this.user_name = 'anonymous user'; // This should never be used, but...
filecomments.user_favs_page = 'User:' + filecomments.user_name + '/' + filecomments.it('user_subpage_favourites');
filecomments.user_comments_page = 'User:' + filecomments.user_name + '/' + filecomments.it('user_subpage_comments');
if ( mw.config.get('wgAction') !== 'view' ) return; // Only on views!
// Redirect to category of my comments:
if ( filecomments.user_comments_page == mw.config.get('wgPageName') ) {
window.location = mw.util.getUrl( 'Category:File comments by ' + this.user_name );
return;
}
// Show interface texts only on file pages
if ( mw.config.get( 'wgNamespaceNumber' ) !== 6 ) return; // Nevermind...
this.initInterfaceTexts();
this.addCommentsBox();
} ,
addCommentsBox : function () {
var cn = '';
var ib = $('#filehistory');
$('#filecomments_container').remove();
var h = "<div id='filecomments_container' class='" + cn + "'>";
h += "<h2>" + filecomments.it('heading') + "</h2>";
h += "<div id='filecomments_top'></div>";
h += "<div id='filecomments_main'></div>";
h += "<div id='filecomments_bottom'></div>";
h += "</div>";
ib.before( h );
filecomments.parseTalkPage();
} ,
parseTalkPage : function () {
filecomments.talk_page = 'File talk:' + mw.config.get('wgTitle');
filecomments.loadBeforeParsing = 1; // Future parallel queries
// plain text
$.getJSON(
mw.util.wikiScript( 'api' ), {
'format': 'json',
'action': 'query',
'titles': filecomments.talk_page,
'prop' : 'revisions' ,
'rvprop' : 'content'
}, function( data ) {
$.each( data.query.pages , function ( k , v ) {
if ( isDef( v.missing ) ) filecomments.talk_page_text = '';
else {
$.each( v.revisions , function ( k2 , v2 ) {
filecomments.talk_page_text = v2['*'];
} );
}
} );
filecomments.renderCommentBox();
}
);
} ,
renderCommentBox : function () {
filecomments.loadBeforeParsing--;
if ( 0 < filecomments.loadBeforeParsing ) return;
var text = filecomments.talk_page_text;
// Parse comments
var comments = text.match( /\{\{filecommentstart\|.+?\{\{filecommentend\}\}/gi );
if ( !comments ) comments = [];
// Parse favourites
var favourites = text.match( /\{\{filecommentfavourite\|.+?\}\}/gi );
if ( !favourites ) favourites = [];
filecomments.isMyFavourite = false;
$.each ( favourites , function ( k , v ) {
var v2 = v.match( /^\{\{filecommentfavourite\|(.+?)\}\}$/i );
if ( v2[1] != filecomments.user_name ) return;
filecomments.isMyFavourite = true;
filecomments.myFavouriteTag = v2[0];
} );
// Top
var h = '';
h += comments.length + " " + filecomments.it('comments') + " | ";
h += favourites.length + " " + filecomments.it('favourites');
if ( !mw.user.isAnon() ) {
if ( filecomments.isMyFavourite ) h += " | <a href='#' onclick='filecomments.setFavourite(false);return false'>" + filecomments.it('rem_fav') + "</a>";
else h += " | <a href='#' onclick='filecomments.setFavourite(true);return false'>" + filecomments.it('set_fav') + "</a>";
h += " | <a href='" + mw.util.getUrl( filecomments.user_favs_page ) + "'>" + filecomments.it('my_favs') + "</a>";
h += " | <a href='" + mw.util.getUrl( filecomments.user_comments_page ) + "'>" + filecomments.it('my_comments') + "</a>";
}
h += "<br/>";
$('#filecomments_top').html( h );
// Main
filecomments.comment_render_counter = 1;
filecomments.comments = {};
$.each( comments , function ( k , v ) {
filecomments.parseComment( v );
} );
h = '';
$('#filecomments_main').html( h );
$('#filecomments_main').html( "<i>" + filecomments.it('loading_comments') + "</i>" );
// Bottom
h = '';
if ( !mw.user.isAnon() ) {
h += "<a href='#' onclick='filecomments.addComment();return false'>" + filecomments.it('add_comment') + "</a> | ";
h += "<a href='" + mw.util.getUrl( filecomments.talk_page ) + "'>" + filecomments.it('edit_comments') + "</a>";
}
$('#filecomments_bottom').html( h );
filecomments.renderComments();
} ,
setFavourite : function ( what ) {
if ( filecomments.isMyFavourite == what ) {
// This should never happen
return;
}
// Edit talk page
var t = filecomments.talk_page_text;
if ( what ) { // Set favourite
t += "\n" + '{{filecommentfavourite|' + filecomments.user_name + '}}';
filecomments.editTalkPage( 'text' , t , filecomments.it('summary_new_fav') + filecomments.user_name );
} else { // Remove favourite
t = t.replace( filecomments.myFavouriteTag , '' );
filecomments.editTalkPage( 'text' , t , filecomments.it('summary_rem_fav') );
}
// Edit favs page
$.getJSON(
mw.util.wikiScript( 'api' ), {
'format': 'json',
'action': 'query',
'titles': filecomments.user_favs_page,
'prop' : 'revisions' ,
'rvprop' : 'content'
}, function( data ) {
// @todo Check for 'error' in data before assuming everything is alright.
var t = "<gallery>\n</gallery>"; // If page is blank
$.each( data.query.pages , function ( k , v ) {
if ( ! isDef( v.missing ) ) {
$.each( v.revisions , function ( k2 , v2 ) {
t = v2['*'];
} );
}
} );
var fn = "\nFile:" + mw.config.get('wgTitle');
t = t.replace( fn , '' ); // Remove if exists
if ( what ) t = t.replace( "\n</gallery>" , fn + "\n</gallery>" );
filecomments.editPage( filecomments.user_favs_page , 'text' , t , mw.config.get('wgTitle') , false );
}
);
} ,
renderComments : function () {
filecomments.comment_render_counter--;
if ( filecomments.comment_render_counter > 0 ) return;
var keys = [];
$.each( filecomments.comments , function ( k , v ) { keys.push( k ); } );
keys.sort();
var h = '';
$.each( keys , function ( kk , k ) {
v = filecomments.comments[k];
h += "<div class='filecomments_comment'>";
h += "<div>";
h += "<a href='" + mw.util.getUrl( 'User:'+v.user ) + "'><b>" + v.user + "</b></a>";
h += " (<a href='" + mw.util.getUrl( 'User talk:'+v.user ) + "'>" + filecomments.it('talk_to_user') + "</a>)";
h += " " + v.time;
h += "</div>";
if ( isDef( v.rendered ) ) h += "<div>" + v.rendered + "</div>";
else h += "<div>" + v.text + "</div>";
h += "</div>";
} );
$('#filecomments_main').html( h );
} ,
parseComment : function ( comment ) {
var user = comment.match( /\|(.+?)\|(.+?)\}\}/ );
var time = user[1];
user = user[2];
var text = comment.match( /\}\}(.+?)\{\{filecommentend\}\}$/ );
text = text[1];
var begin = comment.match( /^(.+?\}\})/ );
var end = comment.match( /\}\}.+?(\{\{filecommentend\}\})$/ );
filecomments.comments[time+"/"+user] = {
'user' : user ,
'time' : time ,
'text' : text ,
'begin' : begin[1] ,
'end' : end[1]
};
if ( !filecomments.containsWikiText( text ) ) return;
filecomments.comment_render_counter++;
$.getJSON(
mw.util.wikiScript( 'api' ), {
'format': 'json',
'action': 'parse',
'text' : text
}, function( data ) {
$.each( data.parse.text , function ( k , v ) {
filecomments.comments[time + '/' + user].rendered = v;
filecomments.renderComments();
} );
}
);
} ,
containsWikiText : function ( text ) {
if ( text.match( /\[\[/ ) ) return true;
if ( text.match( /\{\{/ ) ) return true;
if ( text.match( /''/ ) ) return true;
if ( text.match( /[<>]/ ) ) return true;
return false;
} ,
twoDigits : function ( v ) {
if ( v < 10 ) return "0" + v;
return "" + v;
} ,
addComment : function () {
var comment = prompt( filecomments.it('add_a_comment') + filecomments.user_name );
if ( !comment || comment === '' || comment === null ) return;
var ct = new Date();
var t = ct.getFullYear() + "-";
t += filecomments.twoDigits( ct.getMonth()+1 ) + "-";
t += filecomments.twoDigits( ct.getDate() ) + " ";
t += filecomments.twoDigits( ct.getHours() ) + ":";
t += filecomments.twoDigits( ct.getMinutes() ) + ":";
t += filecomments.twoDigits( ct.getSeconds() );
var line = "\n" + '{{filecommentstart|' + t + "|" + filecomments.user_name + '}}' + comment + '{{filecommentend}}';
filecomments.editTalkPage( 'appendtext' , line , filecomments.it('summary_new_comment') + comment );
line = "\n* [[:File:" + mw.config.get('wgTitle') + "|64px|noframe|]] " + mw.config.get('wgTitle') + " (" + t + ") : " + comment;
filecomments.editPage( filecomments.user_comments_page , 'appendtext' , line , filecomments.it('summary_new_comment') + comment , 0 );
} ,
editTalkPage : function ( mode , text , summary ) {
filecomments.editPage( filecomments.talk_page , mode , text , summary , true );
} ,
editPage : function ( page , mode , text , summary , update_box ) {
$('#filecomments_container').css( 'background-color' , '#DDDDDD' );
$.getJSON(
mw.util.wikiScript( 'api' ), {
'format': 'json',
'action': 'query',
'titles': page,
'prop' : 'info' ,
'intoken' : 'edit'
}, function( data ) {
var token = '';
$.each( data.query.pages , function ( k , v ) {
token = v.edittoken;
} );
if ( token === '' ) {
alert( filecomments.it('alert_no_edit_token') );
$('#filecomments_container').css( 'background-color' , '' );
return;
}
var o = {
'format': 'json',
'action': 'edit',
'title': page,
'token' : token ,
'summary' : summary
};
o[mode] = text;
if ( !mw.user.isAnon() ) o.minor = '';
$.post(
mw.util.wikiScript( 'api' ), o,
function( data ) {
$('#filecomments_container').css( 'background-color' , '' );
if ( data.edit.result != 'Success' ) {
// @todo: just load the "json" module because JSON is not cross-browser supported
alert( filecomments.it('alert_edit_fail') + "\n" + JSON.stringify( data ) );
} else {
if ( update_box ) filecomments.parseTalkPage();
}
}
);
}
);
} ,
the_end_of_the_object : '' // To avoid worrying about the final comma...
};
$( function() {
filecomments.thumb_size = 128;
mw.util.addCSS(
'#filecomments_container { padding:2px; }'
+ '.filecomments_floatright { float:right; max-width:500px; border:1px solid #EEEEEE; margin-left:5px; margin-bottom:5px; }'
+ '#filecomments_top { border-bottom:1px solid #EEEEEE; padding-bottom:2px; margin-bottom:5px; }'
+ '.filecomments_comment { margin-top:3px; margin-bottom:3px; border-left:5px solid #62A9FF; padding-left:2px }'
+ '.filecomments_comment:hover { background-color:#DBEBFF; }'
+ '#filecomments_bottom { margin-top:5px; }'
+ '.filecomments_thumb_container { width:'+filecomments.thumb_size+'px; height:'+filecomments.thumb_size+'px; margin:5px; padding:2px; border:1px solid #EEEEEE; display:inline-block; text-align:center; }'
);
filecomments.init();
});