diff --git a/js/dropzone.integration.js b/js/dropzone.integration.js index 2b8f489..21c9f12 100644 --- a/js/dropzone.integration.js +++ b/js/dropzone.integration.js @@ -9,10 +9,68 @@ (function ($, Drupal, drupalSettings) { "use strict"; + Drupal.AjaxCommands.prototype.update_dropzone = function (ajax, response, status) { + $(response.selector).val(function (i, value) { + value = value.split(';'); + value.push(response.file); + return value.join(';'); + }); + }; + + Drupal.dropzonejs = { + responseHandlers: { + /** + * Handles JSON-RPC response from DropzoneJS' UploadController. + */ + jsonRPC: { + canHandle: function (file, response) { + return response.hasOwnProperty('jsonrpc'); + }, + handle: function (file, response) { + // The file is transliterated on upload. The element has to reflect + // the real filename. + file.processedName = response.result; + + this.element.siblings(':hidden').val(function (i, value) { + value = value.split(';'); + value.push(response.result); + return value.join(';'); + }); + } + }, + + /** + * Handles response from Drupal's AJAX framework (an array of commands). + */ + drupalAjax: { + canHandle: function (file, response) { + return response instanceof Array; + }, + handle: function (file, response) { + // Create a Drupal.Ajax object so that we can call its success() method to + // run the commands in the response. + if (typeof this.drupalAjax === 'undefined') { + var settings = { + element: $(this.element) + }; + settings.url = settings.element.siblings('input[data-upload-path]').attr('data-upload-path'); + this.drupalAjax = Drupal.ajax(settings); + } + response.forEach(function (command) { + if (command.command === 'update_dropzone') { + file.processedName = command.file; + } + }) + this.drupalAjax.success(response); + } + } + } + }; + Drupal.dropzonejsInstances = []; - Drupal.behaviors.dropzonejsIntegraion = { - attach: function(context) { + Drupal.behaviors.dropzonejsIntegration = { + attach: function () { Dropzone.autoDiscover = false; var selector = $(".dropzone-enable"); selector.addClass("dropzone"); @@ -31,37 +89,23 @@ // React on add file. Add only accepted files. dropzoneInstance.on("success", function(file, response) { - var uploadedFilesElement = selector.siblings(':hidden'); - var currentValue = uploadedFilesElement.attr('value'); - - // The file is transliterated on upload. The element has to reflect - // the real filename. - file.processedName = response.result; - - uploadedFilesElement.attr('value', currentValue + response.result + ';'); + // Find the appropriate response handler. + for (var type in Drupal.dropzonejs.responseHandlers) { + var handler = Drupal.dropzonejs.responseHandlers[type]; + if (handler.canHandle.call(this, file, response)) { + handler.handle.call(this, file, response); + break; + } + } }); // React on file removing. dropzoneInstance.on("removedfile", function(file) { - var uploadedFilesElement = selector.siblings(':hidden'); - var currentValue = uploadedFilesElement.attr('value'); - - // Remove the file from the element. - if (currentValue.length) { - var fileNames = currentValue.split(";"); - for (var i in fileNames) { - if (fileNames[i] == file.processedName) { - fileNames.splice(i,1); - break; - } - } - - var newValue = fileNames.join(';'); - uploadedFilesElement.attr('value', newValue); - } + selector.siblings(':hidden').val(function (i, value) { + return value.split(';').filter(function (f) { return f !== file.processedName; }).join(';'); + }); }); } }; - }(jQuery, Drupal, drupalSettings)); diff --git a/src/Ajax/UpdateDropzoneCommand.php b/src/Ajax/UpdateDropzoneCommand.php new file mode 100644 index 0000000..4690145 --- /dev/null +++ b/src/Ajax/UpdateDropzoneCommand.php @@ -0,0 +1,57 @@ +element = $element; + $this->file = $file instanceof UploadedFile ? $file->getFilename() : $file; + } + + /** + * {@inheritdoc} + */ + public function render() { + return [ + 'command' => 'update_dropzone', + 'selector' => 'input[name="' . $this->element['uploaded_files']['#name'] . '"]', + 'file' => $this->file, + ]; + } + +} diff --git a/src/Controller/UploadController.php b/src/Controller/UploadController.php index 4af465b..1550711 100644 --- a/src/Controller/UploadController.php +++ b/src/Controller/UploadController.php @@ -39,12 +39,10 @@ class UploadController extends ControllerBase { /** * Constructs dropzone upload controller route controller. * + * @param \Drupal\dropzonejs\UploadHandlerInterface $upload_handler + * The upload handler service. * @param \Symfony\Component\HttpFoundation\Request $request * Request object. - * @param \Drupal\Core\Config\ConfigFactoryInterface $config - * Config factory. - * @param \Drupal\Core\Transliteration\PhpTransliteration $transliteration - * Transliteration service. */ public function __construct(UploadHandlerInterface $upload_handler, Request $request) { $this->uploadHandler = $upload_handler; @@ -63,6 +61,8 @@ public static function create(ContainerInterface $container) { /** * Handles DropzoneJs uploads. + * + * @return \Symfony\Component\HttpFoundation\Response */ public function handleUploads() { $file = $this->request->files->get('file'); @@ -72,10 +72,12 @@ public function handleUploads() { // @todo: Implement file_validate_size(); try { + $uri = $this->uploadHandler->handleUpload($file); + // Return JSON-RPC response. return new JsonResponse([ 'jsonrpc' => '2.0', - 'result' => basename($this->uploadHandler->handleUpload($file)), + 'result' => basename($uri), 'id' => 'id', ], 200); }