Mudanças entre as edições de "MediaWiki:Common.js"
Ir para navegação
Ir para pesquisar
Linha 1: | Linha 1: | ||
/** Upload form rewrite | |||
Authors: [[User:Lupo]], March 2008 - 2015 | |||
* Multiple user script devloapers, 2015 - | |||
License: Quadruple licensed GFDL, GPL, LGPL and Creative Commons Attribution 3.0 (CC-BY-3.0) | |||
Choose whichever license of these you like best :-) | |||
*/ | |||
// <nowiki> | |||
/* UFUtils, UFUI, UFHelp, UploadForm are made global */ // UFUI is used by HotCat | |||
/* global jQuery:false, mediaWiki:false, importScript:false */ | |||
/* global Buttons, EditTools, LanguageHandler, Tooltip, TextCleaner, UIElements, FormRestorer */ | |||
/* global hotcat_set_state, hotcat_close_form, hotcat_get_state */ // by HotCat | |||
/* global wgUploadLicenseObj, wgUploadWarningObj */ | |||
/* eslint one-var:0, vars-on-top:0, camelcase:0, no-alert:0, no-console:0, no-bitwise:0, no-new:0, no-eval:0, indent:0, curly:0, */ | |||
/* eslint space-in-parens:0, computed-property-spacing:0, array-bracket-spacing:0, */ // extends:wikimedia | |||
/* jslint strict:false, forin:true, bitwise:true */ | |||
(function ($, mw) { | |||
// Guard against multiple inclusions! | |||
if (window.UploadForm) | |||
return; | |||
importScript('MediaWiki:LanguageHandler.js'); | |||
importScript('MediaWiki:FormRestorer.js'); | |||
importScript('MediaWiki:UIElements.js'); | |||
importScript('MediaWiki:Tooltips.js'); | |||
var UFConfig = { | |||
// Configuration. These can be set by a user in their user js. The typeof checks | |||
// are not really needed when this script is globally enabled, but until then, we have to be | |||
// careful not to overwrite a user's settings if he defines these first and then includes this | |||
// script in his monobook.js. | |||
forcebasic: window.UploadForm_forcebasic !== undefined ? window.UploadForm_forcebasic : | |||
(!window.JSconfig || window.JSconfig.keys.UploadForm_newlayout) ? null : true, // If non-null, use the basic form | |||
ownwork_author: window.UploadForm_ownwork_author !== undefined ? window.UploadForm_ownwork_author : | |||
'[[User:' + mw.config.get('wgUserName') + '|]]', // Change to use something else | |||
ownwork_date: window.UploadForm_ownwork_date !== undefined ? window.UploadForm_ownwork_date : | |||
null, // Set to define a pre-fill value for the date field | |||
own_language_first: window.UploadForm_own_language_first !== undefined ? window.UploadForm_own_language_first : | |||
false, // Set to true to have own language description on top | |||
additional_info_height: window.UploadForm_additional_info_height ? window.UploadForm_additional_info_height : 2, | |||
description_height: window.UploadForm_description_height ? window.UploadForm_description_height : 2, | |||
source_field_size: window.UploadForm_source_field_size ? window.UploadForm_source_field_size : 1, | |||
author_field_size: window.UploadForm_author_field_size ? window.UploadForm_author_field_size : 1, | |||
page_preview_in_tooltip: window.UploadForm_page_preview_in_tooltip !== undefined ? window.UploadForm_page_preview_in_tooltip : false, | |||
description_languages: window.UploadForm_description_languages ? window.UploadForm_description_languages : null, | |||
// If false, don't pre-fill description field in basic mode. May be useful | |||
// for people who have their own scripts pre-filling this field. | |||
autofill: window.UploadForm_autofill !== undefined ? window.UploadForm_autofill : true | |||
}; | }; | ||
$(tooltips. | |||
var UFUtils = window.UFUtils = { | |||
makeLink: function (name, url) { | |||
var link = document.createElement('a'); | |||
link.setAttribute('href', url); | |||
link.appendChild(document.createTextNode(name)); | |||
return link; | |||
}, | |||
convert_td_div: function (td) { | |||
// Replace the contents with a div, fixate the width, and give the div the id of the td | |||
var div = document.createElement('div'); | |||
var w = UFUtils.getWidth(td); | |||
if (w) { | |||
td.setAttribute('width', String(w)); | |||
td.style.maxWidth = String(w) + 'px'; | |||
} | |||
div.setAttribute('width', (w ? String(w) : '100%')); | |||
if (w) | |||
div.style.maxWidth = String(w) + 'px'; | |||
// Clear the warningCell and add the div instead | |||
while (td.firstChild) | |||
td.removeChild(td.firstChild); | |||
td.appendChild(div); | |||
var id = td.id; | |||
td.id = ''; | |||
div.id = id; | |||
return div; | |||
}, | |||
getHeight: function (rows, minimum, maximum) { | |||
if (!rows || isNaN(rows / 2) || rows < minimum) | |||
return minimum; | |||
else if (rows > maximum) | |||
return maximum; | |||
return rows; | |||
}, | |||
getWidth: function (element) { | |||
try { | |||
if (element.clientWidth) { // From IE, but Gecko has this, too. | |||
return element.clientWidth; | |||
} else if (window.getComputedStyle) { // Gecko, Opera | |||
return document.defaultView | |||
.getComputedStyle(element, null) | |||
.getPropertyValue('width'); | |||
} | |||
} catch (ex) { | |||
return null; | |||
} | |||
}, | |||
isChildOf: function (child, ancestor) { | |||
if (!ancestor) | |||
return false; | |||
while (child && child !== ancestor) | |||
child = child.parentNode; | |||
return (child === ancestor); | |||
} | |||
}; // end UFUtils | |||
// Used by HotCat | |||
var UFUI = window.UFUI = { | |||
// Encapsulate all UI stuff, with checks such that it works in degraded mode | |||
// (built-in defaults only) if UIElements doesn't exist. | |||
defaultLanguage: 'en', // Default. | |||
userLanguage: 'en', // Sanitized wgUserLanguage. | |||
internalLanguage: 'en', // Same, but with dashes replaced by underscores. | |||
isOwnWork: false, // True if uselang="*ownwork" | |||
isFromFlickr: false, // True if uselang="*fromflickr" | |||
isExperienced: false, // True if uselang="experienced" | |||
sanitizeUserLanguage: function () { | |||
// Try to make sense of wgUserLanguage even if it has been hacked to have special | |||
// pages for particular upload sources. Also sets isOwnWork and isFromFlickr. | |||
var globalUserLanguage = mw.config.get('wgUserLanguage'); | |||
if (!globalUserLanguage) | |||
return; | |||
UFUI.userLanguage = globalUserLanguage; | |||
if (globalUserLanguage.length > 3) { | |||
// Special "hacked" uselang parameters... | |||
var hacks = ['ownwork', 'fromflickr', 'experienced', 'fromwikimedia', 'fromgov']; | |||
var found = false; | |||
for (var i = 0; i < hacks.length; i++) { | |||
var idx = globalUserLanguage.indexOf(hacks[i]); | |||
if (idx >= 0) { | |||
// ULS is not working correctly with hacked uselang parameters, thus hiding it. | |||
$('#pt-uls, .uls-tipsy').hide(); | |||
found = true; | |||
if (idx) | |||
UFUI.userLanguage = globalUserLanguage.substring(0, idx); | |||
else | |||
UFUI.userLanguage = UFUI.defaultLanguage; | |||
if (!i) | |||
UFUI.isOwnWork = true; | |||
else if (i === 1) | |||
UFUI.isFromFlickr = true; | |||
else if (i === 2) | |||
UFUI.isExperienced = true; | |||
break; | |||
} | |||
} | |||
if (!found && typeof LanguageHandler !== 'undefined' && LanguageHandler.getPrefix instanceof Function) { | |||
// None of the "standard" hacks. Try an alternate approach. | |||
var lang_code_length = LanguageHandler.getPrefix(globalUserLanguage); | |||
if (lang_code_length && lang_code_length < globalUserLanguage.length) | |||
UFUI.userLanguage = globalUserLanguage.substr(0, lang_code_length); | |||
} | |||
} | |||
if (UFUI.userLanguage === 'en-gb') | |||
UFUI.userLanguage = 'en'; | |||
UFUI.internalLanguage = UFUI.userLanguage.replace(/-/g, '_'); | |||
}, | |||
defaultLabels: { | |||
wpSourceUploadLbl: 'Original source:', | |||
wpAuthorUploadLbl: 'Author:', | |||
wpDateUploadLbl: 'Date:', | |||
wpDescUploadLbl: 'Description:', | |||
wpPermissionUploadLbl: 'Permission:', | |||
wpCategoriesUploadLbl: 'Categories:', | |||
wpOtherVersionsUploadLbl: 'Other versions:', | |||
wpAdditionalInfoUploadLbl: 'Additional information:', | |||
wpPreviewLicenseUploadLbl: 'Preview the chosen license', | |||
wpOwnWorkUploadLbl: 'Own work', | |||
wpUnknownLanguageUploadLbl: 'Unknown language', | |||
wpPreviewUploadLbl: 'Preview', | |||
wpOkUploadLbl: 'OK', | |||
wpCancelUploadLbl: 'Cancel' | |||
}, | |||
defaultErrorMsgs: { | |||
wpUploadWarningError: 'You must provide the original source of the image, the author of the work, and a license.', | |||
wpNoFilenameError: 'The target filename must not be empty.', | |||
wpHttpFilenameError: 'The target file name appears to be a URL.', | |||
wpNoSlashError: 'The target file name must not contain "/".', | |||
wpNondescriptFilenameError: 'Please use a more descriptive target file name.', | |||
wpNoExtensionError: 'The target file name must have a file type extension (like for example ".jpg").', | |||
wpIllegalExtensionError: 'Files of this type cannot be uploaded.', | |||
wpDoubleExtensionError: 'Please correct the double file type in the target file name.', | |||
wpFlickrURLError: 'The source must be a URL pointing to the image at Flickr.', | |||
wpNoDescriptionError: 'Please give a description of the contents of the file you want to upload.', | |||
wpNoHelpTextError: 'Help text not found.', | |||
wpPreviewOverwriteError: | |||
'You will upload over an already existing file. Please choose a different filename,' + | |||
'unless you are uploading a technically improved version of the same file.' + | |||
'Don\'t overwrite a file with a different image of the same topic.' + | |||
'If you overwrite, the information in this form will not appear on the description page.', | |||
wpReuploadNoSummaryError: 'Please describe the file changes in the text box.' | |||
}, | |||
defaultHints: { | |||
wpUploadFormDestFileHint: 'Name of the file at Commons after the upload.', | |||
wpUploadFormSourceHint: 'Where does this file come from?', | |||
wpUploadFormAuthorHint: 'Who created this file? If it shows some artwork, who created that?', | |||
wpUploadFormDateHint: 'Date of creation and/or first publication of the work.', | |||
wpUploadFormPermissionHint: 'Not your own file? Or already published elsewhere? Use {{OTRS pending}} and send permission by e-mail. Also for specialized license tags.', | |||
wpUploadFormAdditionalInfoHint: 'Use for geolocation tags and other specialized information.', | |||
wpUploadFormCategoryHint: 'Click (+) to add categories.' | |||
}, | |||
// Do *not* use "-" here (as in "be-tarask")!! Use "_" instead: "be_tarask". | |||
translate: { | |||
en: 'translate', | |||
af: 'vertaal', | |||
ar: 'ترجم', | |||
be: 'перакласці', | |||
be_tarask: 'перакласьці', | |||
br: 'treiñ', | |||
bg: 'превеждам', | |||
ca: 'traduïu', | |||
cs: 'přeložit', | |||
cy: 'cyfieithu', | |||
da: 'oversæt', | |||
de: 'übersetzen', | |||
el: 'μεταφράστε', | |||
eo: 'traduki', | |||
es: 'traducir', | |||
et: 'tõlkima', | |||
fa: 'ترجمه\u200cکردن', | |||
fi: 'suomenna', | |||
fo: 'umseta', | |||
fr: 'traduire', | |||
gl: 'traducir', | |||
he: 'לתרגם', | |||
hr: 'prevesti', | |||
hu: 'fordítás', | |||
hy: 'թարգմանել', | |||
id: 'terjemah', | |||
io: 'tradukar', | |||
is: 'þýða', | |||
it: 'tradurre', | |||
ja: '訳す', | |||
ko: '번역하기', | |||
la: 'traducere', | |||
mk: 'преведи', | |||
ml: 'തര\u0d4dജ\u0d4dജമ', | |||
mn: 'орчуулах', | |||
mt: 'traduci', | |||
nn: 'oversett', | |||
no: 'oversett', | |||
nl: 'vertalen', | |||
pap: 'tradusí', | |||
pl: 'przetłumacz', | |||
pt: 'traduzir', | |||
ro: 'a traduce', | |||
ru: 'перевести', | |||
sk: 'preložit', | |||
sl: 'perovodit', | |||
sq: 'përkthej', | |||
ss: 'kuhúmusha', | |||
sv: 'översätt', | |||
ta: 'மொழிபெயர்', | |||
tr: 'tercüme', | |||
ty: 'ʻauvaha', | |||
uk: 'перекласти', | |||
vi: 'dịch', | |||
zh: '翻譯', | |||
zh_min_nan: 'hoan-e̍k', | |||
nan: 'hoan-e̍k', | |||
minnan: 'hoan-e̍k' | |||
}, | |||
labels: null, // Repository for form labels | |||
help: null, // Repository for help texts (and the help button) | |||
error_msgs: null, // Repository for error messages | |||
uiElements: null, // Repository for graphical UI elements | |||
hints: null, // Repository for brief hints | |||
setupRepositories: function () { | |||
if (!UFUI.labels) { | |||
if (window.UIElements) { | |||
var id; | |||
UFUI.labels = UIElements.emptyRepository(); | |||
UFUI.help = UIElements.emptyRepository(); | |||
UFUI.error_msgs = UIElements.emptyRepository(); | |||
UFUI.uiElements = UIElements.emptyRepository(); | |||
UFUI.hints = UIElements.emptyRepository(); | |||
for (id in UFUI.defaultLabels) { | |||
if (id === 'wpDescUploadLbl') { | |||
UIElements.setEntry( | |||
id, | |||
UFUI.labels, | |||
UFUtils.makeLink( | |||
UFUI.defaultLabels[id], | |||
'/wiki/Commons:First_steps/Quality_and_description')); | |||
} else { | |||
UIElements.setEntry(id, UFUI.labels, document.createTextNode(UFUI.defaultLabels[id])); | |||
} | |||
} | |||
for (id in UFUI.defaultErrorMsgs) { | |||
UIElements.setEntry(id, UFUI.error_msgs, | |||
document.createTextNode(UFUI.defaultErrorMsgs[id])); | |||
} | |||
for (id in UFUI.defaultHints) { | |||
UIElements.setEntry(id, UFUI.hints, | |||
document.createTextNode(UFUI.defaultHints[id])); | |||
} | |||
// Now try to read the localized stuff from the uploadfooter. | |||
UIElements.load('wpUploadFormLabels', null, 'span', UFUI.labels); | |||
UIElements.load('wpUploadFormErrorMessages', null, 'span', UFUI.error_msgs); | |||
UIElements.load('wpUploadFormHints', null, 'span', UFUI.hints); | |||
UIElements.load('wpUploadFormUIElements', null, 'div', UFUI.uiElements); | |||
UIElements.load('wpUploadFormHelp', null, 'div', UFUI.help); | |||
UFUI.basic = false; | |||
} else { | |||
UFUI.labels = UFUI.defaultLabels; | |||
UFUI.error_msgs = UFUI.defaultErrorMsgs; | |||
UFUI.hints = UFUI.defaultHints; | |||
UFUI.basic = true; | |||
} | |||
} | |||
}, | |||
getUI: function (id, repository, basic) { | |||
if (!UFUI.labels) { | |||
UFUI.sanitizeUserLanguage(); | |||
UFUI.setupRepositories(); | |||
} | |||
if (!UFUI[repository]) | |||
return null; | |||
var result = null; | |||
var add_plea = false; | |||
if (UFUI.basic) { | |||
result = document.createTextNode(UFUI[repository][id]); | |||
add_plea = (UFUI.internalLanguage !== UFUI.defaultLanguage); | |||
} else { | |||
result = UIElements.getEntry(id, UFUI[repository], UFUI.internalLanguage, null); | |||
add_plea = !result; | |||
if (!result) | |||
result = UIElements.getEntry(id, UFUI[repository]); | |||
if (!result) | |||
return null; | |||
// Hmmm... what happened here? We normally have defaults... | |||
result = result.cloneNode(true); | |||
} | |||
if (add_plea && !basic) { | |||
// Wrap it all into a span -- we can return only one element | |||
var span = document.createElement('span'); | |||
span.appendChild(result); | |||
span.appendChild(UFUI.plea(repository, id)); | |||
result = span; | |||
} | |||
return result; | |||
}, | |||
plea: function (what, msg_id) { | |||
var span = document.createElement('sub'); | |||
span.appendChild(document.createTextNode(' (')); | |||
span.appendChild( | |||
UFUtils.makeLink( | |||
UFUI.translate[UFUI.internalLanguage] || UFUI.translate.en, | |||
'/wiki/MediaWiki_talk:UploadFormLabels/UploadFormTranslations?action=edit§ion=new' + | |||
'&withJS=MediaWiki:UploadFormTranslator.js&language=' + | |||
encodeURIComponent(UFUI.userLanguage) + | |||
'&uploadformurl=' + encodeURIComponent(document.URL) + | |||
(what ? '&uploadformitems=' + encodeURIComponent(what) : '') + | |||
(msg_id ? '&uploadformmsg=' + encodeURIComponent(msg_id) : ''))); | |||
span.appendChild(document.createTextNode(')')); | |||
return span; | |||
}, | |||
getLabel: function (id, basic) { | |||
return UFUI.getUI(id, 'labels', basic); | |||
}, | |||
getErrorMsg: function (id, basic) { | |||
return UFUI.getUI(id, 'error_msgs', basic); | |||
}, | |||
getHint: function (id, basic) { | |||
return UFUI.getUI(id, 'hints', basic); | |||
}, | |||
getEntry: function (id, repository, lang, sel) { | |||
if (!UFUI.labels) { | |||
UFUI.sanitizeUserLanguage(); | |||
UFUI.setupRepositories(); | |||
} | |||
if (!UFUI.basic) | |||
return UIElements.getEntry(id, UFUI[repository], lang, sel); | |||
if (!UFUI[repository] || lang !== UFUI.defaultLanguage || !!sel && sel !== 'default') | |||
return null; | |||
return UFUI[repository][id]; | |||
} | |||
}; // end UFUI | |||
var UFHelp = window.UFHelp = { // Collects all help-related stuff | |||
help_close_imgs: null, | |||
precreate_tooltip_closer: function () { | |||
if (window.Tooltip && window.Buttons) { | |||
var closeImgs = UFUI.getEntry('wpUploadFormHelpCloseButton', 'uiElements', UFUI.internalLanguage); | |||
if (!closeImgs) | |||
closeImgs = UFUI.getEntry('wpUploadFormHelpCloseButton', 'uiElements'); | |||
if (closeImgs) | |||
closeImgs = closeImgs.getElementsByTagName('img'); | |||
if (!closeImgs || !closeImgs.length) | |||
closeImgs = null; | |||
else | |||
closeImgs = Buttons.createClass(closeImgs, 'wpUploadFormHelpCloseClass'); | |||
UFHelp.help_close_imgs = closeImgs; | |||
} | |||
}, | |||
tooltip_styles: { // The style for all our tooltips | |||
border: '1px solid #88A', | |||
backgroundColor: '#f7f8ff', | |||
padding: '0.3em', | |||
fontSize: ((mw.config.get('skin') === 'monobook' || mw.config.get('skin') === 'modern') ? '127%' : '100%') | |||
// Scale up to default text size | |||
}, | |||
getHelp: function (help_id, with_ext) { | |||
// This is a Tooltip callback! Sets the help texts dynamically, depending of the file | |||
// type the user has chosen in wpDestFile. | |||
var fn = null; | |||
if (with_ext) { | |||
fn = document.getElementById('wpDestFile'); | |||
if (fn) | |||
fn = fn.value; | |||
if (fn) { | |||
fn = fn.split('.'); | |||
if (fn.length >= 2) | |||
fn = fn[fn.length - 1]; | |||
else | |||
fn = null; | |||
} | |||
} | |||
var add_plea = false; | |||
var extensions = [fn, 'default']; | |||
var helpMain = null; | |||
for (var i = 0; i < extensions.length && !helpMain; i++) { | |||
if (extensions[i] && extensions[i].length) { | |||
helpMain = UFUI.getEntry(help_id, 'help', UFUI.internalLanguage, extensions[i]); | |||
if (!helpMain) { | |||
helpMain = UFUI.getEntry(help_id, 'help', null, extensions[i]); | |||
add_plea = !!helpMain; | |||
} | |||
} | |||
} | |||
var help_base = UFUI.getEntry(help_id, 'help', UFUI.internalLanguage); | |||
if (!help_base) { | |||
help_base = UFUI.getEntry(help_id, 'help'); | |||
add_plea = add_plea || !!help_base; | |||
} | |||
var help = document.createElement('div'); | |||
if (help_base) | |||
help.appendChild(help_base); | |||
if (helpMain) | |||
help.appendChild(helpMain); | |||
if (!helpMain && !help_base) | |||
help.appendChild(UFUI.getErrorMsg('wpNoHelpTextError')); | |||
else if (add_plea) | |||
help.appendChild(UFUI.plea('help', help_id)); | |||
return help; | |||
}, | |||
showHelp: function (e, id) { // Onclick handler for setup without tooltips | |||
e = e || window.event; | |||
var node = e.target || e.srcElement, | |||
error; | |||
if (!node) { | |||
error = UFUI.getErrorMsg('wpNoHelpTextError', true); | |||
// We need the text contents... | |||
while (error && error.nodeType !== Node.TEXT_NODE) | |||
error = error.firstChild; | |||
if (error) | |||
alert(error.data); | |||
// Otherwise what?? | |||
} else if (!document.getElementById(id + '_Div')) { | |||
var help = UFHelp.getHelp(id, false); | |||
help.style.fontSize = 'small'; | |||
help.style.color = '#666'; | |||
// Now add a new table row after the current one | |||
var tr = node.parentNode; | |||
while (tr && tr.nodeName.toLowerCase() !== 'tr') | |||
tr = tr.parentNode; | |||
if (!tr) { | |||
error = UFUI.getErrorMsg('wpNoHelpTextError', true); | |||
while (error && error.nodeType !== 3) | |||
error = error.firstChild; | |||
if (error) | |||
alert(error.data); | |||
} else { | |||
var new_tr = document.createElement('tr'); | |||
var cell = document.createElement('td'); | |||
new_tr.appendChild(cell); | |||
cell = document.createElement('td'); | |||
cell.id = id + '_Div'; | |||
new_tr.appendChild(cell); | |||
tr.parentNode.insertBefore(new_tr, tr.nextSibling); | |||
cell = UFUtils.convert_td_div(cell); | |||
cell.appendChild(help); | |||
} | |||
} | |||
if (e.stopPropagation) { | |||
e.stopPropagation(); | |||
e.preventDefault(); | |||
} else { e.cancelBubble = true; } | |||
return false; | |||
}, | |||
setupHelp: function (is_reupload) { | |||
var fields = ['wpUploadFile', 'wpUploadFileURL', 'wpDestFile', 'wpSource', 'wpAuthor', 'wpDate', 'wpDesc', 'wpPermission', | |||
'wpOtherVersions', 'wpAdditionalInfo', 'wpPatent', 'wpLicense', 'wpCategories', 'wpWatchthis', 'wpIgnoreWarning']; | |||
if (!UFUI.help) | |||
return; | |||
// Help not loaded | |||
function setHelp(id, imgs, lk, maximum_width, is_reupload) { | |||
// Figure out where to place the help "button" | |||
var field = document.getElementById(id); | |||
var insert_in = null, | |||
before = null; | |||
var help_id = id + 'Help'; | |||
if (!UFUI.help[help_id]) | |||
return; | |||
// Don't add if we have no help at all. | |||
var offset = -5; // Pixels. | |||
switch (id) { | |||
case 'wpWatchthis': | |||
case 'wpIgnoreWarning': | |||
// Right of the element | |||
if (!field) | |||
return; | |||
insert_in = field.parentNode; | |||
// Find the label. | |||
{ | |||
var lbls = insert_in.getElementsByTagName('label'); | |||
if (!lbls) { | |||
before = field.nextSibling; | |||
} else { | |||
for (var i = 0; i < lbls.length; i++) { | |||
if (lbls[i].htmlFor && lbls[i].htmlFor === id) { | |||
before = lbls[i].nextSibling; | |||
break; | |||
} | |||
} | |||
} | |||
} | |||
offset = Math.abs(offset); | |||
break; | |||
case 'wpCategories': | |||
field = document.getElementById('hotcatLabelTranslated'); | |||
if (!field) | |||
return; | |||
insert_in = field; | |||
before = null; | |||
if (field.firstChild) { | |||
field = field.firstChild; | |||
offset = Math.abs(offset); | |||
} | |||
break; | |||
case 'wpAuthor': | |||
case 'wpSource': | |||
if (!field) | |||
return; | |||
field = field.parentNode; // Because the field itself may vanish. | |||
insert_in = field.parentNode.cells[0]; | |||
before = null; | |||
break; | |||
case 'wpDestFile': | |||
if (!field) | |||
return; | |||
insert_in = field.parentNode.parentNode.cells[0]; | |||
before = null; | |||
if (is_reupload) { | |||
help_id = 'wpReuploadDestHelp'; | |||
field = null; // Field is hidden: attach the help text to the button instead | |||
} | |||
break; | |||
case 'wpDesc': | |||
if (!field) { | |||
field = document.getElementById('wpUploadDescription'); | |||
if (field) { // Basic form | |||
help_id = (is_reupload ? 'wpReuploadSummaryHelp' : 'wpUploadDescriptionHelp'); | |||
} else { | |||
insert_in = document.getElementById('wpDescLabel'); | |||
if (!insert_in) | |||
return; | |||
field = insert_in; | |||
offset = Math.abs(offset); | |||
before = insert_in.nextSibling; | |||
insert_in = insert_in.parentNode; | |||
break; | |||
} | |||
} | |||
/* falls through */ | |||
// eslint-disable-next-line no-fallthrough | |||
case 'wpPatent': | |||
field = document.getElementsByName(id)[0]; | |||
if (!field) | |||
return; | |||
insert_in = field.parentNode.parentNode.parentNode.cells[0]; | |||
before = null; | |||
break; | |||
default: | |||
if (!field) | |||
return; | |||
// In the table cell to the left | |||
insert_in = field.parentNode.parentNode.cells[0]; | |||
before = null; | |||
} | |||
// Create and insert the help "button" | |||
var button_construct = null, | |||
button = null; | |||
if (imgs && window.Buttons) { | |||
button = Buttons.makeButton(imgs, id + '_HelpButton', '#'); | |||
button.style.position = 'relative'; | |||
button.style.top = '-0.4em'; | |||
button_construct = button; | |||
} else { | |||
button_construct = lk.cloneNode(true); | |||
button = button_construct.getElementsByTagName('a')[0]; | |||
} | |||
insert_in.insertBefore(button_construct, before); | |||
if (window.Tooltip) { | |||
// Create the tooltip | |||
new Tooltip( | |||
button, | |||
function () { | |||
return UFHelp.getHelp(help_id, true); | |||
}, { | |||
activate: Tooltip.CLICK, | |||
deactivate: (UFHelp.help_close_imgs ? | |||
Tooltip.CLICK_ELEM : | |||
Tooltip.CLICK_TIP | Tooltip.CLICK_ELEM | Tooltip.LOSE_FOCUS), | |||
close_button: UFHelp.help_close_imgs, | |||
mode: Tooltip.FIXED, | |||
fixed_offset: { | |||
x: 10, | |||
y: offset | |||
}, | |||
max_pixels: maximum_width, | |||
target: field, | |||
open_delay: 0, | |||
hide_delay: 0 | |||
}, | |||
UFHelp.tooltip_styles); | |||
} else { | |||
// Alternative setup without Tooltips: insert help text statically in a table field | |||
// below the button. | |||
button.onclick = function (evt) { | |||
return UFHelp.showHelp(evt, help_id); | |||
}; | |||
} | |||
} | |||
var button_imgs = null, | |||
button_lk = null; | |||
if (window.Buttons) { | |||
button_imgs = UFUI.getEntry('wpUploadFormHelpOpenButton', 'uiElements', UFUI.internalLanguage); | |||
if (!button_imgs) | |||
button_imgs = UFUI.getEntry('wpUploadFormHelpOpenButton', 'uiElements'); | |||
button_lk = null; | |||
if (button_imgs) | |||
button_imgs = button_imgs.getElementsByTagName('img'); | |||
} | |||
if (!button_imgs || !button_imgs.length) { | |||
// Alternative text-based "button" | |||
button_lk = document.createElement('sup'); | |||
button_lk.appendChild(document.createElement('b')); | |||
button_lk.firstChild.appendChild(document.createTextNode(' [')); | |||
button_lk.firstChild.appendChild(UFUtils.makeLink('?', '#')); | |||
button_lk.firstChild.appendChild(document.createTextNode(']')); | |||
button_imgs = null; | |||
} else { | |||
button_imgs = Buttons.createClass(button_imgs, 'wpUploadFormHelpOpenClass'); | |||
} | |||
var widest_field = document.getElementById('wpAdditionalInfo'); | |||
var max_width = 0; | |||
if (!widest_field) | |||
widest_field = document.getElementById('wpUploadDescription'); | |||
if (widest_field) { | |||
var w = UFUtils.getWidth(widest_field); | |||
try { | |||
max_width = Math.round(w * 0.9); | |||
} catch (ex) { | |||
max_width = 0; | |||
} | |||
} | |||
fields.forEach(function (f) { | |||
setHelp(f, button_imgs, button_lk, max_width, is_reupload); | |||
}); | |||
} | |||
}; // end UFHelp | |||
var UFFixes = { | |||
fixAutocompletion: function () { | |||
// Do the overwrite check also for selections from the browser's "previous entry list" | |||
var destFile = document.getElementById('wpDestFile'); | |||
if (destFile && destFile.onkeyup) { | |||
// For some reason, onchange doesn't fire upon autocompletion in FF and IE6. Don't use | |||
// onblur (recommended as a workaround on some Internet sites), it cancels button clicks | |||
// that cause the focus change. Unfortunately, FF also doesn't fire the DOMAttrModified | |||
// event upon autocompletion. Thus we're stuck for FF. At least the FF people are about | |||
// to correct this bug (https://bugzilla.mozilla.org/show_bug.cgi?id=388558). On IE, | |||
// there is a workaround. | |||
if (window.ActiveXObject) { // We're on IE... | |||
// See http://msdn2.microsoft.com/en-us/library/ms533032.aspx and | |||
// http://msdn2.microsoft.com/en-us/library/ms536956.aspx | |||
if (!destFile.onpropertychange) { | |||
var previous_onkeyup_handler = destFile.onkeyup; | |||
var previous_onchange_handler = destFile.onchange; | |||
var handler = function (e) { | |||
e = e || window.event; | |||
if (e && e.propertyName && e.propertyName === 'value') { | |||
if (typeof previous_onkeyup_handler === 'string') | |||
eval(previous_onkeyup_handler); | |||
else if (previous_onkeyup_handler instanceof Function) | |||
previous_onkeyup_handler(e); | |||
if (typeof previous_onchange_handler === 'string') | |||
eval(previous_onchange_handler); | |||
else if (previous_onchange_handler instanceof Function) | |||
previous_onchange_handler(e); | |||
} | |||
}; | |||
if (destFile.addEventListener) | |||
destFile.addEventListener('propertychange', handler); | |||
else if (destFile.attachEvent) | |||
destFile.attachEvent('onpropertychange', handler); | |||
else | |||
return; | |||
destFile.onkeyup = null; // Otherwise, both may fire... | |||
destFile.onchange = null; | |||
} | |||
} else { | |||
$(destFile).change(destFile.onkeyup); | |||
// addEvent (destFile, 'change', destFile.onkeyup); | |||
} | |||
} | |||
} | |||
}; // end UFFixes | |||
var UF = window.UploadForm = { | |||
isInstalled: false, // Set to true when the onload hook runs | |||
debug: false, // Can be set to true by adding "&debug=true" to the URL | |||
oldOnSubmit: null, // Possibly already existing onsubmit handler | |||
errorColor: 'lightpink', // The light red from Template:Copyvio | |||
formModified: false, | |||
isReupload: false, | |||
setup_hotcat_label: function () { | |||
// If HotCat is present, translate its label if we can find it | |||
var hotcatLabelCell = document.getElementById('hotcatLabel'); | |||
if (hotcatLabelCell) { | |||
// Change its ID, just to be sure | |||
hotcatLabelCell.setAttribute('id', 'hotcatLabelTranslated'); | |||
// Assumes that the cell has only one child (which is normally the case) | |||
hotcatLabelCell.replaceChild( | |||
UFUI.getLabel('wpCategoriesUploadLbl'), | |||
hotcatLabelCell.firstChild); | |||
} | |||
}, | |||
setup_error_display: function () { | |||
var warningCell = document.getElementById('wpDestFile-warning'); | |||
if (!warningCell) | |||
return; | |||
var row = warningCell.parentNode; | |||
var new_cell = document.createElement('td'); | |||
new_cell.style.padding = '0'; | |||
// Remove the colspan, if any, and insert a new cell to the left | |||
warningCell.colspan = ''; | |||
warningCell.padding = '0'; | |||
row.insertBefore(new_cell, warningCell); | |||
UFUtils.convert_td_div(warningCell); | |||
}, | |||
set_fields_enabled: function (enabled, except) { | |||
// Enables or disables all named fields in the form, except those whose ids are | |||
// listed in except | |||
var skip = except.join(' '); | |||
var elems = UF.the_form.elements; | |||
var changed = false; | |||
for (var i = 0; i < elems.length; i++) { | |||
if (elems[i].type === 'hidden') | |||
continue; | |||
// Don't fool around with hidden elements | |||
var id = elems[i].id; | |||
if (!id || !id.length) | |||
id = elems[i].name; | |||
if (id && id.length) { | |||
if (skip.indexOf(id) < 0) { | |||
if (elems[i].disabled === enabled) { | |||
changed = true; | |||
if (elems[i].type === 'text' || elems[i].type === 'textarea') { | |||
// Set the background. Actually, I'd like to just reset it to whatever the | |||
// default was, but setting it to null doesn't do anything in IE6... We | |||
// force a light gray for disabled fields since IE6 doesn't have a real | |||
// visual "disabled" indicator for input fields. | |||
try { | |||
elems[i].style.backgroundColor = (enabled ? '#FFF' : '#EEE'); | |||
} catch (some_error) { | |||
// Swallow | |||
} | |||
} | |||
elems[i].disabled = !enabled; | |||
} | |||
} | |||
} | |||
} | |||
if (changed) { | |||
// Clear warning messages. If we disabled fields, they're obsolete; if we enabled fields, | |||
// new warnings will be generated upon submit if necessary. | |||
var myWarning = document.getElementById('wpUploadVerifyWarning'); | |||
if (myWarning) | |||
myWarning.style.display = 'none'; | |||
} | |||
}, | |||
previous_hotcat_state: null, | |||
getPrevValue: function (storedForm, element_id) { | |||
// Return a field's previous value, if known | |||
if (!storedForm || storedForm.length <= 1 || !element_id || !element_id.length) | |||
return null; | |||
for (var i = 1; i < storedForm.length; i++) { | |||
if (storedForm[i] && element_id === storedForm[i].id) | |||
return storedForm[i].val; | |||
} | |||
return null; | |||
}, | |||
license_button: null, | |||
license_button_shown: false, | |||
current_license_preview: ' ', | |||
get_license_preview: function () { // Tooltip callback | |||
var div = document.createElement('div'); | |||
div.style.display = 'none'; | |||
document.body.appendChild(div); | |||
div.innerHTML = UF.current_license_preview; | |||
document.body.removeChild(div); | |||
div.style.fontSize = 'smaller'; | |||
div.style.display = ''; | |||
var wrapper = document.createElement('div'); | |||
wrapper.appendChild(div); | |||
return wrapper; | |||
}, | |||
create_license_button: function () { | |||
// Will be called only from our rewritten wgUploadLicenseObj.showPreview, i.e. | |||
// we *know* that we *do* have Tooltips and Buttons here. | |||
var previewButton = UF.customFormButton( | |||
'wpUploadFormPreviewLicenseButton', // Customization ID | |||
'wpUploadPreviewLicense', // ID of button | |||
null, // Default text | |||
null, // Event handler, will be set below | |||
'wpPreviewLicenseUploadLbl' // default label ID | |||
); | |||
new Tooltip( | |||
previewButton, | |||
UF.get_license_preview, { | |||
activate: Tooltip.CLICK, | |||
deactivate: (UFHelp.help_close_imgs ? | |||
Tooltip.CLICK_ELEM : | |||
Tooltip.CLICK_TIP | Tooltip.CLICK_ELEM | Tooltip.LOSE_FOCUS), | |||
close_button: UFHelp.help_close_imgs, | |||
mode: Tooltip.FIXED, | |||
anchor: Tooltip.TOP_LEFT, | |||
fixed_offset: { | |||
x: 10, | |||
y: 5, | |||
dy: -1 | |||
}, | |||
open_delay: 0, | |||
hide_delay: 0 | |||
}, | |||
UFHelp.tooltip_styles); | |||
UF.license_button = previewButton; | |||
}, | |||
setup_license_preview: function () { | |||
var preview_panel = document.getElementById('mw-license-preview'); | |||
if (preview_panel) | |||
UFUtils.convert_td_div(preview_panel); | |||
// Change the license previewer to not overwrite our warning message, if any. | |||
if (window.wgUploadLicenseObj && wgUploadLicenseObj.showPreview && window.Tooltip) { | |||
wgUploadLicenseObj.showPreview = function (preview) { | |||
var preview_panel = document.getElementById('mw-license-preview'); | |||
if (!preview_panel) | |||
return; | |||
if (preview === UF.current_license_preview) | |||
return; | |||
UF.current_license_preview = preview; | |||
var contents = null; | |||
var new_state = false; | |||
if (!preview || !preview.length || preview === ' ') { | |||
contents = document.createTextNode('\xa0'); // a single | |||
new_state = false; | |||
} else { | |||
if (!UF.license_button) | |||
UF.create_license_button(); | |||
if (!UF.license_button_shown) | |||
contents = UF.license_button; | |||
new_state = true; | |||
} | |||
if (contents && new_state !== UF.license_button_shown) { | |||
if (preview_panel.firstChild) | |||
preview_panel.replaceChild(contents, preview_panel.firstChild); | |||
else | |||
preview_panel.appendChild(contents); | |||
} | |||
UF.license_button_shown = new_state; | |||
}; // end function | |||
} | |||
}, | |||
preview_tooltip: null, // Tooltip, if preview so configured | |||
do_preview: null, // Function to call to actually generate the preview | |||
addPreviewButton: function (handler) { | |||
// If we don't have Ajax, our preview won't work anyway. | |||
if (!window.XMLHttpRequest && !window.ActiveXObject) | |||
return; | |||
var uploadButton = document.getElementsByName('wpUpload')[0]; // Has no ID... | |||
// If we can't find the upload button, we don't know where to insert the preview button. | |||
if (!uploadButton) | |||
return; | |||
try { | |||
var previewButton = UF.customFormButton( | |||
'wpUploadFormPreviewButton', // Customization ID | |||
'wpUploadPreview', // ID of button | |||
null, // Default text | |||
UF.generatePreview, // Event handler | |||
'wpPreviewUploadLbl' // default label ID | |||
); | |||
if (UFConfig.page_preview_in_tooltip && window.Tooltip) { | |||
UF.preview_tooltip = new Tooltip( | |||
previewButton, | |||
UF.getPreview, { | |||
activate: Tooltip.NONE, // We'll show it manually in generatePreview. | |||
deactivate: Tooltip.CLICK_TIP, | |||
close_button: UFHelp.help_close_imgs, | |||
mode: Tooltip.FIXED, | |||
target: uploadButton, | |||
anchor: Tooltip.TOP_LEFT, | |||
fixed_offset: { | |||
x: 0, | |||
y: 5, | |||
dy: -1 | |||
}, | |||
open_delay: 0, | |||
hide_delay: 0 | |||
}, | |||
UFHelp.tooltip_styles); | |||
} | |||
UF.do_preview = handler; | |||
previewButton.setAttribute('style', 'margin-left:0.5em;'); | |||
var hotKey = 'p'; | |||
previewButton.setAttribute('accesskey', hotKey); | |||
if (!(/\[\w+\]$/.test(previewButton.title))) | |||
previewButton.title += ' [' + hotKey + ']'; | |||
if ($.fn.updateTooltipAccessKeys) { | |||
$('#t-print').remove(); // Not needed here and collides with same accesskey | |||
$(previewButton).updateTooltipAccessKeys(); | |||
} | |||
uploadButton.parentNode.insertBefore(previewButton, uploadButton.nextSibling); | |||
} catch (ex) {} | |||
}, | |||
getOwnWorkAuthor: function () { | |||
if (typeof UFConfig.ownwork_author === 'string' && | |||
UFConfig.ownwork_author.search(/\S/) >= 0) { | |||
// It's a non-empty string | |||
return UFConfig.ownwork_author; | |||
} else { | |||
return '[[User:' + mw.config.get('wgUserName') + '|]]'; | |||
} | |||
}, | |||
getOwnWorkSource: function () { | |||
var text = UFUI.getLabel('wpOwnWorkUploadLbl', true); | |||
var result = null; | |||
try { | |||
// Must have a text node. | |||
while (text && text.nodeType !== Node.TEXT_NODE) | |||
text = text.firstChild; | |||
if (text) | |||
result = text.data.replace(/^\s+/, '').replace(/\s+$/, ''); | |||
} catch (ex) { | |||
result = null; | |||
} | |||
if (!result) | |||
result = '{{own}} ' + UF.getOwnWorkAuthor(); | |||
return result; | |||
}, | |||
customFormButton: function (ui_id, id, defaultText, handler, defaultId) { | |||
function getButtonSpan(container, idx) { | |||
if (!container) | |||
return null; | |||
var spans = container.getElementsByTagName('span'); | |||
var span = null; | |||
if (!spans || spans.length <= idx) { | |||
// No spans... if idx is zero, try simply to take the first text node within container. | |||
if (!idx) | |||
span = container; | |||
} else { | |||
span = spans[idx]; | |||
} | |||
// Ok, let's see if we have some text... | |||
while (span && span.nodeType !== Node.TEXT_NODE) | |||
span = span.firstChild; | |||
if (span) | |||
return span.data.replace(/^\s+/, '').replace(/\s+$/, ''); | |||
return null; | |||
} | |||
function getDefault(defaultText, defaultId) { | |||
if (!defaultText) { | |||
if (defaultId) { | |||
defaultText = UFUI.getLabel(defaultId, true); | |||
// Must have a text node | |||
while (defaultText && defaultText.nodeType !== Node.TEXT_NODE) | |||
defaultText = defaultText.firstChild; | |||
if (defaultText) | |||
defaultText = defaultText.data.replace(/^\s+/, '').replace(/\s+$/, ''); | |||
} else { | |||
defaultText = 'X'; | |||
} // Hmmm... a serious misconfiguration | |||
} | |||
return defaultText; | |||
} | |||
var button = null, | |||
imgs = null; | |||
button = UFUI.getEntry(ui_id, 'uiElements', UFUI.internalLanguage); | |||
if (!button) | |||
button = UFUI.getEntry(ui_id, 'uiElements'); | |||
if (button) | |||
imgs = button.getElementsByTagName('img'); | |||
if (!imgs || !imgs.length || window.Buttons === undefined) { | |||
var buttonText = getButtonSpan(button, 0); | |||
if (!buttonText) | |||
buttonText = getDefault(defaultText, defaultId); | |||
var alternateText = getButtonSpan(button, 1); | |||
button = document.createElement('input'); | |||
button.setAttribute('id', id); | |||
button.setAttribute('name', id); | |||
button.type = 'button'; | |||
button.value = buttonText; | |||
if (alternateText) | |||
button.title = alternateText; | |||
button.onclick = handler; | |||
} else { | |||
button = Buttons.makeButton(imgs, id, handler); | |||
} | |||
return button; | |||
}, | |||
the_form: null, | |||
// If a needed script that is included hasn't loaded yet, we try at most install_max_attempts | |||
// times install_delay. If it then still has not loaded, we install all the same, and the | |||
// setup routine will have to deal with it. (Note that script loading is asynchronous!) | |||
install_delay: 400, // Milliseconds | |||
installAttempts: 0, | |||
install_max_attempts: 6, // maximum delay 2.4s | |||
reallyInstall: function (force_basic) { | |||
if (this.installAttempts < this.install_max_attempts && | |||
(!window.LanguageHandler || !window.UIElements || !window.Tooltip)) { | |||
// Add needed scripts in the condition above. | |||
window.setTimeout(function () { | |||
UF.reallyInstall(force_basic); | |||
}, this.install_delay); | |||
} else { | |||
UFUI.sanitizeUserLanguage(); | |||
var useBasic = force_basic || !!UFConfig.forcebasic || UFUI.isExperienced; | |||
if (useBasic && !force_basic) { | |||
// Only for autoconfirmed users! | |||
var is_auto = false; | |||
var userGroups = mw.config.get('wgUserGroups'); | |||
if (userGroups) { | |||
for (var i = 0; i < userGroups.length && !is_auto; i++) | |||
is_auto = userGroups[i] === 'autoconfirmed'; | |||
} | |||
if (!is_auto) | |||
useBasic = false; | |||
} | |||
try { | |||
UFHelp.precreate_tooltip_closer(); | |||
this.setFileExtensions(); | |||
if (useBasic || | |||
document.URL.indexOf('uploadformstyle=basic') > 0 || | |||
document.URL.search(/uselang=(\w|-)*fromwikimedia/) > 0) { | |||
// The fromwikimedia forms are special enough to warrant a special setup. | |||
UploadFormBasic.setup(!force_basic); | |||
} else { | |||
UploadFormFull.setup(); | |||
} | |||
this.setup_error_display(); | |||
UFHelp.setupHelp(this.isReupload); | |||
if (!this.isReupload) | |||
UFFixes.fixAutocompletion(); | |||
this.setupOverwriteMsg(); | |||
// Handle the "Upload new version" links, these have &wpDestFile=... in the URL, which | |||
// defeats overwrite detection. Because someone might construct such a URL manually | |||
// *not* actually overwriting an existing file, we still do the check: | |||
if (!this.isReupload) | |||
this.check_initial_dest_file(); | |||
} catch (ex) { | |||
if (console && console.warn) | |||
console.warn(ex); | |||
else | |||
mw.log.warn(ex); | |||
// Not good at all. Something went badly wrong. If we have already modified the form, | |||
// the best thing is probably to reload and make sure we don't try again: | |||
if (this.formModified) { | |||
var reloadURL = document.URL; | |||
reloadURL += (reloadURL.indexOf('?') > 0) ? '&' : '?'; | |||
window.location.href = reloadURL + 'uploadformstyle=plain'; | |||
} | |||
} | |||
// not needed at beginning | |||
importScript('MediaWiki:TextCleaner.js'); | |||
$.when(mw.loader.using('ext.gadget.HotCat'), $.ready) | |||
.then(this.setup_hotcat_label); | |||
this.removeSpinner(); | |||
} | |||
this.installAttempts++; | |||
}, | |||
removeSpinner: function () { | |||
// Installed on ImprovedUploadForm.js | |||
if ($.removeSpinner) $.removeSpinner('UploadLoadingSpinner'); | |||
}, | |||
install: function () { | |||
if (UF.isInstalled || // Do this only once per page! | |||
document.URL.indexOf('uploadformstyle=plain') > 0 || // We're disabled | |||
// Also don't do anything if we're not on an upload form. | |||
mw.config.get('wgCanonicalNamespace') !== 'Special' || | |||
mw.config.get('wgCanonicalSpecialPageName') !== 'Upload') | |||
return UF.removeSpinner(); | |||
var form = document.getElementById('upload') || document.getElementById('mw-upload-form'); | |||
var originalDesc = document.getElementById('wpUploadDescription'); | |||
if (!form || !originalDesc) | |||
return; // Oops. Not good: bail out; don't do anything. (then there should be also no spinner) | |||
var reupload = document.getElementById('wpForReUpload'); | |||
var destFile = document.getElementById('wpDestFile'); | |||
if (reupload) { | |||
UF.isReupload = !!reupload.value; | |||
} else { | |||
UF.isReupload = destFile && (destFile.disabled || destFile.readOnly); | |||
$(form).append($('<input type="hidden" name="wpChangeTags" value="OUploadForm">')); | |||
} | |||
if (destFile && !!destFile.disabled) { | |||
destFile.readOnly = true; | |||
destFile.disabled = false; | |||
} | |||
if (destFile && UF.isReupload) { | |||
destFile.onkeyup = function (/* e */) {}; | |||
destFile.onchange = function (/* e */) {}; | |||
} | |||
// Use the basic form if the description was set *initially*, or if it's a re-upload, or if it's a special | |||
// form | |||
var useBasic = (originalDesc.defaultValue && originalDesc.defaultValue.length) || | |||
UF.isReupload || | |||
document.URL.indexOf('uselang=nlwikilovesmonuments') > 0; | |||
UF.the_form = form; | |||
if (document.URL.indexOf('debug=true') > 0) | |||
UF.debug = true; | |||
UF.reallyInstall(useBasic); | |||
}, | |||
check_initial_dest_file: function () { | |||
var destFile = document.getElementById('wpDestFile'); | |||
if (destFile && destFile.value && destFile.value.length && | |||
wgUploadWarningObj && wgUploadWarningObj.keypress instanceof Function) | |||
wgUploadWarningObj.keypress(); | |||
}, | |||
errorMsgs: null, | |||
warning_pushed: false, | |||
display_errors: function () { | |||
// Give user feedback about what is not ok. | |||
var myWarning = document.getElementById('wpUploadVerifyWarning'); | |||
if (!myWarning) { | |||
// Find the upload button | |||
var uploadButton = document.getElementsByName('wpUpload'); | |||
var warningBox = null; | |||
if (uploadButton) | |||
uploadButton = uploadButton[0]; | |||
if (!uploadButton) { | |||
warningBox = document.getElementById('wpDestFile-warning'); | |||
if (!warningBox) | |||
return; | |||
// We just have the field colors to indicate errors... | |||
} | |||
myWarning = document.createElement('div'); | |||
myWarning.style.border = '1px #F00 solid'; | |||
myWarning.style.backgroundColor = UF.errorColor; | |||
myWarning.style.padding = '0.5em'; | |||
myWarning.style.marginTop = '0.5em'; | |||
myWarning.style.marginBottom = '0.5em'; | |||
myWarning.setAttribute('id', 'wpUploadVerifyWarning'); | |||
myWarning.setAttribute('width', '100%'); | |||
myWarning.style.display = 'none'; | |||
if (uploadButton) | |||
uploadButton.parentNode.insertBefore(myWarning, uploadButton); | |||
else | |||
warningBox.parentNode.insertBefore(myWarning, warningBox.nextSibling); | |||
} | |||
// Now collect all the error messages into one div. | |||
var msgs = document.createElement('ul'); | |||
msgs.style.paddingLeft = '1.0em'; | |||
msgs.style.marginLeft = '0'; | |||
for (var i = 0; i < UF.errorMsgs.length; i++) { | |||
var msg = UFUI.getErrorMsg(UF.errorMsgs[i]); | |||
if (msg) { | |||
var li = document.createElement('li'); | |||
li.appendChild(msg); | |||
msgs.appendChild(li); | |||
} | |||
} | |||
UF.errorMsgs = null; | |||
// And then display the messages | |||
if (myWarning.firstChild) | |||
myWarning.replaceChild(msgs, myWarning.firstChild); | |||
else | |||
myWarning.appendChild(msgs); | |||
myWarning.style.display = 'block'; | |||
}, | |||
call_onsubmit: function (evt) { | |||
var doSubmit = true; | |||
if (UF.oldOnSubmit) { | |||
if (typeof UF.oldOnSubmit === 'string') | |||
doSubmit = eval(UF.oldOnSubmit); | |||
else if (UF.oldOnSubmit instanceof Function) | |||
doSubmit = UF.oldOnSubmit(evt); | |||
} | |||
return doSubmit; | |||
}, | |||
templates: [{ | |||
name: 'information', | |||
fields: ['description', 'date', 'source', 'author', 'permission', 'other versions'], | |||
extract: [3, 1, 0], | |||
desc_mandatory: true, | |||
regexp: null | |||
}, { | |||
name: 'painting', | |||
fields: ['Artist', 'Title', 'Year', 'Technique', 'Dimensions', 'Gallery', | |||
'Location', 'Notes', 'Source', 'Permission', | |||
'other_versions', 'Other versions'], | |||
extract: [0, 8, 7], | |||
desc_mandatory: false, | |||
regexp: null | |||
}, { | |||
name: 'flickr', | |||
fields: ['description', 'flickr_url', 'title', 'taken', 'photographer_url', | |||
'photographer', 'photographer_location', 'reviewer', 'permission'], | |||
extract: [[5, 4], 1, 0], | |||
desc_mandatory: true, | |||
regexp: null | |||
} | |||
], | |||
empty_template: function (name) { | |||
if (!name) | |||
return null; | |||
var test_name = name.toLowerCase(); | |||
for (var i = 0; i < UF.templates.length; i++) { | |||
if (UF.templates[i].name === test_name) { | |||
var result = '{{' + name; | |||
for (var j = 0; j < UF.templates[i].fields.length; j++) { | |||
result += '\n|' + UF.templates[i].fields[j] + '='; | |||
if (UFUI.isOwnWork && !i) { | |||
// Pre-fill some fields if we're on an own-work form and it's an | |||
// information-template | |||
switch (j) { | |||
case 1: // Date | |||
if (typeof UFConfig.ownwork_date === 'string' && | |||
UFConfig.ownwork_date.search(/\S/) >= 0) | |||
result += UF.clean(UFConfig.ownwork_date); | |||
break; | |||
case 2: // Source-field | |||
result += UF.clean(UF.getOwnWorkSource()); | |||
break; | |||
case 3: // Author | |||
result += UF.clean(UF.getOwnWorkAuthor()); | |||
break; | |||
// default: break; | |||
} // end switch | |||
} // end if information for ownWork | |||
} | |||
return result + '\n}}'; | |||
} | |||
} | |||
return null; | |||
}, | |||
extract_fields: function (desc, template_idx, list) { | |||
function get(desc, field, regexp) { | |||
var match_start = new RegExp('\\n\\s*\\| *' + field + ' *\\=', 'i'); | |||
var start = desc.match(match_start); | |||
if (!start) | |||
return null; | |||
var rest = desc.substring(start.index + start[0].length); | |||
var end = rest.search(regexp); | |||
if (end < 0) | |||
return rest; | |||
return rest.substring(0, end); | |||
} | |||
var result = list; | |||
var names = UF.templates[template_idx].fields; | |||
var extract = UF.templates[template_idx].extract; | |||
if (!UF.templates[template_idx].regexp) { | |||
// Build the regexp | |||
var regexp_str = '\\n\\s*(\\| *(' + names.join('|') + ') *\\=|\\}\\})'; | |||
UF.templates[template_idx].regexp = new RegExp(regexp_str); | |||
} | |||
for (var i = 0; i < extract.length; i++) { | |||
var txt = null; | |||
if (extract[i] instanceof Array) { | |||
// It's an array giving alternatives... | |||
var alternatives = extract[i]; | |||
for (var j = 0; j < alternatives.length; j++) { | |||
txt = get(desc, names[alternatives[j]], UF.templates[template_idx].regexp); | |||
if (txt && txt.search(/\S/) >= 0) | |||
break; | |||
// Non-empty: don't look further | |||
txt = null; | |||
} | |||
} else { | |||
txt = get(desc, names[extract[i]], UF.templates[template_idx].regexp); | |||
} | |||
if (txt) | |||
result[result.length] = txt; | |||
// Push one. | |||
// Don't use "if (txt)", it's false if the string is, but empty! | |||
} | |||
return result; | |||
}, | |||
split_description: function (desc) { | |||
if (!desc || !desc.length) return null; | |||
// Returns an array containing (in that order): | |||
// index of template, author, source, description | |||
for (var i = 0; i < UF.templates.length; i++) { | |||
var regexp = new RegExp('\\{\\{' + UF.templates[i].name + '\\s*(\\||\\n)'); | |||
var start = desc.toLowerCase().search(regexp); | |||
if (start >= 0) { | |||
var result = [i]; | |||
// Now try to extract the fields: | |||
return UF.extract_fields(desc.substring(start), i, result); | |||
} | |||
} | |||
return null; | |||
}, | |||
generatePreview: function (evt) { | |||
if (UF.preview_tooltip && | |||
UF.preview_tooltip.popup.style.display !== 'none' && | |||
UF.preview_tooltip.popup.style.display) | |||
UF.preview_tooltip.hide_now(null); | |||
else | |||
UF.do_preview(evt || window.event); | |||
}, | |||
outerHTML: function (node) { | |||
if (!node) | |||
return ''; | |||
if (node.nodeType === 3) | |||
return node.nodeValue; | |||
// Text node | |||
if (node.outerHTML) | |||
return node.outerHTML; | |||
var div = document.createElement('div'); | |||
div.style.display = 'none'; | |||
div.style.position = 'absolute'; | |||
div.appendChild(node); | |||
document.body.appendChild(div); | |||
var txt = div.innerHTML; | |||
document.body.removeChild(div); | |||
return txt; | |||
}, | |||
makePreview: function (description, is_overwrite) { | |||
if (is_overwrite) { | |||
UF.showPreview( | |||
'<div style="border:1px solid red; padding:0.5em;"><div class="previewnote">' + | |||
UF.outerHTML(UFUI.getErrorMsg('wpPreviewOverwriteError')) + | |||
'</div></div>'); | |||
} else { | |||
var text = '<div style="border:1px solid red;padding:0.5em;"><div class="previewnote">\n' + | |||
'{{MediaWiki:Previewnote/' + UFUI.userLanguage + '}}\n' + | |||
'</div>\n'; | |||
var license = document.getElementById('wpLicense'); | |||
var licenseText = null; | |||
if (license && license.selectedIndex > 0 && | |||
license.options[license.selectedIndex].value.length) | |||
licenseText = '{{' + license.options[license.selectedIndex].value + '}}'; | |||
if (licenseText) { | |||
text += '<h2>{{int:filedesc}}</h2>\n' + | |||
description + '\n' + | |||
'<h2>{{int:license-header}}</h2>\n' + | |||
licenseText; | |||
} else { | |||
text += description + '\n'; | |||
} | |||
// Add categories | |||
if (hotcat_get_state instanceof Function) { | |||
if ($('#catlinks').find('.hotcatlink').is(':hidden')) | |||
hotcat_close_form(); | |||
var hotcat_categories = hotcat_get_state(); | |||
if (hotcat_categories && hotcat_categories.length) { | |||
hotcat_categories = hotcat_categories.split('\n'); | |||
for (var i = 0; i < hotcat_categories.length; i++) { | |||
if (hotcat_categories[i] && hotcat_categories[i].length) | |||
text += '[[Category:' + hotcat_categories[i] + ']]'; | |||
} | |||
} | |||
} | |||
text += '</div>'; | |||
// Make the Ajax call | |||
var req; | |||
if (window.XMLHttpRequest) | |||
req = new window.XMLHttpRequest(); | |||
if (!req && window.ActiveXObject) { | |||
try { | |||
req = new window.ActiveXObject('Microsoft.XMLHTTP'); | |||
} catch (any) {} | |||
} | |||
if (!req) | |||
return; | |||
var button = document.getElementById('wpUploadPreview'); | |||
var page = document.getElementById('wpDestFile'); | |||
if (page) | |||
page = page.value; | |||
if ($.fn.injectSpinner) | |||
$(button).injectSpinner('wpUploadPreviewSpinner'); | |||
var uri = mw.config.get('wgServer') + (mw.util ? mw.util.wikiScript('api') : mw.config.get('wgScriptPath') + '/api.php'); | |||
var args = 'action=parse&pst&text=' + encodeURIComponent(text) + | |||
(page ? '&title=File:' + encodeURIComponent(page.replace(/ /g, '_')) : '') + | |||
'&prop=text|categories&format=json'; | |||
// "&pst" is "Pre-save transform": tilde replacement, pipe magic for links like [[foo|]]. | |||
// Don't use a callback directly, add the function call ourselves *after* the call, since | |||
// the API somehow resolves tildes to an IP number instead of the username if a callback | |||
// is used. C.f. https://bugzilla.wikimedia.org/show_bug.cgi?id=16616 | |||
// Apparently, that's a feature, not a bug... | |||
var request_length = uri.length + args.length + 1; | |||
if (request_length > 2000) { | |||
// Long URLs are problematic for GET requests | |||
req.open('POST', uri, true); | |||
req.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded'); | |||
} else { | |||
uri += '?' + args; | |||
args = null; | |||
req.open('GET', uri, true); | |||
} | |||
req.setRequestHeader('Pragma', 'cache=no'); | |||
req.setRequestHeader('Cache-Control', 'no-transform'); | |||
req.onreadystatechange = function () { | |||
if ($.removeSpinner) | |||
$.removeSpinner('wpUploadPreviewSpinner'); | |||
if (req.readyState !== 4 || req.status !== 200) | |||
return; | |||
// Add the "callback"... | |||
if (req.responseText) | |||
UF.jsonPreview(JSON.parse(req.responseText)); | |||
}; | |||
req.send(args); | |||
} | |||
}, | |||
jsonPreview: function (result) { | |||
if (result && result.parse && result.parse.text && result.parse.text['*']) { | |||
var txt = result.parse.text['*']; | |||
var categories = result.parse.categories; | |||
if (categories && categories.length) { | |||
// Add a mock-up of a category bar. We don't care about non-existing categories, and we | |||
// can't identify hidden categories. | |||
var catbar = '<div class="catlinks"><div id="mw-normal-catlinks">' + | |||
UF.outerHTML(UFUI.getLabel('wpCategoriesUploadLbl')); | |||
categories.sort( | |||
function (a, b) { | |||
var key_a = a['*'].toLowerCase(), | |||
key_b = b['*'].toLowerCase(); | |||
if (key_a < key_b) | |||
return -1; | |||
if (key_a > key_b) | |||
return 1; | |||
return 0; | |||
}); | |||
for (var i = 0; i < categories.length; i++) { | |||
var catname = categories[i]['*']; | |||
if (catname && catname.length) { | |||
if (i > 0) | |||
catbar += ' |'; | |||
catbar += ' <a href="/wiki/Category:' + encodeURI(catname) + '">' + | |||
catname.replace(/_/g, ' ') + '</a>'; | |||
} | |||
} | |||
catbar += '</div></div>'; | |||
// Now insert it into text. | |||
var end = txt.lastIndexOf('</div>'); | |||
txt = txt.substring(0, end) + catbar + '</div>'; | |||
} | |||
UF.showPreview(txt); | |||
} | |||
}, | |||
showPreview: function (result) { | |||
if (UF.preview_tooltip) { | |||
UF.preview_content = result; | |||
UF.preview_tooltip.show_tip(null, false); | |||
} else { | |||
var preview = document.getElementById('wpUploadPreviewDisplay'); | |||
if (!preview) { | |||
var before = document.getElementById('mw-upload-permitted'); | |||
if (!before || UFUtils.isChildOf(before, UF.the_form)) | |||
before = UF.the_form; | |||
if (!before) | |||
return; | |||
// Don't know where to insert preview display. Error message here? | |||
preview = document.createElement('div'); | |||
preview.setAttribute('id', 'wpUploadPreviewDisplay'); | |||
before.parentNode.insertBefore(preview, before); | |||
} | |||
try { | |||
preview.innerHTML = result; | |||
} catch (ex) { | |||
preview.innerHTML = ''; // Error message here instead? | |||
} | |||
preview.style.display = ''; // Show it | |||
} | |||
}, | |||
hidePreview: function () { | |||
if (UF.preview_tooltip) { | |||
UF.preview_tooltip.hide_now(null); | |||
} else { | |||
var preview = document.getElementById('wpUploadPreviewDisplay'); | |||
if (preview) | |||
preview.style.display = 'none'; | |||
} | |||
}, | |||
getPreview: function () { // Callback for the tooltip | |||
var div = document.createElement('div'); | |||
div.style.display = 'none'; | |||
document.body.appendChild(div); | |||
div.innerHTML = UF.preview_content; | |||
document.body.removeChild(div); | |||
div.style.fontSize = 'smaller'; | |||
div.style.display = ''; | |||
var wrapper = document.createElement('div'); | |||
wrapper.appendChild(div); | |||
return wrapper; | |||
}, | |||
licenses_regexp: /\{\{(self|pd|gfdl|cc|l?gpl|fal|cecill|attribution|copyrighted free use|SOlicence|geograph|UN map|BArch-License|Apache)/i, | |||
user_license_regexp: new RegExp('\\{\\{[Ss]ubst:[Uu]ser:' + | |||
(mw.config.get('wgUserName') || 'null').replace(/([\\^$.?*+()[\]|{}])/g, '\\$1') + | |||
'/'), | |||
has_license: function (fields) { | |||
if (!fields || !fields.length) | |||
return false; | |||
for (var i = 0; i < fields.length; i++) { | |||
if (fields[i]) { | |||
if (typeof (fields[i]) === 'string') { | |||
if (fields[i].search(UF.licenses_regexp) >= 0) | |||
return true; | |||
} else { | |||
if (fields[i].value.search(UF.licenses_regexp) >= 0) | |||
return true; | |||
} | |||
} | |||
} | |||
for (var j = 0; j < fields.length; j++) { | |||
if (fields[j]) { | |||
if (typeof (fields[j]) === 'string') { | |||
if (fields[j].search(UF.user_license_regexp) >= 0) | |||
return true; | |||
} else { | |||
if (fields[j].value.search(UF.user_license_regexp) >= 0) | |||
return true; | |||
} | |||
} | |||
} | |||
return false; | |||
}, | |||
addAfterField: function (elem_id, element) { | |||
if (!element) | |||
return; | |||
var elem = document.getElementById(elem_id); | |||
if (!elem) | |||
return; | |||
// Find enclosing table cell. | |||
while (elem && elem.nodeName.toLowerCase() !== 'td') | |||
elem = elem.parentNode; | |||
if (!elem) | |||
return; | |||
var container = document.createElement('div'); | |||
container.style.fontSize = 'smaller'; | |||
container.appendChild(element); | |||
elem.appendChild(container); | |||
}, | |||
old_overwrite_warning: null, | |||
setupOverwriteMsg: function () { | |||
if (!window.wgUploadWarningObj || !wgUploadWarningObj.setWarning) | |||
return; | |||
var msg = document.createElement('div'); | |||
msg.id = 'wpUploadFormScriptOverwriteWarning'; | |||
msg.style.display = 'none'; | |||
msg.style.color = 'red'; | |||
msg.appendChild(UFUI.getErrorMsg('wpPreviewOverwriteError')); | |||
UF.addAfterField('wpDestFile', msg); | |||
UF.old_overwrite_warning = wgUploadWarningObj.setWarning; | |||
wgUploadWarningObj.setWarning = UF.overwriteMsg; | |||
}, | |||
overwriteMsg: function (warning) { | |||
if (!UF.old_overwrite_warning || UF.isReupload) | |||
return; | |||
// Make sure that 'this' is set to 'wgUploadWarningObj' in the call below! | |||
UF.old_overwrite_warning.apply(wgUploadWarningObj, [warning]); | |||
var is_overwrite = UF.isOverwrite(); | |||
var my_overwrite_warning = document.getElementById('wpUploadFormScriptOverwriteWarning'); | |||
if (my_overwrite_warning) | |||
my_overwrite_warning.style.display = (is_overwrite ? '' : 'none'); | |||
UF.set_fields_enabled( | |||
!is_overwrite, | |||
['wpUploadFile', 'wpUploadFileURL', 'wpDestFile', 'wpUploadDescription', 'wpAdditionalInfo', | |||
'wpLicense', 'wpWatchthis', 'wpIgnoreWarning', 'wpUpload']); | |||
}, | |||
isOverwrite: function () { | |||
if (document.getElementById('wpUploadWarningFileexists')) | |||
return true; | |||
var destfileWarning = document.getElementById('wpDestFile-warning'); | |||
if (!destfileWarning) | |||
return false; | |||
var destFile = document.getElementById('wpDestFile'); | |||
if (!destFile || !destFile.value) | |||
return false; | |||
var lks = destfileWarning.getElementsByTagName('a'); | |||
if (!lks || !lks.length) | |||
return false; | |||
// Trimmed, blanks replaced by underscores, first character capitalized | |||
var fn1 = destFile.value.replace(/^\s\s*/, '').replace(/\s\s*$/, '').replace(/ /g, '_'); | |||
fn1 = fn1.substr(0, 1).toUpperCase() + fn1.substring(1); | |||
var fn0 = 'Image:' + fn1; | |||
fn1 = 'File:' + fn1; | |||
var script = mw.config.get('wgScript'); | |||
var server = mw.config.get('wgServer'); | |||
for (var i = 0; i < lks.length; i++) { | |||
var href = lks[i].getAttribute('href'); | |||
if (!href || lks[i].className === 'new') | |||
continue; | |||
if (!href.indexOf(script) || !href.indexOf(server + script)) { | |||
var m = /[&?]title=([^&]*)/.exec(href); | |||
if (m && m.length > 1) | |||
href = m[1]; | |||
else | |||
href = null; | |||
} else { | |||
var prefix = mw.config.get('wgArticlePath').replace('$1', ''); | |||
if (href.indexOf(prefix)) | |||
prefix = server + prefix; | |||
// Fully expanded URL? | |||
if (!href.indexOf(prefix)) | |||
href = href.substring(prefix.length); | |||
else | |||
href = null; | |||
} | |||
if (!href) | |||
continue; | |||
href = decodeURIComponent(href).replace(/ /g, '_'); | |||
if (href === fn1 || href === fn0) | |||
return true; | |||
} | |||
return false; | |||
}, | |||
allowedFileTypes: null, | |||
forbiddenFileTypes: null, | |||
badFileNames: /^(test|image|img|bild|example|(dsc|img)?(\s|_|-)*|\d{10}(\s|_|-)[0123456789abcdef]{10}(\s|_|-)[a-z])$/i, | |||
// Filenames that have only components (separated by periods) that fully match this regexp | |||
// are considered illegal. The second-but-last one catches DSC01234, or DSC_01234, or | |||
// DSC_012_34 or also filenames conatining only digits and non-alphanumeric characters. | |||
// The last catches Flickr's raw filenames. How to relax that last expression without catching | |||
// too many legit file names? | |||
// Matching is case-insensitive. | |||
extractFileExtensions: function (div) { | |||
var list = null; | |||
// Get a mw-upload-permitted or mw-upload-prohibited div, extracts all extensions listed | |||
var txt = div; | |||
while (txt && txt.nodeType !== 3) | |||
txt = txt.lastChild; | |||
if (!txt) | |||
return null; | |||
// Try to figure out which comma to use (localizeable through MediaWiki:Comma-separator!) | |||
if (txt.data.indexOf(',') >= 0) { // Standard | |||
txt = txt.data.split(','); | |||
} else if (txt.data.indexOf('،') >= 0) { // Arabic etc. | |||
txt = txt.data.split('،'); | |||
} else if (txt.data.indexOf('、') >= 0) { // Chinese | |||
txt = txt.data.split('、'); | |||
} else { | |||
return null; | |||
} | |||
if (!txt || !txt.length) | |||
return null; | |||
for (var i = 0; i < txt.length; i++) { | |||
var match = /(\w+)\W*$/.exec(txt[i]); | |||
if (match) { | |||
match = match[1].toLowerCase(); // The extension | |||
if (!list) | |||
list = {}; | |||
list[match] = true; | |||
} | |||
} | |||
return list; | |||
}, | |||
setFileExtensions: function () { | |||
var fileExts = mw.config.get('wgFileExtensions'); | |||
if (fileExts) { // New as of 2009-09-17 | |||
UF.allowedFileTypes = {}; | |||
for (var i = 0; i < fileExts.length; i++) | |||
UF.allowedFileTypes[fileExts[i]] = true; | |||
UF.forbiddenFileTypes = null; | |||
return; | |||
} | |||
UF.allowedFileTypes = UF.extractFileExtensions(document.getElementById('mw-upload-permitted')); | |||
UF.forbiddenFileTypes = UF.extractFileExtensions(document.getElementById('mw-upload-prohibited')); | |||
if (UF.allowedFileTypes) { | |||
// Alternate OGG extensions | |||
if (UF.allowedFileTypes.ogg) { | |||
if (!UF.forbiddenFileTypes || !UF.forbiddenFileTypes.ogv) | |||
UF.allowedFileTypes.ogv = true; | |||
if (!UF.forbiddenFileTypes || !UF.forbiddenFileTypes.oga) | |||
UF.allowedFileTypes.oga = true; | |||
if (!UF.forbiddenFileTypes || !UF.forbiddenFileTypes.ogx) | |||
UF.allowedFileTypes.ogx = true; | |||
} | |||
// OpenDoc extensions (are these needed?) | |||
if (!UF.forbiddenFileTypes || !UF.forbiddenFileTypes.sxi) | |||
UF.allowedFileTypes.sxi = true; | |||
if (!UF.forbiddenFileTypes || !UF.forbiddenFileTypes.sxc) | |||
UF.allowedFileTypes.sxc = true; | |||
if (!UF.forbiddenFileTypes || !UF.forbiddenFileTypes.sxd) | |||
UF.allowedFileTypes.sxd = true; | |||
if (!UF.forbiddenFileTypes || !UF.forbiddenFileTypes.sxw) | |||
UF.allowedFileTypes.sxw = true; | |||
// PDF (allowed, but may be hidden in the interface) | |||
if (!UF.forbiddenFileTypes || !UF.forbiddenFileTypes.pdf) | |||
UF.allowedFileTypes.pdf = true; | |||
} | |||
}, | |||
checkFileExtension: function (ext, presence_only) { | |||
if (presence_only) { | |||
return (UF.allowedFileTypes && UF.allowedFileTypes[ext] === true) || | |||
(UF.forbiddenFileTypes && UF.forbiddenFileTypes[ext] === true); | |||
} | |||
return (!UF.allowedFileTypes || UF.allowedFileTypes[ext] === true) && | |||
(!UF.forbiddenFileTypes || UF.forbiddenFileTypes[ext] !== true); | |||
}, | |||
verifyFileName: function (filename) { | |||
if (!filename) { | |||
UF.errorMsgs.push('wpNoFilenameError'); | |||
return false; | |||
} | |||
if (filename.search(/(https?|file|ftp):\/\//i) >= 0) { | |||
UF.errorMsgs.push('wpHttpFilenameError'); | |||
return false; | |||
} | |||
var ok = true; | |||
// Don't allow slashes | |||
if (filename.indexOf('/') >= 0) { | |||
UF.errorMsgs.push('wpNoSlashError'); | |||
ok = false; | |||
} | |||
// Check for double extensions | |||
var fn = filename.split('.'); | |||
if (fn.length < 2 || !fn[fn.length - 1].length) { | |||
UF.errorMsgs.push('wpNoExtensionError'); | |||
ok = false; | |||
} | |||
// Check extension | |||
var nof_extensions = 0; | |||
if (fn.length >= 2) { | |||
nof_extensions++; | |||
if (UF.checkFileExtension(fn[fn.length - 1].toLowerCase())) { | |||
// It's ok, check for double extension | |||
if (fn.length > 2) { | |||
if (UF.checkFileExtension(fn[fn.length - 2].toLowerCase(), true)) { | |||
nof_extensions++; | |||
UF.errorMsgs.push('wpDoubleExtensionError'); | |||
ok = false; | |||
} | |||
} | |||
} else { | |||
UF.errorMsgs.push('wpIllegalExtensionError'); | |||
ok = false; | |||
} | |||
} | |||
// Check for allowed file name | |||
var one_ok = false; | |||
for (var i = 0; i < fn.length - nof_extensions && !one_ok; i++) { | |||
if (fn[i].length && fn[i].search(UF.badFileNames) < 0) | |||
one_ok = true; | |||
} | |||
if (!one_ok) { | |||
UF.errorMsgs.push('wpNondescriptFilenameError'); | |||
ok = false; | |||
} | |||
return ok; | |||
}, | |||
cleaner: null, | |||
clean: function (input) { | |||
if (!UF.cleaner) { | |||
// Because of asynchronous script loading, we need to check whether the TextCleaner is | |||
// already defined. If not, just return the input. | |||
if (window.TextCleaner && TextCleaner.sanitizeWikiText instanceof Function) | |||
UF.cleaner = TextCleaner.sanitizeWikiText; | |||
} | |||
if (UF.cleaner && input && typeof input === 'string') | |||
return UF.cleaner(input, true); | |||
else | |||
return input; | |||
}, | |||
resetBg: function (e) { | |||
e = e || window.event; // W3C, IE | |||
return UF.verifyMandatoryField(e.target || e.srcElement); | |||
}, | |||
verifyMandatoryField: function (node, handler) { | |||
if (!node) | |||
return true; | |||
try { | |||
if (!node.value || | |||
node.value.search(/\S/) < 0 || | |||
handler && handler instanceof Function && handler.length === 1 && | |||
!handler(node.value)) { | |||
// No value set, or a handler was given and it is a function taking one parameter, and | |||
// it returned false | |||
var isError = node.id !== 'wpPermission'; | |||
if (!isError) { | |||
var licenseField = document.getElementById('wpLicense'); | |||
// Careful here. The fromwikimedia forms appear not to have a license selector! | |||
isError = !licenseField || !licenseField.selectedIndex; | |||
} | |||
if (isError) { | |||
node.style.backgroundColor = UF.errorColor; | |||
if (!UF.warning_pushed) { | |||
if (UF.errorMsgs) | |||
UF.errorMsgs.push('wpUploadWarningError'); | |||
UF.warning_pushed = true; | |||
} | |||
return false; | |||
} | |||
} | |||
} catch (ex) { | |||
// Swallow the exception | |||
} | |||
try { | |||
node.style.backgroundColor = '#FFF'; | |||
} catch (some_error) { | |||
// Swallow. | |||
} | |||
return true; | |||
}, | |||
fixCategoryTransclusion: function (str) { | |||
return str.replace(/(\{\{)\s*(:?\s*[Cc]ategory\s*:[^|}]*(\|[^}]*)?)(\}\})/g, '[[$2]]'); | |||
} | |||
}; // end UF | |||
var UploadFormBasic = { | |||
onErrorForm: false, // True iff we're on a re-sent form (error case). | |||
setup: function (auto_fill) { | |||
// Special setup: don't use separate input fields; just verify the filename and that the | |||
// description isn't empty. | |||
var desc = document.getElementById('wpUploadDescription'); | |||
var previousForm = null; | |||
UF.previous_hotcat_state = null; | |||
if (!UF.isReupload && FormRestorer) { | |||
var currentDestFile = document.getElementById('wpDestFile'); | |||
var originalDestFile = null; | |||
if (currentDestFile) { | |||
currentDestFile = currentDestFile.value; | |||
originalDestFile = currentDestFile.defaultValue; | |||
} | |||
if (originalDestFile && originalDestFile.length) { | |||
// If originalDestFile was set to something, we're not on the original upload form but | |||
// on the re-sent form in error cases. | |||
UploadFormBasic.onErrorForm = true; | |||
} else if (currentDestFile && currentDestFile.length) { | |||
previousForm = FormRestorer.readForm('UploadFormBasic'); | |||
if (!previousForm && desc && desc.value && desc.value.length) { | |||
// Hmmm... IE sometimes cannot read the cookie (because it wasn't stored, due to some | |||
// strange security settings on some computers that I've been unable to track down). | |||
// If we're here, we have a target file name *and* a description: assume the description | |||
// comes from the browser's field value cache and make sure we don't overwrite it. | |||
auto_fill = false; | |||
} | |||
} | |||
if (previousForm) { | |||
var additionalData = previousForm[0].val; | |||
if (additionalData) { | |||
additionalData = additionalData.split('\t'); | |||
var previousFile = additionalData[0]; | |||
if (previousFile === currentDestFile) { | |||
if (additionalData.length >= 2) | |||
UF.previous_hotcat_state = additionalData[1]; | |||
} else { | |||
previousForm = null; | |||
} | |||
} | |||
} | |||
} | |||
UF.formModified = true; | |||
if (document.getElementById('wpLicense')) | |||
UF.setup_license_preview(); | |||
UF.oldOnSubmit = UF.the_form.onsubmit; | |||
UF.the_form.onsubmit = UploadFormBasic.submit; | |||
if (!UF.isReupload) | |||
UF.addPreviewButton(UploadFormBasic.preview); | |||
if (previousForm) { | |||
// Restore form values. | |||
if (desc) { | |||
var prev = UF.getPrevValue(previousForm, desc.id); | |||
if (prev) | |||
desc.value = prev; | |||
} | |||
if (UF.previous_hotcat_state && hotcat_set_state instanceof Function) { | |||
if ($('#catlinks').find('.hotcatlink').is(':hidden')) | |||
hotcat_close_form(); | |||
UF.previous_hotcat_state = hotcat_set_state(UF.previous_hotcat_state); | |||
} | |||
} else { | |||
if (!!UFConfig.autofill && auto_fill && !UF.isReupload) { | |||
if (desc) | |||
desc.value = UF.empty_template('Information'); | |||
} | |||
} | |||
if (desc && desc.value && desc.value.indexOf('{{Information') >= 0) { | |||
// Only hide the box in the Uploadtext if there is really an inormation-template in the | |||
// summary! | |||
var infobox = document.getElementById('Uploadtext-template-box'); | |||
if (infobox) | |||
infobox.style.display = 'none'; | |||
} | |||
}, | |||
submit: function (evt) { | |||
var overwrite = false; | |||
if (!UF.isReupload) | |||
overwrite = UF.isOverwrite(); | |||
if (!UploadFormBasic.verify(overwrite)) | |||
return false; | |||
if (!UF.isReupload) { | |||
var targetName = document.getElementById('wpDestFile'); | |||
if (targetName && targetName.value) { // Strip whitespace | |||
targetName.value = targetName.value.replace(/^\s\s*/, '').replace(/\s\s*$/, ''); | |||
} | |||
if (!UploadFormBasic.onErrorForm && | |||
FormRestorer && | |||
targetName && | |||
targetName.value) { | |||
var hotcat_state = null; | |||
if (hotcat_get_state instanceof Function) { | |||
if ($('#catlinks').find('.hotcatlink').is(':hidden')) | |||
hotcat_close_form(); | |||
hotcat_state = hotcat_get_state(); | |||
} | |||
// We already know that targetName.value is set! | |||
FormRestorer.saveForm( | |||
'UploadFormBasic', | |||
UF.the_form.id, | |||
targetName.value + (hotcat_state ? '\t' + hotcat_state : ''), | |||
';path=' + document.location.pathname + ';max-age=1800'); | |||
// Expire after half an hour. | |||
} | |||
} // end if (UF.isReupload) | |||
var desc = document.getElementById('wpUploadDescription'); | |||
var old_desc_value = desc.value; | |||
var doSubmit = UF.call_onsubmit(evt || window.event); | |||
if (!doSubmit) { | |||
desc.value = old_desc_value; | |||
} else { | |||
desc.value = UF.fixCategoryTransclusion(UF.clean(desc.value)); | |||
UF.hidePreview(); | |||
document.getElementById('wpDestFile').disabled = false; | |||
} | |||
return doSubmit; | |||
}, | |||
preview: function (/* e */) { | |||
var overwrite = UF.isOverwrite(); | |||
if (!UploadFormBasic.verify(overwrite)) | |||
return false; | |||
var desc = document.getElementById('wpUploadDescription'); | |||
UF.makePreview(UF.clean(desc.value), overwrite); | |||
return true; | |||
}, | |||
verify: function (overwrite) { | |||
var desc = document.getElementById('wpUploadDescription'); | |||
var ok = true; | |||
if (UF.isReupload) { | |||
// Only check that the description isn't empty | |||
if (UF.errorMsgs) | |||
delete UF.errorMsgs; | |||
UF.errorMsgs = []; | |||
UF.warning_pushed = false; | |||
if (!desc.value || desc.value.search(/\S/) < 0) { | |||
desc.style.backgroundColor = UF.errorColor; | |||
desc.onkeyup = UF.resetBg; | |||
UF.errorMsgs.push('wpReuploadNoSummaryError'); | |||
ok = false; | |||
} | |||
} else { | |||
if (!overwrite) { | |||
if (UF.errorMsgs) | |||
delete UF.errorMsgs; | |||
UF.errorMsgs = []; | |||
UF.warning_pushed = false; | |||
if (!UF.verifyMandatoryField(desc)) { | |||
desc.onkeyup = UF.resetBg; | |||
ok = false; | |||
} else { | |||
// We do have a non-empty description. Try to split it up and check that the fields for | |||
// author, source, and description are filled in. | |||
var fields = UF.split_description(desc.value); | |||
if (fields && fields.length === 4) { | |||
if ( | |||
!fields[1] || | |||
fields[1].search(/\S/) < 0 || // Author | |||
!fields[2] || | |||
fields[2].search(/\S/) < 0 // Source | |||
) { | |||
desc.style.backgroundColor = UF.errorColor; | |||
desc.onkeyup = UF.resetBg; | |||
if (!UF.warning_pushed) { | |||
if (UF.errorMsgs) | |||
UF.errorMsgs.push('wpUploadWarningError'); | |||
UF.warning_pushed = true; | |||
} | |||
ok = false; | |||
} | |||
if (UF.templates[fields[0]].desc_mandatory && | |||
(!fields[3] || fields[3].search(/\S/) < 0) // Description | |||
) { | |||
desc.style.backgroundColor = UF.errorColor; | |||
desc.onkeyup = UF.resetBg; | |||
UF.errorMsgs.push('wpNoDescriptionError'); | |||
ok = false; | |||
} | |||
} | |||
} | |||
// Try a license check | |||
var license = document.getElementById('wpLicense'); | |||
if (!license || !license.selectedIndex) { | |||
// There must be a license somewhere in the description. | |||
if (!UF.has_license([desc])) { | |||
var d = desc.value.replace(/\{\{\s*([Ii]nformation|[Pp]ainting|[Ff]lickr)\s*\n/g, ''); | |||
if (d.indexOf('{{') < 0) { | |||
// No transcludion that could provide a license either | |||
desc.style.backgroundColor = UF.errorColor; | |||
desc.onkeyup = UF.resetBg; | |||
if (!UF.warning_pushed) { | |||
if (UF.errorMsgs) | |||
UF.errorMsgs.push('wpUploadWarningError'); | |||
UF.warning_pushed = true; | |||
} | |||
ok = false; | |||
} | |||
// else assume it's ok. | |||
} | |||
} // end license check | |||
var targetName = document.getElementById('wpDestFile'); | |||
if (targetName) { | |||
// Trim leading and trailing whitespace | |||
targetName.value = targetName.value.replace(/^\s\s*/, '').replace(/\s\s*$/, ''); | |||
if (!UF.verifyFileName(targetName.value)) { | |||
targetName.style.backgroundColor = UF.errorColor; | |||
targetName.onkeyup = function (evt) { | |||
UF.resetBg(evt); | |||
if (wgUploadWarningObj && | |||
wgUploadWarningObj.keypress instanceof Function && | |||
!UF.isReupload) | |||
wgUploadWarningObj.keypress(); | |||
}; | |||
ok = false; | |||
} | |||
} | |||
} | |||
} // end if (reupload or not) | |||
if (!ok) { | |||
UF.hidePreview(); | |||
UF.display_errors(); | |||
} else { | |||
// It's ok: hide our warning box | |||
var myWarning = document.getElementById('wpUploadVerifyWarning'); | |||
if (myWarning) | |||
myWarning.style.display = 'none'; | |||
} | |||
return ok; | |||
} // end verify | |||
}; // end UploadFormBasic | |||
var UploadFormFull = { | |||
form_type: 0, // 0 - single desc field; 1 - one desc field per language | |||
field_state: null, // Will be initialized in setup below. | |||
multi_inputs: null, | |||
// If we're using several description fields, this is an array of objects | |||
pushMultiInput: function (sel, text) { | |||
if (!UploadFormFull.multi_inputs) { | |||
UploadFormFull.multi_inputs = [{ | |||
selector: sel, | |||
textfield: text | |||
} | |||
]; | |||
} else { | |||
UploadFormFull.multi_inputs[UploadFormFull.multi_inputs.length] = { | |||
selector: sel, | |||
textfield: text | |||
}; | |||
} | |||
var idx = UploadFormFull.multi_inputs.length; | |||
sel.id = 'wpLangSel' + idx; | |||
sel.name = sel.id; | |||
text.id = 'wpDescText' + idx; | |||
text.name = text.id; | |||
}, | |||
addDescField: function (content, lang, idx, storedForm) { | |||
var selector = LanguageHandler.getSelect(null, lang, UFUI.getLabel('wpUnknownLanguageUploadLbl', true)); | |||
// These style definitions are needed for IE, which otherwise creates excessively wide | |||
// selectors, pushing the main form to the right. | |||
selector.style.maxWidth = '12em'; | |||
selector.style.width = '12em'; | |||
selector.style.overflow = 'hidden'; | |||
var textfield = document.createElement('textarea'); | |||
textfield.setAttribute('rows', UFUtils.getHeight(UFConfig.description_height, 2, 6)); | |||
textfield.style.width = '100%'; | |||
UploadFormFull.pushMultiInput(selector, textfield); | |||
var newRow = content.insertRow(idx === null ? content.rows.length : idx); | |||
var firstCell = document.createElement('td'); | |||
firstCell.classList.add('mw-label'); | |||
firstCell.setAttribute('vAlign', 'top'); | |||
firstCell.appendChild(selector); | |||
var secondCell = document.createElement('td'); | |||
secondCell.classList.add('mw-input'); | |||
secondCell.setAttribute('vAlign', 'top'); | |||
secondCell.appendChild(textfield); | |||
newRow.appendChild(firstCell); | |||
newRow.appendChild(secondCell); | |||
if (storedForm) { | |||
var prev_idx = UF.getPrevValue(storedForm, selector.id); | |||
var prev_val = UF.getPrevValue(storedForm, textfield.id); | |||
if (prev_val !== null) | |||
textfield.value = prev_val; | |||
if (prev_idx !== null) { | |||
selector.options[selector.selectedIndex].selected = false; | |||
selector.options[prev_idx].selected = true; | |||
} | |||
} | |||
UploadFormFull.enableEdittools(textfield); | |||
}, | |||
addOneDescField: function (/* e */) { // onclick handler for the button | |||
var button = document.getElementById('wpUploadAddDescription'); | |||
var table_row = button.parentNode.parentNode; | |||
var idx = table_row.rowIndex; | |||
UploadFormFull.addDescField(table_row.parentNode, null, idx, null); | |||
}, | |||
addMultiDesc: function (table, idx, storedForm) { | |||
var i; | |||
// Add en and user language, if different | |||
var userLang = LanguageHandler.closestLanguage(UFUI.userLanguage); | |||
if (userLang === 'pt-br') | |||
userLang = 'pt'; | |||
// Per request from Portuguese and Brazilians | |||
var firstCell = document.createElement('td'); | |||
firstCell.classList.add('mw-label'); | |||
var secondCell = document.createElement('td'); | |||
var new_label = document.createElement('label'); | |||
new_label.id = 'wpDescLabel'; | |||
new_label.appendChild(UFUI.getLabel('wpDescUploadLbl')); | |||
firstCell.appendChild(new_label); | |||
var newRow = table.insertRow(idx); | |||
newRow.appendChild(firstCell); | |||
newRow.appendChild(secondCell); | |||
idx++; | |||
var added = false; | |||
if (storedForm) { | |||
// Maybe we had more... find 'wpLangSel1' | |||
var curr = 0; | |||
for (i = 1; i < storedForm.length; i++) { | |||
if (storedForm[i].id === 'wpLangSel1') { | |||
curr = i; | |||
break; | |||
} | |||
} | |||
if (curr > 0) { | |||
while (curr < storedForm.length && !storedForm[curr].id.indexOf('wpLangSel')) { | |||
UploadFormFull.addDescField(table, null, idx++, storedForm); | |||
added = true; | |||
curr++; | |||
if (curr < storedForm.length && !storedForm[curr].id.indexOf('wpDescText')) | |||
curr++; | |||
} | |||
} | |||
} // end if | |||
if (!added) { | |||
if (UFConfig.description_languages && | |||
UFConfig.description_languages instanceof Array && | |||
UFConfig.description_languages.length) { | |||
for (i = 0; i < UFConfig.description_languages.length; i++) { | |||
var lang = LanguageHandler.closestLanguage(UFConfig.description_languages[i]); | |||
UploadFormFull.addDescField(table, lang, idx++, storedForm); | |||
} | |||
} else { | |||
if (UFConfig.own_language_first) { | |||
if (userLang && userLang !== UFUI.defaultLanguage) | |||
UploadFormFull.addDescField(table, userLang, idx++, storedForm); | |||
UploadFormFull.addDescField(table, UFUI.defaultLanguage, idx++, storedForm); | |||
} else { | |||
UploadFormFull.addDescField(table, UFUI.defaultLanguage, idx++, storedForm); | |||
if (userLang && userLang !== UFUI.defaultLanguage) | |||
UploadFormFull.addDescField(table, userLang, idx++, storedForm); | |||
} | |||
} | |||
} | |||
// Now add a "+" button | |||
var additional = UF.customFormButton( | |||
'wpUploadFormAddDescButton', // Customization ID | |||
'wpUploadAddDescription', // ID of button | |||
'+', // Default text | |||
UploadFormFull.addOneDescField // Event handler | |||
); | |||
newRow = table.insertRow(idx++); | |||
firstCell = document.createElement('td'); | |||
secondCell = document.createElement('td'); | |||
secondCell.classList.add('mw-input'); | |||
secondCell.appendChild(additional); | |||
newRow.appendChild(firstCell); | |||
newRow.appendChild(secondCell); | |||
return idx; | |||
}, | |||
changeField: function (field_id) { // Callback for changeable field button | |||
function get_selection(field) { | |||
// Based on code from Jonas Raoni Soares Silva at http://jsfromhell.com/forms/selection | |||
// License: {{tl|attribution}} | |||
// Warning: simplified because we apply it only to an INPUT field. For TEXTAREAs, see the | |||
// URL given. | |||
if (field.selectionStart !== undefined) { | |||
return { | |||
start: field.selectionStart, | |||
end: field.selectionEnd | |||
}; | |||
} else if (field.createTextRange) { | |||
field.focus(); | |||
var s = document.selection.createRange(); | |||
if (s.parentElement() !== field) { | |||
return { | |||
start: 0, | |||
end: 0 | |||
}; | |||
} | |||
var r = field.createTextRange(); | |||
r.setEndPoint('EndToStart', s); | |||
return { | |||
start: r.text.length, | |||
end: r.text.length + s.text.length | |||
}; | |||
} | |||
return { | |||
start: 0, | |||
end: 0 | |||
}; | |||
} | |||
var field = document.getElementById(field_id); | |||
if (field.disabled) | |||
return; | |||
// Don't do anything if the field isn't enabled. | |||
var button = document.getElementById(field_id + '_Button'); | |||
var cell = field.parentNode; | |||
if (!field || !button || !cell) | |||
return; | |||
// Error message here? | |||
var newField = document.createElement('textarea'); | |||
var height = UFUtils.getHeight(UploadFormFull.field_state[field_id].height, 2, 4); | |||
newField.setAttribute('rows', height); | |||
newField.style.width = '100%'; | |||
newField.value = field.value; | |||
var sel = get_selection(field); | |||
var tab_idx = field.getAttribute('tabindex'); | |||
cell.removeChild(button); | |||
cell.replaceChild(newField, field); | |||
field.id = ''; | |||
field.onfocus = null; | |||
newField.id = field_id; | |||
newField.setAttribute('tabindex', tab_idx); | |||
UploadFormFull.enableEdittools(newField); | |||
// Restore the selection | |||
if (newField.setSelectionRange) { // e.g. khtml | |||
newField.setSelectionRange(sel.start, sel.end); | |||
} else if (newField.selectionStart !== undefined) { | |||
newField.selectionStart = sel.start; | |||
newField.selectionEnd = sel.end; | |||
} else if (newField.createTextRange) { // IE | |||
var new_selection = newField.createTextRange(); | |||
new_selection.move('character', sel.start); | |||
new_selection.moveEnd('character', sel.end - sel.start); | |||
new_selection.select(); | |||
} | |||
newField.focus(); | |||
UploadFormFull.field_state[field_id].height = height; | |||
}, | |||
enableEdittools: function (textfield) { | |||
// To be called on each dynamically added field to ensure the edit toolbar works there | |||
if (window.EditTools && EditTools.registerTextField instanceof Function) { | |||
// We have EditTools | |||
var buttons = document.getElementById('specialchars'); | |||
if (buttons && buttons.firstChild && buttons.firstChild.nodeName.toLowerCase() === 'select') { | |||
// EditTools is already set up: we have to add an onfocus handler ourselves | |||
$(textfield).focus(EditTools.registerTextField); | |||
} | |||
// Otherwise, EditTools will be set up later, and will catch this field, so we don't have | |||
// to do anything. | |||
} | |||
}, | |||
switch_intro_text: function () { | |||
// Set up the display of [[MediaWiki:Uploadtext]] | |||
var long_text = document.getElementById('wpUploadFormLongText'); | |||
var short_text = document.getElementById('wpUploadFormShortText'); | |||
if (long_text && short_text) { | |||
long_text.style.display = 'none'; | |||
if (UFUtils.isChildOf(long_text, short_text)) { | |||
// If long_text is a child of short_text, then short_text is already shown, and | |||
// long_text is just a part that isn't needed for the new upload form. Hence | |||
// we're done. | |||
return; | |||
} | |||
if (UFUtils.isChildOf(short_text, long_text)) { | |||
// If the short_text is within the long_text, we need to take it out; otherwise | |||
// it won't be shown. | |||
short_text.parentNode.removeChild(short_text); | |||
long_text.parentNode.insertBefore(short_text, long_text.nextSibling); | |||
} | |||
short_text.style.display = ''; | |||
} else { | |||
// Remove the redundant infobox in the uploadtext explanation. People should *not* | |||
// insert this template into description. | |||
var infobox = document.getElementById('Uploadtext-template-box'); | |||
if (infobox) | |||
infobox.style.display = 'none'; | |||
} | |||
}, | |||
set_hints: function () { | |||
UF.addAfterField('wpDestFile', UFUI.getHint('wpUploadFormDestFileHint')); | |||
UF.addAfterField('wpSource', UFUI.getHint('wpUploadFormSourceHint')); | |||
UF.addAfterField('wpAuthor', UFUI.getHint('wpUploadFormAuthorHint')); | |||
UF.addAfterField('wpDate', UFUI.getHint('wpUploadFormDateHint')); | |||
UF.addAfterField('wpPermission', UFUI.getHint('wpUploadFormPermissionHint')); | |||
UF.addAfterField('wpAdditionalInfo', UFUI.getHint('wpUploadFormAdditionalInfoHint')); | |||
UF.addAfterField('catlinks', UFUI.getHint('wpUploadFormCategoryHint')); | |||
}, | |||
setup: function () { | |||
function addField(table, idx, id, label, field, storedForm) { | |||
if (!label) | |||
label = UFUI.getLabel(id + 'UploadLbl'); | |||
var newRow = table.insertRow(idx); | |||
var firstCell = document.createElement('td'); | |||
firstCell.classList.add('mw-label'); | |||
var new_label = document.createElement('label'); | |||
new_label.htmlFor = id; | |||
new_label.appendChild(label); | |||
firstCell.appendChild(new_label); | |||
var secondCell = document.createElement('td'); | |||
secondCell.classList.add('mw-input'); | |||
field.setAttribute('name', id); | |||
field.setAttribute('id', id); | |||
secondCell.appendChild(field); | |||
newRow.appendChild(firstCell); | |||
newRow.appendChild(secondCell); | |||
var prev_value = UF.getPrevValue(storedForm, id); | |||
if (prev_value) | |||
field.value = prev_value; | |||
UploadFormFull.enableEdittools(field); | |||
} | |||
function addInput(table, idx, id, label, width, storedForm) { | |||
var newField = document.createElement('input'); | |||
newField.setAttribute('type', 'text'); | |||
newField.setAttribute('size', String(width)); | |||
addField(table, idx, id, label, newField, storedForm); | |||
UploadFormFull.enableEdittools(newField); | |||
return newField; | |||
} | |||
function addChangeableField(height, table, idx, id, label, width, storedForm) { | |||
var newField = null; | |||
var field_id = 'wp' + id; | |||
if (!height) | |||
height = UFUtils.getHeight(UploadFormFull.field_state[field_id].height, 1, 4); | |||
if (height > 1) { | |||
newField = document.createElement('textarea'); | |||
newField.setAttribute('rows', height); | |||
newField.style.width = '100%'; | |||
addField(table, idx, 'wp' + id, null, newField, storedForm); | |||
} else { | |||
newField = addInput(table, idx, field_id, null, 80, storedForm); | |||
var button = UF.customFormButton( | |||
'wpUploadForm' + id + 'Button', | |||
field_id + '_Button', | |||
'...', | |||
function () { | |||
UploadFormFull.changeField(field_id); | |||
}); | |||
newField.parentNode.insertBefore(button, newField.nextSibling); | |||
} | |||
UploadFormFull.field_state[field_id].height = height; | |||
UploadFormFull.enableEdittools(newField); | |||
} | |||
function setCheckBoxes(previousForm, boxes) { | |||
if (!boxes || !boxes.length || !previousForm) | |||
return; | |||
for (var i = 0; i < boxes.length; i++) { | |||
if (boxes[i]) { | |||
var prev_val = UF.getPrevValue(previousForm, boxes[i].id); | |||
if (prev_val) | |||
boxes[i].checked = prev_val; | |||
} | |||
} | |||
} | |||
// Init the field states. Cannot be done earlier, otherwise definitions in user's | |||
// monobook.js (or modern.js, or ...) won't be taken aboard. | |||
UploadFormFull.field_state = { | |||
wpSource: { | |||
height: UFConfig.source_field_size | |||
}, | |||
wpAuthor: { | |||
height: UFConfig.author_field_size | |||
} | |||
}; | |||
var previousForm = null; | |||
var previous_type = -1; // unknown | |||
var previous_fields = [0, 0]; | |||
UF.previous_hotcat_state = null; | |||
if (FormRestorer) { | |||
// We know that when we arrive here originally, wpDestFile.value is empty, as is | |||
// wpDestFile.defaultValue. If we entered something, submitted, and then come back, | |||
// modern browsers restore form entries, at least for the fields in the static XHTML. | |||
// wpDestFile is such a static field (it isn't added by Javascript), so if we have a | |||
// non-empty value here, we know that the form needs to restored. (But see the caveat | |||
// about IE and onload handling at the bottom of the file!) | |||
var currentDestFile = document.getElementById('wpDestFile'); | |||
if (currentDestFile) | |||
currentDestFile = currentDestFile.value; | |||
if (currentDestFile && currentDestFile.length) | |||
previousForm = FormRestorer.readForm('UploadForm'); | |||
if (previousForm) { | |||
var additionalData = previousForm[0].val; | |||
if (additionalData) { | |||
additionalData = additionalData.split('\t'); | |||
var previousFile = additionalData[1]; | |||
if (previousFile === currentDestFile) { | |||
previous_type = parseInt(additionalData[0], 10); | |||
previous_fields[0] = parseInt(additionalData[2], 10); | |||
previous_fields[1] = parseInt(additionalData[3], 10); | |||
if (additionalData.length >= 5) | |||
UF.previous_hotcat_state = additionalData[4]; | |||
} else { | |||
previousForm = null; | |||
} | |||
} | |||
} | |||
} | |||
var originalDesc = document.getElementById('wpUploadDescription'); | |||
var original_row = originalDesc.parentNode.parentNode; | |||
var table = original_row.parentNode; | |||
var original_idx = original_row.rowIndex; | |||
UF.formModified = true; | |||
originalDesc.setAttribute('id', ''); | |||
UF.oldOnSubmit = UF.the_form.onsubmit; | |||
UF.the_form.onsubmit = UploadFormFull.submit; | |||
table.deleteRow(original_idx); | |||
var idx = original_idx; | |||
// Insert source field | |||
var newField = null; | |||
addChangeableField(previous_fields[0], table, idx++, 'Source', null, 80, previousForm); | |||
addChangeableField(previous_fields[1], table, idx++, 'Author', null, 80, previousForm); | |||
addInput(table, idx++, 'wpDate', null, 80, previousForm); | |||
// Insert description field | |||
if (window.LanguageHandler === undefined || !previous_type) { | |||
// Basic setup | |||
newField = document.createElement('textarea'); | |||
newField.setAttribute('rows', UFUtils.getHeight(UFConfig.description_height, 6, 12)); | |||
newField.style.width = '100%'; | |||
// Do not name the new field 'wpUploadDescription', otherwise MediaWiki:Upload.js | |||
// might prefill it with an information template! | |||
addField(table, idx++, 'wpDesc', null, newField, previousForm); | |||
UploadFormFull.form_type = 0; | |||
} else { | |||
idx = UploadFormFull.addMultiDesc(table, idx, previousForm); | |||
UploadFormFull.form_type = 1; | |||
} | |||
addInput(table, idx++, 'wpOtherVersions', null, 80, previousForm); | |||
addInput(table, idx++, 'wpPermission', null, 80, previousForm); | |||
newField = document.createElement('textarea'); | |||
newField.setAttribute('rows', UFUtils.getHeight(UFConfig.additional_info_height, 2, 10)); | |||
newField.style.width = '100%'; | |||
// Work-around Firefox's "one additional line" bug | |||
addField(table, idx++, 'wpAdditionalInfo', null, newField, previousForm); | |||
// Add a preview button. | |||
UF.addPreviewButton(UploadFormFull.preview); | |||
// Correct tab indices. | |||
for (var i = 0; i < UF.the_form.length; i++) | |||
UF.the_form.elements[i].setAttribute('tabindex', String(i)); | |||
var license = document.getElementById('wpLicense'); | |||
// Change the license previewer to not cause a table re-layout | |||
if (license) { | |||
// These style definitions are because long option labels result in excessively wide | |||
// selectors, causing also the description fields to go beyond the right border of the | |||
// page. | |||
license.style.maxWidth = '100%'; | |||
license.style.width = '100%'; | |||
license.style.overflow = 'hidden'; | |||
} | |||
UF.setup_license_preview(); | |||
if (license) { | |||
var prev = UF.getPrevValue(previousForm, 'wpLicense'); | |||
if (prev) { | |||
try { | |||
license.options[license.selectedIndex].selected = false; | |||
license.options[prev].selected = true; | |||
} catch (ex) {} | |||
} | |||
} | |||
// Pre-fill in some cases | |||
if (UFUI.isOwnWork) { | |||
var src = document.getElementById('wpSource'); | |||
var author = document.getElementById('wpAuthor'); | |||
if (src && !src.value) | |||
src.value = UF.getOwnWorkSource(); | |||
if (author && !author.value) | |||
author.value = UF.getOwnWorkAuthor(); | |||
if (typeof UFConfig.ownwork_date === 'string' && | |||
UFConfig.ownwork_date.search(/\S/) >= 0) { | |||
var date = document.getElementById('wpDate'); | |||
if (date && !date.value) | |||
date.value = UFConfig.ownwork_date; | |||
} | |||
} | |||
if (previousForm) { | |||
setCheckBoxes( | |||
previousForm, | |||
[ | |||
document.getElementById('wpWatchthis'), | |||
document.getElementById('wpIgnoreWarning') | |||
]); | |||
} | |||
UploadFormFull.switch_intro_text(); | |||
// If HotCat is present, restore its state, too. | |||
if (UF.previous_hotcat_state && hotcat_set_state instanceof Function) { | |||
if ($('#catlinks').find('.hotcatlink').is(':hidden')) | |||
hotcat_close_form(); | |||
UF.previous_hotcat_state = hotcat_set_state(UF.previous_hotcat_state); | |||
} | |||
UploadFormFull.set_hints(); | |||
}, // end setup | |||
getDescText: function (basic) { | |||
var descText = ''; | |||
if (!UploadFormFull.multi_inputs) { | |||
var desc = document.getElementById('wpDesc'); | |||
if (desc && !desc.disabled) | |||
descText = UF.clean(desc.value); | |||
} else { | |||
for (var i = 0; i < UploadFormFull.multi_inputs.length; i++) { | |||
if (!UploadFormFull.multi_inputs[i].textfield.disabled) { | |||
var text = UploadFormFull.multi_inputs[i].textfield.value; | |||
var selector = UploadFormFull.multi_inputs[i].selector; | |||
var lang = selector.options[selector.selectedIndex].value; | |||
if (text) { | |||
text = UF.clean(text); | |||
if (descText.length) | |||
descText += '\n'; | |||
if (!basic && lang && lang !== 'unknown') { | |||
// This is Commons-specific! The tl-template is already used, the template for | |||
// Tagalog is tgl! | |||
if (lang === 'tl') | |||
lang = 'tgl'; | |||
descText += '{{' + lang + '|1=' + text + '}}'; | |||
} else { | |||
descText += text; | |||
} | |||
} | |||
} // end if !disabled | |||
} | |||
} | |||
var more_info = document.getElementById('wpAdditionalInfo'); | |||
if (!basic) { | |||
var date = document.getElementById('wpDate'); | |||
var src = document.getElementById('wpSource'); | |||
var author = document.getElementById('wpAuthor'); | |||
var other = document.getElementById('wpPermission'); | |||
var othervers = document.getElementById('wpOtherVersions'); | |||
descText = '{{Information\n' + | |||
'|description =' + descText + '\n' + | |||
'|date =' + (!date.disabled ? UF.clean(date.value) : '') + '\n' + | |||
'|source =' + (!src.disabled ? UF.clean(src.value) : '') + '\n' + | |||
'|author =' + (!author.disabled ? UF.clean(author.value) : '') + '\n' + | |||
((other && !other.disabled && other.value) ? | |||
'|permission =' + UF.clean(other.value) + '\n' : | |||
'') + | |||
((othervers && !othervers.disabled && othervers.value) ? | |||
'|other versions=' + UF.clean(othervers.value) + '\n' : | |||
'') + | |||
'}}\n'; | |||
} else { | |||
descText += '\n'; | |||
} | |||
// Append the additional info, if any | |||
if (more_info && !more_info.disabled && more_info.value) | |||
descText += UF.clean(more_info.value); | |||
return descText; | |||
}, | |||
submit: function (evt) { | |||
var overwrite = UF.isOverwrite(); | |||
if (!UploadFormFull.verify(overwrite)) | |||
return false; | |||
// Now put together an information-template | |||
var descText = UploadFormFull.getDescText(overwrite); | |||
var doSubmit = true; | |||
var targetName = document.getElementById('wpDestFile'); | |||
if (targetName && targetName.value) { // Strip whitespace | |||
targetName.value = targetName.value.replace(/^\s\s*/, '').replace(/\s\s*$/, ''); | |||
} | |||
var dummyDesc = document.getElementById('wpUploadDescription'); | |||
// Sometimes, we do restore from scratch, and sometimes, the browser manages to keep everything. | |||
// If so, we may have a wpUploadDescription from an earlier submission. Remove it. | |||
if (dummyDesc) | |||
dummyDesc.parentNode.removeChild(dummyDesc); | |||
if (FormRestorer && targetName && targetName.value) { | |||
var hotcat_state = null; | |||
if (hotcat_get_state instanceof Function) { | |||
if ($('#catlinks').find('.hotcatlink').is(':hidden')) | |||
hotcat_close_form(); | |||
hotcat_state = hotcat_get_state(); | |||
} | |||
// We already know that targetName.value is set! | |||
FormRestorer.saveForm( | |||
'UploadForm', | |||
UF.the_form.id, | |||
String(UploadFormFull.form_type) + | |||
'\t' + targetName.value + | |||
'\t' + UploadFormFull.field_state.wpSource.height + | |||
'\t' + UploadFormFull.field_state.wpAuthor.height + | |||
(hotcat_state ? '\t' + hotcat_state : ''), | |||
';path=' + document.location.pathname + ';max-age=1800'); | |||
// Expire after half an hour. | |||
} | |||
dummyDesc = document.createElement('textarea'); | |||
dummyDesc.setAttribute('rows', '6'); | |||
dummyDesc.setAttribute('cols', '80'); | |||
dummyDesc.style.display = 'none'; | |||
dummyDesc.setAttribute('name', 'wpUploadDescription'); | |||
dummyDesc.setAttribute('id', 'wpUploadDescription'); | |||
UF.the_form.appendChild(dummyDesc); | |||
dummyDesc.value = UF.fixCategoryTransclusion(descText); | |||
doSubmit = UF.call_onsubmit(evt || window.event); | |||
if (!doSubmit) { | |||
// Oops. We actually don't submit. Remove the hidden field | |||
UF.the_form.removeChild(dummyDesc); | |||
} else { | |||
UF.hidePreview(); | |||
document.getElementById('wpDestFile').disabled = false; | |||
document.getElementById('wpEditToken').disabled = false; | |||
} | |||
return doSubmit; | |||
}, | |||
preview: function (/* e */) { | |||
var overwrite = UF.isOverwrite(); | |||
if (!UploadFormFull.verify(overwrite)) | |||
return false; | |||
UF.makePreview(UploadFormFull.getDescText(overwrite), overwrite); | |||
return true; | |||
}, | |||
verify: function (overwrite) { | |||
var src = document.getElementById('wpSource'); | |||
var author = document.getElementById('wpAuthor'); | |||
// var date = document.getElementById( 'wpDate' ); | |||
var other = document.getElementById('wpPermission'); | |||
// var othervers = document.getElementById( 'wpOtherVersions' ); | |||
var moreInfo = document.getElementById('wpAdditionalInfo'); | |||
var desc; | |||
var ok = true; | |||
if (!overwrite) { | |||
if (UF.errorMsgs) | |||
delete UF.errorMsgs; | |||
UF.errorMsgs = []; | |||
UF.warning_pushed = false; | |||
if (!UF.verifyMandatoryField(src, function (src) { | |||
var flickr_ok = !UFUI.isFromFlickr || src.search(/https?:\/\/([^./]+\.)*flickr\.com/) >= 0; | |||
if (!flickr_ok) | |||
UF.errorMsgs.push('wpFlickrURLError'); | |||
return flickr_ok; | |||
})) { | |||
src.onkeyup = UF.resetBg; | |||
ok = false; | |||
} | |||
if (!UF.verifyMandatoryField(author)) { | |||
author.onkeyup = UF.resetBg; | |||
ok = false; | |||
} | |||
// Piece the description(s) together | |||
var all_descs = ''; | |||
if (!UploadFormFull.multi_inputs) { | |||
desc = document.getElementById('wpDesc'); | |||
if (desc) | |||
all_descs = desc.value; | |||
} else { | |||
for (var input_idx = 0; input_idx < UploadFormFull.multi_inputs.length; input_idx++) | |||
all_descs += UploadFormFull.multi_inputs[input_idx].textfield.value; | |||
} | |||
// License check | |||
var licenseField = document.getElementById('wpLicense'); | |||
if (!(!licenseField || licenseField.selectedIndex > 0) && !UF.has_license([all_descs, other, moreInfo])) { | |||
if (!UF.warning_pushed) { | |||
UF.errorMsgs.push('wpUploadWarningError'); | |||
UF.warning_pushed = true; | |||
} | |||
ok = false; | |||
} | |||
var targetName = document.getElementById('wpDestFile'); | |||
if (targetName) { | |||
// Trim leading and trailing whitespace | |||
targetName.value = targetName.value.replace(/^\s\s*/, '').replace(/\s\s*$/, ''); | |||
if (!UF.verifyFileName(targetName.value)) { | |||
targetName.style.backgroundColor = UF.errorColor; | |||
targetName.onkeyup = function (evt) { | |||
UF.resetBg(evt); | |||
if (wgUploadWarningObj && wgUploadWarningObj.keypress instanceof Function && !UF.isReupload) | |||
wgUploadWarningObj.keypress(); | |||
}; | |||
ok = false; | |||
} | |||
} | |||
if (UF.templates[0].desc_mandatory) { | |||
if (all_descs.search(/\S/) < 0) { | |||
if (!UploadFormFull.multi_inputs) { | |||
desc = document.getElementById('wpDesc'); | |||
if (desc) { | |||
desc.style.backgroundColor = UF.errorColor; | |||
desc.onkeyup = UF.resetBg; | |||
} | |||
} else { | |||
UploadFormFull.setMultiBg(UF.errorColor, UploadFormFull.resetMultiBg); | |||
} | |||
UF.errorMsgs.push('wpNoDescriptionError'); | |||
ok = false; | |||
} | |||
} // end description check | |||
} // end overwrite | |||
if (!ok) { | |||
UF.hidePreview(); | |||
UF.display_errors(); | |||
} else { | |||
// It's ok: hide our warning box | |||
var myWarning = document.getElementById('wpUploadVerifyWarning'); | |||
if (myWarning) | |||
myWarning.style.display = 'none'; | |||
} | |||
return ok; | |||
}, | |||
setMultiBg: function (color, handler) { | |||
if (!UploadFormFull.multi_inputs) | |||
return; | |||
for (var i = 0; i < UploadFormFull.multi_inputs.length; i++) { | |||
var field = UploadFormFull.multi_inputs[i].textfield; | |||
field.style.backgroundColor = color; | |||
field.onkeyup = handler; | |||
} | |||
}, | |||
resetMultiBg: function (evt) { | |||
if (UF.resetBg(evt)) { | |||
// Reset the backgrounds of all description fields | |||
UploadFormFull.setMultiBg('#FFF', null); | |||
} | |||
} | |||
}; // end UploadFormFull | |||
UF.install(); | |||
}(jQuery, mediaWiki)); | |||
// </nowiki> |
Edição das 08h20min de 18 de julho de 2021
/** Upload form rewrite Authors: [[User:Lupo]], March 2008 - 2015 * Multiple user script devloapers, 2015 - License: Quadruple licensed GFDL, GPL, LGPL and Creative Commons Attribution 3.0 (CC-BY-3.0) Choose whichever license of these you like best :-) */ // <nowiki> /* UFUtils, UFUI, UFHelp, UploadForm are made global */ // UFUI is used by HotCat /* global jQuery:false, mediaWiki:false, importScript:false */ /* global Buttons, EditTools, LanguageHandler, Tooltip, TextCleaner, UIElements, FormRestorer */ /* global hotcat_set_state, hotcat_close_form, hotcat_get_state */ // by HotCat /* global wgUploadLicenseObj, wgUploadWarningObj */ /* eslint one-var:0, vars-on-top:0, camelcase:0, no-alert:0, no-console:0, no-bitwise:0, no-new:0, no-eval:0, indent:0, curly:0, */ /* eslint space-in-parens:0, computed-property-spacing:0, array-bracket-spacing:0, */ // extends:wikimedia /* jslint strict:false, forin:true, bitwise:true */ (function ($, mw) { // Guard against multiple inclusions! if (window.UploadForm) return; importScript('MediaWiki:LanguageHandler.js'); importScript('MediaWiki:FormRestorer.js'); importScript('MediaWiki:UIElements.js'); importScript('MediaWiki:Tooltips.js'); var UFConfig = { // Configuration. These can be set by a user in their user js. The typeof checks // are not really needed when this script is globally enabled, but until then, we have to be // careful not to overwrite a user's settings if he defines these first and then includes this // script in his monobook.js. forcebasic: window.UploadForm_forcebasic !== undefined ? window.UploadForm_forcebasic : (!window.JSconfig || window.JSconfig.keys.UploadForm_newlayout) ? null : true, // If non-null, use the basic form ownwork_author: window.UploadForm_ownwork_author !== undefined ? window.UploadForm_ownwork_author : '[[User:' + mw.config.get('wgUserName') + '|]]', // Change to use something else ownwork_date: window.UploadForm_ownwork_date !== undefined ? window.UploadForm_ownwork_date : null, // Set to define a pre-fill value for the date field own_language_first: window.UploadForm_own_language_first !== undefined ? window.UploadForm_own_language_first : false, // Set to true to have own language description on top additional_info_height: window.UploadForm_additional_info_height ? window.UploadForm_additional_info_height : 2, description_height: window.UploadForm_description_height ? window.UploadForm_description_height : 2, source_field_size: window.UploadForm_source_field_size ? window.UploadForm_source_field_size : 1, author_field_size: window.UploadForm_author_field_size ? window.UploadForm_author_field_size : 1, page_preview_in_tooltip: window.UploadForm_page_preview_in_tooltip !== undefined ? window.UploadForm_page_preview_in_tooltip : false, description_languages: window.UploadForm_description_languages ? window.UploadForm_description_languages : null, // If false, don't pre-fill description field in basic mode. May be useful // for people who have their own scripts pre-filling this field. autofill: window.UploadForm_autofill !== undefined ? window.UploadForm_autofill : true }; var UFUtils = window.UFUtils = { makeLink: function (name, url) { var link = document.createElement('a'); link.setAttribute('href', url); link.appendChild(document.createTextNode(name)); return link; }, convert_td_div: function (td) { // Replace the contents with a div, fixate the width, and give the div the id of the td var div = document.createElement('div'); var w = UFUtils.getWidth(td); if (w) { td.setAttribute('width', String(w)); td.style.maxWidth = String(w) + 'px'; } div.setAttribute('width', (w ? String(w) : '100%')); if (w) div.style.maxWidth = String(w) + 'px'; // Clear the warningCell and add the div instead while (td.firstChild) td.removeChild(td.firstChild); td.appendChild(div); var id = td.id; td.id = ''; div.id = id; return div; }, getHeight: function (rows, minimum, maximum) { if (!rows || isNaN(rows / 2) || rows < minimum) return minimum; else if (rows > maximum) return maximum; return rows; }, getWidth: function (element) { try { if (element.clientWidth) { // From IE, but Gecko has this, too. return element.clientWidth; } else if (window.getComputedStyle) { // Gecko, Opera return document.defaultView .getComputedStyle(element, null) .getPropertyValue('width'); } } catch (ex) { return null; } }, isChildOf: function (child, ancestor) { if (!ancestor) return false; while (child && child !== ancestor) child = child.parentNode; return (child === ancestor); } }; // end UFUtils // Used by HotCat var UFUI = window.UFUI = { // Encapsulate all UI stuff, with checks such that it works in degraded mode // (built-in defaults only) if UIElements doesn't exist. defaultLanguage: 'en', // Default. userLanguage: 'en', // Sanitized wgUserLanguage. internalLanguage: 'en', // Same, but with dashes replaced by underscores. isOwnWork: false, // True if uselang="*ownwork" isFromFlickr: false, // True if uselang="*fromflickr" isExperienced: false, // True if uselang="experienced" sanitizeUserLanguage: function () { // Try to make sense of wgUserLanguage even if it has been hacked to have special // pages for particular upload sources. Also sets isOwnWork and isFromFlickr. var globalUserLanguage = mw.config.get('wgUserLanguage'); if (!globalUserLanguage) return; UFUI.userLanguage = globalUserLanguage; if (globalUserLanguage.length > 3) { // Special "hacked" uselang parameters... var hacks = ['ownwork', 'fromflickr', 'experienced', 'fromwikimedia', 'fromgov']; var found = false; for (var i = 0; i < hacks.length; i++) { var idx = globalUserLanguage.indexOf(hacks[i]); if (idx >= 0) { // ULS is not working correctly with hacked uselang parameters, thus hiding it. $('#pt-uls, .uls-tipsy').hide(); found = true; if (idx) UFUI.userLanguage = globalUserLanguage.substring(0, idx); else UFUI.userLanguage = UFUI.defaultLanguage; if (!i) UFUI.isOwnWork = true; else if (i === 1) UFUI.isFromFlickr = true; else if (i === 2) UFUI.isExperienced = true; break; } } if (!found && typeof LanguageHandler !== 'undefined' && LanguageHandler.getPrefix instanceof Function) { // None of the "standard" hacks. Try an alternate approach. var lang_code_length = LanguageHandler.getPrefix(globalUserLanguage); if (lang_code_length && lang_code_length < globalUserLanguage.length) UFUI.userLanguage = globalUserLanguage.substr(0, lang_code_length); } } if (UFUI.userLanguage === 'en-gb') UFUI.userLanguage = 'en'; UFUI.internalLanguage = UFUI.userLanguage.replace(/-/g, '_'); }, defaultLabels: { wpSourceUploadLbl: 'Original source:', wpAuthorUploadLbl: 'Author:', wpDateUploadLbl: 'Date:', wpDescUploadLbl: 'Description:', wpPermissionUploadLbl: 'Permission:', wpCategoriesUploadLbl: 'Categories:', wpOtherVersionsUploadLbl: 'Other versions:', wpAdditionalInfoUploadLbl: 'Additional information:', wpPreviewLicenseUploadLbl: 'Preview the chosen license', wpOwnWorkUploadLbl: 'Own work', wpUnknownLanguageUploadLbl: 'Unknown language', wpPreviewUploadLbl: 'Preview', wpOkUploadLbl: 'OK', wpCancelUploadLbl: 'Cancel' }, defaultErrorMsgs: { wpUploadWarningError: 'You must provide the original source of the image, the author of the work, and a license.', wpNoFilenameError: 'The target filename must not be empty.', wpHttpFilenameError: 'The target file name appears to be a URL.', wpNoSlashError: 'The target file name must not contain "/".', wpNondescriptFilenameError: 'Please use a more descriptive target file name.', wpNoExtensionError: 'The target file name must have a file type extension (like for example ".jpg").', wpIllegalExtensionError: 'Files of this type cannot be uploaded.', wpDoubleExtensionError: 'Please correct the double file type in the target file name.', wpFlickrURLError: 'The source must be a URL pointing to the image at Flickr.', wpNoDescriptionError: 'Please give a description of the contents of the file you want to upload.', wpNoHelpTextError: 'Help text not found.', wpPreviewOverwriteError: 'You will upload over an already existing file. Please choose a different filename,' + 'unless you are uploading a technically improved version of the same file.' + 'Don\'t overwrite a file with a different image of the same topic.' + 'If you overwrite, the information in this form will not appear on the description page.', wpReuploadNoSummaryError: 'Please describe the file changes in the text box.' }, defaultHints: { wpUploadFormDestFileHint: 'Name of the file at Commons after the upload.', wpUploadFormSourceHint: 'Where does this file come from?', wpUploadFormAuthorHint: 'Who created this file? If it shows some artwork, who created that?', wpUploadFormDateHint: 'Date of creation and/or first publication of the work.', wpUploadFormPermissionHint: 'Not your own file? Or already published elsewhere? Use {{OTRS pending}} and send permission by e-mail. Also for specialized license tags.', wpUploadFormAdditionalInfoHint: 'Use for geolocation tags and other specialized information.', wpUploadFormCategoryHint: 'Click (+) to add categories.' }, // Do *not* use "-" here (as in "be-tarask")!! Use "_" instead: "be_tarask". translate: { en: 'translate', af: 'vertaal', ar: 'ترجم', be: 'перакласці', be_tarask: 'перакласьці', br: 'treiñ', bg: 'превеждам', ca: 'traduïu', cs: 'přeložit', cy: 'cyfieithu', da: 'oversæt', de: 'übersetzen', el: 'μεταφράστε', eo: 'traduki', es: 'traducir', et: 'tõlkima', fa: 'ترجمه\u200cکردن', fi: 'suomenna', fo: 'umseta', fr: 'traduire', gl: 'traducir', he: 'לתרגם', hr: 'prevesti', hu: 'fordítás', hy: 'թարգմանել', id: 'terjemah', io: 'tradukar', is: 'þýða', it: 'tradurre', ja: '訳す', ko: '번역하기', la: 'traducere', mk: 'преведи', ml: 'തര\u0d4dജ\u0d4dജമ', mn: 'орчуулах', mt: 'traduci', nn: 'oversett', no: 'oversett', nl: 'vertalen', pap: 'tradusí', pl: 'przetłumacz', pt: 'traduzir', ro: 'a traduce', ru: 'перевести', sk: 'preložit', sl: 'perovodit', sq: 'përkthej', ss: 'kuhúmusha', sv: 'översätt', ta: 'மொழிபெயர்', tr: 'tercüme', ty: 'ʻauvaha', uk: 'перекласти', vi: 'dịch', zh: '翻譯', zh_min_nan: 'hoan-e̍k', nan: 'hoan-e̍k', minnan: 'hoan-e̍k' }, labels: null, // Repository for form labels help: null, // Repository for help texts (and the help button) error_msgs: null, // Repository for error messages uiElements: null, // Repository for graphical UI elements hints: null, // Repository for brief hints setupRepositories: function () { if (!UFUI.labels) { if (window.UIElements) { var id; UFUI.labels = UIElements.emptyRepository(); UFUI.help = UIElements.emptyRepository(); UFUI.error_msgs = UIElements.emptyRepository(); UFUI.uiElements = UIElements.emptyRepository(); UFUI.hints = UIElements.emptyRepository(); for (id in UFUI.defaultLabels) { if (id === 'wpDescUploadLbl') { UIElements.setEntry( id, UFUI.labels, UFUtils.makeLink( UFUI.defaultLabels[id], '/wiki/Commons:First_steps/Quality_and_description')); } else { UIElements.setEntry(id, UFUI.labels, document.createTextNode(UFUI.defaultLabels[id])); } } for (id in UFUI.defaultErrorMsgs) { UIElements.setEntry(id, UFUI.error_msgs, document.createTextNode(UFUI.defaultErrorMsgs[id])); } for (id in UFUI.defaultHints) { UIElements.setEntry(id, UFUI.hints, document.createTextNode(UFUI.defaultHints[id])); } // Now try to read the localized stuff from the uploadfooter. UIElements.load('wpUploadFormLabels', null, 'span', UFUI.labels); UIElements.load('wpUploadFormErrorMessages', null, 'span', UFUI.error_msgs); UIElements.load('wpUploadFormHints', null, 'span', UFUI.hints); UIElements.load('wpUploadFormUIElements', null, 'div', UFUI.uiElements); UIElements.load('wpUploadFormHelp', null, 'div', UFUI.help); UFUI.basic = false; } else { UFUI.labels = UFUI.defaultLabels; UFUI.error_msgs = UFUI.defaultErrorMsgs; UFUI.hints = UFUI.defaultHints; UFUI.basic = true; } } }, getUI: function (id, repository, basic) { if (!UFUI.labels) { UFUI.sanitizeUserLanguage(); UFUI.setupRepositories(); } if (!UFUI[repository]) return null; var result = null; var add_plea = false; if (UFUI.basic) { result = document.createTextNode(UFUI[repository][id]); add_plea = (UFUI.internalLanguage !== UFUI.defaultLanguage); } else { result = UIElements.getEntry(id, UFUI[repository], UFUI.internalLanguage, null); add_plea = !result; if (!result) result = UIElements.getEntry(id, UFUI[repository]); if (!result) return null; // Hmmm... what happened here? We normally have defaults... result = result.cloneNode(true); } if (add_plea && !basic) { // Wrap it all into a span -- we can return only one element var span = document.createElement('span'); span.appendChild(result); span.appendChild(UFUI.plea(repository, id)); result = span; } return result; }, plea: function (what, msg_id) { var span = document.createElement('sub'); span.appendChild(document.createTextNode(' (')); span.appendChild( UFUtils.makeLink( UFUI.translate[UFUI.internalLanguage] || UFUI.translate.en, '/wiki/MediaWiki_talk:UploadFormLabels/UploadFormTranslations?action=edit§ion=new' + '&withJS=MediaWiki:UploadFormTranslator.js&language=' + encodeURIComponent(UFUI.userLanguage) + '&uploadformurl=' + encodeURIComponent(document.URL) + (what ? '&uploadformitems=' + encodeURIComponent(what) : '') + (msg_id ? '&uploadformmsg=' + encodeURIComponent(msg_id) : ''))); span.appendChild(document.createTextNode(')')); return span; }, getLabel: function (id, basic) { return UFUI.getUI(id, 'labels', basic); }, getErrorMsg: function (id, basic) { return UFUI.getUI(id, 'error_msgs', basic); }, getHint: function (id, basic) { return UFUI.getUI(id, 'hints', basic); }, getEntry: function (id, repository, lang, sel) { if (!UFUI.labels) { UFUI.sanitizeUserLanguage(); UFUI.setupRepositories(); } if (!UFUI.basic) return UIElements.getEntry(id, UFUI[repository], lang, sel); if (!UFUI[repository] || lang !== UFUI.defaultLanguage || !!sel && sel !== 'default') return null; return UFUI[repository][id]; } }; // end UFUI var UFHelp = window.UFHelp = { // Collects all help-related stuff help_close_imgs: null, precreate_tooltip_closer: function () { if (window.Tooltip && window.Buttons) { var closeImgs = UFUI.getEntry('wpUploadFormHelpCloseButton', 'uiElements', UFUI.internalLanguage); if (!closeImgs) closeImgs = UFUI.getEntry('wpUploadFormHelpCloseButton', 'uiElements'); if (closeImgs) closeImgs = closeImgs.getElementsByTagName('img'); if (!closeImgs || !closeImgs.length) closeImgs = null; else closeImgs = Buttons.createClass(closeImgs, 'wpUploadFormHelpCloseClass'); UFHelp.help_close_imgs = closeImgs; } }, tooltip_styles: { // The style for all our tooltips border: '1px solid #88A', backgroundColor: '#f7f8ff', padding: '0.3em', fontSize: ((mw.config.get('skin') === 'monobook' || mw.config.get('skin') === 'modern') ? '127%' : '100%') // Scale up to default text size }, getHelp: function (help_id, with_ext) { // This is a Tooltip callback! Sets the help texts dynamically, depending of the file // type the user has chosen in wpDestFile. var fn = null; if (with_ext) { fn = document.getElementById('wpDestFile'); if (fn) fn = fn.value; if (fn) { fn = fn.split('.'); if (fn.length >= 2) fn = fn[fn.length - 1]; else fn = null; } } var add_plea = false; var extensions = [fn, 'default']; var helpMain = null; for (var i = 0; i < extensions.length && !helpMain; i++) { if (extensions[i] && extensions[i].length) { helpMain = UFUI.getEntry(help_id, 'help', UFUI.internalLanguage, extensions[i]); if (!helpMain) { helpMain = UFUI.getEntry(help_id, 'help', null, extensions[i]); add_plea = !!helpMain; } } } var help_base = UFUI.getEntry(help_id, 'help', UFUI.internalLanguage); if (!help_base) { help_base = UFUI.getEntry(help_id, 'help'); add_plea = add_plea || !!help_base; } var help = document.createElement('div'); if (help_base) help.appendChild(help_base); if (helpMain) help.appendChild(helpMain); if (!helpMain && !help_base) help.appendChild(UFUI.getErrorMsg('wpNoHelpTextError')); else if (add_plea) help.appendChild(UFUI.plea('help', help_id)); return help; }, showHelp: function (e, id) { // Onclick handler for setup without tooltips e = e || window.event; var node = e.target || e.srcElement, error; if (!node) { error = UFUI.getErrorMsg('wpNoHelpTextError', true); // We need the text contents... while (error && error.nodeType !== Node.TEXT_NODE) error = error.firstChild; if (error) alert(error.data); // Otherwise what?? } else if (!document.getElementById(id + '_Div')) { var help = UFHelp.getHelp(id, false); help.style.fontSize = 'small'; help.style.color = '#666'; // Now add a new table row after the current one var tr = node.parentNode; while (tr && tr.nodeName.toLowerCase() !== 'tr') tr = tr.parentNode; if (!tr) { error = UFUI.getErrorMsg('wpNoHelpTextError', true); while (error && error.nodeType !== 3) error = error.firstChild; if (error) alert(error.data); } else { var new_tr = document.createElement('tr'); var cell = document.createElement('td'); new_tr.appendChild(cell); cell = document.createElement('td'); cell.id = id + '_Div'; new_tr.appendChild(cell); tr.parentNode.insertBefore(new_tr, tr.nextSibling); cell = UFUtils.convert_td_div(cell); cell.appendChild(help); } } if (e.stopPropagation) { e.stopPropagation(); e.preventDefault(); } else { e.cancelBubble = true; } return false; }, setupHelp: function (is_reupload) { var fields = ['wpUploadFile', 'wpUploadFileURL', 'wpDestFile', 'wpSource', 'wpAuthor', 'wpDate', 'wpDesc', 'wpPermission', 'wpOtherVersions', 'wpAdditionalInfo', 'wpPatent', 'wpLicense', 'wpCategories', 'wpWatchthis', 'wpIgnoreWarning']; if (!UFUI.help) return; // Help not loaded function setHelp(id, imgs, lk, maximum_width, is_reupload) { // Figure out where to place the help "button" var field = document.getElementById(id); var insert_in = null, before = null; var help_id = id + 'Help'; if (!UFUI.help[help_id]) return; // Don't add if we have no help at all. var offset = -5; // Pixels. switch (id) { case 'wpWatchthis': case 'wpIgnoreWarning': // Right of the element if (!field) return; insert_in = field.parentNode; // Find the label. { var lbls = insert_in.getElementsByTagName('label'); if (!lbls) { before = field.nextSibling; } else { for (var i = 0; i < lbls.length; i++) { if (lbls[i].htmlFor && lbls[i].htmlFor === id) { before = lbls[i].nextSibling; break; } } } } offset = Math.abs(offset); break; case 'wpCategories': field = document.getElementById('hotcatLabelTranslated'); if (!field) return; insert_in = field; before = null; if (field.firstChild) { field = field.firstChild; offset = Math.abs(offset); } break; case 'wpAuthor': case 'wpSource': if (!field) return; field = field.parentNode; // Because the field itself may vanish. insert_in = field.parentNode.cells[0]; before = null; break; case 'wpDestFile': if (!field) return; insert_in = field.parentNode.parentNode.cells[0]; before = null; if (is_reupload) { help_id = 'wpReuploadDestHelp'; field = null; // Field is hidden: attach the help text to the button instead } break; case 'wpDesc': if (!field) { field = document.getElementById('wpUploadDescription'); if (field) { // Basic form help_id = (is_reupload ? 'wpReuploadSummaryHelp' : 'wpUploadDescriptionHelp'); } else { insert_in = document.getElementById('wpDescLabel'); if (!insert_in) return; field = insert_in; offset = Math.abs(offset); before = insert_in.nextSibling; insert_in = insert_in.parentNode; break; } } /* falls through */ // eslint-disable-next-line no-fallthrough case 'wpPatent': field = document.getElementsByName(id)[0]; if (!field) return; insert_in = field.parentNode.parentNode.parentNode.cells[0]; before = null; break; default: if (!field) return; // In the table cell to the left insert_in = field.parentNode.parentNode.cells[0]; before = null; } // Create and insert the help "button" var button_construct = null, button = null; if (imgs && window.Buttons) { button = Buttons.makeButton(imgs, id + '_HelpButton', '#'); button.style.position = 'relative'; button.style.top = '-0.4em'; button_construct = button; } else { button_construct = lk.cloneNode(true); button = button_construct.getElementsByTagName('a')[0]; } insert_in.insertBefore(button_construct, before); if (window.Tooltip) { // Create the tooltip new Tooltip( button, function () { return UFHelp.getHelp(help_id, true); }, { activate: Tooltip.CLICK, deactivate: (UFHelp.help_close_imgs ? Tooltip.CLICK_ELEM : Tooltip.CLICK_TIP | Tooltip.CLICK_ELEM | Tooltip.LOSE_FOCUS), close_button: UFHelp.help_close_imgs, mode: Tooltip.FIXED, fixed_offset: { x: 10, y: offset }, max_pixels: maximum_width, target: field, open_delay: 0, hide_delay: 0 }, UFHelp.tooltip_styles); } else { // Alternative setup without Tooltips: insert help text statically in a table field // below the button. button.onclick = function (evt) { return UFHelp.showHelp(evt, help_id); }; } } var button_imgs = null, button_lk = null; if (window.Buttons) { button_imgs = UFUI.getEntry('wpUploadFormHelpOpenButton', 'uiElements', UFUI.internalLanguage); if (!button_imgs) button_imgs = UFUI.getEntry('wpUploadFormHelpOpenButton', 'uiElements'); button_lk = null; if (button_imgs) button_imgs = button_imgs.getElementsByTagName('img'); } if (!button_imgs || !button_imgs.length) { // Alternative text-based "button" button_lk = document.createElement('sup'); button_lk.appendChild(document.createElement('b')); button_lk.firstChild.appendChild(document.createTextNode(' [')); button_lk.firstChild.appendChild(UFUtils.makeLink('?', '#')); button_lk.firstChild.appendChild(document.createTextNode(']')); button_imgs = null; } else { button_imgs = Buttons.createClass(button_imgs, 'wpUploadFormHelpOpenClass'); } var widest_field = document.getElementById('wpAdditionalInfo'); var max_width = 0; if (!widest_field) widest_field = document.getElementById('wpUploadDescription'); if (widest_field) { var w = UFUtils.getWidth(widest_field); try { max_width = Math.round(w * 0.9); } catch (ex) { max_width = 0; } } fields.forEach(function (f) { setHelp(f, button_imgs, button_lk, max_width, is_reupload); }); } }; // end UFHelp var UFFixes = { fixAutocompletion: function () { // Do the overwrite check also for selections from the browser's "previous entry list" var destFile = document.getElementById('wpDestFile'); if (destFile && destFile.onkeyup) { // For some reason, onchange doesn't fire upon autocompletion in FF and IE6. Don't use // onblur (recommended as a workaround on some Internet sites), it cancels button clicks // that cause the focus change. Unfortunately, FF also doesn't fire the DOMAttrModified // event upon autocompletion. Thus we're stuck for FF. At least the FF people are about // to correct this bug (https://bugzilla.mozilla.org/show_bug.cgi?id=388558). On IE, // there is a workaround. if (window.ActiveXObject) { // We're on IE... // See http://msdn2.microsoft.com/en-us/library/ms533032.aspx and // http://msdn2.microsoft.com/en-us/library/ms536956.aspx if (!destFile.onpropertychange) { var previous_onkeyup_handler = destFile.onkeyup; var previous_onchange_handler = destFile.onchange; var handler = function (e) { e = e || window.event; if (e && e.propertyName && e.propertyName === 'value') { if (typeof previous_onkeyup_handler === 'string') eval(previous_onkeyup_handler); else if (previous_onkeyup_handler instanceof Function) previous_onkeyup_handler(e); if (typeof previous_onchange_handler === 'string') eval(previous_onchange_handler); else if (previous_onchange_handler instanceof Function) previous_onchange_handler(e); } }; if (destFile.addEventListener) destFile.addEventListener('propertychange', handler); else if (destFile.attachEvent) destFile.attachEvent('onpropertychange', handler); else return; destFile.onkeyup = null; // Otherwise, both may fire... destFile.onchange = null; } } else { $(destFile).change(destFile.onkeyup); // addEvent (destFile, 'change', destFile.onkeyup); } } } }; // end UFFixes var UF = window.UploadForm = { isInstalled: false, // Set to true when the onload hook runs debug: false, // Can be set to true by adding "&debug=true" to the URL oldOnSubmit: null, // Possibly already existing onsubmit handler errorColor: 'lightpink', // The light red from Template:Copyvio formModified: false, isReupload: false, setup_hotcat_label: function () { // If HotCat is present, translate its label if we can find it var hotcatLabelCell = document.getElementById('hotcatLabel'); if (hotcatLabelCell) { // Change its ID, just to be sure hotcatLabelCell.setAttribute('id', 'hotcatLabelTranslated'); // Assumes that the cell has only one child (which is normally the case) hotcatLabelCell.replaceChild( UFUI.getLabel('wpCategoriesUploadLbl'), hotcatLabelCell.firstChild); } }, setup_error_display: function () { var warningCell = document.getElementById('wpDestFile-warning'); if (!warningCell) return; var row = warningCell.parentNode; var new_cell = document.createElement('td'); new_cell.style.padding = '0'; // Remove the colspan, if any, and insert a new cell to the left warningCell.colspan = ''; warningCell.padding = '0'; row.insertBefore(new_cell, warningCell); UFUtils.convert_td_div(warningCell); }, set_fields_enabled: function (enabled, except) { // Enables or disables all named fields in the form, except those whose ids are // listed in except var skip = except.join(' '); var elems = UF.the_form.elements; var changed = false; for (var i = 0; i < elems.length; i++) { if (elems[i].type === 'hidden') continue; // Don't fool around with hidden elements var id = elems[i].id; if (!id || !id.length) id = elems[i].name; if (id && id.length) { if (skip.indexOf(id) < 0) { if (elems[i].disabled === enabled) { changed = true; if (elems[i].type === 'text' || elems[i].type === 'textarea') { // Set the background. Actually, I'd like to just reset it to whatever the // default was, but setting it to null doesn't do anything in IE6... We // force a light gray for disabled fields since IE6 doesn't have a real // visual "disabled" indicator for input fields. try { elems[i].style.backgroundColor = (enabled ? '#FFF' : '#EEE'); } catch (some_error) { // Swallow } } elems[i].disabled = !enabled; } } } } if (changed) { // Clear warning messages. If we disabled fields, they're obsolete; if we enabled fields, // new warnings will be generated upon submit if necessary. var myWarning = document.getElementById('wpUploadVerifyWarning'); if (myWarning) myWarning.style.display = 'none'; } }, previous_hotcat_state: null, getPrevValue: function (storedForm, element_id) { // Return a field's previous value, if known if (!storedForm || storedForm.length <= 1 || !element_id || !element_id.length) return null; for (var i = 1; i < storedForm.length; i++) { if (storedForm[i] && element_id === storedForm[i].id) return storedForm[i].val; } return null; }, license_button: null, license_button_shown: false, current_license_preview: ' ', get_license_preview: function () { // Tooltip callback var div = document.createElement('div'); div.style.display = 'none'; document.body.appendChild(div); div.innerHTML = UF.current_license_preview; document.body.removeChild(div); div.style.fontSize = 'smaller'; div.style.display = ''; var wrapper = document.createElement('div'); wrapper.appendChild(div); return wrapper; }, create_license_button: function () { // Will be called only from our rewritten wgUploadLicenseObj.showPreview, i.e. // we *know* that we *do* have Tooltips and Buttons here. var previewButton = UF.customFormButton( 'wpUploadFormPreviewLicenseButton', // Customization ID 'wpUploadPreviewLicense', // ID of button null, // Default text null, // Event handler, will be set below 'wpPreviewLicenseUploadLbl' // default label ID ); new Tooltip( previewButton, UF.get_license_preview, { activate: Tooltip.CLICK, deactivate: (UFHelp.help_close_imgs ? Tooltip.CLICK_ELEM : Tooltip.CLICK_TIP | Tooltip.CLICK_ELEM | Tooltip.LOSE_FOCUS), close_button: UFHelp.help_close_imgs, mode: Tooltip.FIXED, anchor: Tooltip.TOP_LEFT, fixed_offset: { x: 10, y: 5, dy: -1 }, open_delay: 0, hide_delay: 0 }, UFHelp.tooltip_styles); UF.license_button = previewButton; }, setup_license_preview: function () { var preview_panel = document.getElementById('mw-license-preview'); if (preview_panel) UFUtils.convert_td_div(preview_panel); // Change the license previewer to not overwrite our warning message, if any. if (window.wgUploadLicenseObj && wgUploadLicenseObj.showPreview && window.Tooltip) { wgUploadLicenseObj.showPreview = function (preview) { var preview_panel = document.getElementById('mw-license-preview'); if (!preview_panel) return; if (preview === UF.current_license_preview) return; UF.current_license_preview = preview; var contents = null; var new_state = false; if (!preview || !preview.length || preview === ' ') { contents = document.createTextNode('\xa0'); // a single new_state = false; } else { if (!UF.license_button) UF.create_license_button(); if (!UF.license_button_shown) contents = UF.license_button; new_state = true; } if (contents && new_state !== UF.license_button_shown) { if (preview_panel.firstChild) preview_panel.replaceChild(contents, preview_panel.firstChild); else preview_panel.appendChild(contents); } UF.license_button_shown = new_state; }; // end function } }, preview_tooltip: null, // Tooltip, if preview so configured do_preview: null, // Function to call to actually generate the preview addPreviewButton: function (handler) { // If we don't have Ajax, our preview won't work anyway. if (!window.XMLHttpRequest && !window.ActiveXObject) return; var uploadButton = document.getElementsByName('wpUpload')[0]; // Has no ID... // If we can't find the upload button, we don't know where to insert the preview button. if (!uploadButton) return; try { var previewButton = UF.customFormButton( 'wpUploadFormPreviewButton', // Customization ID 'wpUploadPreview', // ID of button null, // Default text UF.generatePreview, // Event handler 'wpPreviewUploadLbl' // default label ID ); if (UFConfig.page_preview_in_tooltip && window.Tooltip) { UF.preview_tooltip = new Tooltip( previewButton, UF.getPreview, { activate: Tooltip.NONE, // We'll show it manually in generatePreview. deactivate: Tooltip.CLICK_TIP, close_button: UFHelp.help_close_imgs, mode: Tooltip.FIXED, target: uploadButton, anchor: Tooltip.TOP_LEFT, fixed_offset: { x: 0, y: 5, dy: -1 }, open_delay: 0, hide_delay: 0 }, UFHelp.tooltip_styles); } UF.do_preview = handler; previewButton.setAttribute('style', 'margin-left:0.5em;'); var hotKey = 'p'; previewButton.setAttribute('accesskey', hotKey); if (!(/\[\w+\]$/.test(previewButton.title))) previewButton.title += ' [' + hotKey + ']'; if ($.fn.updateTooltipAccessKeys) { $('#t-print').remove(); // Not needed here and collides with same accesskey $(previewButton).updateTooltipAccessKeys(); } uploadButton.parentNode.insertBefore(previewButton, uploadButton.nextSibling); } catch (ex) {} }, getOwnWorkAuthor: function () { if (typeof UFConfig.ownwork_author === 'string' && UFConfig.ownwork_author.search(/\S/) >= 0) { // It's a non-empty string return UFConfig.ownwork_author; } else { return '[[User:' + mw.config.get('wgUserName') + '|]]'; } }, getOwnWorkSource: function () { var text = UFUI.getLabel('wpOwnWorkUploadLbl', true); var result = null; try { // Must have a text node. while (text && text.nodeType !== Node.TEXT_NODE) text = text.firstChild; if (text) result = text.data.replace(/^\s+/, '').replace(/\s+$/, ''); } catch (ex) { result = null; } if (!result) result = '{{own}} ' + UF.getOwnWorkAuthor(); return result; }, customFormButton: function (ui_id, id, defaultText, handler, defaultId) { function getButtonSpan(container, idx) { if (!container) return null; var spans = container.getElementsByTagName('span'); var span = null; if (!spans || spans.length <= idx) { // No spans... if idx is zero, try simply to take the first text node within container. if (!idx) span = container; } else { span = spans[idx]; } // Ok, let's see if we have some text... while (span && span.nodeType !== Node.TEXT_NODE) span = span.firstChild; if (span) return span.data.replace(/^\s+/, '').replace(/\s+$/, ''); return null; } function getDefault(defaultText, defaultId) { if (!defaultText) { if (defaultId) { defaultText = UFUI.getLabel(defaultId, true); // Must have a text node while (defaultText && defaultText.nodeType !== Node.TEXT_NODE) defaultText = defaultText.firstChild; if (defaultText) defaultText = defaultText.data.replace(/^\s+/, '').replace(/\s+$/, ''); } else { defaultText = 'X'; } // Hmmm... a serious misconfiguration } return defaultText; } var button = null, imgs = null; button = UFUI.getEntry(ui_id, 'uiElements', UFUI.internalLanguage); if (!button) button = UFUI.getEntry(ui_id, 'uiElements'); if (button) imgs = button.getElementsByTagName('img'); if (!imgs || !imgs.length || window.Buttons === undefined) { var buttonText = getButtonSpan(button, 0); if (!buttonText) buttonText = getDefault(defaultText, defaultId); var alternateText = getButtonSpan(button, 1); button = document.createElement('input'); button.setAttribute('id', id); button.setAttribute('name', id); button.type = 'button'; button.value = buttonText; if (alternateText) button.title = alternateText; button.onclick = handler; } else { button = Buttons.makeButton(imgs, id, handler); } return button; }, the_form: null, // If a needed script that is included hasn't loaded yet, we try at most install_max_attempts // times install_delay. If it then still has not loaded, we install all the same, and the // setup routine will have to deal with it. (Note that script loading is asynchronous!) install_delay: 400, // Milliseconds installAttempts: 0, install_max_attempts: 6, // maximum delay 2.4s reallyInstall: function (force_basic) { if (this.installAttempts < this.install_max_attempts && (!window.LanguageHandler || !window.UIElements || !window.Tooltip)) { // Add needed scripts in the condition above. window.setTimeout(function () { UF.reallyInstall(force_basic); }, this.install_delay); } else { UFUI.sanitizeUserLanguage(); var useBasic = force_basic || !!UFConfig.forcebasic || UFUI.isExperienced; if (useBasic && !force_basic) { // Only for autoconfirmed users! var is_auto = false; var userGroups = mw.config.get('wgUserGroups'); if (userGroups) { for (var i = 0; i < userGroups.length && !is_auto; i++) is_auto = userGroups[i] === 'autoconfirmed'; } if (!is_auto) useBasic = false; } try { UFHelp.precreate_tooltip_closer(); this.setFileExtensions(); if (useBasic || document.URL.indexOf('uploadformstyle=basic') > 0 || document.URL.search(/uselang=(\w|-)*fromwikimedia/) > 0) { // The fromwikimedia forms are special enough to warrant a special setup. UploadFormBasic.setup(!force_basic); } else { UploadFormFull.setup(); } this.setup_error_display(); UFHelp.setupHelp(this.isReupload); if (!this.isReupload) UFFixes.fixAutocompletion(); this.setupOverwriteMsg(); // Handle the "Upload new version" links, these have &wpDestFile=... in the URL, which // defeats overwrite detection. Because someone might construct such a URL manually // *not* actually overwriting an existing file, we still do the check: if (!this.isReupload) this.check_initial_dest_file(); } catch (ex) { if (console && console.warn) console.warn(ex); else mw.log.warn(ex); // Not good at all. Something went badly wrong. If we have already modified the form, // the best thing is probably to reload and make sure we don't try again: if (this.formModified) { var reloadURL = document.URL; reloadURL += (reloadURL.indexOf('?') > 0) ? '&' : '?'; window.location.href = reloadURL + 'uploadformstyle=plain'; } } // not needed at beginning importScript('MediaWiki:TextCleaner.js'); $.when(mw.loader.using('ext.gadget.HotCat'), $.ready) .then(this.setup_hotcat_label); this.removeSpinner(); } this.installAttempts++; }, removeSpinner: function () { // Installed on ImprovedUploadForm.js if ($.removeSpinner) $.removeSpinner('UploadLoadingSpinner'); }, install: function () { if (UF.isInstalled || // Do this only once per page! document.URL.indexOf('uploadformstyle=plain') > 0 || // We're disabled // Also don't do anything if we're not on an upload form. mw.config.get('wgCanonicalNamespace') !== 'Special' || mw.config.get('wgCanonicalSpecialPageName') !== 'Upload') return UF.removeSpinner(); var form = document.getElementById('upload') || document.getElementById('mw-upload-form'); var originalDesc = document.getElementById('wpUploadDescription'); if (!form || !originalDesc) return; // Oops. Not good: bail out; don't do anything. (then there should be also no spinner) var reupload = document.getElementById('wpForReUpload'); var destFile = document.getElementById('wpDestFile'); if (reupload) { UF.isReupload = !!reupload.value; } else { UF.isReupload = destFile && (destFile.disabled || destFile.readOnly); $(form).append($('<input type="hidden" name="wpChangeTags" value="OUploadForm">')); } if (destFile && !!destFile.disabled) { destFile.readOnly = true; destFile.disabled = false; } if (destFile && UF.isReupload) { destFile.onkeyup = function (/* e */) {}; destFile.onchange = function (/* e */) {}; } // Use the basic form if the description was set *initially*, or if it's a re-upload, or if it's a special // form var useBasic = (originalDesc.defaultValue && originalDesc.defaultValue.length) || UF.isReupload || document.URL.indexOf('uselang=nlwikilovesmonuments') > 0; UF.the_form = form; if (document.URL.indexOf('debug=true') > 0) UF.debug = true; UF.reallyInstall(useBasic); }, check_initial_dest_file: function () { var destFile = document.getElementById('wpDestFile'); if (destFile && destFile.value && destFile.value.length && wgUploadWarningObj && wgUploadWarningObj.keypress instanceof Function) wgUploadWarningObj.keypress(); }, errorMsgs: null, warning_pushed: false, display_errors: function () { // Give user feedback about what is not ok. var myWarning = document.getElementById('wpUploadVerifyWarning'); if (!myWarning) { // Find the upload button var uploadButton = document.getElementsByName('wpUpload'); var warningBox = null; if (uploadButton) uploadButton = uploadButton[0]; if (!uploadButton) { warningBox = document.getElementById('wpDestFile-warning'); if (!warningBox) return; // We just have the field colors to indicate errors... } myWarning = document.createElement('div'); myWarning.style.border = '1px #F00 solid'; myWarning.style.backgroundColor = UF.errorColor; myWarning.style.padding = '0.5em'; myWarning.style.marginTop = '0.5em'; myWarning.style.marginBottom = '0.5em'; myWarning.setAttribute('id', 'wpUploadVerifyWarning'); myWarning.setAttribute('width', '100%'); myWarning.style.display = 'none'; if (uploadButton) uploadButton.parentNode.insertBefore(myWarning, uploadButton); else warningBox.parentNode.insertBefore(myWarning, warningBox.nextSibling); } // Now collect all the error messages into one div. var msgs = document.createElement('ul'); msgs.style.paddingLeft = '1.0em'; msgs.style.marginLeft = '0'; for (var i = 0; i < UF.errorMsgs.length; i++) { var msg = UFUI.getErrorMsg(UF.errorMsgs[i]); if (msg) { var li = document.createElement('li'); li.appendChild(msg); msgs.appendChild(li); } } UF.errorMsgs = null; // And then display the messages if (myWarning.firstChild) myWarning.replaceChild(msgs, myWarning.firstChild); else myWarning.appendChild(msgs); myWarning.style.display = 'block'; }, call_onsubmit: function (evt) { var doSubmit = true; if (UF.oldOnSubmit) { if (typeof UF.oldOnSubmit === 'string') doSubmit = eval(UF.oldOnSubmit); else if (UF.oldOnSubmit instanceof Function) doSubmit = UF.oldOnSubmit(evt); } return doSubmit; }, templates: [{ name: 'information', fields: ['description', 'date', 'source', 'author', 'permission', 'other versions'], extract: [3, 1, 0], desc_mandatory: true, regexp: null }, { name: 'painting', fields: ['Artist', 'Title', 'Year', 'Technique', 'Dimensions', 'Gallery', 'Location', 'Notes', 'Source', 'Permission', 'other_versions', 'Other versions'], extract: [0, 8, 7], desc_mandatory: false, regexp: null }, { name: 'flickr', fields: ['description', 'flickr_url', 'title', 'taken', 'photographer_url', 'photographer', 'photographer_location', 'reviewer', 'permission'], extract: [[5, 4], 1, 0], desc_mandatory: true, regexp: null } ], empty_template: function (name) { if (!name) return null; var test_name = name.toLowerCase(); for (var i = 0; i < UF.templates.length; i++) { if (UF.templates[i].name === test_name) { var result = '{{' + name; for (var j = 0; j < UF.templates[i].fields.length; j++) { result += '\n|' + UF.templates[i].fields[j] + '='; if (UFUI.isOwnWork && !i) { // Pre-fill some fields if we're on an own-work form and it's an // information-template switch (j) { case 1: // Date if (typeof UFConfig.ownwork_date === 'string' && UFConfig.ownwork_date.search(/\S/) >= 0) result += UF.clean(UFConfig.ownwork_date); break; case 2: // Source-field result += UF.clean(UF.getOwnWorkSource()); break; case 3: // Author result += UF.clean(UF.getOwnWorkAuthor()); break; // default: break; } // end switch } // end if information for ownWork } return result + '\n}}'; } } return null; }, extract_fields: function (desc, template_idx, list) { function get(desc, field, regexp) { var match_start = new RegExp('\\n\\s*\\| *' + field + ' *\\=', 'i'); var start = desc.match(match_start); if (!start) return null; var rest = desc.substring(start.index + start[0].length); var end = rest.search(regexp); if (end < 0) return rest; return rest.substring(0, end); } var result = list; var names = UF.templates[template_idx].fields; var extract = UF.templates[template_idx].extract; if (!UF.templates[template_idx].regexp) { // Build the regexp var regexp_str = '\\n\\s*(\\| *(' + names.join('|') + ') *\\=|\\}\\})'; UF.templates[template_idx].regexp = new RegExp(regexp_str); } for (var i = 0; i < extract.length; i++) { var txt = null; if (extract[i] instanceof Array) { // It's an array giving alternatives... var alternatives = extract[i]; for (var j = 0; j < alternatives.length; j++) { txt = get(desc, names[alternatives[j]], UF.templates[template_idx].regexp); if (txt && txt.search(/\S/) >= 0) break; // Non-empty: don't look further txt = null; } } else { txt = get(desc, names[extract[i]], UF.templates[template_idx].regexp); } if (txt) result[result.length] = txt; // Push one. // Don't use "if (txt)", it's false if the string is, but empty! } return result; }, split_description: function (desc) { if (!desc || !desc.length) return null; // Returns an array containing (in that order): // index of template, author, source, description for (var i = 0; i < UF.templates.length; i++) { var regexp = new RegExp('\\{\\{' + UF.templates[i].name + '\\s*(\\||\\n)'); var start = desc.toLowerCase().search(regexp); if (start >= 0) { var result = [i]; // Now try to extract the fields: return UF.extract_fields(desc.substring(start), i, result); } } return null; }, generatePreview: function (evt) { if (UF.preview_tooltip && UF.preview_tooltip.popup.style.display !== 'none' && UF.preview_tooltip.popup.style.display) UF.preview_tooltip.hide_now(null); else UF.do_preview(evt || window.event); }, outerHTML: function (node) { if (!node) return ''; if (node.nodeType === 3) return node.nodeValue; // Text node if (node.outerHTML) return node.outerHTML; var div = document.createElement('div'); div.style.display = 'none'; div.style.position = 'absolute'; div.appendChild(node); document.body.appendChild(div); var txt = div.innerHTML; document.body.removeChild(div); return txt; }, makePreview: function (description, is_overwrite) { if (is_overwrite) { UF.showPreview( '<div style="border:1px solid red; padding:0.5em;"><div class="previewnote">' + UF.outerHTML(UFUI.getErrorMsg('wpPreviewOverwriteError')) + '</div></div>'); } else { var text = '<div style="border:1px solid red;padding:0.5em;"><div class="previewnote">\n' + '{{MediaWiki:Previewnote/' + UFUI.userLanguage + '}}\n' + '</div>\n'; var license = document.getElementById('wpLicense'); var licenseText = null; if (license && license.selectedIndex > 0 && license.options[license.selectedIndex].value.length) licenseText = '{{' + license.options[license.selectedIndex].value + '}}'; if (licenseText) { text += '<h2>{{int:filedesc}}</h2>\n' + description + '\n' + '<h2>{{int:license-header}}</h2>\n' + licenseText; } else { text += description + '\n'; } // Add categories if (hotcat_get_state instanceof Function) { if ($('#catlinks').find('.hotcatlink').is(':hidden')) hotcat_close_form(); var hotcat_categories = hotcat_get_state(); if (hotcat_categories && hotcat_categories.length) { hotcat_categories = hotcat_categories.split('\n'); for (var i = 0; i < hotcat_categories.length; i++) { if (hotcat_categories[i] && hotcat_categories[i].length) text += '[[Category:' + hotcat_categories[i] + ']]'; } } } text += '</div>'; // Make the Ajax call var req; if (window.XMLHttpRequest) req = new window.XMLHttpRequest(); if (!req && window.ActiveXObject) { try { req = new window.ActiveXObject('Microsoft.XMLHTTP'); } catch (any) {} } if (!req) return; var button = document.getElementById('wpUploadPreview'); var page = document.getElementById('wpDestFile'); if (page) page = page.value; if ($.fn.injectSpinner) $(button).injectSpinner('wpUploadPreviewSpinner'); var uri = mw.config.get('wgServer') + (mw.util ? mw.util.wikiScript('api') : mw.config.get('wgScriptPath') + '/api.php'); var args = 'action=parse&pst&text=' + encodeURIComponent(text) + (page ? '&title=File:' + encodeURIComponent(page.replace(/ /g, '_')) : '') + '&prop=text|categories&format=json'; // "&pst" is "Pre-save transform": tilde replacement, pipe magic for links like [[foo|]]. // Don't use a callback directly, add the function call ourselves *after* the call, since // the API somehow resolves tildes to an IP number instead of the username if a callback // is used. C.f. https://bugzilla.wikimedia.org/show_bug.cgi?id=16616 // Apparently, that's a feature, not a bug... var request_length = uri.length + args.length + 1; if (request_length > 2000) { // Long URLs are problematic for GET requests req.open('POST', uri, true); req.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded'); } else { uri += '?' + args; args = null; req.open('GET', uri, true); } req.setRequestHeader('Pragma', 'cache=no'); req.setRequestHeader('Cache-Control', 'no-transform'); req.onreadystatechange = function () { if ($.removeSpinner) $.removeSpinner('wpUploadPreviewSpinner'); if (req.readyState !== 4 || req.status !== 200) return; // Add the "callback"... if (req.responseText) UF.jsonPreview(JSON.parse(req.responseText)); }; req.send(args); } }, jsonPreview: function (result) { if (result && result.parse && result.parse.text && result.parse.text['*']) { var txt = result.parse.text['*']; var categories = result.parse.categories; if (categories && categories.length) { // Add a mock-up of a category bar. We don't care about non-existing categories, and we // can't identify hidden categories. var catbar = '<div class="catlinks"><div id="mw-normal-catlinks">' + UF.outerHTML(UFUI.getLabel('wpCategoriesUploadLbl')); categories.sort( function (a, b) { var key_a = a['*'].toLowerCase(), key_b = b['*'].toLowerCase(); if (key_a < key_b) return -1; if (key_a > key_b) return 1; return 0; }); for (var i = 0; i < categories.length; i++) { var catname = categories[i]['*']; if (catname && catname.length) { if (i > 0) catbar += ' |'; catbar += ' <a href="/wiki/Category:' + encodeURI(catname) + '">' + catname.replace(/_/g, ' ') + '</a>'; } } catbar += '</div></div>'; // Now insert it into text. var end = txt.lastIndexOf('</div>'); txt = txt.substring(0, end) + catbar + '</div>'; } UF.showPreview(txt); } }, showPreview: function (result) { if (UF.preview_tooltip) { UF.preview_content = result; UF.preview_tooltip.show_tip(null, false); } else { var preview = document.getElementById('wpUploadPreviewDisplay'); if (!preview) { var before = document.getElementById('mw-upload-permitted'); if (!before || UFUtils.isChildOf(before, UF.the_form)) before = UF.the_form; if (!before) return; // Don't know where to insert preview display. Error message here? preview = document.createElement('div'); preview.setAttribute('id', 'wpUploadPreviewDisplay'); before.parentNode.insertBefore(preview, before); } try { preview.innerHTML = result; } catch (ex) { preview.innerHTML = ''; // Error message here instead? } preview.style.display = ''; // Show it } }, hidePreview: function () { if (UF.preview_tooltip) { UF.preview_tooltip.hide_now(null); } else { var preview = document.getElementById('wpUploadPreviewDisplay'); if (preview) preview.style.display = 'none'; } }, getPreview: function () { // Callback for the tooltip var div = document.createElement('div'); div.style.display = 'none'; document.body.appendChild(div); div.innerHTML = UF.preview_content; document.body.removeChild(div); div.style.fontSize = 'smaller'; div.style.display = ''; var wrapper = document.createElement('div'); wrapper.appendChild(div); return wrapper; }, licenses_regexp: /\{\{(self|pd|gfdl|cc|l?gpl|fal|cecill|attribution|copyrighted free use|SOlicence|geograph|UN map|BArch-License|Apache)/i, user_license_regexp: new RegExp('\\{\\{[Ss]ubst:[Uu]ser:' + (mw.config.get('wgUserName') || 'null').replace(/([\\^$.?*+()[\]|{}])/g, '\\$1') + '/'), has_license: function (fields) { if (!fields || !fields.length) return false; for (var i = 0; i < fields.length; i++) { if (fields[i]) { if (typeof (fields[i]) === 'string') { if (fields[i].search(UF.licenses_regexp) >= 0) return true; } else { if (fields[i].value.search(UF.licenses_regexp) >= 0) return true; } } } for (var j = 0; j < fields.length; j++) { if (fields[j]) { if (typeof (fields[j]) === 'string') { if (fields[j].search(UF.user_license_regexp) >= 0) return true; } else { if (fields[j].value.search(UF.user_license_regexp) >= 0) return true; } } } return false; }, addAfterField: function (elem_id, element) { if (!element) return; var elem = document.getElementById(elem_id); if (!elem) return; // Find enclosing table cell. while (elem && elem.nodeName.toLowerCase() !== 'td') elem = elem.parentNode; if (!elem) return; var container = document.createElement('div'); container.style.fontSize = 'smaller'; container.appendChild(element); elem.appendChild(container); }, old_overwrite_warning: null, setupOverwriteMsg: function () { if (!window.wgUploadWarningObj || !wgUploadWarningObj.setWarning) return; var msg = document.createElement('div'); msg.id = 'wpUploadFormScriptOverwriteWarning'; msg.style.display = 'none'; msg.style.color = 'red'; msg.appendChild(UFUI.getErrorMsg('wpPreviewOverwriteError')); UF.addAfterField('wpDestFile', msg); UF.old_overwrite_warning = wgUploadWarningObj.setWarning; wgUploadWarningObj.setWarning = UF.overwriteMsg; }, overwriteMsg: function (warning) { if (!UF.old_overwrite_warning || UF.isReupload) return; // Make sure that 'this' is set to 'wgUploadWarningObj' in the call below! UF.old_overwrite_warning.apply(wgUploadWarningObj, [warning]); var is_overwrite = UF.isOverwrite(); var my_overwrite_warning = document.getElementById('wpUploadFormScriptOverwriteWarning'); if (my_overwrite_warning) my_overwrite_warning.style.display = (is_overwrite ? '' : 'none'); UF.set_fields_enabled( !is_overwrite, ['wpUploadFile', 'wpUploadFileURL', 'wpDestFile', 'wpUploadDescription', 'wpAdditionalInfo', 'wpLicense', 'wpWatchthis', 'wpIgnoreWarning', 'wpUpload']); }, isOverwrite: function () { if (document.getElementById('wpUploadWarningFileexists')) return true; var destfileWarning = document.getElementById('wpDestFile-warning'); if (!destfileWarning) return false; var destFile = document.getElementById('wpDestFile'); if (!destFile || !destFile.value) return false; var lks = destfileWarning.getElementsByTagName('a'); if (!lks || !lks.length) return false; // Trimmed, blanks replaced by underscores, first character capitalized var fn1 = destFile.value.replace(/^\s\s*/, '').replace(/\s\s*$/, '').replace(/ /g, '_'); fn1 = fn1.substr(0, 1).toUpperCase() + fn1.substring(1); var fn0 = 'Image:' + fn1; fn1 = 'File:' + fn1; var script = mw.config.get('wgScript'); var server = mw.config.get('wgServer'); for (var i = 0; i < lks.length; i++) { var href = lks[i].getAttribute('href'); if (!href || lks[i].className === 'new') continue; if (!href.indexOf(script) || !href.indexOf(server + script)) { var m = /[&?]title=([^&]*)/.exec(href); if (m && m.length > 1) href = m[1]; else href = null; } else { var prefix = mw.config.get('wgArticlePath').replace('$1', ''); if (href.indexOf(prefix)) prefix = server + prefix; // Fully expanded URL? if (!href.indexOf(prefix)) href = href.substring(prefix.length); else href = null; } if (!href) continue; href = decodeURIComponent(href).replace(/ /g, '_'); if (href === fn1 || href === fn0) return true; } return false; }, allowedFileTypes: null, forbiddenFileTypes: null, badFileNames: /^(test|image|img|bild|example|(dsc|img)?(\s|_|-)*|\d{10}(\s|_|-)[0123456789abcdef]{10}(\s|_|-)[a-z])$/i, // Filenames that have only components (separated by periods) that fully match this regexp // are considered illegal. The second-but-last one catches DSC01234, or DSC_01234, or // DSC_012_34 or also filenames conatining only digits and non-alphanumeric characters. // The last catches Flickr's raw filenames. How to relax that last expression without catching // too many legit file names? // Matching is case-insensitive. extractFileExtensions: function (div) { var list = null; // Get a mw-upload-permitted or mw-upload-prohibited div, extracts all extensions listed var txt = div; while (txt && txt.nodeType !== 3) txt = txt.lastChild; if (!txt) return null; // Try to figure out which comma to use (localizeable through MediaWiki:Comma-separator!) if (txt.data.indexOf(',') >= 0) { // Standard txt = txt.data.split(','); } else if (txt.data.indexOf('،') >= 0) { // Arabic etc. txt = txt.data.split('،'); } else if (txt.data.indexOf('、') >= 0) { // Chinese txt = txt.data.split('、'); } else { return null; } if (!txt || !txt.length) return null; for (var i = 0; i < txt.length; i++) { var match = /(\w+)\W*$/.exec(txt[i]); if (match) { match = match[1].toLowerCase(); // The extension if (!list) list = {}; list[match] = true; } } return list; }, setFileExtensions: function () { var fileExts = mw.config.get('wgFileExtensions'); if (fileExts) { // New as of 2009-09-17 UF.allowedFileTypes = {}; for (var i = 0; i < fileExts.length; i++) UF.allowedFileTypes[fileExts[i]] = true; UF.forbiddenFileTypes = null; return; } UF.allowedFileTypes = UF.extractFileExtensions(document.getElementById('mw-upload-permitted')); UF.forbiddenFileTypes = UF.extractFileExtensions(document.getElementById('mw-upload-prohibited')); if (UF.allowedFileTypes) { // Alternate OGG extensions if (UF.allowedFileTypes.ogg) { if (!UF.forbiddenFileTypes || !UF.forbiddenFileTypes.ogv) UF.allowedFileTypes.ogv = true; if (!UF.forbiddenFileTypes || !UF.forbiddenFileTypes.oga) UF.allowedFileTypes.oga = true; if (!UF.forbiddenFileTypes || !UF.forbiddenFileTypes.ogx) UF.allowedFileTypes.ogx = true; } // OpenDoc extensions (are these needed?) if (!UF.forbiddenFileTypes || !UF.forbiddenFileTypes.sxi) UF.allowedFileTypes.sxi = true; if (!UF.forbiddenFileTypes || !UF.forbiddenFileTypes.sxc) UF.allowedFileTypes.sxc = true; if (!UF.forbiddenFileTypes || !UF.forbiddenFileTypes.sxd) UF.allowedFileTypes.sxd = true; if (!UF.forbiddenFileTypes || !UF.forbiddenFileTypes.sxw) UF.allowedFileTypes.sxw = true; // PDF (allowed, but may be hidden in the interface) if (!UF.forbiddenFileTypes || !UF.forbiddenFileTypes.pdf) UF.allowedFileTypes.pdf = true; } }, checkFileExtension: function (ext, presence_only) { if (presence_only) { return (UF.allowedFileTypes && UF.allowedFileTypes[ext] === true) || (UF.forbiddenFileTypes && UF.forbiddenFileTypes[ext] === true); } return (!UF.allowedFileTypes || UF.allowedFileTypes[ext] === true) && (!UF.forbiddenFileTypes || UF.forbiddenFileTypes[ext] !== true); }, verifyFileName: function (filename) { if (!filename) { UF.errorMsgs.push('wpNoFilenameError'); return false; } if (filename.search(/(https?|file|ftp):\/\//i) >= 0) { UF.errorMsgs.push('wpHttpFilenameError'); return false; } var ok = true; // Don't allow slashes if (filename.indexOf('/') >= 0) { UF.errorMsgs.push('wpNoSlashError'); ok = false; } // Check for double extensions var fn = filename.split('.'); if (fn.length < 2 || !fn[fn.length - 1].length) { UF.errorMsgs.push('wpNoExtensionError'); ok = false; } // Check extension var nof_extensions = 0; if (fn.length >= 2) { nof_extensions++; if (UF.checkFileExtension(fn[fn.length - 1].toLowerCase())) { // It's ok, check for double extension if (fn.length > 2) { if (UF.checkFileExtension(fn[fn.length - 2].toLowerCase(), true)) { nof_extensions++; UF.errorMsgs.push('wpDoubleExtensionError'); ok = false; } } } else { UF.errorMsgs.push('wpIllegalExtensionError'); ok = false; } } // Check for allowed file name var one_ok = false; for (var i = 0; i < fn.length - nof_extensions && !one_ok; i++) { if (fn[i].length && fn[i].search(UF.badFileNames) < 0) one_ok = true; } if (!one_ok) { UF.errorMsgs.push('wpNondescriptFilenameError'); ok = false; } return ok; }, cleaner: null, clean: function (input) { if (!UF.cleaner) { // Because of asynchronous script loading, we need to check whether the TextCleaner is // already defined. If not, just return the input. if (window.TextCleaner && TextCleaner.sanitizeWikiText instanceof Function) UF.cleaner = TextCleaner.sanitizeWikiText; } if (UF.cleaner && input && typeof input === 'string') return UF.cleaner(input, true); else return input; }, resetBg: function (e) { e = e || window.event; // W3C, IE return UF.verifyMandatoryField(e.target || e.srcElement); }, verifyMandatoryField: function (node, handler) { if (!node) return true; try { if (!node.value || node.value.search(/\S/) < 0 || handler && handler instanceof Function && handler.length === 1 && !handler(node.value)) { // No value set, or a handler was given and it is a function taking one parameter, and // it returned false var isError = node.id !== 'wpPermission'; if (!isError) { var licenseField = document.getElementById('wpLicense'); // Careful here. The fromwikimedia forms appear not to have a license selector! isError = !licenseField || !licenseField.selectedIndex; } if (isError) { node.style.backgroundColor = UF.errorColor; if (!UF.warning_pushed) { if (UF.errorMsgs) UF.errorMsgs.push('wpUploadWarningError'); UF.warning_pushed = true; } return false; } } } catch (ex) { // Swallow the exception } try { node.style.backgroundColor = '#FFF'; } catch (some_error) { // Swallow. } return true; }, fixCategoryTransclusion: function (str) { return str.replace(/(\{\{)\s*(:?\s*[Cc]ategory\s*:[^|}]*(\|[^}]*)?)(\}\})/g, '[[$2]]'); } }; // end UF var UploadFormBasic = { onErrorForm: false, // True iff we're on a re-sent form (error case). setup: function (auto_fill) { // Special setup: don't use separate input fields; just verify the filename and that the // description isn't empty. var desc = document.getElementById('wpUploadDescription'); var previousForm = null; UF.previous_hotcat_state = null; if (!UF.isReupload && FormRestorer) { var currentDestFile = document.getElementById('wpDestFile'); var originalDestFile = null; if (currentDestFile) { currentDestFile = currentDestFile.value; originalDestFile = currentDestFile.defaultValue; } if (originalDestFile && originalDestFile.length) { // If originalDestFile was set to something, we're not on the original upload form but // on the re-sent form in error cases. UploadFormBasic.onErrorForm = true; } else if (currentDestFile && currentDestFile.length) { previousForm = FormRestorer.readForm('UploadFormBasic'); if (!previousForm && desc && desc.value && desc.value.length) { // Hmmm... IE sometimes cannot read the cookie (because it wasn't stored, due to some // strange security settings on some computers that I've been unable to track down). // If we're here, we have a target file name *and* a description: assume the description // comes from the browser's field value cache and make sure we don't overwrite it. auto_fill = false; } } if (previousForm) { var additionalData = previousForm[0].val; if (additionalData) { additionalData = additionalData.split('\t'); var previousFile = additionalData[0]; if (previousFile === currentDestFile) { if (additionalData.length >= 2) UF.previous_hotcat_state = additionalData[1]; } else { previousForm = null; } } } } UF.formModified = true; if (document.getElementById('wpLicense')) UF.setup_license_preview(); UF.oldOnSubmit = UF.the_form.onsubmit; UF.the_form.onsubmit = UploadFormBasic.submit; if (!UF.isReupload) UF.addPreviewButton(UploadFormBasic.preview); if (previousForm) { // Restore form values. if (desc) { var prev = UF.getPrevValue(previousForm, desc.id); if (prev) desc.value = prev; } if (UF.previous_hotcat_state && hotcat_set_state instanceof Function) { if ($('#catlinks').find('.hotcatlink').is(':hidden')) hotcat_close_form(); UF.previous_hotcat_state = hotcat_set_state(UF.previous_hotcat_state); } } else { if (!!UFConfig.autofill && auto_fill && !UF.isReupload) { if (desc) desc.value = UF.empty_template('Information'); } } if (desc && desc.value && desc.value.indexOf('{{Information') >= 0) { // Only hide the box in the Uploadtext if there is really an inormation-template in the // summary! var infobox = document.getElementById('Uploadtext-template-box'); if (infobox) infobox.style.display = 'none'; } }, submit: function (evt) { var overwrite = false; if (!UF.isReupload) overwrite = UF.isOverwrite(); if (!UploadFormBasic.verify(overwrite)) return false; if (!UF.isReupload) { var targetName = document.getElementById('wpDestFile'); if (targetName && targetName.value) { // Strip whitespace targetName.value = targetName.value.replace(/^\s\s*/, '').replace(/\s\s*$/, ''); } if (!UploadFormBasic.onErrorForm && FormRestorer && targetName && targetName.value) { var hotcat_state = null; if (hotcat_get_state instanceof Function) { if ($('#catlinks').find('.hotcatlink').is(':hidden')) hotcat_close_form(); hotcat_state = hotcat_get_state(); } // We already know that targetName.value is set! FormRestorer.saveForm( 'UploadFormBasic', UF.the_form.id, targetName.value + (hotcat_state ? '\t' + hotcat_state : ''), ';path=' + document.location.pathname + ';max-age=1800'); // Expire after half an hour. } } // end if (UF.isReupload) var desc = document.getElementById('wpUploadDescription'); var old_desc_value = desc.value; var doSubmit = UF.call_onsubmit(evt || window.event); if (!doSubmit) { desc.value = old_desc_value; } else { desc.value = UF.fixCategoryTransclusion(UF.clean(desc.value)); UF.hidePreview(); document.getElementById('wpDestFile').disabled = false; } return doSubmit; }, preview: function (/* e */) { var overwrite = UF.isOverwrite(); if (!UploadFormBasic.verify(overwrite)) return false; var desc = document.getElementById('wpUploadDescription'); UF.makePreview(UF.clean(desc.value), overwrite); return true; }, verify: function (overwrite) { var desc = document.getElementById('wpUploadDescription'); var ok = true; if (UF.isReupload) { // Only check that the description isn't empty if (UF.errorMsgs) delete UF.errorMsgs; UF.errorMsgs = []; UF.warning_pushed = false; if (!desc.value || desc.value.search(/\S/) < 0) { desc.style.backgroundColor = UF.errorColor; desc.onkeyup = UF.resetBg; UF.errorMsgs.push('wpReuploadNoSummaryError'); ok = false; } } else { if (!overwrite) { if (UF.errorMsgs) delete UF.errorMsgs; UF.errorMsgs = []; UF.warning_pushed = false; if (!UF.verifyMandatoryField(desc)) { desc.onkeyup = UF.resetBg; ok = false; } else { // We do have a non-empty description. Try to split it up and check that the fields for // author, source, and description are filled in. var fields = UF.split_description(desc.value); if (fields && fields.length === 4) { if ( !fields[1] || fields[1].search(/\S/) < 0 || // Author !fields[2] || fields[2].search(/\S/) < 0 // Source ) { desc.style.backgroundColor = UF.errorColor; desc.onkeyup = UF.resetBg; if (!UF.warning_pushed) { if (UF.errorMsgs) UF.errorMsgs.push('wpUploadWarningError'); UF.warning_pushed = true; } ok = false; } if (UF.templates[fields[0]].desc_mandatory && (!fields[3] || fields[3].search(/\S/) < 0) // Description ) { desc.style.backgroundColor = UF.errorColor; desc.onkeyup = UF.resetBg; UF.errorMsgs.push('wpNoDescriptionError'); ok = false; } } } // Try a license check var license = document.getElementById('wpLicense'); if (!license || !license.selectedIndex) { // There must be a license somewhere in the description. if (!UF.has_license([desc])) { var d = desc.value.replace(/\{\{\s*([Ii]nformation|[Pp]ainting|[Ff]lickr)\s*\n/g, ''); if (d.indexOf('{{') < 0) { // No transcludion that could provide a license either desc.style.backgroundColor = UF.errorColor; desc.onkeyup = UF.resetBg; if (!UF.warning_pushed) { if (UF.errorMsgs) UF.errorMsgs.push('wpUploadWarningError'); UF.warning_pushed = true; } ok = false; } // else assume it's ok. } } // end license check var targetName = document.getElementById('wpDestFile'); if (targetName) { // Trim leading and trailing whitespace targetName.value = targetName.value.replace(/^\s\s*/, '').replace(/\s\s*$/, ''); if (!UF.verifyFileName(targetName.value)) { targetName.style.backgroundColor = UF.errorColor; targetName.onkeyup = function (evt) { UF.resetBg(evt); if (wgUploadWarningObj && wgUploadWarningObj.keypress instanceof Function && !UF.isReupload) wgUploadWarningObj.keypress(); }; ok = false; } } } } // end if (reupload or not) if (!ok) { UF.hidePreview(); UF.display_errors(); } else { // It's ok: hide our warning box var myWarning = document.getElementById('wpUploadVerifyWarning'); if (myWarning) myWarning.style.display = 'none'; } return ok; } // end verify }; // end UploadFormBasic var UploadFormFull = { form_type: 0, // 0 - single desc field; 1 - one desc field per language field_state: null, // Will be initialized in setup below. multi_inputs: null, // If we're using several description fields, this is an array of objects pushMultiInput: function (sel, text) { if (!UploadFormFull.multi_inputs) { UploadFormFull.multi_inputs = [{ selector: sel, textfield: text } ]; } else { UploadFormFull.multi_inputs[UploadFormFull.multi_inputs.length] = { selector: sel, textfield: text }; } var idx = UploadFormFull.multi_inputs.length; sel.id = 'wpLangSel' + idx; sel.name = sel.id; text.id = 'wpDescText' + idx; text.name = text.id; }, addDescField: function (content, lang, idx, storedForm) { var selector = LanguageHandler.getSelect(null, lang, UFUI.getLabel('wpUnknownLanguageUploadLbl', true)); // These style definitions are needed for IE, which otherwise creates excessively wide // selectors, pushing the main form to the right. selector.style.maxWidth = '12em'; selector.style.width = '12em'; selector.style.overflow = 'hidden'; var textfield = document.createElement('textarea'); textfield.setAttribute('rows', UFUtils.getHeight(UFConfig.description_height, 2, 6)); textfield.style.width = '100%'; UploadFormFull.pushMultiInput(selector, textfield); var newRow = content.insertRow(idx === null ? content.rows.length : idx); var firstCell = document.createElement('td'); firstCell.classList.add('mw-label'); firstCell.setAttribute('vAlign', 'top'); firstCell.appendChild(selector); var secondCell = document.createElement('td'); secondCell.classList.add('mw-input'); secondCell.setAttribute('vAlign', 'top'); secondCell.appendChild(textfield); newRow.appendChild(firstCell); newRow.appendChild(secondCell); if (storedForm) { var prev_idx = UF.getPrevValue(storedForm, selector.id); var prev_val = UF.getPrevValue(storedForm, textfield.id); if (prev_val !== null) textfield.value = prev_val; if (prev_idx !== null) { selector.options[selector.selectedIndex].selected = false; selector.options[prev_idx].selected = true; } } UploadFormFull.enableEdittools(textfield); }, addOneDescField: function (/* e */) { // onclick handler for the button var button = document.getElementById('wpUploadAddDescription'); var table_row = button.parentNode.parentNode; var idx = table_row.rowIndex; UploadFormFull.addDescField(table_row.parentNode, null, idx, null); }, addMultiDesc: function (table, idx, storedForm) { var i; // Add en and user language, if different var userLang = LanguageHandler.closestLanguage(UFUI.userLanguage); if (userLang === 'pt-br') userLang = 'pt'; // Per request from Portuguese and Brazilians var firstCell = document.createElement('td'); firstCell.classList.add('mw-label'); var secondCell = document.createElement('td'); var new_label = document.createElement('label'); new_label.id = 'wpDescLabel'; new_label.appendChild(UFUI.getLabel('wpDescUploadLbl')); firstCell.appendChild(new_label); var newRow = table.insertRow(idx); newRow.appendChild(firstCell); newRow.appendChild(secondCell); idx++; var added = false; if (storedForm) { // Maybe we had more... find 'wpLangSel1' var curr = 0; for (i = 1; i < storedForm.length; i++) { if (storedForm[i].id === 'wpLangSel1') { curr = i; break; } } if (curr > 0) { while (curr < storedForm.length && !storedForm[curr].id.indexOf('wpLangSel')) { UploadFormFull.addDescField(table, null, idx++, storedForm); added = true; curr++; if (curr < storedForm.length && !storedForm[curr].id.indexOf('wpDescText')) curr++; } } } // end if if (!added) { if (UFConfig.description_languages && UFConfig.description_languages instanceof Array && UFConfig.description_languages.length) { for (i = 0; i < UFConfig.description_languages.length; i++) { var lang = LanguageHandler.closestLanguage(UFConfig.description_languages[i]); UploadFormFull.addDescField(table, lang, idx++, storedForm); } } else { if (UFConfig.own_language_first) { if (userLang && userLang !== UFUI.defaultLanguage) UploadFormFull.addDescField(table, userLang, idx++, storedForm); UploadFormFull.addDescField(table, UFUI.defaultLanguage, idx++, storedForm); } else { UploadFormFull.addDescField(table, UFUI.defaultLanguage, idx++, storedForm); if (userLang && userLang !== UFUI.defaultLanguage) UploadFormFull.addDescField(table, userLang, idx++, storedForm); } } } // Now add a "+" button var additional = UF.customFormButton( 'wpUploadFormAddDescButton', // Customization ID 'wpUploadAddDescription', // ID of button '+', // Default text UploadFormFull.addOneDescField // Event handler ); newRow = table.insertRow(idx++); firstCell = document.createElement('td'); secondCell = document.createElement('td'); secondCell.classList.add('mw-input'); secondCell.appendChild(additional); newRow.appendChild(firstCell); newRow.appendChild(secondCell); return idx; }, changeField: function (field_id) { // Callback for changeable field button function get_selection(field) { // Based on code from Jonas Raoni Soares Silva at http://jsfromhell.com/forms/selection // License: {{tl|attribution}} // Warning: simplified because we apply it only to an INPUT field. For TEXTAREAs, see the // URL given. if (field.selectionStart !== undefined) { return { start: field.selectionStart, end: field.selectionEnd }; } else if (field.createTextRange) { field.focus(); var s = document.selection.createRange(); if (s.parentElement() !== field) { return { start: 0, end: 0 }; } var r = field.createTextRange(); r.setEndPoint('EndToStart', s); return { start: r.text.length, end: r.text.length + s.text.length }; } return { start: 0, end: 0 }; } var field = document.getElementById(field_id); if (field.disabled) return; // Don't do anything if the field isn't enabled. var button = document.getElementById(field_id + '_Button'); var cell = field.parentNode; if (!field || !button || !cell) return; // Error message here? var newField = document.createElement('textarea'); var height = UFUtils.getHeight(UploadFormFull.field_state[field_id].height, 2, 4); newField.setAttribute('rows', height); newField.style.width = '100%'; newField.value = field.value; var sel = get_selection(field); var tab_idx = field.getAttribute('tabindex'); cell.removeChild(button); cell.replaceChild(newField, field); field.id = ''; field.onfocus = null; newField.id = field_id; newField.setAttribute('tabindex', tab_idx); UploadFormFull.enableEdittools(newField); // Restore the selection if (newField.setSelectionRange) { // e.g. khtml newField.setSelectionRange(sel.start, sel.end); } else if (newField.selectionStart !== undefined) { newField.selectionStart = sel.start; newField.selectionEnd = sel.end; } else if (newField.createTextRange) { // IE var new_selection = newField.createTextRange(); new_selection.move('character', sel.start); new_selection.moveEnd('character', sel.end - sel.start); new_selection.select(); } newField.focus(); UploadFormFull.field_state[field_id].height = height; }, enableEdittools: function (textfield) { // To be called on each dynamically added field to ensure the edit toolbar works there if (window.EditTools && EditTools.registerTextField instanceof Function) { // We have EditTools var buttons = document.getElementById('specialchars'); if (buttons && buttons.firstChild && buttons.firstChild.nodeName.toLowerCase() === 'select') { // EditTools is already set up: we have to add an onfocus handler ourselves $(textfield).focus(EditTools.registerTextField); } // Otherwise, EditTools will be set up later, and will catch this field, so we don't have // to do anything. } }, switch_intro_text: function () { // Set up the display of [[MediaWiki:Uploadtext]] var long_text = document.getElementById('wpUploadFormLongText'); var short_text = document.getElementById('wpUploadFormShortText'); if (long_text && short_text) { long_text.style.display = 'none'; if (UFUtils.isChildOf(long_text, short_text)) { // If long_text is a child of short_text, then short_text is already shown, and // long_text is just a part that isn't needed for the new upload form. Hence // we're done. return; } if (UFUtils.isChildOf(short_text, long_text)) { // If the short_text is within the long_text, we need to take it out; otherwise // it won't be shown. short_text.parentNode.removeChild(short_text); long_text.parentNode.insertBefore(short_text, long_text.nextSibling); } short_text.style.display = ''; } else { // Remove the redundant infobox in the uploadtext explanation. People should *not* // insert this template into description. var infobox = document.getElementById('Uploadtext-template-box'); if (infobox) infobox.style.display = 'none'; } }, set_hints: function () { UF.addAfterField('wpDestFile', UFUI.getHint('wpUploadFormDestFileHint')); UF.addAfterField('wpSource', UFUI.getHint('wpUploadFormSourceHint')); UF.addAfterField('wpAuthor', UFUI.getHint('wpUploadFormAuthorHint')); UF.addAfterField('wpDate', UFUI.getHint('wpUploadFormDateHint')); UF.addAfterField('wpPermission', UFUI.getHint('wpUploadFormPermissionHint')); UF.addAfterField('wpAdditionalInfo', UFUI.getHint('wpUploadFormAdditionalInfoHint')); UF.addAfterField('catlinks', UFUI.getHint('wpUploadFormCategoryHint')); }, setup: function () { function addField(table, idx, id, label, field, storedForm) { if (!label) label = UFUI.getLabel(id + 'UploadLbl'); var newRow = table.insertRow(idx); var firstCell = document.createElement('td'); firstCell.classList.add('mw-label'); var new_label = document.createElement('label'); new_label.htmlFor = id; new_label.appendChild(label); firstCell.appendChild(new_label); var secondCell = document.createElement('td'); secondCell.classList.add('mw-input'); field.setAttribute('name', id); field.setAttribute('id', id); secondCell.appendChild(field); newRow.appendChild(firstCell); newRow.appendChild(secondCell); var prev_value = UF.getPrevValue(storedForm, id); if (prev_value) field.value = prev_value; UploadFormFull.enableEdittools(field); } function addInput(table, idx, id, label, width, storedForm) { var newField = document.createElement('input'); newField.setAttribute('type', 'text'); newField.setAttribute('size', String(width)); addField(table, idx, id, label, newField, storedForm); UploadFormFull.enableEdittools(newField); return newField; } function addChangeableField(height, table, idx, id, label, width, storedForm) { var newField = null; var field_id = 'wp' + id; if (!height) height = UFUtils.getHeight(UploadFormFull.field_state[field_id].height, 1, 4); if (height > 1) { newField = document.createElement('textarea'); newField.setAttribute('rows', height); newField.style.width = '100%'; addField(table, idx, 'wp' + id, null, newField, storedForm); } else { newField = addInput(table, idx, field_id, null, 80, storedForm); var button = UF.customFormButton( 'wpUploadForm' + id + 'Button', field_id + '_Button', '...', function () { UploadFormFull.changeField(field_id); }); newField.parentNode.insertBefore(button, newField.nextSibling); } UploadFormFull.field_state[field_id].height = height; UploadFormFull.enableEdittools(newField); } function setCheckBoxes(previousForm, boxes) { if (!boxes || !boxes.length || !previousForm) return; for (var i = 0; i < boxes.length; i++) { if (boxes[i]) { var prev_val = UF.getPrevValue(previousForm, boxes[i].id); if (prev_val) boxes[i].checked = prev_val; } } } // Init the field states. Cannot be done earlier, otherwise definitions in user's // monobook.js (or modern.js, or ...) won't be taken aboard. UploadFormFull.field_state = { wpSource: { height: UFConfig.source_field_size }, wpAuthor: { height: UFConfig.author_field_size } }; var previousForm = null; var previous_type = -1; // unknown var previous_fields = [0, 0]; UF.previous_hotcat_state = null; if (FormRestorer) { // We know that when we arrive here originally, wpDestFile.value is empty, as is // wpDestFile.defaultValue. If we entered something, submitted, and then come back, // modern browsers restore form entries, at least for the fields in the static XHTML. // wpDestFile is such a static field (it isn't added by Javascript), so if we have a // non-empty value here, we know that the form needs to restored. (But see the caveat // about IE and onload handling at the bottom of the file!) var currentDestFile = document.getElementById('wpDestFile'); if (currentDestFile) currentDestFile = currentDestFile.value; if (currentDestFile && currentDestFile.length) previousForm = FormRestorer.readForm('UploadForm'); if (previousForm) { var additionalData = previousForm[0].val; if (additionalData) { additionalData = additionalData.split('\t'); var previousFile = additionalData[1]; if (previousFile === currentDestFile) { previous_type = parseInt(additionalData[0], 10); previous_fields[0] = parseInt(additionalData[2], 10); previous_fields[1] = parseInt(additionalData[3], 10); if (additionalData.length >= 5) UF.previous_hotcat_state = additionalData[4]; } else { previousForm = null; } } } } var originalDesc = document.getElementById('wpUploadDescription'); var original_row = originalDesc.parentNode.parentNode; var table = original_row.parentNode; var original_idx = original_row.rowIndex; UF.formModified = true; originalDesc.setAttribute('id', ''); UF.oldOnSubmit = UF.the_form.onsubmit; UF.the_form.onsubmit = UploadFormFull.submit; table.deleteRow(original_idx); var idx = original_idx; // Insert source field var newField = null; addChangeableField(previous_fields[0], table, idx++, 'Source', null, 80, previousForm); addChangeableField(previous_fields[1], table, idx++, 'Author', null, 80, previousForm); addInput(table, idx++, 'wpDate', null, 80, previousForm); // Insert description field if (window.LanguageHandler === undefined || !previous_type) { // Basic setup newField = document.createElement('textarea'); newField.setAttribute('rows', UFUtils.getHeight(UFConfig.description_height, 6, 12)); newField.style.width = '100%'; // Do not name the new field 'wpUploadDescription', otherwise MediaWiki:Upload.js // might prefill it with an information template! addField(table, idx++, 'wpDesc', null, newField, previousForm); UploadFormFull.form_type = 0; } else { idx = UploadFormFull.addMultiDesc(table, idx, previousForm); UploadFormFull.form_type = 1; } addInput(table, idx++, 'wpOtherVersions', null, 80, previousForm); addInput(table, idx++, 'wpPermission', null, 80, previousForm); newField = document.createElement('textarea'); newField.setAttribute('rows', UFUtils.getHeight(UFConfig.additional_info_height, 2, 10)); newField.style.width = '100%'; // Work-around Firefox's "one additional line" bug addField(table, idx++, 'wpAdditionalInfo', null, newField, previousForm); // Add a preview button. UF.addPreviewButton(UploadFormFull.preview); // Correct tab indices. for (var i = 0; i < UF.the_form.length; i++) UF.the_form.elements[i].setAttribute('tabindex', String(i)); var license = document.getElementById('wpLicense'); // Change the license previewer to not cause a table re-layout if (license) { // These style definitions are because long option labels result in excessively wide // selectors, causing also the description fields to go beyond the right border of the // page. license.style.maxWidth = '100%'; license.style.width = '100%'; license.style.overflow = 'hidden'; } UF.setup_license_preview(); if (license) { var prev = UF.getPrevValue(previousForm, 'wpLicense'); if (prev) { try { license.options[license.selectedIndex].selected = false; license.options[prev].selected = true; } catch (ex) {} } } // Pre-fill in some cases if (UFUI.isOwnWork) { var src = document.getElementById('wpSource'); var author = document.getElementById('wpAuthor'); if (src && !src.value) src.value = UF.getOwnWorkSource(); if (author && !author.value) author.value = UF.getOwnWorkAuthor(); if (typeof UFConfig.ownwork_date === 'string' && UFConfig.ownwork_date.search(/\S/) >= 0) { var date = document.getElementById('wpDate'); if (date && !date.value) date.value = UFConfig.ownwork_date; } } if (previousForm) { setCheckBoxes( previousForm, [ document.getElementById('wpWatchthis'), document.getElementById('wpIgnoreWarning') ]); } UploadFormFull.switch_intro_text(); // If HotCat is present, restore its state, too. if (UF.previous_hotcat_state && hotcat_set_state instanceof Function) { if ($('#catlinks').find('.hotcatlink').is(':hidden')) hotcat_close_form(); UF.previous_hotcat_state = hotcat_set_state(UF.previous_hotcat_state); } UploadFormFull.set_hints(); }, // end setup getDescText: function (basic) { var descText = ''; if (!UploadFormFull.multi_inputs) { var desc = document.getElementById('wpDesc'); if (desc && !desc.disabled) descText = UF.clean(desc.value); } else { for (var i = 0; i < UploadFormFull.multi_inputs.length; i++) { if (!UploadFormFull.multi_inputs[i].textfield.disabled) { var text = UploadFormFull.multi_inputs[i].textfield.value; var selector = UploadFormFull.multi_inputs[i].selector; var lang = selector.options[selector.selectedIndex].value; if (text) { text = UF.clean(text); if (descText.length) descText += '\n'; if (!basic && lang && lang !== 'unknown') { // This is Commons-specific! The tl-template is already used, the template for // Tagalog is tgl! if (lang === 'tl') lang = 'tgl'; descText += '{{' + lang + '|1=' + text + '}}'; } else { descText += text; } } } // end if !disabled } } var more_info = document.getElementById('wpAdditionalInfo'); if (!basic) { var date = document.getElementById('wpDate'); var src = document.getElementById('wpSource'); var author = document.getElementById('wpAuthor'); var other = document.getElementById('wpPermission'); var othervers = document.getElementById('wpOtherVersions'); descText = '{{Information\n' + '|description =' + descText + '\n' + '|date =' + (!date.disabled ? UF.clean(date.value) : '') + '\n' + '|source =' + (!src.disabled ? UF.clean(src.value) : '') + '\n' + '|author =' + (!author.disabled ? UF.clean(author.value) : '') + '\n' + ((other && !other.disabled && other.value) ? '|permission =' + UF.clean(other.value) + '\n' : '') + ((othervers && !othervers.disabled && othervers.value) ? '|other versions=' + UF.clean(othervers.value) + '\n' : '') + '}}\n'; } else { descText += '\n'; } // Append the additional info, if any if (more_info && !more_info.disabled && more_info.value) descText += UF.clean(more_info.value); return descText; }, submit: function (evt) { var overwrite = UF.isOverwrite(); if (!UploadFormFull.verify(overwrite)) return false; // Now put together an information-template var descText = UploadFormFull.getDescText(overwrite); var doSubmit = true; var targetName = document.getElementById('wpDestFile'); if (targetName && targetName.value) { // Strip whitespace targetName.value = targetName.value.replace(/^\s\s*/, '').replace(/\s\s*$/, ''); } var dummyDesc = document.getElementById('wpUploadDescription'); // Sometimes, we do restore from scratch, and sometimes, the browser manages to keep everything. // If so, we may have a wpUploadDescription from an earlier submission. Remove it. if (dummyDesc) dummyDesc.parentNode.removeChild(dummyDesc); if (FormRestorer && targetName && targetName.value) { var hotcat_state = null; if (hotcat_get_state instanceof Function) { if ($('#catlinks').find('.hotcatlink').is(':hidden')) hotcat_close_form(); hotcat_state = hotcat_get_state(); } // We already know that targetName.value is set! FormRestorer.saveForm( 'UploadForm', UF.the_form.id, String(UploadFormFull.form_type) + '\t' + targetName.value + '\t' + UploadFormFull.field_state.wpSource.height + '\t' + UploadFormFull.field_state.wpAuthor.height + (hotcat_state ? '\t' + hotcat_state : ''), ';path=' + document.location.pathname + ';max-age=1800'); // Expire after half an hour. } dummyDesc = document.createElement('textarea'); dummyDesc.setAttribute('rows', '6'); dummyDesc.setAttribute('cols', '80'); dummyDesc.style.display = 'none'; dummyDesc.setAttribute('name', 'wpUploadDescription'); dummyDesc.setAttribute('id', 'wpUploadDescription'); UF.the_form.appendChild(dummyDesc); dummyDesc.value = UF.fixCategoryTransclusion(descText); doSubmit = UF.call_onsubmit(evt || window.event); if (!doSubmit) { // Oops. We actually don't submit. Remove the hidden field UF.the_form.removeChild(dummyDesc); } else { UF.hidePreview(); document.getElementById('wpDestFile').disabled = false; document.getElementById('wpEditToken').disabled = false; } return doSubmit; }, preview: function (/* e */) { var overwrite = UF.isOverwrite(); if (!UploadFormFull.verify(overwrite)) return false; UF.makePreview(UploadFormFull.getDescText(overwrite), overwrite); return true; }, verify: function (overwrite) { var src = document.getElementById('wpSource'); var author = document.getElementById('wpAuthor'); // var date = document.getElementById( 'wpDate' ); var other = document.getElementById('wpPermission'); // var othervers = document.getElementById( 'wpOtherVersions' ); var moreInfo = document.getElementById('wpAdditionalInfo'); var desc; var ok = true; if (!overwrite) { if (UF.errorMsgs) delete UF.errorMsgs; UF.errorMsgs = []; UF.warning_pushed = false; if (!UF.verifyMandatoryField(src, function (src) { var flickr_ok = !UFUI.isFromFlickr || src.search(/https?:\/\/([^./]+\.)*flickr\.com/) >= 0; if (!flickr_ok) UF.errorMsgs.push('wpFlickrURLError'); return flickr_ok; })) { src.onkeyup = UF.resetBg; ok = false; } if (!UF.verifyMandatoryField(author)) { author.onkeyup = UF.resetBg; ok = false; } // Piece the description(s) together var all_descs = ''; if (!UploadFormFull.multi_inputs) { desc = document.getElementById('wpDesc'); if (desc) all_descs = desc.value; } else { for (var input_idx = 0; input_idx < UploadFormFull.multi_inputs.length; input_idx++) all_descs += UploadFormFull.multi_inputs[input_idx].textfield.value; } // License check var licenseField = document.getElementById('wpLicense'); if (!(!licenseField || licenseField.selectedIndex > 0) && !UF.has_license([all_descs, other, moreInfo])) { if (!UF.warning_pushed) { UF.errorMsgs.push('wpUploadWarningError'); UF.warning_pushed = true; } ok = false; } var targetName = document.getElementById('wpDestFile'); if (targetName) { // Trim leading and trailing whitespace targetName.value = targetName.value.replace(/^\s\s*/, '').replace(/\s\s*$/, ''); if (!UF.verifyFileName(targetName.value)) { targetName.style.backgroundColor = UF.errorColor; targetName.onkeyup = function (evt) { UF.resetBg(evt); if (wgUploadWarningObj && wgUploadWarningObj.keypress instanceof Function && !UF.isReupload) wgUploadWarningObj.keypress(); }; ok = false; } } if (UF.templates[0].desc_mandatory) { if (all_descs.search(/\S/) < 0) { if (!UploadFormFull.multi_inputs) { desc = document.getElementById('wpDesc'); if (desc) { desc.style.backgroundColor = UF.errorColor; desc.onkeyup = UF.resetBg; } } else { UploadFormFull.setMultiBg(UF.errorColor, UploadFormFull.resetMultiBg); } UF.errorMsgs.push('wpNoDescriptionError'); ok = false; } } // end description check } // end overwrite if (!ok) { UF.hidePreview(); UF.display_errors(); } else { // It's ok: hide our warning box var myWarning = document.getElementById('wpUploadVerifyWarning'); if (myWarning) myWarning.style.display = 'none'; } return ok; }, setMultiBg: function (color, handler) { if (!UploadFormFull.multi_inputs) return; for (var i = 0; i < UploadFormFull.multi_inputs.length; i++) { var field = UploadFormFull.multi_inputs[i].textfield; field.style.backgroundColor = color; field.onkeyup = handler; } }, resetMultiBg: function (evt) { if (UF.resetBg(evt)) { // Reset the backgrounds of all description fields UploadFormFull.setMultiBg('#FFF', null); } } }; // end UploadFormFull UF.install(); }(jQuery, mediaWiki)); // </nowiki>