Merge "Remove unused messages 'edit-externally' and 'edit-externally-help'"
[mediawiki.git] / skins / common / upload.js
blobd639f63a140a97da3143cdef4374b8bf6dc6ee7d
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;
15                 }
16         }
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;
34                         }
35                 }
36         }
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;
47                         }
48                 }
49         }
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 );
57                 };
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 );
67         }
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 );
86         }
89         // fillDestFile setup
90         uploadSourceIds = mw.config.get( 'wgUploadSourceIds' );
91         len = uploadSourceIds.length;
92         onchange = function () {
93                 fillDestFilename( this.id );
94         };
95         for ( i = 0; i < len; i += 1 ) {
96                 document.getElementById( uploadSourceIds[i] ).onchange = onchange;
97         }
100 wgUploadWarningObj = window.wgUploadWarningObj = {
101         responseCache: { '' : '&nbsp;' },
102         nameToCheck: '',
103         typing: false,
104         delay: 500, // ms
105         timeoutID: false,
107         keypress: function () {
108                 var cached, destFile, warningElt;
110                 if ( !ajaxUploadDestCheck ) {
111                         return;
112                 }
114                 // Find file to upload
115                 destFile = document.getElementById( 'wpDestFile' );
116                 warningElt = document.getElementById( 'wpDestFile-warning' );
117                 if ( !destFile || !warningElt ) {
118                         return;
119                 }
121                 this.nameToCheck = destFile.value;
123                 // Clear timer
124                 if ( this.timeoutID ) {
125                         clearTimeout( this.timeoutID );
126                 }
127                 // Check response cache
128                 for ( cached in this.responseCache ) {
129                         if ( this.nameToCheck === cached ) {
130                                 this.setWarning(this.responseCache[this.nameToCheck]);
131                                 return;
132                         }
133                 }
135                 this.timeoutID = setTimeout( function () {
136                         wgUploadWarningObj.timeout();
137                 }, this.delay );
138         },
140         checkNow: function ( fname ) {
141                 if ( !ajaxUploadDestCheck ) {
142                         return;
143                 }
144                 if ( this.timeoutID ) {
145                         clearTimeout( this.timeoutID );
146                 }
147                 this.nameToCheck = fname;
148                 this.timeout();
149         },
151         timeout: function () {
152                 if ( !ajaxUploadDestCheck || this.nameToCheck === '' ) {
153                         return;
154                 }
155                 $spinnerDestCheck = $.createSpinner().insertAfter( '#wpDestFile' );
157                 var uploadWarningObj = this;
158                 ( new mw.Api() ).get( {
159                         action: 'query',
160                         titles: ( new mw.Title( this.nameToCheck, mw.config.get( 'wgNamespaceIds' ).file ) ).getPrefixedText(),
161                         prop: 'imageinfo',
162                         iiprop: 'uploadwarning',
163                         indexpageids: ''
164                 } ).done( function ( result ) {
165                         var resultOut = '';
166                         if ( result.query ) {
167                                 resultOut = result.query.pages[result.query.pageids[0]].imageinfo[0];
168                         }
169                         uploadWarningObj.processResult( resultOut, uploadWarningObj.nameToCheck );
170                 } );
171         },
173         processResult: function ( result, fileName ) {
174                 $spinnerDestCheck.remove();
175                 $spinnerDestCheck = undefined;
176                 this.setWarning( result.html );
177                 this.responseCache[fileName] = result.html;
178         },
180         setWarning: function ( warning ) {
181                 var warningElt = document.getElementById( 'wpDestFile-warning' ),
182                         ackElt = document.getElementsByName( 'wpDestFileWarningAck' );
184                 this.setInnerHTML( warningElt, warning );
186                 // Set a value in the form indicating that the warning is acknowledged and
187                 // doesn't need to be redisplayed post-upload
188                 if ( !warning ) {
189                         ackElt[0].value = '';
190                 } else {
191                         ackElt[0].value = '1';
192                 }
194         },
195         setInnerHTML: function ( element, text ) {
196                 // Check for no change to avoid flicker in IE 7
197                 if ( element.innerHTML !== text ) {
198                         element.innerHTML = text;
199                 }
200         }
203 fillDestFilename = window.fillDestFilename = function ( id ) {
204         var e, path, slash, backslash, fname,
205                 found, ext, i,
206                 destFile;
207         if ( !mw.config.get( 'wgUploadAutoFill' ) ) {
208                 return;
209         }
210         if ( !document.getElementById ) {
211                 return;
212         }
213         // Remove any previously flagged errors
214         e = document.getElementById( 'mw-upload-permitted' );
215         if ( e ) {
216                 e.className = '';
217         }
219         e = document.getElementById( 'mw-upload-prohibited' );
220         if ( e ) {
221                 e.className = '';
222         }
224         path = document.getElementById( id ).value;
225         // Find trailing part
226         slash = path.lastIndexOf( '/' );
227         backslash = path.lastIndexOf( '\\' );
228         if ( slash === -1 && backslash === -1 ) {
229                 fname = path;
230         } else if ( slash > backslash ) {
231                 fname = path.substring( slash + 1, 10000 );
232         } else {
233                 fname = path.substring( backslash + 1, 10000 );
234         }
236         // Clear the filename if it does not have a valid extension.
237         // URLs are less likely to have a useful extension, so don't include them in the
238         // extension check.
239         if ( mw.config.get( 'wgStrictFileExtensions' ) && fileExtensions && id !== 'wpUploadFileURL' ) {
240                 found = false;
241                 if ( fname.lastIndexOf( '.' ) !== -1 ) {
242                         ext = fname.substr( fname.lastIndexOf( '.' ) + 1 );
243                         for ( i = 0; i < fileExtensions.length; i += 1 ) {
244                                 if ( fileExtensions[i].toLowerCase() === ext.toLowerCase() ) {
245                                         found = true;
246                                         break;
247                                 }
248                         }
249                 }
250                 if ( !found ) {
251                         // Not a valid extension
252                         // Clear the upload and set mw-upload-permitted to error
253                         document.getElementById( id ).value = '';
254                         e = document.getElementById( 'mw-upload-permitted' );
255                         if ( e ) {
256                                 e.className = 'error';
257                         }
259                         e = document.getElementById( 'mw-upload-prohibited' );
260                         if ( e ) {
261                                 e.className = 'error';
262                         }
264                         // Clear wpDestFile as well
265                         e = document.getElementById( 'wpDestFile' );
266                         if ( e ) {
267                                 e.value = '';
268                         }
270                         return false;
271                 }
272         }
274         // Replace spaces by underscores
275         fname = fname.replace( / /g, '_' );
276         // Capitalise first letter if needed
277         if ( mw.config.get( 'wgCapitalizeUploads' ) ) {
278                 fname = fname.charAt( 0 ).toUpperCase().concat( fname.substring( 1, 10000 ) );
279         }
281         // Output result
282         destFile = document.getElementById( 'wpDestFile' );
283         if ( destFile ) {
284                 // Call decodeURIComponent function to remove possible URL-encoded characters
285                 // from the file name (bug 30390). Especially likely with upload-form-url.
286                 // decodeURIComponent can throw an exception in input is invalid utf-8
287                 try {
288                         destFile.value = decodeURIComponent( fname );
289                 } catch ( err ) {
290                         destFile.value = fname;
291                 }
292                 wgUploadWarningObj.checkNow( fname );
293         }
296 window.toggleFilenameFiller = function () {
297         if ( !document.getElementById ) {
298                 return;
299         }
300         var destName = document.getElementById( 'wpDestFile' ).value;
301         mw.config.set( 'wgUploadAutoFill', !destName );
304 wgUploadLicenseObj = window.wgUploadLicenseObj = {
306         responseCache: { '' : '' },
308         fetchPreview: function ( license ) {
309                 var cached, title;
310                 if ( !mw.config.get( 'wgAjaxLicensePreview' ) ) {
311                         return;
312                 }
313                 for ( cached in this.responseCache ) {
314                         if ( cached === license ) {
315                                 this.showPreview( this.responseCache[license] );
316                                 return;
317                         }
318                 }
320                 $spinnerLicense = $.createSpinner().insertAfter( '#wpLicense' );
322                 title = document.getElementById( 'wpDestFile' ).value;
323                 if ( !title ) {
324                         title = 'File:Sample.jpg';
325                 }
327                 ( new mw.Api() ).get( {
328                         action: 'parse',
329                         text: '{{' + license + '}}',
330                         title: title,
331                         prop: 'text',
332                         pst: ''
333                 } ).done( function ( result ) {
334                         wgUploadLicenseObj.processResult( result, license );
335                 } );
336         },
338         processResult: function ( result, license ) {
339                 $spinnerLicense.remove();
340                 $spinnerLicense = undefined;
341                 this.responseCache[license] = result.parse.text['*'];
342                 this.showPreview( this.responseCache[license] );
343         },
345         showPreview: function ( preview ) {
346                 var previewPanel = document.getElementById( 'mw-license-preview' );
347                 if ( previewPanel.innerHTML !== preview ) {
348                         previewPanel.innerHTML = preview;
349                 }
350         }
354 $( uploadSetup );
356 }( mediaWiki, jQuery ) );