The version of vichan running on lainchan.org
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

193 lines
4.9KB

  1. /*
  2. * file-selector.js - Add support for drag and drop file selection, and paste from clipboard on supported browsers.
  3. *
  4. * Usage:
  5. * $config['additional_javascript'][] = 'js/jquery.min.js';
  6. * $config['additional_javascript'][] = 'js/ajax.js';
  7. * $config['additional_javascript'][] = 'js/file-selector.js';
  8. */
  9. function init_file_selector(max_images) {
  10. $(document).ready(function () {
  11. // add options panel item
  12. if (window.Options && Options.get_tab('general')) {
  13. Options.extend_tab('general', '<label id="file-drag-drop"><input type="checkbox">' + _('Drag and drop file selection') + '</label>');
  14. $('#file-drag-drop>input').on('click', function() {
  15. if ($('#file-drag-drop>input').is(':checked')) {
  16. localStorage.file_dragdrop = 'true';
  17. } else {
  18. localStorage.file_dragdrop = 'false';
  19. }
  20. });
  21. if (typeof localStorage.file_dragdrop === 'undefined') localStorage.file_dragdrop = 'true';
  22. if (localStorage.file_dragdrop === 'true') $('#file-drag-drop>input').prop('checked', true);
  23. }
  24. });
  25. // disabled by user, or incompatible browser.
  26. if (localStorage.file_dragdrop == 'false' || !(window.URL.createObjectURL && window.File))
  27. return;
  28. // multipost not enabled
  29. if (typeof max_images == 'undefined') {
  30. var max_images = 1;
  31. }
  32. $('<div class="dropzone-wrap" style="display: none;">'+
  33. '<div class="dropzone" tabindex="0">'+
  34. '<div class="file-hint">'+_('Select/drop/paste files here')+'</div>'+
  35. '<div class="file-thumbs"></div>'+
  36. '</div>'+
  37. '</div>'+
  38. '</div>').prependTo('#upload td');
  39. var files = [];
  40. $('#upload_file').remove(); // remove the original file selector
  41. $('.dropzone-wrap').css('user-select', 'none').show(); // let jquery add browser specific prefix
  42. function addFile(file) {
  43. if (files.length == max_images)
  44. return;
  45. files.push(file);
  46. addThumb(file);
  47. }
  48. function removeFile(file) {
  49. files.splice(files.indexOf(file), 1);
  50. }
  51. function getThumbElement(file) {
  52. return $('.tmb-container').filter(function(){return($(this).data('file-ref')==file);});
  53. }
  54. function addThumb(file) {
  55. var fileName = (file.name.length < 24) ? file.name : file.name.substr(0, 22) + '…';
  56. var fileType = file.type.split('/')[0];
  57. var fileExt = file.type.split('/')[1];
  58. var $container = $('<div>')
  59. .addClass('tmb-container')
  60. .data('file-ref', file)
  61. .append(
  62. $('<div>').addClass('remove-btn').html('✖'),
  63. $('<div>').addClass('file-tmb'),
  64. $('<div>').addClass('tmb-filename').html(fileName)
  65. )
  66. .appendTo('.file-thumbs');
  67. var $fileThumb = $container.find('.file-tmb');
  68. if (fileType == 'image') {
  69. // if image file, generate thumbnail
  70. var objURL = window.URL.createObjectURL(file);
  71. $fileThumb.css('background-image', 'url('+ objURL +')');
  72. } else {
  73. $fileThumb.html('<span>' + fileExt.toUpperCase() + '</span>');
  74. }
  75. }
  76. $(document).on('ajax_before_post', function (e, formData) {
  77. for (var i=0; i<max_images; i++) {
  78. var key = 'file';
  79. if (i > 0) key += i + 1;
  80. if (typeof files[i] === 'undefined') break;
  81. formData.append(key, files[i]);
  82. }
  83. });
  84. // clear file queue and UI on success
  85. $(document).on('ajax_after_post', function () {
  86. files = [];
  87. $('.file-thumbs').empty();
  88. });
  89. var dragCounter = 0;
  90. var dropHandlers = {
  91. dragenter: function (e) {
  92. e.stopPropagation();
  93. e.preventDefault();
  94. if (dragCounter === 0) $('.dropzone').addClass('dragover');
  95. dragCounter++;
  96. },
  97. dragover: function (e) {
  98. // needed for webkit to work
  99. e.stopPropagation();
  100. e.preventDefault();
  101. },
  102. dragleave: function (e) {
  103. e.stopPropagation();
  104. e.preventDefault();
  105. dragCounter--;
  106. if (dragCounter === 0) $('.dropzone').removeClass('dragover');
  107. },
  108. drop: function (e) {
  109. e.stopPropagation();
  110. e.preventDefault();
  111. $('.dropzone').removeClass('dragover');
  112. dragCounter = 0;
  113. var fileList = e.originalEvent.dataTransfer.files;
  114. for (var i=0; i<fileList.length; i++) {
  115. addFile(fileList[i]);
  116. }
  117. }
  118. };
  119. // attach handlers
  120. $(document).on(dropHandlers);
  121. $(document).on('click', '.dropzone .remove-btn', function (e) {
  122. e.stopPropagation();
  123. var file = $(e.target).parent().data('file-ref');
  124. getThumbElement(file).remove();
  125. removeFile(file);
  126. });
  127. $(document).on('keypress click', '.dropzone', function (e) {
  128. e.stopPropagation();
  129. // accept mouse click or Enter
  130. if ((e.which != 1 || e.target.className != 'file-hint') &&
  131. e.which != 13)
  132. return;
  133. var $fileSelector = $('<input type="file" multiple>');
  134. $fileSelector.on('change', function (e) {
  135. if (this.files.length > 0) {
  136. for (var i=0; i<this.files.length; i++) {
  137. addFile(this.files[i]);
  138. }
  139. }
  140. $(this).remove();
  141. });
  142. $fileSelector.click();
  143. });
  144. $(document).on('paste', function (e) {
  145. var clipboard = e.originalEvent.clipboardData;
  146. if (typeof clipboard.items != 'undefined' && clipboard.items.length != 0) {
  147. //Webkit
  148. for (var i=0; i<clipboard.items.length; i++) {
  149. if (clipboard.items[i].kind != 'file')
  150. continue;
  151. //convert blob to file
  152. var file = new File([clipboard.items[i].getAsFile()], 'ClipboardImage.png', {type: 'image/png'});
  153. addFile(file);
  154. }
  155. }
  156. });
  157. }