how can i create a preview for multiple upload buttons - javascript

How can i preview the selected ico with multiple inputs? The problem is that it select the input by id which is everywhere the same. How can i run the js with a indefined amount of inputs? The amount of inputs depends on the number of loops it ran. What can i do to make it work with multiple inputs
for ($x = 1; $x <= $number; $x++) {
$bar .= '<input type="text" name="title[]" placeholder="Name '.$x.'" id="title" value=""><input type="file" accept="video/*" name="file[]"/><input type="file" name="" class="icofile" id="icofile" accept="image/*" name="icon[]" hidden>
<label for="icofile" class="icofile" id="selector"><img src="../images/none.png"></label><br>';
}
}
?>
<script type="text/javascript">
var loader = function(e){
let file = e.target.files;
//let show= "<span>Selected file : </span>"+file[0].name;
let show= "<img src='none.png'>";
let output= document.getElementById("selector");
output.innerHTML = show;
output.classList.add("active");
if(file[0].type.match("image")){
let reader = new FileReader();
reader.addEventListener("load", function(e){
let data=e.target.result;
let image= document.createElement("img");
image.src=data;
output.innerHTML="";
output.insertBefore(image,null);
output.classList.add("image");
});
reader.readAsDataURL(file[0]);
}else{
let show="<img src='none.png'>";
//show= show+file[0].name;
output.innerHTML=show;
output.classList.add("active");
if(output.classList.contains("image")){
output.classList.remove("image");
}
}
};
let fileInput = document.getElementById("icofile");
fileInput.addEventListener("change", loader);
</script>

You got quite some redundant (repetitive) code that you could remove. Using Object URLs could make it easier for you if you ditch the unnecessary FileReader that waste time encoding decoding long base64 urls.
also you don't have uniq id's throughout your html. and you used name twice on the icofile input... so this problems have to be fixed first before you move on.
also the label with the for="icofile" will only point to the first input so it also needs to be uniq.
globalThis.preview = function preview (evt) {
const file = evt.target.files[0]
// Get matching label
const output = document.querySelector(`label[for=${evt.target.id}]`)
// Reuse the existing image instead of clearing and rebuilding
const img = output.querySelector('img')
output.classList.add('active')
output.classList.remove('image')
// This if statement is almost useless since
// accept="image/*" ensure that you only get images
if (file.type.match('image')) {
img.src = URL.createObjectURL(file)
output.classList.add('image')
} else {
img.src = 'https://dummyimage.com/50x50/ff0000/000000&text=None'
}
}
<!-- for loop that did output this: -->
<!-- foreach id in this list append an index -->
<input type="text" name="title[]" placeholder="Name" id="title-1">
<input type="file" name="file[]" accept="video/*" />
<input type="file" name="icon[]" accept="image/*" onchange="preview(event)" id="icofile-1" hidden>
<label for="icofile-1" class="icofile">
<img width="50" height="50" src="https://dummyimage.com/50x50/ff0000/000000&text=None">
</label>
<hr> <!-- for better look/seperation without css. -->
<input type="text" name="title[]" placeholder="Name" id="title-2">
<input type="file" name="file[]" accept="video/*" />
<input type="file" name="icon[]" accept="image/*" onchange="preview(event)" id="icofile-2" hidden>
<label for="icofile-2" class="icofile">
<img width="50" height="50" src="https://dummyimage.com/50x50/ff0000/000000&text=None">
</label>

Related

CKFinder SetFileField for two seperate text inputs in the same form

I have a form to record/update some information for a book. There is a text box which contains only the file path and another textbox for attached file's path.
<input type="text" id="image" name="set[image]" value="<?=$document->image?>" />
<input type="button" value="Choose Image" onclick="BrowseServer('image');" />
<input type="text" id="attachment" name="set[attachment]" value="<?=$document->attachment?>" />
<input type="button" value="Choose File" onclick="BrowseServer('attachment');" />
Both call BrowseServer() function:
function BrowseServer(field) {
var finder = new CKFinder();
finder.basePath = 'repo/';
finder.selectActionFunction = SetFileField;
finder.popup();
}
function SetFileField(fileUrl) {
document.getElementById('attachment').value = fileUrl;
}
First, there was only one field (Choose File). Then I've decided to add another to select image path in the same way. And I have modified the SetFileField(fileUrl) function:
function SetFileField(fileUrl, fieldName) {
document.getElementById(fieldName).value = fileUrl;
}
This does not work as I guessed. How can I pass field name to SetFileField function?
I have duplicated both functions for image and attachment as BrowseServerForFile(), SetFileField() and BrowseServerForImage(), SetImageField().
It works. But this is not so efficient.

How to validate an image file in a form using spry or any other tweak

I have a form that checks 4 parameters, the first three are easy to check with spry and working fine. But the fourth is an upload of an image, i want to check if the extension of the file is correct or not. But there is not an option that i see that does that. How is it possible to check the extension of the file uploaded?
What i've done:
I had in an older version (only implemented a file upload and submit button) is a script that worked based on using ID, that detected the click on a sending buttong and then check the file description. When i simply link the script to the current form it does not work, also i want the same behaviour as the other form inputs with the hidden message, not with alert as it is in the code.
To put the file i copied a spry text validation and changed the input type to file.
EDIT: It wasn't clear enought so i wanna make an aclaration, i want to validate the input files. Dont want the user to be able to upload anything that is not allowed in the list of extensions allowed.
Here is the part of the HTML that defines the form i use, also both methos used to do it (only used once at a time, but easy to show like this).
<form action="../Data/Product.Insert.php" method="post" enctype="multipart/form-data" name="Insert">
<span id="sprytextfield1">
<label for="Name">Name</label>
<input type="text" name="Name" id="Name" tabindex="1">
<span class="textfieldRequiredMsg">A value is required.</span> <br>
</span> <span id="sprytextfield2">
<label for="Ref">Ref</label>
<input type="text" name="Ref" id="Ref" tabindex="2">
<span class="textfieldRequiredMsg">A value is required.</span></span> <br>
<span id="spryselect1">
<label for="Cat">Cat</label>
<select name="Cat" id="Cat" tabindex="3">
<option value="test">test</option>
</select>
<span class="selectRequiredMsg">Please select an item.</span></span> <br>
<span id="sprytextfield3">
<label for="Image">Image</label>
<input type="file" name="Image" id="Image" tabindex="4" id="image">
<span class="textfieldRequiredMsg">A value is required.</span></span><br>
<input name="Send" type="submit" value="Send" tabindex="5" id="insert">
</form>
<script type="text/javascript">
var sprytextfield1 = new Spry.Widget.ValidationTextField("sprytextfield1", "none");
var sprytextfield2 = new Spry.Widget.ValidationTextField("sprytextfield2");
var spryselect1 = new Spry.Widget.ValidationSelect("spryselect1");
var spryselect1 = new Spry.Widget.ValidationSelect("sprytextfield3","image");
$(document).ready(function(){
$('#insert').click(function(){
var image_name = $('#image').val();
if(image_name == '')
{
alert("Please Select Image");
return false;
}
else
{
var extension = $('#image').val().split('.').pop().toLowerCase();
if(jQuery.inArray(extension, ['gif','png','jpg','jpeg']) == -1)
{
alert('Invalid Image File');
$('#image').val('');
return false;
}
}
});
});
</script>
Here is my failure to convert that code into a validation type in a spry, this only makes the whole form not to work.
'image'{
validation: function(value, options) {
if(value = ""){
return false;
}
var extension = $('#image').val().split('.').pop().toLowerCase();
if(jQuery.inArray(extension, ['gif','png','jpg','jpeg']) == -1)
{
return false;
}
return true;
}
},
you can use accept="image/*" attribute to validate images
Thanks
Here is one example using the file reader api. hope this helps
Regards
$('.UploadImage').change(function (ev) { // this triggers when file upload is clicked
.readImage(this);
});
public readImage(input) {
let reader = new FileReader();
let imageName = input.files[0].name.split(".").slice(0, -1).join(".").replace(/[^A-Z0-9]+/ig, "");
let MIMEType = input.files[0].type;
// Do validation stuff here based on the mime type
reader.onload = function () {
el.attr('src', reader.result);
console.log(reader.result);
}
reader.readAsDataURL(input.files[0]);
}

How to dynamically set background image url in CSS using Javascript

I've been trying to make this work for a little while now.
I thought the following code would work since I'm getting the value from the input and setting the background-image URL to said value.
Thanks!
The code inside of the head tag.
<script type="text/javascript">
function loadImg() {
var imageUrl = $('#hostImage').attr('value')
document.getElementById("upload-success-bg").style.backgroundImage=imageUrl
}
</script>
<style>
#upload-success-bg {
background-image: url();
}
</style>
Input field code
<div class="status">
<input class="image-url" type="text" id="hostImage" name="hostImage" required="true"
value="URL LOADS HERE">
</div>
Where I would like to the image to show
<div class="dropzone upload-success" id="upload-success-bg">
<div class="info"><p>Drag image file here</p><p>Or click here to select image</p></div>
<input type="file" required="" class="input" accept="image/*"></div>
If you wish to use an URL for backgound and background-color CSS properties you have to use the url() syntax even within javascript, so changing your code to the following should work:
document.getElementById("upload-success-bg").style.backgroundImage = "url(" + imageUrl + ")"
In jquery, you can do it this way:
function loadImg() {
var imageUrl = $('#hostImage').attr('value')
$("#upload-success-bg").css("background-image", "url(" + imageUrl + ")");
}
A File object does not have a URL property. A Blob URL or data URL can be created which points to the uploaded file. A Blob URLs lifetime is linked to the document which created the URL. A data URL string
data:[<mediatype>][;base64],<data>
can be opened at a different window or browser.
You can use FileReader to convert File object to a data URL and set the <input type="text"> value to the FileReader instance result.
const input = document.querySelector("#file");
const [label] = input.labels;
const upload = document.querySelector("#upload-success-bg");
const uploadURL = document.querySelector("#hostImage");
const reader = new FileReader();
reader.addEventListener("load", e => {
const {result} = reader;
upload.style.backgroundImage = `url(${result})`;
hostImage.style.width = `calc(${result.length}px)`;
hostImage.value = result;
});
input.addEventListener("change", e => {
const [file] = input.files;
console.log(file)
if (file && /^image/.test(file.type)) {
reader.readAsDataURL(file);
}
});
#file {
display: none;
}
label[for="file"] {
white-space: pre;
}
<div class="dropzone upload-success" id="upload-success-bg">
<label class="info" for="file">
Drag image file here
Or click here to select image
</label>
<input type="file" required="" id="file" class="input" accept="image/*"></div>
<div class="status">
<input class="image-url" type="text" id="hostImage" name="hostImage" required="true" readonly="true" value="URL LOADS HERE">
</div>

Previewing multiple uploaded images individually

I have three image upload fields in my form. I am trying to preview the images before uploading. Till now i have been able to preview only one at a time. but i am trying to preview all of them simultaneously. Like
I am currently previewing like this.
function previewImages() {
var $preview = $('#preview').empty();
if (this.files) $.each(this.files, readAndPreview);
function readAndPreview(i, file) {
if (!/\.(jpe?g|png|gif)$/i.test(file.name)){
return alert(file.name +" is not an image");
} // else...
var reader = new FileReader();
$(reader).on("load", function() {
$preview.append($("<img/>", {src:this.result, height:500}));
});
reader.readAsDataURL(file);
}
}
$('#file-input').on("change", previewImages);
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="form-group">
<label>Image 2</label>
<input id="file-input" type="file" multiple>
<div id="preview"></div>
</div>
<img id='img-upload'/>
</div>
<div class="form-group">
<label>Image 3</label>
<input id="file-input" type="file" multiple>
<div id="preview"></div>
</div>
You have some problems in your code.
Never use duplicate id's . That's the main reason your code works only for the first input type file. You use id='file-input' on all inputs. That's not correct HTML wise. Use classes instead or other html attributes.
You select the preview container but only the first one. $preview = $('#preview').empty(); where by writing $('#preview'), jquery finds the first item with id preview, selects it, empties it and then ignores all other divs with the same id. This is firstly because you don't select the corresponding preview div to the changed input file ( no connection between them in your var declaration ) and because again you use duplicate ( multiple ) id's in your HTML structure. Which will generate a lot of ' strange ' errors.
But even if you would use classes instead of id's ( class='preview' ) it won't exactly work because it will just select the first div with class preview and append all previews to that div.
So to make a connection between input and it's preview, use something like var $preview = $(this).next('.preview').empty(); . This way you know jQuery will select the next sibling with class preview of the changed input.
Alternatively ( if your HTML structure should change and preview is not exactly after the input ) you should use $(this).siblings('.preview').empty()
The most important thing you should learn from this answer is NOT to use same id`s on the page. And when you have multiple items with corresponding elements, select them accordingly.
function previewImages() {
const $preview = $(this).next('.preview').empty();
if (this.files) $.each(this.files, readAndPreview);
function readAndPreview(i, file) {
if (!/\.(jpe?g|png|gif)$/i.test(file.name)) {
return alert(file.name + " is not an image");
} // else...
const reader = new FileReader();
$(reader).on("load", function() {
$preview.append($("<img/>", {
src: this.result,
height: 100
}));
});
reader.readAsDataURL(file);
}
}
$('.file-input').on("change", previewImages);
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="form-group">
<label>Image 1</label>
<input class="file-input" type="file" multiple>
<div class="preview"></div>
</div>
<img class='img-upload' />
<div class="form-group">
<label>Image 2</label>
<input class="file-input" type="file" multiple>
<div class="preview"></div>
</div>
<img class='img-upload' />
<div class="form-group">
<label>Image 3</label>
<input class="file-input" type="file" multiple>
<div class="preview"></div>
</div>
SIDE NOTE . You should use const and/or let instead of var when declaring variables.
var $preview=null;
function previewImages() {
$preview = $(this).next('#preview').empty();
if (this.files)
$.each(this.files,function(index,file){
readAndPreview(index,file);
});
}
function readAndPreview(i, file) {
if (!/\.(jpe?g|png|gif)$/i.test(file.name)){
return alert(file.name +" is not an image");
} // else...
var reader = new FileReader();
$(reader).on("load", function() {
$preview.append($("<img/>", {src:this.result, height:100}));
});
reader.readAsDataURL(file);
}
$('.file-input').on("change", previewImages);
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.0/jquery.min.js"></script>
<div class="form-group">
<label>Image 2</label>
<input class="file-input" type="file" multiple>
<div id="preview"></div>
</div>
<img id='img-upload'/>
</div>
<div class="form-group">
<label>Image 3</label>
<input class="file-input" type="file" multiple>
<div id="preview"></div>
</div>
Try this. css ids are unique for a page. if you want to access multiple elements with same selector use class.

Onclick image change the input value

Really stuck with this concept. IN my Old code have separate input fields for % input fields and $ input fields. its Working.
Old UI code :
<td>Estimate Property Tax</td>
<td>
<input name="propertytaxpc" type="text" size="8" maxlength="8" value="<?php echo $dproperty_tax; ?>" onChange="javascript:propertyTaxPcChanged(true)" />
%</td>
<td>Or $
<input name="propertytaxamt" type="text" size="8" maxlength="8" onChange="javascript:propertyTaxAmountChanged(true)" />
</td>
OLD UI i have used two separate input fields for % and $. its Working. Now i changed NEW UI code
using Single Input Fields
NEW UI CODE:
<div class="col-md-4 padding-rht bdy">
<label id="lblEstimatePropertyTax"class="pull-left"style="font-weight: 600">
Estimate Property Tax</label>
</div>
<div class="col-md-3 padding-rht">
<input name="propertytaxpc" class="txt" type="text" size="8" maxlength="8" value="<?php echo $dproperty_tax;?>" onChange="javascript:propertyTaxPcChanged(true)" />
</div>
<div class="col-md-1 padding-lft">
<img src="Content/Images/percent.png" onclick="changeColor(event,this.src)" style="cursor:pointer"/>
</div>
In My UI I'm Using IMAGE ICON FOR % AND $ . In My Previous Code I AM
Using Each Input Fields for % and$. Now i'm Using new UI using % AND
$ Image .when user change % to $ Image Icon values also changes.
i have tired many method really stuck with concept
already created ICON change script:
function changeColor(event, _src) {
var fname = _src;
var ImageName = fname.substring(fname.lastIndexOf('/') + 1);
//alert(ImageName);
if (ImageName == "percent.png") {
$(event.target).attr("src", "Content/Images/RedDoller.png");
}
else {
$(event.target).attr("src", "Content/Images/percent.png");
}
}
Now i want pass value for Onclick image change ? when user change image value need to change.
please help me any body really i am stuck with this concept ? thanks in advance
Js Change Image
<img id="myImage" onclick="changeImage()" src="D:\\Images\\Img1.jpg" width="100" height="100">
<p id="myImageText">10</p>
</image>
script
<script type="text/javascript">
function changeImage() {
var image = document.getElementById('myImage');
var txt = document.getElementById('myImageText');
if (image.src.match("Img1")) {
image.src = "D:\\Images\\Img2.jpg";
txt.innerHTML = '20';
} else {
image.src = "D:\\Images\\Img1.jpg";
txt.innerHTML = 10;
}
}
</script>
place all script tag data at the end so that the page loads fast.

Categories