Merge "Add method parameter type documentation"
[lhc/web/wiklou.git] / skins / common / upload.js
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
7 licenseSelectorCheck = window.licenseSelectorCheck = function () {
8 var selector = document.getElementById( 'wpLicense' ),
9 selection = selector.options[selector.selectedIndex].value;
10 if ( selector.selectedIndex > 0 ) {
11 if ( !selection ) {
12 // Option disabled, but browser is broken and doesn't respect this
13 selector.selectedIndex = 0;
14 }
15 }
16 // We might show a preview
17 wgUploadLicenseObj.fetchPreview( selection );
18 };
19
20 function uploadSetup() {
21 // Disable URL box if the URL copy upload source type is not selected
22 var ein,
23 selector, ua, isMacIe, i,
24 optionsTable, row, td,
25 wpLicense, wpLicenseRow, wpLicenseTbody,
26 uploadSourceIds, len, onchange,
27 e = document.getElementById( 'wpSourceTypeurl' );
28 if ( e ) {
29 if ( !e.checked ) {
30 ein = document.getElementById( 'wpUploadFileURL' );
31 if ( ein ) {
32 ein.disabled = true;
33 }
34 }
35 }
36
37 // For MSIE/Mac: non-breaking spaces cause the <option> not to render.
38 // But for some reason, setting the text to itself works
39 selector = document.getElementById( 'wpLicense' );
40 if ( selector ) {
41 ua = navigator.userAgent;
42 isMacIe = ua.indexOf( 'MSIE' ) !== -1 && ua.indexOf( 'Mac' ) !== -1;
43 if ( isMacIe ) {
44 for ( i = 0; i < selector.options.length; i++ ) {
45 selector.options[i].text = selector.options[i].text;
46 }
47 }
48 }
49
50 // AJAX wpDestFile warnings
51 if ( ajaxUploadDestCheck ) {
52 // Insert an event handler that fetches upload warnings when wpDestFile
53 // has been changed
54 document.getElementById( 'wpDestFile' ).onchange = function () {
55 wgUploadWarningObj.checkNow( this.value );
56 };
57 // Insert a row where the warnings will be displayed just below the
58 // wpDestFile row
59 optionsTable = document.getElementById( 'mw-htmlform-description' ).tBodies[0];
60 row = optionsTable.insertRow( 1 );
61 td = document.createElement( 'td' );
62 td.id = 'wpDestFile-warning';
63 td.colSpan = 2;
64
65 row.appendChild( td );
66 }
67
68 wpLicense = document.getElementById( 'wpLicense' );
69 if ( mw.config.get( 'wgAjaxLicensePreview' ) && wpLicense ) {
70 // License selector check
71 wpLicense.onchange = licenseSelectorCheck;
72
73 // License selector table row
74 wpLicenseRow = wpLicense.parentNode.parentNode;
75 wpLicenseTbody = wpLicenseRow.parentNode;
76
77 row = document.createElement( 'tr' );
78 td = document.createElement( 'td' );
79 row.appendChild( td );
80 td = document.createElement( 'td' );
81 td.id = 'mw-license-preview';
82 row.appendChild( td );
83
84 wpLicenseTbody.insertBefore( row, wpLicenseRow.nextSibling );
85 }
86
87
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 }
97 }
98
99 wgUploadWarningObj = window.wgUploadWarningObj = {
100 responseCache: { '' : '&nbsp;' },
101 nameToCheck: '',
102 typing: false,
103 delay: 500, // ms
104 timeoutID: false,
105
106 keypress: function () {
107 var cached, destFile, warningElt;
108
109 if ( !ajaxUploadDestCheck ) {
110 return;
111 }
112
113 // Find file to upload
114 destFile = document.getElementById( 'wpDestFile' );
115 warningElt = document.getElementById( 'wpDestFile-warning' );
116 if ( !destFile || !warningElt ) {
117 return;
118 }
119
120 this.nameToCheck = destFile.value;
121
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 }
133
134 this.timeoutID = setTimeout( function () {
135 wgUploadWarningObj.timeout();
136 }, this.delay );
137 },
138
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 },
149
150 timeout: function () {
151 if ( !ajaxUploadDestCheck || this.nameToCheck === '' ) {
152 return;
153 }
154 window.injectSpinner( document.getElementById( 'wpDestFile' ), 'destcheck' );
155
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 },
171
172 processResult: function ( result, fileName ) {
173 window.removeSpinner( 'destcheck' );
174 this.setWarning( result.html );
175 this.responseCache[fileName] = result.html;
176 },
177
178 setWarning: function ( warning ) {
179 var warningElt = document.getElementById( 'wpDestFile-warning' ),
180 ackElt = document.getElementsByName( 'wpDestFileWarningAck' );
181
182 this.setInnerHTML(warningElt, warning);
183
184 // Set a value in the form indicating that the warning is acknowledged and
185 // doesn't need to be redisplayed post-upload
186 if ( !warning ) {
187 ackElt[0].value = '';
188 } else {
189 ackElt[0].value = '1';
190 }
191
192 },
193 setInnerHTML: function ( element, text ) {
194 // Check for no change to avoid flicker in IE 7
195 if ( element.innerHTML !== text ) {
196 element.innerHTML = text;
197 }
198 }
199 };
200
201 fillDestFilename = window.fillDestFilename = function ( id ) {
202 var e, path, slash, backslash, fname,
203 found, ext, i,
204 destFile;
205 if ( !mw.config.get( 'wgUploadAutoFill' ) ) {
206 return;
207 }
208 if ( !document.getElementById ) {
209 return;
210 }
211 // Remove any previously flagged errors
212 e = document.getElementById( 'mw-upload-permitted' );
213 if ( e ) {
214 e.className = '';
215 }
216
217 e = document.getElementById( 'mw-upload-prohibited' );
218 if ( e ) {
219 e.className = '';
220 }
221
222 path = document.getElementById( id ).value;
223 // Find trailing part
224 slash = path.lastIndexOf( '/' );
225 backslash = path.lastIndexOf( '\\' );
226 if ( slash === -1 && backslash === -1 ) {
227 fname = path;
228 } else if ( slash > backslash ) {
229 fname = path.substring( slash + 1, 10000 );
230 } else {
231 fname = path.substring( backslash + 1, 10000 );
232 }
233
234 // Clear the filename if it does not have a valid extension.
235 // URLs are less likely to have a useful extension, so don't include them in the
236 // extension check.
237 if ( mw.config.get( 'wgStrictFileExtensions' ) && fileExtensions && id !== 'wpUploadFileURL' ) {
238 found = false;
239 if ( fname.lastIndexOf( '.' ) !== -1 ) {
240 ext = fname.substr( fname.lastIndexOf( '.' ) + 1 );
241 for ( i = 0; i < fileExtensions.length; i += 1 ) {
242 if ( fileExtensions[i].toLowerCase() === ext.toLowerCase() ) {
243 found = true;
244 break;
245 }
246 }
247 }
248 if ( !found ) {
249 // Not a valid extension
250 // Clear the upload and set mw-upload-permitted to error
251 document.getElementById( id ).value = '';
252 e = document.getElementById( 'mw-upload-permitted' );
253 if ( e ) {
254 e.className = 'error';
255 }
256
257 e = document.getElementById( 'mw-upload-prohibited' );
258 if ( e ) {
259 e.className = 'error';
260 }
261
262 // Clear wpDestFile as well
263 e = document.getElementById( 'wpDestFile' );
264 if ( e ) {
265 e.value = '';
266 }
267
268 return false;
269 }
270 }
271
272 // Replace spaces by underscores
273 fname = fname.replace( / /g, '_' );
274 // Capitalise first letter if needed
275 if ( mw.config.get( 'wgCapitalizeUploads' ) ) {
276 fname = fname.charAt( 0 ).toUpperCase().concat( fname.substring( 1, 10000 ) );
277 }
278
279 // Output result
280 destFile = document.getElementById( 'wpDestFile' );
281 if ( destFile ) {
282 // Call decodeURIComponent function to remove possible URL-encoded characters
283 // from the file name (bug 30390). Especially likely with upload-form-url.
284 // decodeURIComponent can throw an exception in input is invalid utf-8
285 try {
286 destFile.value = decodeURIComponent( fname );
287 } catch ( err ) {
288 destFile.value = fname;
289 }
290 wgUploadWarningObj.checkNow( fname );
291 }
292 };
293
294 window.toggleFilenameFiller = function () {
295 if ( !document.getElementById ) {
296 return;
297 }
298 var destName = document.getElementById( 'wpDestFile' ).value;
299 mw.config.set( 'wgUploadAutoFill', !destName );
300 };
301
302 wgUploadLicenseObj = window.wgUploadLicenseObj = {
303
304 responseCache: { '' : '' },
305
306 fetchPreview: function ( license ) {
307 var cached, title;
308 if ( !mw.config.get( 'wgAjaxLicensePreview' ) ) {
309 return;
310 }
311 for ( cached in this.responseCache ) {
312 if ( cached === license ) {
313 this.showPreview( this.responseCache[license] );
314 return;
315 }
316 }
317 window.injectSpinner( document.getElementById( 'wpLicense' ), 'license' );
318
319 title = document.getElementById( 'wpDestFile' ).value;
320 if ( !title ) {
321 title = 'File:Sample.jpg';
322 }
323
324 ( new mw.Api() ).get( {
325 action: 'parse',
326 text: '{{' + license + '}}',
327 title: title,
328 prop: 'text',
329 pst: ''
330 } ).done( function ( result ) {
331 wgUploadLicenseObj.processResult( result, license );
332 } );
333 },
334
335 processResult: function ( result, license ) {
336 window.removeSpinner( 'license' );
337 this.responseCache[license] = result.parse.text['*'];
338 this.showPreview( this.responseCache[license] );
339 },
340
341 showPreview: function ( preview ) {
342 var previewPanel = document.getElementById( 'mw-license-preview' );
343 if ( previewPanel.innerHTML !== preview ) {
344 previewPanel.innerHTML = preview;
345 }
346 }
347
348 };
349
350 $( uploadSetup );
351
352 }( mediaWiki, jQuery ) );