1/* vim: set expandtab sw=4 ts=4 sts=4: */ 2 3/* This script handles PMA Drag Drop Import, loaded only when configuration is enabled.*/ 4 5/** 6 * Class to handle PMA Drag and Drop Import 7 * feature 8 */ 9var DragDropImport = { 10 /** 11 * @var int, count of total uploads in this view 12 */ 13 uploadCount: 0, 14 /** 15 * @var int, count of live uploads 16 */ 17 liveUploadCount: 0, 18 /** 19 * @var string array, allowed extensions 20 */ 21 allowedExtensions: ['sql', 'xml', 'ldi', 'mediawiki', 'shp'], 22 /** 23 * @var string array, allowed extensions for compressed files 24 */ 25 allowedCompressedExtensions: ['gz', 'bz2', 'zip'], 26 /** 27 * @var obj array to store message returned by import_status.php 28 */ 29 importStatus: [], 30 /** 31 * Checks if any dropped file has valid extension or not 32 * 33 * @param file filename 34 * 35 * @return string, extension for valid extension, '' otherwise 36 */ 37 getExtension: function (file) { 38 var arr = file.split('.'); 39 var ext = arr[arr.length - 1]; 40 41 // check if compressed 42 if (jQuery.inArray(ext.toLowerCase(), 43 DragDropImport.allowedCompressedExtensions) !== -1) { 44 ext = arr[arr.length - 2]; 45 } 46 47 // Now check for extension 48 if (jQuery.inArray(ext.toLowerCase(), 49 DragDropImport.allowedExtensions) !== -1) { 50 return ext; 51 } 52 return ''; 53 }, 54 /** 55 * Shows upload progress for different sql uploads 56 * 57 * @param: hash (string), hash for specific file upload 58 * @param: percent (float), file upload percentage 59 * 60 * @return void 61 */ 62 setProgress: function (hash, percent) { 63 $('.pma_sql_import_status div li[data-hash="' + hash + '"]') 64 .children('progress').val(percent); 65 }, 66 /** 67 * Function to upload the file asynchronously 68 * 69 * @param formData FormData object for a specific file 70 * @param hash hash of the current file upload 71 * 72 * @return void 73 */ 74 sendFileToServer: function (formData, hash) { 75 var uploadURL = './import.php'; // Upload URL 76 var jqXHR = $.ajax({ 77 xhr: function () { 78 var xhrobj = $.ajaxSettings.xhr(); 79 if (xhrobj.upload) { 80 xhrobj.upload.addEventListener('progress', function (event) { 81 var percent = 0; 82 var position = event.loaded || event.position; 83 var total = event.total; 84 if (event.lengthComputable) { 85 percent = Math.ceil(position / total * 100); 86 } 87 // Set progress 88 DragDropImport.setProgress(hash, percent); 89 }, false); 90 } 91 return xhrobj; 92 }, 93 url: uploadURL, 94 type: 'POST', 95 contentType:false, 96 processData: false, 97 cache: false, 98 data: formData, 99 success: function (data) { 100 DragDropImport.importFinished(hash, false, data.success); 101 if (!data.success) { 102 DragDropImport.importStatus[DragDropImport.importStatus.length] = { 103 hash: hash, 104 message: data.error 105 }; 106 } 107 } 108 }); 109 110 // -- provide link to cancel the upload 111 $('.pma_sql_import_status div li[data-hash="' + hash + 112 '"] span.filesize').html('<span hash="' + 113 hash + '" class="pma_drop_file_status" task="cancel">' + 114 Messages.dropImportMessageCancel + '</span>'); 115 116 // -- add event listener to this link to abort upload operation 117 $('.pma_sql_import_status div li[data-hash="' + hash + 118 '"] span.filesize span.pma_drop_file_status') 119 .on('click', function () { 120 if ($(this).attr('task') === 'cancel') { 121 jqXHR.abort(); 122 $(this).html('<span>' + Messages.dropImportMessageAborted + '</span>'); 123 DragDropImport.importFinished(hash, true, false); 124 } else if ($(this).children('span').html() === 125 Messages.dropImportMessageFailed) { 126 // -- view information 127 var $this = $(this); 128 $.each(DragDropImport.importStatus, 129 function (key, value) { 130 if (value.hash === hash) { 131 $('.pma_drop_result:visible').remove(); 132 var filename = $this.parent('span').attr('data-filename'); 133 $('body').append('<div class="pma_drop_result"><h2>' + 134 Messages.dropImportImportResultHeader + ' - ' + 135 filename + '<span class="close">x</span></h2>' + value.message + '</div>'); 136 $('.pma_drop_result').draggable(); // to make this dialog draggable 137 } 138 }); 139 } 140 }); 141 }, 142 /** 143 * Triggered when an object is dragged into the PMA UI 144 * 145 * @param event obj 146 * 147 * @return void 148 */ 149 dragEnter : function (event) { 150 // We don't want to prevent users from using 151 // browser's default drag-drop feature on some page(s) 152 if ($('.noDragDrop').length !== 0) { 153 return; 154 } 155 156 event.stopPropagation(); 157 event.preventDefault(); 158 if (!DragDropImport.hasFiles(event)) { 159 return; 160 } 161 if (CommonParams.get('db') === '') { 162 $('.pma_drop_handler').html(Messages.dropImportSelectDB); 163 } else { 164 $('.pma_drop_handler').html(Messages.dropImportDropFiles); 165 } 166 $('.pma_drop_handler').fadeIn(); 167 }, 168 /** 169 * Check if dragged element contains Files 170 * 171 * @param event the event object 172 * 173 * @return bool 174 */ 175 hasFiles: function (event) { 176 return !(typeof event.originalEvent.dataTransfer.types === 'undefined' || 177 $.inArray('Files', event.originalEvent.dataTransfer.types) < 0 || 178 $.inArray( 179 'application/x-moz-nativeimage', 180 event.originalEvent.dataTransfer.types 181 ) >= 0); 182 }, 183 /** 184 * Triggered when dragged file is being dragged over PMA UI 185 * 186 * @param event obj 187 * 188 * @return void 189 */ 190 dragOver: function (event) { 191 // We don't want to prevent users from using 192 // browser's default drag-drop feature on some page(s) 193 if ($('.noDragDrop').length !== 0) { 194 return; 195 } 196 197 event.stopPropagation(); 198 event.preventDefault(); 199 if (!DragDropImport.hasFiles(event)) { 200 return; 201 } 202 $('.pma_drop_handler').fadeIn(); 203 }, 204 /** 205 * Triggered when dragged objects are left 206 * 207 * @param event obj 208 * 209 * @return void 210 */ 211 dragLeave: function (event) { 212 // We don't want to prevent users from using 213 // browser's default drag-drop feature on some page(s) 214 if ($('.noDragDrop').length !== 0) { 215 return; 216 } 217 event.stopPropagation(); 218 event.preventDefault(); 219 var $dropHandler = $('.pma_drop_handler'); 220 $dropHandler.clearQueue().stop(); 221 $dropHandler.fadeOut(); 222 $dropHandler.html(Messages.dropImportDropFiles); 223 }, 224 /** 225 * Called when upload has finished 226 * 227 * @param string, unique hash for a certain upload 228 * @param bool, true if upload was aborted 229 * @param bool, status of sql upload, as sent by server 230 * 231 * @return void 232 */ 233 importFinished: function (hash, aborted, status) { 234 $('.pma_sql_import_status div li[data-hash="' + hash + '"]') 235 .children('progress').hide(); 236 var icon = 'icon ic_s_success'; 237 // -- provide link to view upload status 238 if (!aborted) { 239 if (status) { 240 $('.pma_sql_import_status div li[data-hash="' + hash + 241 '"] span.filesize span.pma_drop_file_status') 242 .html('<span>' + Messages.dropImportMessageSuccess + '</a>'); 243 } else { 244 $('.pma_sql_import_status div li[data-hash="' + hash + 245 '"] span.filesize span.pma_drop_file_status') 246 .html('<span class="underline">
246' + Messages.dropImportMessageFailed + 247 '</a>'); 248 icon = 'icon ic_s_error'; 249 } 250 } else { 251 icon = 'icon ic_s_notice'; 252 } 253 $('.pma_sql_import_status div li[data-hash="' + hash + 254 '"] span.filesize span.pma_drop_file_status') 255 .attr('task', 'info'); 256 257 // Set icon 258 $('.pma_sql_import_status div li[data-hash="' + hash + '"]') 259 .prepend('<img src="./themes/dot.gif" title="finished" class="' + 260 icon + '"> '); 261 262 // Decrease liveUploadCount by one 263 $('.pma_import_count').html(--DragDropImport.liveUploadCount); 264 if (!DragDropImport.liveUploadCount) { 265 $('.pma_sql_import_status h2 .close').fadeIn(); 266 } 267 }, 268 /** 269 * Triggered when dragged objects are dropped to UI 270 * From this function, the AJAX Upload operation is initiated 271 * 272 * @param event object 273 * 274 * @return void 275 */ 276 drop: function (event) { 277 // We don't want to prevent users from using 278 // browser's default drag-drop feature on some page(s) 279 if ($('.noDragDrop').length !== 0) { 280 return; 281 } 282 283 var dbname = CommonParams.get('db'); 284 var server = CommonParams.get('server'); 285 286 // if no database is selected -- no 287 if (dbname !== '') { 288 var files = event.originalEvent.dataTransfer.files; 289 if (!files || files.length === 0) { 290 // No files actually transferred 291 $('.pma_drop_handler').fadeOut(); 292 event.stopPropagation(); 293 event.preventDefault(); 294 return; 295 } 296 $('.pma_sql_import_status').slideDown(); 297 for (var i = 0; i < files.length; i++) { 298 var ext = (DragDropImport.getExtension(files[i].name)); 299 var hash = AJAX.hash(++DragDropImport.uploadCount); 300 301 var $sqlImportStatusDiv = $('.pma_sql_import_status div'); 302 $sqlImportStatusDiv.append('<li data-hash="' + hash + '">' + 303 ((ext !== '') ? '' : '<img src="./themes/dot.gif" title="invalid format" class="icon ic_s_notice"> ') + 304 Functions.escapeHtml(files[i].name) + '<span class="filesize" data-filename="' + 305 Functions.escapeHtml(files[i].name) + '">' + (files[i].size / 1024).toFixed(2) + 306 ' kb</span></li>'); 307 308 // scroll the UI to bottom 309 $sqlImportStatusDiv.scrollTop( 310 $sqlImportStatusDiv.scrollTop() + 50 311 ); // 50 hardcoded for now 312 313 if (ext !== '') { 314 // Increment liveUploadCount by one 315 $('.pma_import_count').html(++DragDropImport.liveUploadCount); 316 $('.pma_sql_import_status h2 .close').fadeOut(); 317 318 $('.pma_sql_import_status div li[data-hash="' + hash + '"]') 319 .append('<br><progress max="100" value="2"></progress>'); 320 321 // uploading 322 var fd = new FormData(); 323 fd.append('import_file', files[i]); 324 fd.append('noplugin', Math.random().toString(36).substring(2, 12)); 325 fd.append('db', dbname); 326 fd.append('server', server); 327 fd.append('token', CommonParams.get('token')); 328 fd.append('import_type', 'database'); 329 // todo: method to find the value below 330 fd.append('MAX_FILE_SIZE', '4194304'); 331 // todo: method to find the value below 332 fd.append('charset_of_file','utf-8'); 333 // todo: method to find the value below 334 fd.append('allow_interrupt', 'yes'); 335 fd.append('skip_queries', '0'); 336 fd.append('format',ext); 337 fd.append('sql_compatibility','NONE'); 338 fd.append('sql_no_auto_value_on_zero','something'); 339 fd.append('ajax_request','true'); 340 fd.append('hash', hash); 341 342 // init uploading 343 DragDropImport.sendFileToServer(fd, hash); 344 } else if (!DragDropImport.liveUploadCount) { 345 $('.pma_sql_import_status h2 .close').fadeIn(); 346 } 347 } 348 } 349 $('.pma_drop_handler').fadeOut(); 350 event.stopPropagation(); 351 event.preventDefault(); 352 } 353}; 354 355/** 356 * Called when some user drags, dragover, leave 357 * a file to the PMA UI 358 * @param object Event data 359 * @return void 360 */ 361$(document).on('dragenter', DragDropImport.dragEnter); 362$(document).on('dragover', DragDropImport.dragOver); 363$(document).on('dragleave', '.pma_drop_handler', DragDropImport.dragLeave); 364 365// when file is dropped to PMA UI 366$(document).on('drop', 'body', DragDropImport.drop); 367 368// minimizing-maximising the sql ajax upload status 369$(document).on('click', '.pma_sql_import_status h2 .minimize', function () { 370 if ($(this).attr('toggle') === 'off') { 371 $('.pma_sql_import_status div').css('height','270px'); 372 $(this).attr('toggle','on'); 373 $(this).html('-'); // to minimize 374 } else { 375 $('.pma_sql_import_status div').css('height','0px'); 376 $(this).attr('toggle','off'); 377 $(this).html('+'); // to maximise 378 } 379}); 380 381// closing sql ajax upload status 382$(document).on('click', '.pma_sql_import_status h2 .close', function () { 383 $('.pma_sql_import_status').fadeOut(function () { 384 $('.pma_sql_import_status div').html(''); 385 DragDropImport.importStatus = []; // clear the message array 386 }); 387}); 388 389// Closing the import result box 390$(document).on('click', '.pma_drop_result h2 .close', function () { 391 $(this).parent('h2').parent('div').remove(); 392});
Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.