Closed clementmas closed 5 years ago
Thanks @clementmas !
I think the best approach would be to fork the image-preview plugin and then make alterations there. It should be relatively easy to add an input field to the HTML, you could use the setMetadata
method on the item
to add data to each file.
Hi, Rik, I would like to add a caption-input field to any item, too, but I cannot find the HTML in your image-preview-plugin, where I could put it in. Can you perhaps help me? I'm quite a newbie in JS and don't understand it. Thx a lot! And by the way, awesome job with filepond. We will buy your Pintura-Plugin, soon.
Greetings Stefan
@sbritz This is where in the poster plugin (which is used with Pintura) the image element is added, it's similar for the image preview plugin: https://github.com/pqina/filepond-plugin-file-poster/blob/master/src/js/view/createPosterView.js#L14-L15
@clementmas did you manage to find an easy way?
I do have a working solution. This code adds <input name="captions[]" />
fields for all the uploaded items:
/* filepond-plugin-image-caption.js */
import { FileStatus } from 'filepond';
/**
* FilePond image caption plugin
*
* FilePondPluginImageCaption 1.0.3
* Author: clementmas
* Licensed under MIT, https://opensource.org/licenses/MIT
*/
export default function ({ addFilter, utils }) {
const { Type, createRoute, createView } = utils;
// Called when a new file is added
addFilter('CREATE_VIEW', function (viewAPI) {
const { is, view, query } = viewAPI;
// Make sure the option `addImageCaption` is enabled
if (!query('GET_ADD_IMAGE_CAPTION')) return;
// Skip invalid file types
if (!is('file')) return;
function onItemAdded({ root, props: { id } }) {
const item = query('GET_ITEM', id);
// Item could theoretically have been removed in the mean time
if (!item || item.archived) return;
const value = item.getMetadata('caption');
const isInvalid = item.status === FileStatus.LOAD_ERROR;
// Append image caption input
root.ref.imagePreview = view.appendChildView(
view.createChildView(
createView(addCaptionInputField(value, isInvalid)),
{
id,
},
),
);
// Disable file action buttons tabindex (cancel, revert, etc.)
// to easily tab from one caption input to another
view.element
.querySelectorAll('button')
.forEach((button) => button.setAttribute('tabindex', -1));
}
view.registerWriter(
createRoute({
DID_INIT_ITEM: onItemAdded,
}),
);
});
// Plugin config options
return {
options: {
// Enable or disable image captions
addImageCaption: [true, Type.BOOLEAN],
// Input placeholder
imageCaptionPlaceholder: [null, Type.STRING],
// Input max length
imageCaptionMaxLength: [null, Type.INT],
},
};
}
// Create DOM input
function addCaptionInputField(value, isInvalid) {
return {
name: 'image-caption-input',
tag: 'input',
ignoreRect: true,
create: function create({ root }) {
// Input name
root.element.setAttribute('name', 'captions[]');
// Value
if (value) {
root.element.value = value;
}
// Placeholder
const placeholder = root.query('GET_IMAGE_CAPTION_PLACEHOLDER');
if (placeholder) {
root.element.setAttribute('placeholder', placeholder);
}
// Max length
const maxLength = root.query('GET_IMAGE_CAPTION_MAX_LENGTH');
if (maxLength) {
root.element.setAttribute('maxlength', maxLength);
}
// Autocomplete off
root.element.setAttribute('autocomplete', 'off');
// Visually hide the element if the file is invalid but keep the input
// to make sure the "captions[]" index will stay in sync with the FilePond photos
if (isInvalid) {
root.element.classList.add('image-caption-input-invalid');
}
// Prevent Enter key from submitting form
root.element.addEventListener('keydown', function (e) {
if (e.key === 'Enter') {
e.preventDefault();
}
});
},
};
}
/* filepond-plugin-image-caption.css */
input.filepond--image-caption-input {
position: absolute;
width: 100%;
height: 38px;
bottom: 0;
left: 0;
opacity: 0.7;
padding: 0 10px;
border: 0;
outline: 0;
border-bottom-left-radius: 4px;
border-bottom-right-radius: 4px;
z-index: 10;
transition: opacity 0.2s;
background: white;
font-size: 14px;
font-weight: normal;
color: rgba(0, 0, 0, 0.87);
}
input.filepond--image-caption-input:focus {
opacity: 0.9;
}
input.filepond--image-caption-input.image-caption-input-invalid {
visibility: hidden;
width: 0;
height: 0;
padding: 0;
}
Usage:
import * as FilePond from 'filepond';
import FilePondPluginImageCaption from './filepond-plugin-image-caption.js';
import 'filepond/dist/filepond.min.css';
import './filepond-plugin-image-caption.css';
// Register the plugin
FilePond.registerPlugin(FilePondPluginImageCaption);
FilePond.create(fileInputEl, {
// ...
// Caption (custom plugin)
imageCaptionPlaceholder: 'Description...',
imageCaptionMaxLength: 255,
});
Then I deal with the input values on the backend on form submission.
I considered creating an official plugin but I find the code quite messy. It's mostly boilerplate. I think FilePond v5 needs to seriously improve the plugin system.
@clementmas wow thanks!
@clementmas
~import './filepond-plugin-image-caption.css';
this line doesn't seem to have any effect, the input was visible for a moment while image was loading and disappeared after things settled. I'm not that familiar with JS, but is this how CSS should be imported?~
I was adding this in another project https://github.com/filamentphp/filament and managed to resolve the issue, thanks!
@clementmas
I'm totally new to filepond and its API interface indeed looks hard to comprehend. Would you know of any examples to write the description into the exif of the images?
Most people read the EXIF data but I don't know how or why you would write to it.
If you're just looking to associate the description to each uploaded file on the frontend, you can use the setMetadata
method as Rik suggested.
However, if you're not familiar with JS, you should post your question on a support forum or hire someone.
I think FilePond v5 needs to seriously improve the plugin system.
It's going to be a lot easier.
@clementmas
My reason for EXIF is due to the multiple "interfaces" I need to bridge: JS, filepond, Filament, Livewire, Laravel.
Having it in just JS will avoid the need to submit PRs which may not be accepted, and EXIFs are glued to the images.
Thanks anyway, your example was already of great help!
Thanks @clementmas !
I think the best approach would be to fork the image-preview plugin and then make alterations there. It should be relatively easy to add an input field to the HTML, you could use the
setMetadata
method on theitem
to add data to each file.
@rikschennink
I'm looking into this. Would it mean that we can only add captions before uploading? Or can we also update captions of images that have already been uploaded?
Most people read the EXIF data but I don't know how or why you would write to it.
If you're just looking to associate the description to each uploaded file on the frontend, you can use the
setMetadata
method as Rik suggested.However, if you're not familiar with JS, you should post your question on a support forum or hire someone.
I managed to setMetadata('caption')
on the file now. So here is the flow:
setMetadata('caption', caption)
is triggeredAppreciate if someone can help me out with the lifecycle of filepond. Thank you.
@clementmas
~
import './filepond-plugin-image-caption.css';
this line doesn't seem to have any effect, the input was visible for a moment while image was loading and disappeared after things settled. I'm not that familiar with JS, but is this how CSS should be imported?~I was adding this in another project https://github.com/filamentphp/filament and managed to resolve the issue, thanks!
Hi friend, I would like to add this functionality to Filament and I see that you did it, can you help me? How did you implement it?
But I have faced one issue that I still haven't fixed. When I go to our Edit page, it loads very slowly. I debugged the code and found the issue with FilePond, which is used five times on the page to upload images in Laravel Livewire. I reduced the number of FilePond instances one by one, and the page became more efficient in terms of speed as I reduced them.
Do you have any ideas on how to fix this issue in Laravel?
Hi @rikschennink, great work with this modern file upload library!
I need to allow users to add a caption/description for each photo uploaded. I looked into creating a custom plugin to add an input below each file but it looks like quite an undertaking.
Would you have any pointers on how to go about this? Or is there already some code out there I could use?
Thanks! Clement