MediaWiki:Gadget-addMe-WishlistSurvey.js
Patanid: Pakatapos ipublikar, baad kaipuhanon mong i-bypass an cache kan saimong browser para mahiling an mga pagbabago.
- Sa Firefox / Safari: Pinduton an Shift mantang pinipindot an Reload, o pinduton an Ctrl-F5 o Ctrl-R (⌘-R sa Mac)
- Sa Google Chrome: Pinduton an Ctrl-Shift-R (⌘-Shift-R sa Mac)
- Sa Internet Explorer / Edge: Pinduton Ctrl mantang pinipindot an Refresh, o pinduton an Ctrl-F5
- Sa Opera: Pinduton an Ctrl-F5.
// <nowiki>
/**
* Fork of [[MediaWiki:Gadget-addMe.js]] for use in the [[Community Wishlist Survey]].
* This gadget will be default-on until voting ends on December 10.
* Please direct inquiries/concerns to [[Talk:Community Wishlist Survey]] or [[User talk:MusikAnimal (WMF)]].
*/
/* global RJSON */
/* eslint-disable no-implicit-globals, one-var, vars-on-top, no-jquery/no-global-selector */
/* eslint-disable no-jquery/no-trim, new-cap, no-useless-concat */
/* eslint-disable no-jquery/no-parse-html-literal, no-multi-str */
/* eslint-disable no-console */
/*
* Common utilities for both the endorse & the join gadget
*/
var gadgetUtilities = function () {
// A reference to the object
var that = this;
/*
* 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 = 'Community Wishlist Survey/AddMe/InterfaceText';
this.configPath = 'Community Wishlist Survey/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 () {
mw.storage.set( 'showWishlistSurveyThanks', true );
};
/*
* 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 () {
if ( mw.storage.get( 'showWishlistSurveyThanks' ) ) {
mw.storage.remove( 'showWishlistSurveyThanks' );
return true;
} 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 type of grant. IEG,PEG etc
*/
this.grantType = function ( config ) {
var grant = mw.config.get( 'wgTitle' ).split( '/' )[ 0 ].replace( / /g, '_' );
if ( grant in config ) {
return config[ grant ];
} else {
return config.default;
}
};
/*
* 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 ) {
text = $.trim( text ) + ' ';
var indexOf = text.indexOf( '~~~~' );
if ( indexOf === -1 ) {
return text;
} else {
return text.slice( 0, indexOf ) + text.slice( indexOf + 4 );
}
};
/*
* 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;
};
/*
* The function creates the markup for the link to a
* user's user page
*/
this.addToInfobox = function ( username ) {
return username;
};
/*
* 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 ) {
var $li = $( '#' + config[ 'section-header-read' ] ).parent().next().find( 'li' ).eq( -1 );
var $speechBubble = $li.append( $( '<div class="grantsSpeechBubbleContainer"></div>' ).html( '<div class="grantsSpeechBubble">\
<span>Thank you for participating in the survey!</span></div><div class="grantsSpeechBubbleArrowDown"></div>' ) ).find( '.grantsSpeechBubbleContainer' );
var width = $li.css( 'display', 'inline-block' ).width();
$li.css( 'display', '' );
$li.css( 'position', 'relative' );
$speechBubble.css( 'left', width / 2 + 'px' );
$( 'body, html' ).animate( { scrollTop: $li[ 0 ].offsetTop }, that.feedbackScrollTime );
setTimeout( function () {
$speechBubble.hide();
}, that.feedbackDisappearDelay );
};
};
/*
* The Endorse Gadget
*/
var endorseGadget = function () {
/* Variables */
var util = new gadgetUtilities();
var dialog = null;
var api = new mw.Api();
var that = this;
var supportTemplates = '{{\\s*(support|s|yes|vote+|Sì|賛成|موافق|strong support|weak support)\\s*}}';
/*
* This function creates the dialog box for the gadget.
* It is also where all the dialog related interactions are defined.
*/
var createDialog = function () {
dialog = $( "<div id='devEndorseDialog'></div>" ).html(
'<div class="mw-ui-vform">\
<div class="error grantsHide" localize="error-save">An error occurred</div>\
<div class="error grantsHide" localize="error-login">An error occurred</div>\
</div>\
<div localize="message-description" class="messageDescription">Explaining your endorsement improves process</div>' + '\
<textarea rows="5" cols="10" placeholder="Add your comment" id="devEndorseComment" class="" localize="placeholder-comment" style="color: #333;"></textarea>\
<span localize="message-signature" class="messageSignature">Your signature will be added automatically</span>\
<div class="gadgetControls">\
<span localize="button-cancel" class="mw-ui-button cancel mw-ui-quiet">Cancel</span>\
<input type="submit" localize="button-submit" class="mw-ui-button mw-ui-progressive addme-support" localize="button" value="Support"></input>\
</div>'
).dialog( {
dialogClass: 'grantsGadget endorseGadget',
autoOpen: false,
title: '<span localize="title">Support proposal</span>',
width: '495px',
modal: true,
closeOnEscape: true,
resizable: false,
draggable: false,
close: function () {
$( '#devEndorseComment' ).val( '' );
}
} );
$( '.addme-support' ).on( 'click', function () {
that.addEndorsement( util.cleanupText( $( '#devEndorseComment' ).val() ) );
} );
$( '.endorseGadget .cancel' ).on( 'click', function () {
dialog.dialog( 'close' );
} );
util.localizeGadget( '.endorseGadget', that.interfaceMessages );
};
this.Dialog = function () {
if ( dialog === null ) {
createDialog();
} else {
dialog.dialog( 'open' );
}
};
/*
* The main function to add the feedback/endorsement to the page. It first checks if the page has an endorsement section.
* If it dosent it creates a new section called Endorsements and appends the feedback/endorsement comment to that section,
* else it appends the feedback/endorsement comment to existing Endorsements section.
* The name of the endorsement section is defined in the config.
*/
this.addEndorsement = function ( text ) {
// Remove support template for comment if present.
text = text.replace( new RegExp( supportTemplates ), '' ).trim();
var endorseComment = '\n* {{support}}' + ( text.length ? ' ' + text : '' ) + ' ~~~~' + '\n';
var proposalUrl = 'https://meta.wikimedia.org' + ( new mw.Title( that.title ) ).getUrl();
var summary = 'Support proposal' + ( text.length > 0 ? ': ' + text : '' ).trim();
api.get( {
format: 'json',
action: 'parse',
prop: 'sections',
page: that.title,
uselang: 'en'
} ).then( function ( result ) {
var sections = result.parse.sections;
var sectionCount = 0;
var sectionFound = false;
for ( var section in sections ) {
if ( sections[ section ].level > 3 ) {
continue;
}
if ( $.trim( sections[ section ].anchor ) === that.config[ 'section-header-read' ] ) {
sectionFound = true;
break;
}
sectionCount++;
}
if ( sectionFound ) {
api.get( {
format: 'json',
action: 'parse',
prop: 'wikitext',
page: that.title,
section: sectionCount
} ).then( function ( result ) {
var wikitext = result.parse.wikitext[ '*' ];
// Check if they've already voted.
var regexp = new RegExp(
supportTemplates + '.*?' +
mw.config.get( 'wgUserName' ).replace( /[-\/\\^$*+?.()|[\]{}]/g, '\\$&' ) +
'.*?\\(UTC\\)'
);
if ( regexp.test( wikitext ) && !window.confirm( 'It looks like you already voted on this proposal! Should we still attempt to add your vote?' ) ) {
return $( '.endorseGadget .cancel' ).trigger( 'click' );
}
var endorsementSection = wikitext + endorseComment;
api.post( {
action: 'edit',
title: that.title,
text: endorsementSection,
summary: summary,
section: sectionCount,
// 'watchlist':'watch',
token: mw.user.tokens.get( 'csrfToken' )
} ).then( function () {
console.log( 'Successfully added endorsement' );
window.location = proposalUrl;
util.setFeedbackCookie();
}, function () {
util.showErrorMessage( 'endorseGadget', 'save' );
} );
} );
} else {
api.get( {
format: 'json',
action: 'parse',
prop: 'wikitext',
page: that.title,
section: sectionCount
} ).then( function ( result ) {
var wikitext = result.parse.wikitext[ '*' ] + '\n=== ' + that.config[ 'section-header-write' ] + ' ===\n';
api.post( {
action: 'edit',
title: that.title,
text: wikitext + endorseComment,
summary: summary,
section: sectionCount,
// 'watchlist': 'watch',
token: mw.user.tokens.get( 'csrfToken' )
} ).then( function () {
console.log( 'Successfully added endorsement' );
window.location = proposalUrl;
util.setFeedbackCookie();
}, function () {
util.showErrorMessage( 'endorseGadget', 'save' );
} );
} );
}
}, function () {
util.showErrorMessage( 'endorseGadget', 'save' );
} );
};
};
/* End of functions */
$( function () {
if ( !$( '.wp-addme-button' ).length ) {
// Ignore this page
return;
}
mw.loader.using( [ 'jquery.ui', 'mediawiki.api', 'mediawiki.ui', 'jquery.chosen' ], function () {
/*
* Fix mw.config.get('wgPageContentLanguage') == 'en') checking with a better solution,
* either when pages can be tagged with arbitary language or when we set langauge markers later on.
*
*/
if ( mw.config.get( 'wgPageContentLanguage' ) === 'en' ) {
var endorse = new endorseGadget();
var util = new gadgetUtilities();
var api = new mw.Api();
var interfaceMessagesFullPath = util.interfaceMessagesPath;
var configFullPath = util.configPath;
/*
* 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 + '/' + util.userLanguage() + '|' + configFullPath + '/' + util.userLanguage() , format: 'json' } ).then( function ( data ) {
for ( var id in data.query.pages ) {
if ( data.query.pages[ id ].title === util.interfaceMessagesPath + '/' + util.userLanguage() && id > 0 ) {
interfaceMessagesFullPath = util.interfaceMessagesPath + '/' + util.userLanguage();
}
if ( data.query.pages[ id ].title === util.configPath + '/' + util.contentLanguage() && id > 0 ) {
configFullPath = util.configPath + '/' + util.userLanguage();
}
}
var interfaceMessagesUrl = 'https://meta.wikimedia.org/w/index.php?title=' + interfaceMessagesFullPath + '&action=raw';
var configUrl = 'https://meta.wikimedia.org/w/index.php?title=' + configFullPath + '&action=raw';
// Get the config for the detected language
$.when( $.get( interfaceMessagesUrl ), $.get( configUrl ) ).then( function ( interfaceStr, configStr ) {
var interfaceData = RJSON.parse( interfaceStr[ 0 ] ),
configData = RJSON.parse( configStr[ 0 ] );
endorse.config = util.stripWhiteSpace( util.grantType( configData.endorse ) );
endorse.interfaceMessages = util.stripWhiteSpace( util.grantType( interfaceData.endorse ) );
endorse.Dialog();
$( '.wp-addme-button' ).off();
$( '.wp-addme-button' ).on( 'click', function ( e ) {
var section = $( this ).attr( 'data-addme-section' ),
// hack - proper entity encoding is hard in wikitext
proposal = decodeURIComponent( $( this ).attr( 'data-addme-proposal' ).replace( /\+/g, '_' ) );
e.preventDefault();
// Checking if the user is logged in
if ( !mw.config.get( 'wgUserName' ) ) {
util.showErrorMessage( 'gadget', 'login' );
return;
}
endorse.section = section;
endorse.title = mw.config.get( 'wgTitle' ).split( '/' )[ 0 ] + '/' + proposal;
endorse.Dialog();
} );
if ( util.checkFeedbackCookie() ) {
util.showFeedback( endorse.config, endorse.interfaceMessages );
}
} );
} );
} else {
$( '.wp-addme-button' ).hide();
}
} );
} );
// </nowiki>