MediaWiki:Gadget-addMe.js

// AddMe gadget, taken from Meta and heavily edited for the Developer Wishlist. // Supports endorse / join / vote by adding your signature and possibly other text // See https://meta.wikimedia.org/wiki/Meta:AddMe for usage and description.

/* * Common utilities for both the endorse & the join gadget */ var gadgetUtilities = function { //A reference to the object var that = this; //The mw wrapper to access the API var api = new mw.Api; /*	 * The interface messages or strings are maintained in interfaceMessagesPath & config values eg, * section-header, the section where the comments are added etc are maintained in configPath */	this.interfaceMessagesPath = 'MediaWiki:AddMe/InterfaceText'; this.configPath = 'MediaWiki:AddMe/Config'; //The time taken for the page to scroll to the feedback speech bubble (milliseconds) this.feedbackScrollTime = 2000; //The time taken for the feedback speech bubble to disappear (milliseconds) this.feedbackDisappearDelay = 10000; /*	 * This function is used to set a cookie to show the speech bubble * on page reload */	this.setFeedbackCookie = function(value, domain){ $.cookie('addme-'+value, domain); };	/*	 * This function is used to check if a has been set by the above function * to show the speech bubble on page reload */	this.checkFeedbackCookie = function(value){ var val = $.cookie('addme-'+value); if(val){ $.cookie('addme-'+value,null); return val; }		else{ return false; }	};	/*	 * To display an error message when an error occurs * in the gadget */	this.showErrorMessage = function(gadget,type){ var errorAttr = '[localize=error-'+type+']'; var gadgetID = '.'+gadget; $(gadgetID + ' ' + errorAttr).show; };	/*	 * To remove the error message displayed by the above function */	this.removeErrorMessage = function(gadget){ var gadgetID = '.'+gadget; $(gadgetID + ' [localize^="error-"]').hide; };	/*	 * To detect the users default language */	this.userLanguage = function{ return mw.config.get('wgUserLanguage'); };	/*	 * To detect the language of the page */	this.contentLanguage = function{ return mw.config.get('wgContentLanguage'); };	/*	 * To remove extra spaces & cleanup the comment string */	this.cleanupText = function(text){ return $.trim(text).replace(/~{3,5}/, '')+' '; };	/*	 * The config files which can be translated with the help of the * translation tool generates the dict with the values having a * lot of space in the key value pairs. This function strips the * whitespace. */	this.stripWhiteSpace = function(dict){ for (var key in dict){ //Temp fix for section header if(key == 'section-header'){ dict['section-header-read'] = dict[key].replace(/ /g,'_'); dict['section-header-write'] = dict[key]; }			dict[key] = typeof(dict[key]) == 'object' ? that.stripWhiteSpace(dict[key]) : $.trim(dict[key]); }		return dict; };	/*	 * To localize the gadget's interface messages based on the user's language setting */	this.localizeGadget = function (gadgetClass,localizeDict){ $(gadgetClass+' [localize]').each(function{			var localizeValue = localizeDict[$(this).attr('localize')];			if($(this).attr('value')){				$(this).attr('value',localizeValue);			}			else if($(this).attr('placeholder')){				$(this).attr('placeholder',localizeValue);			}			else if($(this).attr('data-placeholder')){				$(this).attr('data-placeholder',localizeValue);			}			else{				$(this).html(localizeValue);			}		}); };	/*	 * This function show the feedback speech bubble after an 	 * endorsement has been made or after joining a project */	this.showFeedback = function(config,InterfaceMessages){ var li = $('#'+config['section-header-read']).parent.next.find('li').eq(-1); speechBubble = li.append($(' ').html(' \ Thank You  ')).find('.grantsSpeechBubbleContainer'); var width = li.css('display','inline-block').width; li.css('display',''); li.css('position','relative'); speechBubble.css('left',width/2+'px'); $('[localize=message-feedback]').html(InterfaceMessages['message-feedback']); $("body, html").animate({ scrollTop : li[0].offsetTop}, that.feedbackScrollTime); setTimeout(function{ speechBubble.hide;},that.feedbackDisappearDelay); }; }; var Gadget = function{ /* Variables */ var util = new gadgetUtilities; var dialogs = []; var api = new mw.Api; var that = this;

/*	 * This function creates the dialog box for the gadget. * It is also where all the dialog related interactions are defined. */ 	var createDialog = function(domain){ var dialog = $( " " ) .html(					' \					 	 An error occured \					 	 An error occured \					 \					 Endorse the proposal (optional) ' + '\					  \					 Your signature will be added automatically \					 \						Cancel\						 \					 '		).dialog({			dialogClass: 'grantsGadget endorseGadget',			autoOpen: false,			title: 'Endorse Comment', width: '495px', modal: true, closeOnEscape: true, resizable: false, draggable: false, close: function( event, ui ) { $('#devEndorseComment').val(''); }		});

$('.add-endorse').click(function{			that.addEndorsement(util.cleanupText($('#devEndorseComment').val));		}); $('#devEndorseComment').on('change keyup paste',function{			util.removeErrorMessage('endorseGadget');			if($(this).val){				$('.add-endorse').attr('disabled',false);				$('.messageSignature').css('visibility','visible');			}			else{				$('.add-endorse').attr('disabled',true);				$('.messageSignature').css('visibility','hidden');			}		}); $('.endorseGadget .ui-dialog-title').attr('localize','title'); $('.endorseGadget .cancel').click(function{			dialog.dialog('close');		}); util.localizeGadget('.endorseGadget',that.interfaceMessages); $('.messageSignature').css('visibility','hidden'); dialogs[domain] = dialog; };	/**	 * Tells which configuration/i18n subset to use. */	this.setDomain = function (domain) { this.domain = domain; this.config = util.stripWhiteSpace(this.allConfig); this.interfaceMessages = util.stripWhiteSpace(this.allInterfaceMessages); };	this.Dialog = function { if (dialogs[that.domain] === null){ createDialog(that.domain); }		else{ dialogs[that.domain].dialog('open'); }	};	/*	 * The main function to add text + a signature to the page. */	this.addEndorsement = function( sectionName, text ) { var endorseComment = '\n*' + text + 'Tgr (WMF) (talk) 22:44, 5 February 2017 (UTC)' + '\n'; var newText, baseTimestamp, revId, sectionCount; api.get({			'format':'json',			'action':'parse',			'prop':'wikitext',			'page':mw.config.get('wgPageName')		}).then(function(result){			var sections = result.parse.sections;			sectionCount = 1;			var sectionFound = false;			for (var section in sections ){				if ($.trim(sections[section].line) === sectionName ){					sectionFound = true;					break;				}				sectionCount++;			}			if (sectionFound){				return api.get({ 'format':'json', 'action':'parse', 'prop':'revid|sections|wikitext', 'page': mw.config.get('wgPageName'), 'section': sectionCount });			} else {				return $.Deferred.reject( 'addme-sectionnotfound', 'Did not find the right section to edit!' );			}		}).then(function(result){			if ( result.parse.sections[0].line !== sectionName ) { // sanity				return $.Deferred.reject( 'addme-sectionchanged', 'Edit conflict, please retry' );			}			revId = result.parse.revid;			var wikitext = result.parse.wikitext['*'];			newText = wikitext.replace( /\n#\s*$/, '' ) + endorseComment;			// fetch the base timestamp			return api.get({ 'format':'json', 'action':'query', 'indexpageids': 1, 'prop':'revisions', 'page': mw.config.get('wgPageName'), 'rvprop': 'ids|timestamp' });		}).then(function(result){			var data = result.query.pages[result.query.pageids[0]].revisions[0];			if ( data.revid !== revId ) { // sanity				return $.Deferred.reject( 'addme-sectionchanged', 'Edit conflict, please retry' );			}			return api.postWithToken( 'edit', { 'action' : 'edit', 'title' : mw.config.get('wgPageName'), 'text' : newText, 'summary' : 'Supported by ' + mw.user.getName, 'section': sectionCount, 'basetimestamp': baseTimestamp });		}).then(function{			console.log('Successfully added endorsement');			window.location.reload(true);			util.setFeedbackCookie('feedback', that.domain);			},function(code, data){			console.log('Error!', code, data);			util.showErrorMessage('gadget','save');		}); }; };

/* End of functions */ if ( $('.wp-addme-button').length) { mw.loader.using( ['jquery.ui.dialog', 'mediawiki.api', 'mediawiki.ui','jquery.chosen'], function {		var gadget = new Gadget;			var util = new gadgetUtilities;	var api = new mw.Api;	var interfaceMessagesFullPath = util.interfaceMessagesPath+'/'+util.userLanguage;	var configFullPath = util.configPath+'/'+util.contentLanguage;	/*	 * To detect if we have the gadget translations and config in the desired languages.	 * Currently page language is English always. So the config returned is in en. The InterfaceMessages is	 * in the user's language	 */	api.get({'action':'query','titles':interfaceMessagesFullPath+'|'+configFullPath,'format':'json'}).then(function(data){ for(var id in data.query.pages){ if (data.query.pages[id].title == util.interfaceMessagesPath+'/'+util.userLanguage &&id == -1){ interfaceMessagesFullPath = util.interfaceMessagesPath; }			if (data.query.pages[id].title == util.configPath+'/'+util.contentLanguage && id == -1){ configFullPath = util.configPath; }		}

var interfaceMessagesUrl = mw.config.get('wgScript')+'?title='+interfaceMessagesFullPath+'&action=raw'; var configUrl = mw.config.get('wgScript')+'?title='+configFullPath+'&action=raw'; //Get the config for the detected language return $.when(jQuery.get(interfaceMessagesUrl),jQuery.get(configUrl)).then(function( interfaceStr, configStr ){			var interfaceData = JSON.parse( interfaceStr[0] ),				configData = JSON.parse( configStr[0] );			return $.Deferred.resolve(interfaceData, configData);		}); }).then(function(interfaceData, configData) { gadget.allConfig = configData; gadget.allInterfaceMessages = util.interfaceData;

var feedbackDomain = util.checkFeedbackCookie('feedback'); if(feedbackDomain){ gadget.setDomain(feedbackDomain); util.showFeedback(gadget.config, gadget.interfaceMessages); }		gadget.Dialog; $('.wp-addme-button').click(function(e){			var $this = $(this),				domain = $this.attr('data-addme-domain');			e.preventDefault;			//Checking if the user is logged in			if(!mw.config.get('wgUserName')){				util.showErrorMessage('gadget','login');				return;			}			gadget.setDomain(domain);			gadget.Dialog;		}); }); }); }