How to display an image uploaded with input type="file" as a src attribute - forms

I tried creating an input which allows users to display images they uploaded as an html img. All of this needs to happen on 'submit'.
My js code for input (which is inside a form) looks like this:
const imageInput = document.createElement('input');
imageInput.type = 'file';
imageInput.accept = ".png, .jpg, .jpeg";
and this is how I'd like to output my image
const displayImg = (e) => {
e.preventDefault();
const questionImg = document.createElement('img');
questionImg.src = imageInput.value;
}
image.addEventListener('submit', displayImg);
It obviously doesn't work since imageInput.value looks something like this C:\fakepath\pizza.jpg
Then how can I set the uploaded file as the source of an image.
I found some helpful code on youtube that I tried that manages to output the uploaded img as div's background-image https://codepen.io/codefoxx/pen/QWvqMya but it stops working once I try to output it as the src or add form, submit button and change the event listener to "submit".

Related

Tinymce - How can I specify a directory on my server to use when I insert an image?

This works fine if I was to implement uploading an image via tinymce etc, which I'm really not interested in doing.
I already have hundreds of images uploaded from another part of the website that I'd like to insert into pages being edited and created with tinymce v5.
But how can I indicate in the Insert/Edit dialog box to show just the contents of one directory on the server?
I had a hack from vers 3 something I think it was that I can't locate, and it being so ancient I'm sure it's pretty useless, it didn't even support Safari, so it had to be 10+ years old.
Can't find anything in tinymce docs about indicating a directory to use with insert image.
Some custom javascript to include somewhere???
My basic starter tinymce code:
<script>
tinymce.init({
selector: '#editor',
plugins: 'image code',
toolbar: 'undo redo | link image | code',
/* enable title field in the Image dialog*/
image_title: true,
/* enable automatic uploads of images represented by blob or data URIs*/
automatic_uploads: true,
/*
URL of our upload handler (for more details check: https://www.tiny.cloud/docs/configure/file-
image-upload/#images_upload_url)
images_upload_url: 'postAcceptor.php',
here we add custom filepicker only to Image dialog
*/
file_picker_types: 'image',
/* and here's our custom image picker*/
file_picker_callback: function (cb, value, meta) {
var input = document.createElement('input');
input.setAttribute('type', 'file');
input.setAttribute('accept', 'image/*');
/*
Note: In modern browsers input[type="file"] is functional without
even adding it to the DOM, but that might not be the case in some older
or quirky browsers like IE, so you might want to add it to the DOM
just in case, and visually hide it. And do not forget do remove it
once you do not need it anymore.
*/
input.onchange = function () {
var file = this.files[0];
var reader = new FileReader();
reader.onload = function () {
/*
Note: Now we need to register the blob in TinyMCEs image blob
registry. In the next release this part hopefully won't be
necessary, as we are looking to handle it internally.
*/
var id = 'blobid' + (new Date()).getTime();
var blobCache = tinymce.activeEditor.editorUpload.blobCache;
var base64 = reader.result.split(',')[1];
var blobInfo = blobCache.create(id, file, base64);
blobCache.add(blobInfo);
/* call the callback and populate the Title field with the file name */
cb(blobInfo.blobUri(), { title: file.name });
};
reader.readAsDataURL(file);
};
input.click();
},
content_style: 'body { font-family:Helvetica,Arial,sans-serif; font-size:14px }'
});
</strict>
There are several ways to do so:
MoxieManager plugin. Here is the demo. However, it's a premium feature.
Depends on the number of images you have on the server. If there aren't many, you can try to use the image_list option of the Image plugin. It will load the editor with a predefined set of images.
Implement the custom file picker with the file_picker_callback option.

Express [413 too large] with QuillJS image

I am trying to use QuillJS to let the user write a rich text, and then store it as JSON to display later on. There are 2 of these rich text areas in a single form, and may include images. QuillJS encodes images as base64 strings, and my POST request results in 413 by Express.
I have tried to change the limits by adding express json parameters, even trying extreme numbers.
// app.js
//----------------------------------------------------
// Middlewares
//----------------------------------------------------
app.use(express.json({limit: '2000mb'}));
app.use(express.urlencoded({extended: true, limit:'2000mb'}));
Even this did not help and I think it is not logical to let these parameters with such values.
I tried with json and urlencoded enctypes. When I tried to post with multipart/form, req.body was empty.
// My html page (pugJS)
form(enctype='application/x-www-form-urlencoded', action='/editor/page',
method='POST', onsubmit='return addContent()')
.form-control
label Content-1
div#toolbar
div#editor
input#content(name='content', type='text', hidden)
addContent() function that runs before form submit simply changes input#content's value with JSON.stringify(#editor.getContents())
I want to be able to store two quill content in a single database row, to display later.
A better approach to this would be to overwrite the image upload function and then save the image in Amazon S3 or some cloud server. Then you paste it inside the editor as <img src="http://uploaded-image-url"> This would solve your problem of maximum memory issue.
I fixed my problem few hours before #argo mentioned and I did it that way. So I wanted to post little bit of detail to the solution. I have been also guided by a github issue but can't seem to find the link again, in case I find it I will edit the post and add it.
// Quill - EN content
var quillEn = new Quill('#editor-en', {
modules: {
toolbar: toolbarOptions
},
theme: 'snow'
});
// set custom image handler
quillEn.getModule('toolbar').addHandler('image', () => {
selectLocalImage(quillEn);
});
// create fake input to upload image to quill
function selectLocalImage(editor) {
const input = document.createElement('input');
input.setAttribute('type', 'file');
input.setAttribute('accept', 'image/png, image/jpeg')
input.click();
// Listen upload local image and save to server
input.onchange = () => {
const file = input.files[0];
saveImageToServer(editor, file);
};
}
// upload image to server
function saveImageToServer(editor, file) {
const fd = new FormData();
fd.append('image', file);
const xhr = new XMLHttpRequest();
xhr.open('POST', '/api/page/upload_image', true);
xhr.onload = () => {
if (xhr.status === 200) {
// this is callback data: url
const url = JSON.parse(xhr.responseText).data;
insertToEditor(editor, url);
}
};
xhr.send(fd);
}
// manipulate quill to replace b64 image with uploaded image
function insertToEditor(editor, url) {
// push image url to rich editor.
const range = editor.getSelection();
editor.insertEmbed(range.index, 'image', url.toString());
}
In the backend where you POST image, you must return json as { data: FullUrlToImg } with 200 response, if you want to change your status to 201 or something else, don't forget to update it in saveImageToServer function.
So to summarize, you set custom image handler for your quill editor, you post the image to server as soon as user chooses to insert, then you replace the URL with your uploaded image in the editor.
Thanks.

Show loading Screen while Image is loading in wicket

I'am populating a ListView with images.
In pseudocode:
populateItem(model){
load base64 from database
image.setDefaultModel(base64)
The image is just a webcomponent and in html it is just <img src="">
How can i show a indicator while the image is loaded?.
I first thought of adding IAjaxIndicatorAware but this triggers the indicator when the image is doing an AjaxRequest.
Since you seem to load and display the image as a Base64 src it will directly get send in the html response and not loaded later (in contrast to images with a src that links to another URI).
You could wrap the image in an AjaxLazyLoadPanel.
This will first display an AjaxIndicator while the content is generated and get later replaced by the actual loaded content once it is done loading/generating:
edit
I got an Exception : Component must be applied to a tag of type [img].
i didn't consider that problem. AjaxLazyLoadPanel allways uses a <div> as a html tag to display the component it loads. To display a base 64 image you would need to wrap it in another Panel:
public class Base64ImagePanel extends Panel {
public Base64ImagePanel(String wicketId, String base64Data, String contentType) {
super(wicketId);
WebMarkupContainer image = new WebMarkupContainer("image") {
protected void onComponentTag(ComponentTag tag) {
super.onComponentTag(tag);
checkComponentTag(tag, "img");
tag.put("src", "data:" + contentType + ";base64," + base64Data);
}
}
add(image);
}
}
Base64ImagePanel.html:
<wicket:panel>
<img wicket:id="image"></img>
</wicket:panel>
And then use that wrapper Panel in the AjaxLazyLoadPanel:
add(new AjaxLazyLoadPanel("imageLazyLoad") {
#Override
public Component getLazyLoadComponent(String id) {
//load your actual base64 from database, i use some example Strings for demonstration in the following line
Base64ImagePanel imagePanel = new Base64ImagePanel(id, "iVBORw0KGgoAAAANSUhEUgAAAAUAAAAFCAYAAACNbyblAAAAHElEQVQI12P4//8/w38GIAXDIBKE0DHxgljNBAAO9TXL0Y4OHwAAAABJRU5ErkJggg==", "image/png");
return imagePanel;
}
});

How to save and display uploaded image via tinymce editor in MOODLE 2.9

Save and display tinymce content in Moodle.
I have a block that save question and answer in db.
I use tinymce editor for this, so that user can enter text and image.
My editor form is:
.....
$editoroptions = array('maxfiles' => EDITOR_UNLIMITED_FILES, 'noclean'=>true, 'context'=>$context);
$mform->addElement('editor', 'title_editor', 'Questions', null, $editoroptions);
$mform->addRule('title_editor', null, 'required', null, 'client');
$mform->setType('title_editor', PARAM_RAW);
.....
I submit the form and save the data(text+image) from tinymce in db
......
if($data = $sample_form->get_data()) {
if ($draftitemid = file_get_submitted_draft_itemid('title_editor')) {
$data->title_editor['text'] = file_save_draft_area_files($draftitemid, $contextid, 'block_sample', questiontext, array('subdirs' => true, 'maxfiles' => 5),$data->title_editor['text']);
}
//insert to database
$inserRecord = new stdClass();
$inserRecord->suggestion = $sgid;
$inserRecord->questiontext = $data->title_editor['text'];
$inserRecord->answertext = $data->answer['text'];
$insertRes = add_question_desc($inserRecord);
......
In db the data(here question and answer) saved. The question data is looks like:
<p>What color is this?</p>
<p><img src="##PLUGINFILE##/sample_image.png" width="309" height="212" alt="green" /></p>
Is this complete to save the data? Where did the uploaded file saved. How I retreive/display the uploaded file.
I use:
$qn = file_rewrite_pluginfile_urls($qnDetails[$qnid]->questiontext, "pluginfile.php", $context->id, "block_sample", 'questiontext', $qnid);
echo $qn;
The above code only display the text and image is not displaying.
I inspect the broken image field and it is:
<img src="http://localhost/moodle/pluginfile.php/24/block_sample/questiontext/12/mc4.png" width="309" height="212" alt="mc4.png">
To manipulate files in an editor you must use the following methods:
Prior to displaying the form: file_prepare_standard_editor()
When saving the form: file_postupdate_standard_editor()
When displaying the content: file_rewrite_pluginfile_urls() followed by format_text()
You can find an example of this in cohort/edit.php and cohort/index.php.
Once that is done, you need to implement the function _pluginfile which Moodle core will call to get the file. The _pluginfile functions are required so that your plugin can check whether or not the user can access the file. You can find default implementations in filelib.php file_pluginfile() and in various lib.php <component_name>_pluginfile().

Tinymce 4 file_browser_callback: Function for opening a local file browser

I use Tinymce 4.0 on my web application. But I really don't know how to do this: when the user click on the browse button, how to open a local file browser and add an image URL to the dialog window from this local file browser? I have this source code:
file_browser_callback: function(field_name, url, type, win) {win.document.getElementById(field_name).value = ''; }
But I don' t know how to solve this problem. I don't need a special file browser but function for opening local file browser.
Here the snippet from Basic Local File Picker demo from TinyMCE docs:
Note: Unfortunately it doesn't seem to work here as a StackOverflow snippet.
tinymce.init({
selector: '#editor',
plugins: 'image code',
toolbar: 'undo redo | link image | code',
// enable title field in the Image dialog
image_title: true,
// enable automatic uploads of images represented by blob or data URIs
automatic_uploads: true,
// URL of our upload handler (for more details check: https://www.tinymce.com/docs/configure/file-image-upload/#images_upload_url)
images_upload_url: 'postAcceptor.php',
// here we add custom filepicker only to Image dialog
file_picker_types: 'image',
// and here's our custom image picker
file_picker_callback: function(cb, value, meta) {
var input = document.createElement('input');
input.setAttribute('type', 'file');
input.setAttribute('accept', 'image/*');
// Note: In modern browsers input[type="file"] is functional without
// even adding it to the DOM, but that might not be the case in some older
// or quirky browsers like IE, so you might want to add it to the DOM
// just in case, and visually hide it. And do not forget do remove it
// once you do not need it anymore.
input.onchange = function() {
var file = this.files[0];
// Note: Now we need to register the blob in TinyMCEs image blob
// registry. In the next release this part hopefully won't be
// necessary, as we are looking to handle it internally.
var id = 'blobid' + (new Date()).getTime();
var blobCache = tinymce.activeEditor.editorUpload.blobCache;
var blobInfo = blobCache.create(id, file);
blobCache.add(blobInfo);
// call the callback and populate the Title field with the file name
cb(blobInfo.blobUri(), { title: file.name });
};
input.click();
}
});
<script src="//cdn.tinymce.com/4/tinymce.js"></script>
<textarea id="editor"></textarea>