میڈیا وکی:AxUserMsg.js
شکل و صورت
یاددہانی: محفوظ کرݨ دے بعد انہاں تبدیلیاں کوں ݙیکھݨ کیتے تہاکوں آپݨے براؤزر دا کیشی (cache) صاف کرݨاں ہوسی۔
- فائرفاکس/ سفاری: ڄݙݨ Reload تے کلک کرو تاں Shift دبا تے رکھو، یا Ctrl-F5 یا Ctrl-R دباؤ (Mac تے R-⌘)
- گوگل کروم: Ctrl-Shift-R دباؤ (Mac تے Shift-R-⌘)
- انٹرنیٹ ایکسپلورر: ڄݙݨ Refresh تے کلک کرو تاں Ctrl یا Ctrl-F5 دباؤ
- اوپیرا: Ctrl-F5 دباؤ۔
/**
** AxUserMsg.js - Ajax/API based adding comments and templates to User-Talk-Pages
** written in 2011 by [[User:Rillke]]; little parts are from [[MediaWiki:AjaxQuickDelete.js]] by DieBuche and from the old [[MediaWiki:Gadget-UserMessages.js]]
** bootstrap-code at [[MediaWiki:Gadget-UserMessages.js]] (which severed as idea for writing this script), help at [[Help:Gadget-UserMessages]]
**
**/
//<nowiki>
// Invoke automated jsHint-validation on save: A feature on Wikimedia Commons.
// Interested? See [[:commons:MediaWiki:JSValidator.js]].
/*global $:false, mw:false, jsMsgAppend:false */
/*jshint curly:false, bitwise:false, laxbreak:true*/
(function() {
'use strict';
if (window.AxUserMsg) return;
function ClsUPC($userInputField, $outputField, stCallBack, callingObject, CBValidChange) { // User Presence Check
this.$userInputField = $userInputField;
this.$outputField = $outputField;
this.callingObject = callingObject;
this.stCallBack = stCallBack;
this.CBValidChange = CBValidChange;
this.pendingCalls = 0;
this.pendingSetTimeouts = 0;
this.oldValue = '';
this.userNameExists = 2;
var o = this;
$userInputField.keyup( function (event) {
var tmpUNE = o.userNameExists;
if ( o.isValidIP($(this).val()) ) {
o.setToIP(tmpUNE);
} else {
o.execApiCall(false, $(this).val());
}
});
$userInputField.on('input', function() {
$userInputField.keyup();
});
$userInputField.on('selected', function() {
$userInputField.keyup();
});
}
ClsUPC.prototype.isValidIP = function (username) {
if ( mw.util.isIPv4Address(username) ) return true; //IP v.4
return mw.util.isIPv6Address(username); //IP v.6
};
ClsUPC.prototype.setToIP = function (tmpUNE) {
var o = this;
o.userNameExists = -1;
if ('function' === typeof(o.CBValidChange) && tmpUNE !== o.userNameExists ) {
o.$outputField.attr('src', o.callingObject.umImgUserIsIP);
o.$outputField.attr('alt', 'IP');
o.oldValue = o.callingObject.umCleanFileAndUser(o.$userInputField.val());
o.CBValidChange(o, o.callingObject);
}
};
ClsUPC.prototype.execApiCall = function (isTimeout, val) {
if (isTimeout) this.pendingSetTimeouts--;
if (this.oldValue !== this.callingObject.umCleanFileAndUser(val)) {
if (this.pendingCalls > 0) {
if (!this.pendingSetTimeouts) {
this.pendingSetTimeouts++;
var o = this;
setTimeout( function () {
o.execApiCall(true, o.$userInputField.val());
}, 1000); // do not use the old value, use the current instead
}
return;
}
var User = this.oldValue = this.callingObject.umCleanFileAndUser(val);
var query = {
action: 'query',
list: 'allusers',
aufrom: User,
auto: User
};
this.callingObject.umCurrentUserQuery = this;
this.pendingCalls++;
this.callingObject.doAPICall(query, this.stCallBack);
}
};
ClsUPC.prototype.evalAPICall = function(result) {
this.pendingCalls--;
var uifval = this.$userInputField.val();
if (this.oldValue !== this.callingObject.umCleanFileAndUser(uifval)) {
// Don't do anything if user updated the field in-between
return;
}
if (this.isValidIP(uifval)) {
return;
}
if ('object' === typeof(result.query) && 'object' === typeof(result.query.allusers)) {
var tmpUNE = this.userNameExists;
if (!result.query.allusers.length) {
this.$outputField.attr('src', this.callingObject.umImgUserNotExists);
this.$outputField.attr('alt', '!! invalid !!');
this.userNameExists = false;
} else {
if (this.callingObject.umCleanFileAndUser(this.$userInputField.val()) === result.query.allusers[0].name) {
this.$outputField.attr('src', this.callingObject.umImgUserExists);
this.$outputField.attr('alt', 'OK');
this.userNameExists = true;
} else {
if (!this.pendingSetTimeouts) { // Only overwrite if there is nothing pending
this.$outputField.attr('src', this.callingObject.umImgUserUndefined);
this.$outputField.attr('alt', '?');
this.userNameExists = 2;
}
}
}
if ('function' === typeof(this.CBValidChange) && tmpUNE !== this.userNameExists) this.CBValidChange(this, this.callingObject);
}
};
var umsg = window.AxUserMsg = {
umInstall: function () {
if (!$('#t-AjaxUserMessage').length) {
var _this = this;
var $LODLinkNode = $('#t-AjaxUserMessageLOD');
var $Href = $LODLinkNode.length ? $LODLinkNode.eq(0) : $(mw.util.addPortletLink('p-tb', '#', "Notify this user", 't-AjaxUserMessage', 'Click here to launch user messages'));
$Href.click(function(e) {
e.preventDefault();
_this.fireImmediately = false;
_this.umNotifyUser();
});
}
window.AxUserMsgPreSelect = (window.AxUserMsgPreSelect || this.umTemplate.length - 1); // default last msg
},
umInstallOldLinks: function () {
// written for Herby, who needs this for working on Commons
var _this = this;
$.each(this.umTemplate, function(id, ti) {
// Create portlet link
var portletLink = mw.util.addPortletLink( 'p-tb', '#' + id, ti[1], 't-gadgetUserMessage' + id, ti[2]);
// Bind click handler
$(portletLink).click( function( e ) {
e.preventDefault();
window.AxUserMsgPreSelect = $(this).find('a').attr('href').split('#')[1];
if (window.AxUserMsgFireAsYouClick) {
var umType = _this.umTemplate[window.AxUserMsgPreSelect][3];
if (!(umType & _this.umFlagUQ) && !(umType & _this.umFlagReq))
_this.fireImmediately = true;
else {
_this.fireImmediately = false;
}
}
_this.umNotifyUser();
});
});
},
umNotifyUser: function () {
var css = 'a.new {color: #BA0000 !important;}';
mw.util.addCSS(css);
this.umUser = '';
this.editToken = '';
this.umDlgPresent = false;
this.umExecuting = false;
this.umPendingParser = 0;
this.umPendingParserTimeouts = 0;
this.umParserTimerID = 0;
this.umDelay = (window.AxUserMsgDelay || 100);
this.umUserCache = {};
this.umFileCache = {};
this.umParserCache = {};
this.focusOwner = '';
this.umObtainEditToken();
this.umUser = mw.libs.commons.guessUser();
this.umDlg();
},
umFillSelect: function (caller, o) {
var userstate = caller.userNameExists;
$.each(o.umTemplate, function(id, currentTag) {
if ( !$('#umOpt' + id, o.$tagSelect).length ) { // check wether to add
if ( (-1 === userstate && !(currentTag[3] & o.umFlagUM)) || (true === userstate && !(currentTag[3] & o.umFlagIP)) ) {
o.$tagSelect.append( '<option id="umOpt' + id + '" value="' + id + '">' + mw.html.escape(currentTag[1] + ' - ' + currentTag[2]) + '</option>' );
return;
}
} else { // check wether to remove
if ( (-1 === userstate && (currentTag[3] & o.umFlagUM)) || (true === userstate && (currentTag[3] & o.umFlagIP)) ) {
$('#umOpt' + id, o.$tagSelect).remove();
return;
}
}
});
if (-1 === userstate) { if (window.AxUserMsgPreSelectIP) { o.$tagSelect.val(window.AxUserMsgPreSelectIP); }
} else { if (window.AxUserMsgPreSelect) { o.$tagSelect.val(window.AxUserMsgPreSelect); }
}
o.umValidateInput(o);
o.$tagSelect.change();
},
umDlg: function () {
var _this = this,
dlgButtons = {};
dlgButtons[this.i18n.submitButtonLabel] = function () {
try {
if (_this.umIsValid) _this.umNotifyUserExecute();
} catch (ex) {
_this.fail(ex);
}
};
dlgButtons[this.i18n.cancelButtonLabel] = function () {
$(this).dialog("close");
};
this.dlg = $('<div>').html('<div id="AjaxUmContainer"></div>').dialog({
modal: true,
closeOnEscape: true,
position: [Math.round(($(window).width() - Math.min($(window).width(), 850)) / 2),
Math.round(($(window).height() - Math.min($(window).height(), 800)) / 2)],
title: '<a href="//ur.wikipedia.org/wiki/وپ:تذکیر" target="_blank">ویکی آلہ تذکیر</a>',
height: Math.min($(window).height(), 800),
width: Math.min($(window).width(), 850),
buttons: dlgButtons,
close: function () {
$(this).dialog("destroy");
$(this).remove();
_this.umDlgPresent = false;
},
open: function() {
var $dlg = $(this),
$buttons = $dlg.parent().find('.ui-dialog-buttonpane button'),
$submitButton = $buttons.eq(0).specialButton('proceed'),
$cancelButton = $buttons.eq(1).specialButton('cancel');
$dlg.parents('.ui-dialog').css({position:'fixed', top:Math.round(($(window).height() - Math.min($(window).height(), 800)) / 2) + 'px'});
}
});
this.umDlgPresent = true;
if (this.dlg) {
var $AjaxUmContainer = $('#AjaxUmContainer');
$AjaxUmContainer.append('<label for="umUser">' + mw.html.escape(this.i18n.umFillInUser) + '</label><br><input type="text" id="umUser" style="width: 95%;" value="' + mw.html.escape(this.umUser) + '"/>' +
this.umInitImgUserExists.replace('%ID%', 'umUserExists') + '<br><br>');
this.$tagSelect = $('<select>', {
size : '1',
id : 'umTagToInsert',
style: 'width: 99%;'
} );
$AjaxUmContainer.append([
'<label for="umTagToInsert">' + mw.html.escape(this.i18n.umSelectTag) + '</label><br>',
this.$tagSelect, '<br><br>',
'<span id="umMediaWrapper"><label for="umMedia">' + mw.html.escape(this.i18n.umFillInMedia) + '</label><br><input type="text" id="umMedia" style="width: 95%;" value="فائل:"/><br><br></span>',
'<span id="umP2Wrapper"><label for="umP2">' + mw.html.escape(this.i18n.umFillInAdditional) + '</label><br><input type="text" id="umP2" style="width: 95%;"/><br><br></span>',
'<span id="umP3Wrapper"><label for="umP3">' + mw.html.escape(this.i18n.umFillInAdditional) + '</label><br><input type="text" id="umP3" style="width: 95%;"/><br><br></span>',
'<span id="umRelatedUserWrapper"><label for="umRelatedUser">' + mw.html.escape(this.i18n.umFillInRelUser) + '</label><br><input type="text" id="umRelatedUser" style="width: 95%;" value="صارف:"/>' + this.umInitImgUserExists.replace('%ID%', 'umRelatedUserExists') + '<br><br></span>',
'<span id="umSummaryWrapper"><label for="umSummary">' + mw.html.escape(this.i18n.umFillInSummary) + '</label><br><input type="text" id="umSummary" style="width: 95%;" value="خلاصہ"/><br><br></span>',
'<label for="umAddText">' + mw.html.escape(this.i18n.umAddText) + '</label><br><textarea id="umAddText" style="width: 95%; height: 5em;">' + (mw.html.escape(window.AxUserMsgCustomText || '')) + '</textarea><br><br>'
]);
this.talkTag = '';
var $umMedia = $('#umMedia'),
$umP2 = $('#umP2'),
$umP3 = $('#umP3'),
$umUser = $('#umUser'),
$umRelatedUser = $('#umRelatedUser'),
$umSummary = $('#umSummary'),
$umAddText = $('#umAddText');
this.uUPC = new ClsUPC($umUser, $('#umUserExists'), 'umUserExistsCB', this, this.umFillSelect);
this.ouUPC = new ClsUPC($umRelatedUser, $('#umRelatedUserExists'), 'umUserExistsCB', this, this.umUserValidChange);
var submitButton = $('.ui-dialog-buttonpane button:first');
this.$tagSelect.keyup( function(event) {
if (13 === event.which) submitButton.click();
});
// guessing the related file thanks User:Platonides
var guessFile = function() {
var f = mw.util.getParamValue('title', document.referrer);
if (f && /File:/.test(f)) return f;
f = mw.util.getParamValue('page', document.referrer);
if (f && /File:/.test(f)) return f;
f = mw.util.getParamValue('target', document.referrer);
if (f && /File:/.test(f)) return f;
var m = document.referrer.match(/File:(.+)/);
try {
if (m) { if (/&.+=/.test(m[1])) return('File:' + decodeURI(m[1]).match(/^(.+)&/)[1]); else return('File:' + m[1]); }
} catch (ex) {}
};
var umFile = guessFile();
if (umFile) $umMedia.val(decodeURIComponent(umFile).replace(/_/g, ' '));
$umUser.keyup( function(event) {
$(this).val( $(this).val().replace(/<|>|\^/g, '') );
if (event) if (event.which) if (13 === event.which) submitButton.click();
});
$umUser.autocomplete({
minLength: 1,
source: function ( request, callback ) { _this.umSeekUsers( request, callback ); },
close: function( event, ui ) { $umUser.triggerHandler('selected'); }
});
$umMedia.change( function() {
_this.umValidateInput(_this);
});
$umMedia.on('input', function() {
$(this).val( $(this).val().replace(/<|>|\^/g, '') );
_this.umValidateInput(_this);
});
$umMedia.keyup( function(event) {
$(this).val( $(this).val().replace(/<|>|\^/g, '') );
if (13 === event.which) submitButton.click();
});
$umMedia.autocomplete({
minLength: 1,
source: function ( request, callback ) { _this.umSeekFiles( request, callback ); },
close: function( e, ui ) { $umMedia.triggerHandler('input'); }
});
$umRelatedUser.keyup( function(event) {
$(this).val( $(this).val().replace(/<|>|\^/g, '') );
if (event) if (event.which) if (13 === event.which) submitButton.click();
_this.umValidateInput(_this);
});
$umRelatedUser.autocomplete({
minLength: 1,
source: function ( request, callback ) { _this.umSeekUsers( request, callback ); },
close: function( e, ui ) { $umRelatedUser.triggerHandler('selected'); }
});
$umP2.change( function() {
_this.umValidateInput(_this);
});
$umP2.on('input', function() {
_this.umValidateInput(_this);
});
$umP2.keyup( function(event) {
if (13 === event.which) submitButton.click();
});
$umP3.change( function() {
_this.umValidateInput(_this);
});
$umP3.on('input', function() {
_this.umValidateInput(_this);
});
$umP3.keyup( function(event) {
if (13 === event.which) submitButton.click();
});
$umAddText.change( function() {
_this.umValidateInput(_this);
});
$umAddText.on('input', function() {
_this.umValidateInput(_this);
});
$umSummary.keyup( function(event) {
if (13 === event.which) submitButton.click();
});
submitButton.focus();
$AjaxUmContainer.append(this.umInstPrevContainer.clone().text('فوری نمائش کا خانہ خالی ہے۔'));
this.$tagSelect.change( function (/* e*/) {
var umType = _this.umTemplate[$(this).val()][3];
$umSummary.val(_this.umTemplate[$('#umTagToInsert').val()][4] ? _this.umTemplate[$('#umTagToInsert').val()][4] : (_this.umTemplate[$('#umTagToInsert').val()][2] + '۔'));
_this.umValidateInput(_this);
_this.$tagSelect.combobox({'displaytext': _this.$tagSelect.val() ? _this.$tagSelect.children( ":selected" ).text() : ""});
if (umType & _this.umFlagP2) {
$('#umP2Wrapper').show();
if (document.activeElement) if ($umUser.attr('id') !== $(document.activeElement).attr('id')) $('#umP2').select();
} else {
$('#umP2Wrapper').hide();
}
if (umType & _this.umFlagP3) {
$('#umP3Wrapper').show();
if (document.activeElement) if ($umUser.attr('id') !== $(document.activeElement).attr('id')) $('#umP3').select();
} else {
$('#umP3Wrapper').hide();
}
if (umType & _this.umFlagMQ) {
$('#umMediaWrapper').show();
if (document.activeElement) if ($umUser.attr('id') !== $(document.activeElement).attr('id')) $('#umMedia').select();
} else {
$('#umMediaWrapper').hide();
}
if (umType & _this.umFlagUQ) {
$('#umRelatedUserWrapper').show();
if (document.activeElement) if ($umUser.attr('id') !== $(document.activeElement).attr('id')) $('#umMedia').select();
} else {
$('#umRelatedUserWrapper').hide();
}
});
if (window.AxUserMsgPreSelect) this.$tagSelect.val(window.AxUserMsgPreSelect);
$('#umUser').keyup();
$('#umTagToInsert').combobox();
}
},
umSeekUsers: function ( request, pCallback ) {
var query = {
action: 'query',
list: 'allusers',
auprefix: request.term.replace(/^(?:User):/, "")
};
this.doGetApiCall(query, 'umSeekUsersCB', pCallback);
},
umSeekUsersCB: function ( result, pCallback ) {
var searchTerms = [];
$.each(result, function(id, usi) {
searchTerms.push( { 'id': usi.userid, 'value': usi.name } );
});
if ('function' === typeof pCallback) pCallback(searchTerms);
},
umSeekFiles: function ( request, pCallback ) {
var query = {
action: 'query',
list: 'allimages',
aiprefix: request.term.replace(/^(?:File|Image):/, "")
};
this.doGetApiCall(query, 'umSeekFilesCB', pCallback);
},
umSeekFilesCB: function ( result, pCallback ) {
var searchTerms = [];
$.each(result, function(id, fii) {
searchTerms.push( { 'id': fii.timestamp, 'value': 'File:' + fii.name } );
});
if ('function' === typeof pCallback) pCallback(searchTerms);
},
umUserExistsCB: function (result) {
this.umCurrentUserQuery.evalAPICall(result);
},
umShowInfo: function(info, o) {
$('#umInstantPreviewContainer').empty().html('<p align="center"><img src="' + o.umImgInfo + '" width="64" height="64"/><br>' +
info + '</p>');
},
umValidateInput: function (o) {
this.umIsValid = true;
var umType = this.umTemplate[$('#umTagToInsert').val()][3];
var submitButton = $('.ui-dialog-buttonpane button:first');
var validRelatedUser = function() {
if (umType & o.umFlagUQ) {
if (o.umCleanFileAndUser($('#umRelatedUser').val()).length < 1 ) {
o.umShowInfo('No related user specified.', o);
return false;
}
if ( !o.ouUPC.userNameExists ) {
o.umShowInfo('Related user does not exist.', o);
return false;
}
}
return true; };
var validMedia = function() {
if (umType & o.umFlagMQ) {
if ( (o.umCleanFileAndUser($('#umMedia').val()).length < 5 ) && (umType & o.umFlagReq) ) {
o.umShowInfo('No file specified. This is mandatory in this case.', o);
return false;
}
}
return true; };
var validUser = function() {
if ( o.umCleanFileAndUser($('#umUser').val()).length < 1 ) {
o.umShowInfo('No user specified.', o);
return false;
}
if ( !o.uUPC.userNameExists ) {
o.umShowInfo('User does not exist.', o);
return false;
}
return true; };
this.umIsValid = this.umIsValid && validRelatedUser() && validMedia() && validUser();
if (this.umIsValid) {
submitButton.removeClass('ui-state-disabled');
if (umType & this.umFlagMQ) {
this.talkTag = '\n{{subst:' + this.umTemplate[$('#umTagToInsert').val()][0] +
(this.umCleanFileAndUser($('#umMedia').val()) ? ('|1=' + ((umType & this.umFlagNS) ? ('File:' + this.umCleanFileAndUser($('#umMedia').val())) : $('#umMedia').val())) : '' );
} else if (umType & this.umFlagUQ) {
this.talkTag = '\n{{subst:' + this.umTemplate[$('#umTagToInsert').val()][0] + '|1=' + this.umCleanFileAndUser($('#umRelatedUser').val());
}
else {
this.talkTag = '\n{{subst:' + this.umTemplate[$('#umTagToInsert').val()][0];
}
var paramCount = ((umType & this.umFlagUQ) ? 1 : 0) + ((umType & this.umFlagMQ) ? 1 : 0);
if (umType & this.umFlagP2) {
paramCount++;
this.talkTag += '|' + paramCount + '=' + $('#umP2').val();
}
if (umType & this.umFlagP3) {
paramCount++;
this.talkTag += '|' + paramCount + '=' + $('#umP3').val();
}
this.talkTag += '}}';
if ('\n{{subst:}}' === this.talkTag) this.talkTag = '\n';
this.talkTag += '\n' + $('#umAddText').val().replace(/~{3,5}$/, '') + '~~~~\n';
this.umParseTemplate(false);
// If the user wants the old behaviour back, we fire immediately
if (this.fireImmediately) this.umNotifyUserExecute();
} else {
submitButton.addClass('ui-state-disabled');
}
},
umUserValidChange: function (caller, o) {
o.umValidateInput(o);
},
umCleanFileAndUser: function (input) {
var output = '';
if (input) {
output = input.replace(/\_/g, " ").replace(/File\:/g, "").replace(/Image\:/g, "").replace(/User\:/g, "").replace(/^\s+|\s+$/g, '');
output = output.substring(0, 1).toUpperCase() + output.substring(1);
}
return output;
},
umParseTemplate: function (viaSetTimeout) {
if (window.AxUserMsgNoParse) return;
var _this = this;
if (viaSetTimeout) _this.umPendingParserTimeouts--;
if (_this.umPendingParser > 0) {
if (!_this.umPendingParserTimeouts) {
// call me later
var o = _this;
_this.umPendingParserTimeouts++;
setTimeout( function () {
o.umParseTemplate(true);
}, 300);
}
return;
}
function maybeParse() {
_this.umPendingParser++;
var action = {
action: 'parse',
uselang: mw.config.get('wgUserLanguage'),
redirects: true,
prop: 'text',
pst: true,
title: _this.umUserTalkPrefix + $('#umUser').val(),
text: _this.talkTag
};
_this.umDelay = Math.min((_this.umDelay + 30), 1500); // Save server resources.
_this.doAPICall(action, 'umParsedTemplate');
}
if (_this.umParserTimerID) {
clearTimeout(_this.umParserTimerID);
}
_this.umParserTimerID = setTimeout( maybeParse, _this.umDelay );
},
umParsedTemplate: function(result) {
this.umPendingParser--;
if ( 'object' === typeof(result.parse) && ('object' === typeof(result.parse.text)) && this.umDlgPresent && (!this.umExecuting) && this.umIsValid ) {
var $containerText = result.parse.text['*'].replace(' API', ' ' + this.umCleanFileAndUser($('#umUser').val())).replace('>API', '>' + this.umCleanFileAndUser($('#umUser').val()));
$containerText = $($containerText);
$('.editsection', $containerText).remove();
$('a', $containerText).attr('target', '_blank');
$('#umInstantPreviewContainer').empty().append($containerText).resizable({ alsoResize: '#AjaxUmContainer' });
}
},
umObtainEditToken: function () {
if (mw.user && mw.user.tokens) this.editToken = mw.user.tokens.get( 'csrfToken' );
this.editToken = (this.editToken || (mw.user.isAnon() ? '+\\' : '') );
if (this.editToken) return;
var query = {
action: 'query',
prop: 'info',
intoken: 'edit',
titles: 'FAQ' // Random title
};
this.doAPICall(query, 'umObtainEditTokenCB');
},
umObtainEditTokenCB: function (result) {
var pages = result.query.pages;
for (var id in pages) { // there should be only one, but we don't know its ID
if (pages.hasOwnProperty(id)) {
this.editToken = pages[id].edittoken;
}
}
},
umNotifyUserExecute: function () {
if (this.umExecuting) return;
this.pageName = this.umUserTalkPrefix + $('#umUser').val();
this.talkSummary = $('#umSummary').val();
this.appendTemplate();
},
appendTemplate: function () {
var page = [];
page.title = this.pageName;
page.text = this.talkTag;
page.editType = 'appendtext';
page.redirect = true;
if (window.AjaxDeleteWatchFile) page.watchlist = 'watch';
this.umExecuting = true;
$('#umInstantPreviewContainer').empty().html('<p align="center"><img src="//upload.wikimedia.org/wikipedia/commons/c/ce/RE_Ajax-Loader.gif"/></p>');
this.savePage(page, this.talkSummary, 'umNotifyUserExecuteCB');
},
savePage: function (page, summary, callback) {
var edit = {
action: 'edit',
summary: summary,
watchlist: (page.watchlist || 'preferences'),
title: page.title
};
if (page.redirect) edit.redirect = '';
edit[page.editType] = page.text;
edit.token = this.editToken;
this.doAPICall(edit, callback);
},
umNotifyUserExecuteCB: function (/* result*/) {
var encTitle = this.umUserTalkPrefix + $('#umUser').val();
encTitle = encodeURIComponent(encTitle.replace(/ /g, '_')).replace(/%2F/ig, '/').replace(/%3A/ig, ':');
var newLoc = mw.config.get('wgServer') + mw.config.get('wgArticlePath').replace("$1", encTitle);
if (window.location.pathname === mw.config.get('wgArticlePath').replace("$1", encTitle)) {
window.location.hash = '#footer';
window.location.reload();
} else {
window.location.href = newLoc + '#footer';
}
this.umExecuting = false;
},
doGetApiCall: function (params, callback, pCallback) {
var o = this;
// Local Cache
if (params.list) {
if ("allusers" === params.list) {
if (params.auprefix in o.umUserCache) {
o[callback](o.umUserCache[params.auprefix], pCallback);
return;
}
} else if ("allimages" === params.list) {
if (params.aiprefix in o.umFileCache) {
o[callback](o.umFileCache[params.aiprefix], pCallback);
return;
}
}
}
params.format = 'json';
$.ajax({
url: this.apiURL,
cache: true,
dataType: 'json',
data: params,
type: 'GET',
async: true,
success: function (result, status, x) {
if (!result) { if ('function' === typeof pCallback) pCallback(); return; }
try {
if (params.list) if ("allusers" === params.list) {
// cache the result
o.umUserCache[ params.auprefix ] = result.query.allusers;
o[callback](result.query.allusers, pCallback);
return;
}
if (params.list) if ("allimages" === params.list) {
// cache the result
o.umFileCache[ params.aiprefix ] = result.query.allimages;
o[callback](result.query.allimages, pCallback);
return;
}
// This is a "must", the doc sais
if ('function' === typeof pCallback) pCallback();
o[callback](result);
} catch (e) {
return o.fail(e);
}
},
error: function () {
// This is a "must", the doc sais
if ('function' === typeof pCallback) pCallback();
}
});
},
doAPICall: function (params, callback) {
var o = this;
if (params.action) if ("parse" === params.action) {
if (params.text in o.umParserCache) {
o[callback](o.umParserCache[params.text]);
return;
}
}
params.format = 'json';
$.ajax({
url: this.apiURL,
cache: false,
dataType: 'json',
data: params,
type: 'POST',
success: function (result, status, x) {
if (!result) return o.fail("Receive empty API response:\n" + x.responseText);
// In case we get the mysterious 231 unknown error, just try again
if (result.error && result.error.info.indexOf('231') !== -1) return setTimeout(function () {
o.doAPICall(params, callback);
}, 500);
if (result.error) return o.fail("API request failed (" + result.error.code + "): " + result.error.info);
if (result.edit && result.edit.spamblacklist) {
return o.fail("The edit failed because " + result.edit.spamblacklist + " is on the Spam Blacklist");
}
if (params.action) if ("parse" === params.action) {
o.umParserCache[params.text] = result;
}
try {
o[callback](result);
} catch (e) {
return o.fail(e);
}
},
error: function (x, status, error) {
return o.fail("API request returned code " + x.status + " " + status + "Error code is " + error);
}
});
},
fail: function (err) {
if ('object' === typeof err) {
var stErr = mw.html.escape(err.message) + '<br>' + err.name;
if (err.lineNumber) stErr += ' @line' + err.lineNumber;
if (err.line) stErr += ' @line' + err.line;
err = stErr;
} else {
err = mw.html.escape(err.toString());
}
if (this.umDlgPresent) {
$('#umInstantPreviewContainer').empty().html('<p align="center"><img src="' + this.umImgErr + '" width="64" height="64"/></p><br>' +
"During the execution of AxUserMsg, the following error occured:<br>" + mw.html.escape(err));
} else {
jsMsgAppend("During the execution of AxUserMsg, the following error occured: " + err);
}
},
i18n: {
umFillInUser: "صارف کا نام درج کریں:",
umSelectTag: "صارف کو جس امر کی یاد دہانی کرانا مقصود ہو اس کا سانچہ یہاں سے منتخب کریں:",
umFillInMedia: "براہ کرم اس فائل کو درج کریں جس سے متعلق آپ اطلاع دے رہے ہیں:",
umFillInAdditional: "اس سانچہ میں اضافی پیرامیٹر ہیں جنہیں آپ یہاں درج کر سکتے ہیں۔",
umFillInRelUser: "اس سے پیغام سے متعلق صارف کون ہے؟",
umFillInSummary: "خلاصہ ترمیم",
umAddText: "اگر مذکورہ پیغام کے ساتھ مزید کوئی پیغام دینا ہو تو اسے یہاں درج کریں:",
submitButtonLabel: "پیغام درج کریں",
cancelButtonLabel: "منسوخ کریں"
},
umInstPrevContainer: $('<div>', { id: 'umInstantPreviewContainer', style: 'background-color:#EFD;height:380px;overflow:scroll;vertical-align:middle;' }),
umInitImgUserExists: '<img id="%ID%" src="//upload.wikimedia.org/wikipedia/commons/thumb/4/42/P_no.svg/20px-P_no.svg.png" alt="?"/>',
umImgUserUndefined: '//upload.wikimedia.org/wikipedia/commons/thumb/4/42/P_no.svg/20px-P_no.svg.png',
umImgUserNotExists: '//upload.wikimedia.org/wikipedia/commons/thumb/4/42/P_no_red.svg/20px-P_no_red.svg.png',
umImgUserExists: '//upload.wikimedia.org/wikipedia/commons/thumb/b/be/P_yes.svg/20px-P_yes.svg.png',
umImgUserIsIP: '//upload.wikimedia.org/wikipedia/commons/thumb/6/6e/IP.svg/20px-IP.svg.png',
umImgErr: '//upload.wikimedia.org/wikipedia/commons/c/ca/Crystal_error.png',
umImgWarn: '//upload.wikimedia.org/wikipedia/commons/a/af/Crystal_Clear_app_error-info.png',
umImgInfo: '//upload.wikimedia.org/wikipedia/commons/0/09/Crystal_Clear_action_info.png',
umFlagMQ: 1, // Media Query
umFlagUQ: 2, // Username Query
umFlagReq: 4, // Required - must filled in
umFlagNS: 8, // Add Namespace
umFlagP2: 16, // add a universal parameter
umFlagP3: 32, // add a universal parameter
umFlagIP: 64, // Message for IP only
umFlagUM: 128, // User message only
umFlagReqMqNs: 13, // Combination of (umFlagReq | umFlagMQ | umFlagNS)
umUserTalkPrefix: mw.config.get('wgFormattedNamespaces')[3] + ":",
apiURL: mw.util.wikiScript( 'api' )
};
umsg.umTemplate = [
/*!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
* Append new messages at the bottom. Otherwise pre-selection for users will break.
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!*/
// ['Template name', "Name in Sidebar", "Detailed text", Type/Prompt statement, 'Talk summary'];
['Welcome', "خوش آمدید", "اگر صارف کو ویکیپیڈیا پر خوش آمدید نہیں کہا گیا ہے تو اسے خوش آمدید کہیں", 0, "خیر مقدمی پیغام"],
['Test', "تختہ مشق", "تجربات کے لیے تختہ مشق پر بھیجیں", umsg.umFlagP2 + umsg.umFlagP3, "تجربات کے لیے تختہ مشق کی رہنمائی"],
['Test2', "تخریب کاری", "تخریب کاری سے گریز کی تاکید", umsg.umFlagP2 + umsg.umFlagP3, "غیر تعمیری ترامیم نہ کریں۔"],
['Test3', "تخریب کاری 2", "مسلسل تخریب کاری پر انتباہ اور جاری رکھنے پر پابندی عائد کی اطلاع", umsg.umFlagP2 + umsg.umFlagP3, "براہ کرم تخریب کاری سے گریز کریں۔"],
['Test4', "تخریب کاری 3", "تخریب کاری پر آخری انتباہ اور پابندی عائد کرنے کی اطلاع", 0, "آخری انتباہ: تخریبی ترامیم سے احتراز کریں!"],
['Please register', "کھاتا بنائیں", "کھاتا بنانے کی درخواست", umsg.umFlagIP],
['No advertising', "تشہیر نہ کریں", "تشہیر سے گریز کریں", 0],
['Sign', "دستخط کریں", "تبصروں کے آخر میں چار دفعہ ~ کی علامت (~~~~) درج کر کے اپنے دستخط لازماً شامل کریں", 0],
['Blocked', "پابندی", "آپ کے کھاتے پر پابندی عائد کر دی گئی ہے", umsg.umFlagP2 + umsg.umFlagP3],
['Anonblock', "گمنام ترمیم پر پابندی", "آپ کے آئی پی پتے سے ترمیم کرنے پر پابندی عائد کر دی گئی ہے، براہ کرم کھاتا بنائیں۔", umsg.umFlagIP],
['You\'ve got mail', "ڈاک ارسال", "برقی ڈاک ارسال کرنے کی اطلاع", umsg.umFlagUM],
['', "پیغام منتخب کریں! خالی آپشن", "آپ کی خدمت میں نیا پیغام!", 0]
];
/**
* A custom widget built by composition of Autocomplete and Button.
* You can either type something into the field to get filtered suggestions based on your input,
* or use the button to get the full list of selections.
*
* The input is read from an existing select-element for progressive enhancement,
* passed to Autocomplete with a customized source-option.
*
* Autor: someone from the jQuery UI-Team?
* slightly altered
**/
var initCombobox = function( $ ) {
$.widget( 'ui.combobox', {
// These options will be used as defaults
options: {
displaytext: '',
emptyMessage: 42,
passEnter: true,
shutOff: window.AxUserMsgUseSelect
},
// Use the _setOption method to respond to changes to options
_setOption: function(key, value) {
if (this.options.shutOff) return;
switch( key ) {
case 'displaytext':
this.input.val(value);
break;
case 'passEnter':
this.options.passEnter = value;
break;
}
// In jQuery UI 1.8, you have to manually invoke the _setOption method from the base widget
$.Widget.prototype._setOption.apply( this, arguments );
},
_create: function() {
if (this.options.shutOff) return;
var self = this,
select = this.element.hide(),
selectWidth = select.width(),
selectId = select.attr('id'),
selectLabels,
selected = select.children( ":selected" ),
value = selected.val() ? selected.text() : "",
ownId = 'j' + Math.floor(Math.random() * 10000000000),
isOpen = false,
valid = true;
if (selectId) {
selectLabels = $('label[for="' + selectId + '"]');
}
var portMessure = this.portMessure = $('<div>', { id: ownId + 'vp' }).css({ position: 'fixed', top: '0', height: '0' });
$('body').append(portMessure);
var input = this.input = $( "<input>", { id: ownId } )
.insertAfter( select )
.val( value )
.autocomplete({
delay: 0,
minLength: 0,
source: function( request, response ) {
var i = 0,
matcher = new RegExp( $.ui.autocomplete.escapeRegex(request.term), "i" );
response( select.children( "option" ).map(function() {
if ( (i > (window.AxUserMsgMaxSelect || 20)) && request.term ) return;
var text = $( this ).text();
if ( this.value && ( !request.term || matcher.test(text) ) ) {
i++;
return {
label: text.replace(
new RegExp(
"(?![^&;]+;)(?!<[^<>]*)(" +
$.ui.autocomplete.escapeRegex(request.term) +
")(?![^<>]*>)(?![^&;]+;)", "gi"
), "<b>$1</b>" ),
value: text,
option: this
};
}
}) );
},
select: function( event, ui ) {
ui.item.option.selected = true;
self._trigger( "selected", event, {
item: ui.item.option
});
select.triggerHandler('change');
},
change: function( event, ui ) {
if ( !ui.item ) {
var matcher = new RegExp( "^" + $.ui.autocomplete.escapeRegex( $(this).val() ) + "$", "i" );
valid = false;
select.children( "option" ).each(function() {
if ( $( this ).text().match( matcher ) ) {
this.selected = valid = true;
return false;
}
});
if ( !valid ) {
// remove invalid value, as it didn't match anything
$( this ).val( "" );
input.data( "autocomplete" ).term = "";
select.val(self.options.emptyMessage);
select.triggerHandler('change');
return false;
} else {
select.triggerHandler('change');
}
}
},
create: function (e, ui) {
var _t = $(this),
t_top = _t.offset().top - portMessure.offset().top;
$('.ui-autocomplete.ui-menu').css({
'position': 'fixed',
'overflow': 'auto',
'max-height': Math.round($(window).height() - t_top - _t.height() - 20 ) + 'px'
});
},
close: function (e, ui) { setTimeout( function() { isOpen = false; }, 1 ); },
open: function (e, ui) {
isOpen = true;
var _t = $(this),
t_top = _t.offset().top - portMessure.offset().top;
$('.ui-autocomplete.ui-menu')
.css({
'position': 'fixed',
'max-height': Math.round($(window).height() - t_top - _t.height() - 20 ) + 'px'
});
}
})
.addClass( "ui-widget ui-widget-content ui-corner-right" ).css('width', (selectWidth - 70) + 'px')
.click(function() { $(this).select(); })
.keydown(function(e) {
if (self.options.passEnter && (13 === e.which) && !isOpen && valid) {
var kup = $.Event("keyup");
kup.ctrlKey = false;
kup.keyCode = kup.which = 13;
select.triggerHandler(kup);
}
});
if (selectLabels) {
selectLabels.attr('for', ownId);
}
input.data( "autocomplete" )._renderItem = function( ul, item ) {
return $( "<li>" )
.data( "item.autocomplete", item )
.append( "<a>" + item.label + "</a>" )
.appendTo( ul );
};
this.button = $( "<button>", {
"tabIndex": -1,
"type": "button",
"text": " ",
"title": "Show All Items",
"style": "height:1.5em;padding:0!important;width:20px;margin:0!important;position:relative;top:5px;"
} )
.insertAfter( input )
.button({
icons: {
primary: "ui-icon-triangle-1-s"
},
text: false
})
.removeClass( "ui-corner-all" )
.addClass( "ui-corner-left ui-button-icon" )
.click(function() {
// close if already visible
if ( input.autocomplete( "widget" ).is( ":visible" ) ) {
input.autocomplete( "close" );
return;
}
// work around a bug (likely same cause as #5265)
$( this ).blur();
// pass empty string as value to search for, displaying all results
input.autocomplete( "search", "" );
input.focus();
});
},
destroy: function() {
if (this.options.shutOff) return;
this.input.remove();
this.portMessure.remove();
this.button.remove();
this.element.show();
$.Widget.prototype.destroy.call( this );
}
});
};
if ($.inArray(mw.config.get('wgNamespaceNumber'), [-1, 2, 3]) !== -1) {
// alternative for jquery.ui autocomplete: jquery.suggestions
// http://jqueryui.com/demos/autocomplete/ http://svn.wikimedia.org/viewvc/mediawiki/trunk/phase3/resources/jquery/jquery.suggestions.js?view=markup
$.when(mw.loader.using([
'jquery.ui',
'mediawiki.util',
'mediawiki.user',
'ext.gadget.libUtil',
'ext.gadget.libJQuery'
]), $.ready)
.then(function () {
initCombobox($);
umsg.umInstall();
if (window.installOldLinks) umsg.umInstallOldLinks();
$(document).triggerHandler('scriptLoaded', ['AxUserMsg', umsg]);
});
}
})();
//</nowiki>