Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Qu 4501 #1556

Merged
merged 7 commits into from
Sep 12, 2024
Merged

Qu 4501 #1556

Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 14 additions & 0 deletions js/DropZone/DropZoneComponent.js
Original file line number Diff line number Diff line change
Expand Up @@ -138,6 +138,20 @@ class DropZoneComponent {
input.value = '';
input.type = '';
input.type = 'file';

let rawFiles = this.instanceManager.getFiles(id);
const dataTransfer = new DataTransfer();
let wasFile = false;
for (let i = 0; i < rawFiles.length; i++) {
if (rawFiles[i].raw instanceof File){
dataTransfer.items.add(rawFiles[i].raw);
wasFile = true;
}
}
if (wasFile){
// this guard exists as some js tests do not provide a file type as the input value.
input.files = dataTransfer.files;
}
});

// visually hide input - this should ideally be done in the CSS also to prevent a
Expand Down
43 changes: 43 additions & 0 deletions tests/js/web/DropZone/DropZoneComponentTest.js
Original file line number Diff line number Diff line change
Expand Up @@ -148,6 +148,49 @@ describe('DropZoneComponent', () => {
expect($fileInput.val()).to.equal('');
});

it('should retain the input node files on change', () => {
// we need to explicitly set type="file" here. Originally it is configured as type="text" presumably to avoid the same security issue explained below
$fileInput = $('<input type="file" id="fileInput" value="foo">');
const change = new Event('change');
const getDTFileList = (fileInput, ...appendFiles) => {
const dataTransfer = new DataTransfer();
if (fileInput.files && fileInput.files.length > 0) {
// add all our File objects to prepopulate the DataTransfer
for (let i = 0; i < fileInput.files.length; i++) {
dataTransfer.items.add(fileInput.files[i]);
}
}
appendFiles.forEach((appendFile)=>{
dataTransfer.items.add(appendFile);
});
return dataTransfer.files;
}
/**
* There is actually no way to programatically add a File object to Input.files other than to duplicate the DataTransfer process...
* This is due to strict browser security measures. Yes it is a bit of a hack, but there are simply no other options for initalising our input.
* Feel free to refactor this should a future version of ES add this functionality in some way.
*/
const file = new File(['Lorem ipsum dolor'], 'example.txt', { type: 'text/plain' });
$fileInput[0].files = getDTFileList($fileInput[0], file);

let rawFiles = [];
for (let i = 0; i < $fileInput[0].files.length; i++) {
$fileInput[0].files[i]
rawFiles.push({'raw': $fileInput[0].files[i]})
}

instanceManager.getFiles.returns(rawFiles);
dropZoneComponent.processInputNode($fileInput[0], 0, options.showInputNode);
$fileInput[0].dispatchEvent(change);
//debugger;
const dataTransferFile = getDTFileList($fileInput[0])[0];
const inputFile = $fileInput[0].files[0];
expect(inputFile.name).to.equal(dataTransferFile.name);
expect(inputFile.lastModified).to.equal(dataTransferFile.lastModified);
expect(inputFile.size).to.equal(dataTransferFile.size);
expect(inputFile.type).to.equal(dataTransferFile.type);
});

it('should not hide the input if specified in options', () => {
const options = { showInputNode: true, inputNodeId: 'fileInput' };
const display = $fileInput.css('display');
Expand Down
Loading