Language: s/error_log/wfWarn/
[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 // 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 $spinnerDestCheck = $.createSpinner().insertAfter( '#wpDestFile' );
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 $spinnerDestCheck.remove();
174 $spinnerDestCheck = undefined;
175 this.setWarning( result.html );
176 this.responseCache[fileName] = result.html;
177 },
178
179 setWarning: function ( warning ) {
180 var warningElt = document.getElementById( 'wpDestFile-warning' ),
181 ackElt = document.getElementsByName( 'wpDestFileWarningAck' );
182
183 this.setInnerHTML( warningElt, warning );
184
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 }
192
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 }
200 };
201
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 }
217
218 e = document.getElementById( 'mw-upload-prohibited' );
219 if ( e ) {
220 e.className = '';
221 }
222
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 }
234
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 }
257
258 e = document.getElementById( 'mw-upload-prohibited' );
259 if ( e ) {
260 e.className = 'error';
261 }
262
263 // Clear wpDestFile as well
264 e = document.getElementById( 'wpDestFile' );
265 if ( e ) {
266 e.value = '';
267 }
268
269 return false;
270 }
271 }
272
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 }
279
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 }
293 };
294
295 window.toggleFilenameFiller = function () {
296 if ( !document.getElementById ) {
297 return;
298 }
299 var destName = document.getElementById( 'wpDestFile' ).value;
300 mw.config.set( 'wgUploadAutoFill', !destName );
301 };
302
303 wgUploadLicenseObj = window.wgUploadLicenseObj = {
304
305 responseCache: { '': '' },
306
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 }
318
319 $spinnerLicense = $.createSpinner().insertAfter( '#wpLicense' );
320
321 title = document.getElementById( 'wpDestFile' ).value;
322 if ( !title ) {
323 title = 'File:Sample.jpg';
324 }
325
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 },
336
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 },
343
344 showPreview: function ( preview ) {
345 var previewPanel = document.getElementById( 'mw-license-preview' );
346 if ( previewPanel.innerHTML !== preview ) {
347 previewPanel.innerHTML = preview;
348 }
349 }
350
351 };
352
353 $( uploadSetup );
354
355 }( mediaWiki, jQuery ) );