Merge "Make update.php file executable"
[mediawiki.git] / skins / common / upload.js
blob7933cafb7050f5a6c80718204baca367792096e0
1 /*jshint camelcase:false */
2 ( function ( mw, $ ) {
3 var licenseSelectorCheck, wgUploadWarningObj, wgUploadLicenseObj, fillDestFilename,
4 ajaxUploadDestCheck = mw.config.get( 'wgAjaxUploadDestCheck' ),
5 fileExtensions = mw.config.get( 'wgFileExtensions' ),
6 $spinnerDestCheck, $spinnerLicense;
8 licenseSelectorCheck = window.licenseSelectorCheck = function () {
9 var selector = document.getElementById( 'wpLicense' ),
10 selection = selector.options[selector.selectedIndex].value;
11 if ( selector.selectedIndex > 0 ) {
12 if ( !selection ) {
13 // Option disabled, but browser is broken and doesn't respect this
14 selector.selectedIndex = 0;
17 // We might show a preview
18 wgUploadLicenseObj.fetchPreview( selection );
21 function uploadSetup() {
22 // Disable URL box if the URL copy upload source type is not selected
23 var ein,
24 selector, ua, isMacIe, i,
25 optionsTable, row, td,
26 wpLicense, wpLicenseRow, wpLicenseTbody,
27 uploadSourceIds, len, onchange,
28 e = document.getElementById( 'wpSourceTypeurl' );
29 if ( e ) {
30 if ( !e.checked ) {
31 ein = document.getElementById( 'wpUploadFileURL' );
32 if ( ein ) {
33 ein.disabled = true;
38 // For MSIE/Mac: non-breaking spaces cause the <option> not to render.
39 // But for some reason, setting the text to itself works
40 selector = document.getElementById( 'wpLicense' );
41 if ( selector ) {
42 ua = navigator.userAgent;
43 isMacIe = ua.indexOf( 'MSIE' ) !== -1 && ua.indexOf( 'Mac' ) !== -1;
44 if ( isMacIe ) {
45 for ( i = 0; i < selector.options.length; i++ ) {
46 selector.options[i].text = selector.options[i].text;
51 // AJAX wpDestFile warnings
52 if ( ajaxUploadDestCheck ) {
53 // Insert an event handler that fetches upload warnings when wpDestFile
54 // has been changed
55 document.getElementById( 'wpDestFile' ).onchange = function () {
56 wgUploadWarningObj.checkNow( this.value );
58 // Insert a row where the warnings will be displayed just below the
59 // wpDestFile row
60 optionsTable = document.getElementById( 'mw-htmlform-description' ).tBodies[0];
61 row = optionsTable.insertRow( 1 );
62 td = document.createElement( 'td' );
63 td.id = 'wpDestFile-warning';
64 td.colSpan = 2;
66 row.appendChild( td );
69 wpLicense = document.getElementById( 'wpLicense' );
70 if ( mw.config.get( 'wgAjaxLicensePreview' ) && wpLicense ) {
71 // License selector check
72 wpLicense.onchange = licenseSelectorCheck;
74 // License selector table row
75 wpLicenseRow = wpLicense.parentNode.parentNode;
76 wpLicenseTbody = wpLicenseRow.parentNode;
78 row = document.createElement( 'tr' );
79 td = document.createElement( 'td' );
80 row.appendChild( td );
81 td = document.createElement( 'td' );
82 td.id = 'mw-license-preview';
83 row.appendChild( td );
85 wpLicenseTbody.insertBefore( row, wpLicenseRow.nextSibling );
88 // fillDestFile setup
89 uploadSourceIds = mw.config.get( 'wgUploadSourceIds' );
90 len = uploadSourceIds.length;
91 onchange = function () {
92 fillDestFilename( this.id );
94 for ( i = 0; i < len; i += 1 ) {
95 document.getElementById( uploadSourceIds[i] ).onchange = onchange;
99 wgUploadWarningObj = window.wgUploadWarningObj = {
100 responseCache: { '': '&nbsp;' },
101 nameToCheck: '',
102 typing: false,
103 delay: 500, // ms
104 timeoutID: false,
106 keypress: function () {
107 var cached, destFile, warningElt;
109 if ( !ajaxUploadDestCheck ) {
110 return;
113 // Find file to upload
114 destFile = document.getElementById( 'wpDestFile' );
115 warningElt = document.getElementById( 'wpDestFile-warning' );
116 if ( !destFile || !warningElt ) {
117 return;
120 this.nameToCheck = destFile.value;
122 // Clear timer
123 if ( this.timeoutID ) {
124 clearTimeout( this.timeoutID );
126 // Check response cache
127 for ( cached in this.responseCache ) {
128 if ( this.nameToCheck === cached ) {
129 this.setWarning(this.responseCache[this.nameToCheck]);
130 return;
134 this.timeoutID = setTimeout( function () {
135 wgUploadWarningObj.timeout();
136 }, this.delay );
139 checkNow: function ( fname ) {
140 if ( !ajaxUploadDestCheck ) {
141 return;
143 if ( this.timeoutID ) {
144 clearTimeout( this.timeoutID );
146 this.nameToCheck = fname;
147 this.timeout();
150 timeout: function () {
151 if ( !ajaxUploadDestCheck || this.nameToCheck === '' ) {
152 return;
154 $spinnerDestCheck = $.createSpinner().insertAfter( '#wpDestFile' );
156 var uploadWarningObj = this;
157 ( new mw.Api() ).get( {
158 action: 'query',
159 titles: ( new mw.Title( this.nameToCheck, mw.config.get( 'wgNamespaceIds' ).file ) ).getPrefixedText(),
160 prop: 'imageinfo',
161 iiprop: 'uploadwarning',
162 indexpageids: ''
163 } ).done( function ( result ) {
164 var resultOut = '';
165 if ( result.query ) {
166 resultOut = result.query.pages[result.query.pageids[0]].imageinfo[0];
168 uploadWarningObj.processResult( resultOut, uploadWarningObj.nameToCheck );
169 } );
172 processResult: function ( result, fileName ) {
173 $spinnerDestCheck.remove();
174 $spinnerDestCheck = undefined;
175 this.setWarning( result.html );
176 this.responseCache[fileName] = result.html;
179 setWarning: function ( warning ) {
180 var warningElt = document.getElementById( 'wpDestFile-warning' ),
181 ackElt = document.getElementsByName( 'wpDestFileWarningAck' );
183 this.setInnerHTML( warningElt, warning );
185 // Set a value in the form indicating that the warning is acknowledged and
186 // doesn't need to be redisplayed post-upload
187 if ( !warning ) {
188 ackElt[0].value = '';
189 } else {
190 ackElt[0].value = '1';
194 setInnerHTML: function ( element, text ) {
195 // Check for no change to avoid flicker in IE 7
196 if ( element.innerHTML !== text ) {
197 element.innerHTML = text;
202 fillDestFilename = window.fillDestFilename = function ( id ) {
203 var e, path, slash, backslash, fname,
204 found, ext, i,
205 destFile;
206 if ( !mw.config.get( 'wgUploadAutoFill' ) ) {
207 return;
209 if ( !document.getElementById ) {
210 return;
212 // Remove any previously flagged errors
213 e = document.getElementById( 'mw-upload-permitted' );
214 if ( e ) {
215 e.className = '';
218 e = document.getElementById( 'mw-upload-prohibited' );
219 if ( e ) {
220 e.className = '';
223 path = document.getElementById( id ).value;
224 // Find trailing part
225 slash = path.lastIndexOf( '/' );
226 backslash = path.lastIndexOf( '\\' );
227 if ( slash === -1 && backslash === -1 ) {
228 fname = path;
229 } else if ( slash > backslash ) {
230 fname = path.substring( slash + 1, 10000 );
231 } else {
232 fname = path.substring( backslash + 1, 10000 );
235 // Clear the filename if it does not have a valid extension.
236 // URLs are less likely to have a useful extension, so don't include them in the
237 // extension check.
238 if ( mw.config.get( 'wgStrictFileExtensions' ) && fileExtensions && id !== 'wpUploadFileURL' ) {
239 found = false;
240 if ( fname.lastIndexOf( '.' ) !== -1 ) {
241 ext = fname.substr( fname.lastIndexOf( '.' ) + 1 );
242 for ( i = 0; i < fileExtensions.length; i += 1 ) {
243 if ( fileExtensions[i].toLowerCase() === ext.toLowerCase() ) {
244 found = true;
245 break;
249 if ( !found ) {
250 // Not a valid extension
251 // Clear the upload and set mw-upload-permitted to error
252 document.getElementById( id ).value = '';
253 e = document.getElementById( 'mw-upload-permitted' );
254 if ( e ) {
255 e.className = 'error';
258 e = document.getElementById( 'mw-upload-prohibited' );
259 if ( e ) {
260 e.className = 'error';
263 // Clear wpDestFile as well
264 e = document.getElementById( 'wpDestFile' );
265 if ( e ) {
266 e.value = '';
269 return false;
273 // Replace spaces by underscores
274 fname = fname.replace( / /g, '_' );
275 // Capitalise first letter if needed
276 if ( mw.config.get( 'wgCapitalizeUploads' ) ) {
277 fname = fname.charAt( 0 ).toUpperCase().concat( fname.substring( 1, 10000 ) );
280 // Output result
281 destFile = document.getElementById( 'wpDestFile' );
282 if ( destFile ) {
283 // Call decodeURIComponent function to remove possible URL-encoded characters
284 // from the file name (bug 30390). Especially likely with upload-form-url.
285 // decodeURIComponent can throw an exception in input is invalid utf-8
286 try {
287 destFile.value = decodeURIComponent( fname );
288 } catch ( err ) {
289 destFile.value = fname;
291 wgUploadWarningObj.checkNow( fname );
295 window.toggleFilenameFiller = function () {
296 if ( !document.getElementById ) {
297 return;
299 var destName = document.getElementById( 'wpDestFile' ).value;
300 mw.config.set( 'wgUploadAutoFill', !destName );
303 wgUploadLicenseObj = window.wgUploadLicenseObj = {
305 responseCache: { '': '' },
307 fetchPreview: function ( license ) {
308 var cached, title;
309 if ( !mw.config.get( 'wgAjaxLicensePreview' ) ) {
310 return;
312 for ( cached in this.responseCache ) {
313 if ( cached === license ) {
314 this.showPreview( this.responseCache[license] );
315 return;
319 $spinnerLicense = $.createSpinner().insertAfter( '#wpLicense' );
321 title = document.getElementById( 'wpDestFile' ).value;
322 if ( !title ) {
323 title = 'File:Sample.jpg';
326 ( new mw.Api() ).get( {
327 action: 'parse',
328 text: '{{' + license + '}}',
329 title: title,
330 prop: 'text',
331 pst: ''
332 } ).done( function ( result ) {
333 wgUploadLicenseObj.processResult( result, license );
334 } );
337 processResult: function ( result, license ) {
338 $spinnerLicense.remove();
339 $spinnerLicense = undefined;
340 this.responseCache[license] = result.parse.text['*'];
341 this.showPreview( this.responseCache[license] );
344 showPreview: function ( preview ) {
345 var previewPanel = document.getElementById( 'mw-license-preview' );
346 if ( previewPanel.innerHTML !== preview ) {
347 previewPanel.innerHTML = preview;
353 $( uploadSetup );
355 }( mediaWiki, jQuery ) );