Skip to content
This repository has been archived by the owner on Jan 5, 2018. It is now read-only.

Integrate with Drupal's AJAX framework #20

Open
wants to merge 11 commits into
base: 8.x-1.x
Choose a base branch
from
98 changes: 71 additions & 27 deletions js/dropzone.integration.js
Original file line number Diff line number Diff line change
Expand Up @@ -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");
Expand All @@ -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));
57 changes: 57 additions & 0 deletions src/Ajax/UpdateDropzoneCommand.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
<?php

/**
* @file
* Contains \Drupal\dropzonejs\Ajax\UpdateDropzoneCommand.
*/

namespace Drupal\dropzonejs\Ajax;

use Drupal\Core\Ajax\CommandInterface;
use Symfony\Component\HttpFoundation\File\UploadedFile;

/**
* Defines an Ajax command which updates a dropzone element with a list of
* successfully uploaded file names.
*/
class UpdateDropzoneCommand implements CommandInterface {

/**
* The form element to be updated.
*
* @var array
*/
protected $element;

/**
* The name of the uploaded file.
*
* @var string
*/
protected $file;

/**
* UpdateDropzoneCommand constructor.
*
* @param array $element
* The form element to be updated.
* @param string|\Symfony\Component\HttpFoundation\File\UploadedFile $file
* The uploaded file name, or an UploadedFile object.
*/
public function __construct(array $element, $file) {
$this->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,
];
}

}
12 changes: 7 additions & 5 deletions src/Controller/UploadController.php
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand All @@ -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');
Expand All @@ -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);
}
Expand Down