Merge "Align image frame padding with core"
[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;
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         }
88         // fillDestFile setup
89         uploadSourceIds = mw.config.get( 'wgUploadSourceIds' );
90         len = uploadSourceIds.length;
91         onchange = function () {
92                 fillDestFilename( this.id );
93         };
94         for ( i = 0; i < len; i += 1 ) {
95                 document.getElementById( uploadSourceIds[i] ).onchange = onchange;
96         }
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;
111                 }
113                 // Find file to upload
114                 destFile = document.getElementById( 'wpDestFile' );
115                 warningElt = document.getElementById( 'wpDestFile-warning' );
116                 if ( !destFile || !warningElt ) {
117                         return;
118                 }
120                 this.nameToCheck = destFile.value;
122                 // Clear timer
123                 if ( this.timeoutID ) {
124                         clearTimeout( this.timeoutID );
125                 }
126                 // Check response cache
127                 for ( cached in this.responseCache ) {
128                         if ( this.nameToCheck === cached ) {
129                                 this.setWarning(this.responseCache[this.nameToCheck]);
130                                 return;
131                         }
132                 }
134                 this.timeoutID = setTimeout( function () {
135                         wgUploadWarningObj.timeout();
136                 }, this.delay );
137         },
139         checkNow: function ( fname ) {
140                 if ( !ajaxUploadDestCheck ) {
141                         return;
142                 }
143                 if ( this.timeoutID ) {
144                         clearTimeout( this.timeoutID );
145                 }
146                 this.nameToCheck = fname;
147                 this.timeout();
148         },
150         timeout: function () {
151                 if ( !ajaxUploadDestCheck || this.nameToCheck === '' ) {
152                         return;
153                 }
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];
167                         }
168                         uploadWarningObj.processResult( resultOut, uploadWarningObj.nameToCheck );
169                 } );
170         },
172         processResult: function ( result, fileName ) {
173                 $spinnerDestCheck.remove();
174                 $spinnerDestCheck = undefined;
175                 this.setWarning( result.html );
176                 this.responseCache[fileName] = result.html;
177         },
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';
191                 }
193         },
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;
198                 }
199         }
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;
208         }
209         if ( !document.getElementById ) {
210                 return;
211         }
212         // Remove any previously flagged errors
213         e = document.getElementById( 'mw-upload-permitted' );
214         if ( e ) {
215                 e.className = '';
216         }
218         e = document.getElementById( 'mw-upload-prohibited' );
219         if ( e ) {
220                 e.className = '';
221         }
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 );
233         }
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;
246                                 }
247                         }
248                 }
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';
256                         }
258                         e = document.getElementById( 'mw-upload-prohibited' );
259                         if ( e ) {
260                                 e.className = 'error';
261                         }
263                         // Clear wpDestFile as well
264                         e = document.getElementById( 'wpDestFile' );
265                         if ( e ) {
266                                 e.value = '';
267                         }
269                         return false;
270                 }
271         }
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 ) );
278         }
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;
290                 }
291                 wgUploadWarningObj.checkNow( fname );
292         }
295 window.toggleFilenameFiller = function () {
296         if ( !document.getElementById ) {
297                 return;
298         }
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;
311                 }
312                 for ( cached in this.responseCache ) {
313                         if ( cached === license ) {
314                                 this.showPreview( this.responseCache[license] );
315                                 return;
316                         }
317                 }
319                 $spinnerLicense = $.createSpinner().insertAfter( '#wpLicense' );
321                 title = document.getElementById( 'wpDestFile' ).value;
322                 if ( !title ) {
323                         title = 'File:Sample.jpg';
324                 }
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                 } );
335         },
337         processResult: function ( result, license ) {
338                 $spinnerLicense.remove();
339                 $spinnerLicense = undefined;
340                 this.responseCache[license] = result.parse.text['*'];
341                 this.showPreview( this.responseCache[license] );
342         },
344         showPreview: function ( preview ) {
345                 var previewPanel = document.getElementById( 'mw-license-preview' );
346                 if ( previewPanel.innerHTML !== preview ) {
347                         previewPanel.innerHTML = preview;
348                 }
349         }
353 $( uploadSetup );
355 }( mediaWiki, jQuery ) );