PageRenderTime 25ms CodeModel.GetById 18ms RepoModel.GetById 0ms app.codeStats 0ms

/js/drag_drop_import.js

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