Merge changes I8b6b8510,I1cae6174
[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 $spinnerDestCheck, $spinnerLicense;
7
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 );
19 };
20
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 }
37
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 }
50
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;
65
66 row.appendChild( td );
67 }
68
69 wpLicense = document.getElementById( 'wpLicense' );
70 if ( mw.config.get( 'wgAjaxLicensePreview' ) && wpLicense ) {
71 // License selector check
72 wpLicense.onchange = licenseSelectorCheck;
73
74 // License selector table row
75 wpLicenseRow = wpLicense.parentNode.parentNode;
76 wpLicenseTbody = wpLicenseRow.parentNode;
77
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 );
84
85 wpLicenseTbody.insertBefore( row, wpLicenseRow.nextSibling );
86 }
87
88
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 }
98 }
99
100 wgUploadWarningObj = window.wgUploadWarningObj = {
101 responseCache: { '' : '&nbsp;' },
102 nameToCheck: '',
103 typing: false,
104 delay: 500, // ms
105 timeoutID: false,
106
107 keypress: function () {
108 var cached, destFile, warningElt;
109
110 if ( !ajaxUploadDestCheck ) {
111 return;
112 }
113
114 // Find file to upload
115 destFile = document.getElementById( 'wpDestFile' );
116 warningElt = document.getElementById( 'wpDestFile-warning' );
117 if ( !destFile || !warningElt ) {
118 return;
119 }
120
121 this.nameToCheck = destFile.value;
122
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 }
134
135 this.timeoutID = setTimeout( function () {
136 wgUploadWarningObj.timeout();
137 }, this.delay );
138 },
139
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 },
150
151 timeout: function () {
152 if ( !ajaxUploadDestCheck || this.nameToCheck === '' ) {
153 return;
154 }
155 $spinnerDestCheck = $.createSpinner().insertAfter( '#wpDestFile' );
156
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 },
172
173 processResult: function ( result, fileName ) {
174 $spinnerDestCheck.remove();
175 $spinnerDestCheck = undefined;
176 this.setWarning( result.html );
177 this.responseCache[fileName] = result.html;
178 },
179
180 setWarning: function ( warning ) {
181 var warningElt = document.getElementById( 'wpDestFile-warning' ),
182 ackElt = document.getElementsByName( 'wpDestFileWarningAck' );
183
184 this.setInnerHTML( warningElt, warning );
185
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 }
193
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 }
201 };
202
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 }
218
219 e = document.getElementById( 'mw-upload-prohibited' );
220 if ( e ) {
221 e.className = '';
222 }
223
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 }
235
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 }
258
259 e = document.getElementById( 'mw-upload-prohibited' );
260 if ( e ) {
261 e.className = 'error';
262 }
263
264 // Clear wpDestFile as well
265 e = document.getElementById( 'wpDestFile' );
266 if ( e ) {
267 e.value = '';
268 }
269
270 return false;
271 }
272 }
273
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 }
280
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 }
294 };
295
296 window.toggleFilenameFiller = function () {
297 if ( !document.getElementById ) {
298 return;
299 }
300 var destName = document.getElementById( 'wpDestFile' ).value;
301 mw.config.set( 'wgUploadAutoFill', !destName );
302 };
303
304 wgUploadLicenseObj = window.wgUploadLicenseObj = {
305
306 responseCache: { '' : '' },
307
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 }
319
320 $spinnerLicense = $.createSpinner().insertAfter( '#wpLicense' );
321
322 title = document.getElementById( 'wpDestFile' ).value;
323 if ( !title ) {
324 title = 'File:Sample.jpg';
325 }
326
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 },
337
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 },
344
345 showPreview: function ( preview ) {
346 var previewPanel = document.getElementById( 'mw-license-preview' );
347 if ( previewPanel.innerHTML !== preview ) {
348 previewPanel.innerHTML = preview;
349 }
350 }
351
352 };
353
354 $( uploadSetup );
355
356 }( mediaWiki, jQuery ) );