Actually, I want to select folder path and not upload but I am okay with the solution provided on here.
document.getElementById("folder").addEventListener("change", function(event) {
var output = document.querySelector("ul");
var files = event.target.files;
for (var i=0; i<files.length; i++) {
var item = document.createElement("li");
item.innerHTML = files[i].webkitRelativePath;
output.appendChild(item);
};
}, false);
label {
font-weight: bold;
display: block;
margin-bottom: 10px;
}
body {
font-family: sans-serif;
}
<h1>Folder upload</h1>
<label for="folder">Select folder</label>
<input type="file" id="folder" webkitdirectory multiple/>
<h2>Selected Files</h2>
<ul>
</ul>
But I am getting this post conformation message.
I want to know is there any way (any library anything) to avoid that confirmation box?
Related
I want to turn any value added to the form to be link with title (hyperlink)
for example:
Value: https://www.udemy.com/
Result (hyperlink): Udemy: Online Courses - Learn Anything, On Your Schedule
this is my code
HTML
<div class="container">
<form action="" class="addform">
<div class="input-group mb-3">
<input type="url" class="form-control" id="item" aria-describedby="emailHelp" placeholder="Enter link"> <div class="input-group-append">
<button class="btn btn-primary" id="addItem" type="button">Submit</button>
</div>
</div>
</form>
</div>
JS
document.getElementById('addItem').addEventListener('click', function() {
var value = document.getElementById('item').value;
if (value) addItemToList(value);
});
function addItemToList(text) {
var list = document.getElementById('linkss')
var item = document.createElement('li');
item.innerHTML = text;
var buttons = document.createElement('linkss');
buttons.classList.add('buttons')
var remove = document.createElement('button');
remove.classList.add('remove');
// remove.innerHTML = removeIcon;
var add = document.createElement('button');
add.classList.add('add');
// buttons.appendChild(remove);
item.appendChild(buttons);
list.appendChild(item);
}
🌈 What you need to do
In order to do that you would have to load that page and get its <title> element.
❌ Fetching the page from the frontend
You might try to do that in two different ways:
With an AJAX GET request to get the content of the page, in which case you will get a CORS error:
Failed to load https://www.udemy.com/: No 'Access-Control-Allow-Origin' header is present on the requested resource. Origin 'https://stackoverflow.com' is therefore not allowed access. If an opaque response serves your needs, set the request's mode to 'no-cors' to fetch the resource with CORS disabled.
fetch('https://www.udemy.com');
Using an <iframe>, in which case you will get an X-Frame-Options error:
Refused to display 'https://www.udemy.com/' in a frame because it set 'X-Frame-Options' to 'sameorigin'.
<iframe src="https://udemy.com" />
🌎 Using an API
The right way to do this would be to use a proxy/API that would make that same GET request for you, get the title of the page and send it back. For example:
Textance: A simple API that will just retrieve the title of the page. This one is just an example, as you would also get an Access-Control-Allow-Origin error if you try to use it on your page.
For example, https://textance.herokuapp.com/rest/title/http%3A%2F%2Fudemy.com returns the text:
Online Courses - Learn Anything, On Your Schedule | Udemy
URL Meta: Another API that returns additional metadata and is publicly available, so you can use this one directly from your application, but it's a bit slower and it can be down sometimes.
For example, https://url-meta.herokuapp.com/?url=http%3A%2F%2Fwww.udemy.com returns the following JSON response:
{
"result": {
"status": "OK"
},
"meta": {
"url": "http://udemy.com",
"type": "text/html",
"title": "Online Courses - Learn Anything, On Your Schedule | Udemy",
"image": "https://www.udemy.com/staticx/udemy/images/v6/logo-coral.svg",
"description": "Udemy is an online learning and teaching marketplace with over 65,000 courses and 15 million students. Learn programming, marketing, data science and more.",
"favicon": "https://www.udemy.com/staticx/udemy/images/v6/favicon-128.png",
"feed": {
"link": "http://udemy.com/"
}
}
}
✨ Working example
To use it, just make a GET request with the URL you want to get the title from. For example, using the Fetch API, which is not supported in IE:
const input = document.getElementById('input');
const list = document.getElementById('list');
document.getElementById('add').onclick = () => {
let url = input.value;
if (!url) return;
if (url.indexOf('http') !== 0) {
// Make sure the url we send always starts with http or https:
url = `http://${ url }`;
}
// Clear input field:
input.value = '';
const li = document.createElement('li');
// Create a new entry in the list indicating we are still loading the title:
li.innerText = `Loading title for ${ url }...`;
list.appendChild(li);
// Request the actual title of that URL from the URL Meta API:
fetch(`https://url-meta.herokuapp.com/?url=${ encodeURIComponent(url) }`)
.then(res => res.json())
.then(data => {
// Once we get a response back, update the text/HTML inside the <li> we have just added
// with the right text and <a> or an error message:
if (data.result.status === 'ERROR') {
li.innerText = `There was an error loading ${ url }: ${ data.result.reason }`;
} else {
li.innerHTML = `${ data.meta.title }`;
}
}).catch(() => {
li.innerText = `There was an error loading ${ url }.`;
});
};
body {
margin: 0;
font-family: monospace;
line-height: 15px;
}
#menu {
position: fixed;
top: 0;
left: 0;
width: 100%;
display: flex;
border-bottom: 3px solid #000;
height: 33px;
}
#input,
#add {
border: 0;
outline: none;
padding: 4px 8px;
box-sizing: border-box;
background: #FFF;
font-family: monospace;
text-align: left;
}
#input {
width: 70%;
border-right: 3px solid #000;
}
#add {
width: 30%;
}
#input:hover,
#add:hover {
background: #EEE;
}
#list {
list-style: none;
margin: 0;
padding: 35px 0 0;
}
#list > li {
border-bottom: 1px solid #000;
padding: 10px;
}
#list > li > a {
word-break: break-word;
word-break: break-all;
}
<header id="menu">
<input id="input" type="text" placeholder="URL" value="http://www.udemy.com" />
<button id="add">ADD LINK</button>
</header>
<ul id="list"></ul>
🛠️ Building your own API/proxy
Alternatively, you could implement your own proxy/API. This would be a good starting point: Getting the page title from a scraped webpage
The main issue here is finding a way to grab the title without CORS preventing it. One way to solve this is to use a CORS proxy, or an API that allows CORS requests and provides website info.
Here's an implementation that also fixes adding an actual link / <a>.
getTitle uses the fetch API to make the request and extract the title from the returned JSON.
In the click listener, the Promise returned by getTitle passes the title on to addItemToList, which does exactly that, creating the elements in the process.
Creating and adding elements is easier / less tedious with jQuery, which is required by Bootstrap anyway. I've used Vanilla JS though since you didn't use jQuery.
document.getElementById('addItem').addEventListener('click', function() {
var url = document.getElementById('item').value;
if (url) getTitle(url).then(title => addItemToList(url, title));
});
function getTitle(url) {
return fetch("https://api.urlmeta.org/?url=" + url).then(response => response.json()).then(info => info.meta.title);
}
function addItemToList(url, title) {
// create <a>
var a = document.createElement('a');
a.innerHTML = title;
a.href = url;
a.target = "_blank";
var list = document.getElementById('links')
var li = document.createElement('li');
li.classList.add('list-group-item');
var remove = document.createElement('button');
remove.classList.add('btn');
remove.classList.add('remove');
remove.classList.add('float-right');
remove.innerHTML = "X";
let p = li;
remove.onclick = function() {
list.removeChild(p);
};
li.appendChild(a);
li.appendChild(remove);
list.appendChild(li);
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.1.1/css/bootstrap.min.css">
<script src="https://stackpath.bootstrapcdn.com/bootstrap/4.1.1/js/bootstrap.min.js"></script>
<div class="container">
<form action="" class="addform">
<div class="input-group mb-3">
<input type="url" class="form-control" id="item" aria-describedby="emailHelp" placeholder="Enter link" value="https://udemy.com">
<div class="input-group-append">
<button class="btn btn-primary" id="addItem" type="button">Submit</button>
</div>
</div>
</form>
</div>
<div class="container">
<ul id="links" class="list-group">
</ul>
</div>
I need to add multiple images for upload. Below is my form. In the form, if you kindly check run code snippet`, when I upload image one by one, images with preview shown but no of images are not increased (here shows 2 files though total 4 images are present). but when I select multiple images at a time, then no of selected images shows.
In the attached image, it shows 4 images but no of count shows only 2 files. This is the problem.
I want to know, is it possible to increase no of files, when I choose images one by one i.e. with single click and select one image?
$(document).ready(function() {
if (window.File && window.FileList && window.FileReader) {
$("#files").on("change", function(e) {
var files = e.target.files,
filesLength = files.length;
for (var i = 0; i < filesLength; i++) {
var f = files[i]
var fileReader = new FileReader();
fileReader.onload = (function(e) {
var file = e.target;
$("<span class=\"pip\">" +
"<img class=\"imageThumb\" src=\"" + e.target.result + "\" title=\"" + file.name + "\"/>" +
"<br/><span class=\"remove\">Remove image</span>" +
"</span>").insertAfter("#files");
$(".remove").click(function(){
$(this).parent(".pip").remove();
});
});
fileReader.readAsDataURL(f);
}
});
} else {
alert("Your browser doesn't support to File API")
}
});
input[type="file"] {display: block;}
.imageThumb {max-height: 75px; border: 2px solid; padding: 1px; cursor: pointer;}
.pip {display: inline-block; margin: 10px 10px 0 0;}
.remove { display: block;background: #444;border: 1px solid black;color: white;text-align: center;cursor: pointer;}
.remove:hover {background: white;color: black;}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div>
<h3>Upload your images</h3>
<input type="file" id="files" name="files[]" multiple /></br>
<input type="submit" name="submit" value="Submit">
</div>
This is because you are relying on the browser's default <input>'s UI, which will only show its current content.
So if you want to upload all the Files that got selected, create an Array where you'll store all your Files, at every change.
Then to send it to your server, you will block the default behavior of your <form> by blocking its submit event, and sending a FormData filled with your files through XHR.
$(document).ready(function() {
// First define the Array where we will store all our files
var myFiles = [];
// now, every time the user selects new Files,
$("#files").on("change", function(e) {
var files = e.target.files, file;
// iterate through all the given files
for (var i = 0; i < files.length; i++) {
file = files[i];
myFiles.push(file); // store it in our array
$('<span class="pip">' +
'<img class="imageThumb" ' +
// no need for a FileReader here,
// a blobURI is better (sync & uses less memory)
'src="' + URL.createObjectURL(file) + '" ' +
'title="' + file.name + '"/>' +
'<br/>' +
'<span class="remove">Remove image</span>' +
'</span>')
.insertAfter("#files")
// add the event listener only on the new .remove
.find(".remove").click(removeFile.bind(null, file));
}
updateCounters();
});
// now override the default form submission
$('form').on('submit', upload);
// removes both the preview elements from doc and the file from our array
function removeFile(file, evt) {
$(evt.target).parent(".pip").remove();
myFiles.splice(myFiles.indexOf(file), 1);
updateCounters();
}
// ...
function updateCounters() {
$('#counter').text(myFiles.length + ' files selected');
}
// from submission overriding function
function upload(evt) {
evt.preventDefault(); // first block the default event
var fd = new FormData(); // create a new FormData
for (var i = 0; i < myFiles.length; i++) {
fd.append('files[]', myFiles[i]); // append all our files to it
}
// Post the formdata through XHR
var xhr = new XMLHttpRequest();
xhr.open('POST', 'YOUR_FORM_ACTION_URL');
// if you wanted to do something after the files are submitted
// xhr.onload = callback;
xhr.send(fd);
}
});
input[type="file"] {
display: block;
}
.imageThumb {
max-height: 75px;
border: 2px solid;
padding: 1px;
cursor: pointer;
}
.pip {
display: inline-block;
margin: 10px 10px 0 0;
}
.remove {
display: block;
background: #444;
border: 1px solid black;
color: white;
text-align: center;
cursor: pointer;
}
.remove:hover {
background: white;
color: black;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div>
<h3>Upload your images</h3>
<span id="counter">0 files selected</span>
<input type="file" id="files" name="files[]" multiple /><br>
<input type="submit" name="submit" value="Submit">
</div>
I'm just trying to dynamically add to a div within a form depending on which checkboxes are checked. So, I am creating the li tag and then they are added as li elements within an ol parent element so its just a list of values. I do not know what is wrong with my code, I'm not sure how to remove the appropriate value if the relevant checkbox is unchecked, and when I uncheck and then recheck a checkbox, it keeps adding the value over and over again.
<!DOCTYPE html>
<html>
<head>
<title></title>
<style>
input {
margin: 18px;
}
#o {
list-style-type: none;
}
.u {
list-style: none;
}
</style>
</head>
<body style="width: 700px">
<div style="float: left; width: 340px; height: 250px; border: 1px solid black; padding: 20px 0 10px 20px;">
<form id="myForm">
<ul class="u">
<li><input id="showAlert1" type="checkbox" name="thing" value="laptop">laptop</li>
<li><input id="showAlert2" type="checkbox" name="thing" value="iphone">iphone</li>
</ul>
</form>
</div>
<div id="myDiv" style="float: right; width: 317px; height: 250px; border: solid black; border-width: 1px 1px 1px 0; padding: 20px 0 10px 20px;">
<ol id="o">
</ol>
</div>
<script>
document.getElementById('myForm').addEventListener('change', function () {
var a = document.getElementsByName('thing');
for (var i = 0; i < a.length; i++) {
if (a[i].checked){
createDynamicElement();
} else if (!a[i].checked){
removeDynamicElement();
}
}
function createDynamicElement(){
var node = document.createElement("LI");
node.setAttribute("id1", "Hey");
var textnode = document.createTextNode(event.target.nextSibling.data);
node.appendChild(textnode);
document.getElementById("o").appendChild(node);
}
function removeDynamicElement() {
document.querySelector("#o li").innerHTML = "";
}
});
</script>
</body>
</html>
It looks like that you are adding an event listener to the form instead of the input elements themselves. I dont think the change event will be fired when an input element in a form changes. (see: https://developer.mozilla.org/en-US/docs/Web/Events/change)
On your event listener, try targeting the input elements themselves.
} else if (!a[i].checked){
removeDynamicElement();
}
...
function removeDynamicElement() {
document.querySelector("#o li").innerHTML = "";
}
Will empty the first or all matches(not sure) but wont remove them. Instead you should give li tags a unique ID and remove them completely via something like:
for (var i = 0; i < a.length; i++) {
if (a[i].checked){
console.log(a[i])
createDynamicElement(a[i].value);
} else if (!a[i].checked){
removeDynamicElement(a[i].value);
}
}
function createDynamicElement(id){
var node = document.createElement("LI");
node.setAttribute("id", id);
var textnode = document.createTextNode(id);
node.appendChild(textnode);
console.log(node)
document.getElementById("o").appendChild(node);
}
function removeDynamicElement(id) {
var target = document.getElementById(id)
target.parentElement.removeChild(target);
}
Or you could clear the ol completely on every change and repopulate it again like:
var a = document.getElementsByName('thing');
document.getElementById("o").innerHTML = null;
for (var i = 0; i < a.length; i++) {
if (a[i].checked){
console.log(a[i])
createDynamicElement(a[i].value);
}
}
function createDynamicElement(id){
var node = document.createElement("LI");
var textnode = document.createTextNode(id);
node.appendChild(textnode);
console.log(node)
document.getElementById("o").appendChild(node);
}
Edit:
A proper FIFO solution:
var a = document.getElementsByName('thing');
for (var i = 0; i < 2; i++) {
var target = document.getElementById(a[i].value);
if (a[i].checked && !target){
createDynamicElement(a[i].value);
} else if ((!a[i].checked) && target){
removeDynamicElement(a[i].value);
}
}
function createDynamicElement(id){
var node = document.createElement("li");
node.setAttribute("id", id);
var textnode = document.createTextNode(id);
node.appendChild(textnode);
document.getElementById("o").appendChild(node);
console.log("a")
}
function removeDynamicElement(id) {
target.parentElement.removeChild(target);
}
});
I am using this source: http://opoloo.github.io/jquery_upload_preview/
until now, I can upload one image with preview.
<style type="text/css">
.image-preview {
width: 200px;
height: 200px;
position: relative;
overflow: hidden;
background-color: #000000;
color: #ecf0f1;
}
input[type="file"] {
line-height: 200px;
font-size: 200px;
position: absolute;
opacity: 0;
z-index: 10;
}
label {
position: absolute;
z-index: 5;
opacity: 0.7;
cursor: pointer;
background-color: #bdc3c7;
width: 200px;
height: 50px;
font-size: 20px;
line-height: 50px;
text-transform: uppercase;
top: 0;
left: 0;
right: 0;
bottom: 0;
margin: auto;
text-align: center;
}
</style>
<script type="text/javascript">
$(document).ready(function() {
$("image-preview").each(
function(){
$.uploadPreview({
input_field: $(this).find(".image-upload"),
preview_box: this,
label_field: $(this).find(".image-label")
});
}
);
});
</script>
<!--| catatan penting: yang penting action="" & input type="file" name="image" |-->
<form action="upload.php" method="POST" enctype="multipart/form-data">
<div class="image-preview">
<label for="image-upload" class="image-label">+ GAMBAR</label>
<input type="file" name="my_field[]" class="image-upload" />
</div>
<div class="image-preview">
<label for="image-upload" class="image-label">+ GAMBAR</label>
<input type="file" name="my_field[]" class="image-upload" />
</div>
<input type="submit"/>
</form>
then try to add more div class image preview, i want add another button with image preview. i don't want multiple upload with one button.
$(document).ready(function() {$.uploadPreview => use id, of course when change to class and add more div, when upload a button, another button will change. i am confused with the logic. Anyone can help? maybe using array but, i don't know how..
Since upload button is dependent on state of uploadPreview you need to initialize for each div separately to get separate upload buttons.
Change your html like this give each container a class say imgBox
<div class="imgBox">
<label for="image-upload" class="image-label">Choose File</label>
<input type="file" name="image" class="image-upload" />
</div>
.....
....
...
<div class="imgBox">
<label for="image-upload" class="image-label">Choose File</label>
<input type="file" name="image" class="image-upload" />
</div>
..
Now initialize each one using jquery each()
$(".imgBox").each(
function(){
$.uploadPreview({
input_field: $(this).find(".image-upload"),
preview_box: this,
label_field: $(this).find(".image-label")
});
});
I created a simple image uploading index.html file for image uploading and preview.
Needs j-query.No need of extra plugins.
If you have any questions ask me ;)
//to preview image you need only these lines of code
var imageId=idOfClicked;
var output = document.getElementById(imageId);
output.src = URL.createObjectURL(event.target.files[0]);
Check it here:
https://jsfiddle.net/chs3s0jk/6/
I have one better option for the file upload it's easy to use and you can try it.
window.onload = function(){
if(window.File && window.FileList && window.FileReader){
$(document).on("change",'.file', function(event) {
var files = event.target.files; //FileList object
var output = document.getElementById("upload-preview");
$("#upload-preview").html("");
if(files.length>5){
$(".file").after("<div class='alert alert-error'><span class='close'></span>Maximum 5 files can be uploaded.</div>");
$(this).val("");
return false;
}
else{
$(".file").next(".alert").remove();
}
for(var i = 0; i< files.length; i++)
{
var file = files[i];
//Only pics
// if(!file.type.match('image'))
if(file.type.match('image.*')){
if(this.files[0].size < 2097152){
// continue;
var picReader = new FileReader();
picReader.addEventListener("load",function(event){
var picFile = event.target;
var div = document.createElement("div");
div.className = "upload-preview-thumb";
div.style.backgroundImage = 'url('+picFile.result+')';
output.insertBefore(div,null);
});
//Read the image
$('#clear, #upload-preview').show();
picReader.readAsDataURL(file);
}else{
alert("Image Size is too big. Minimum size is 1MB.");
$(this).val("");
}
}else{
alert("You can only upload image file.");
$(this).val("");
}
}
});
$(".file2").change(function(event){
var err=0;
var input = $(event.currentTarget);
var ele = $(this);
var file = input[0].files[0];
var u = URL.createObjectURL(this.files[0]);
var w = ele.attr("data-width");
var h = ele.attr("data-height");
var img = new Image;
img.onload = function(){
if(w){
if(img.width!=w || img.height!=h){
ele.parent().find(".alert").remove();
ele.parent().find(".upload-preview").before("<div class='alert alert-error'>Please upload a image with specified dimensions.</div>");
ele.val("");
}
else{
ele.parent().find(".alert").remove();
}
}
};
img.src = u;
var nh;
if($(this).attr('data-preview')=='full')
nh = (h/w*150)
else
nh=150
var preview = ele.parent().find(".upload-preview");
var reader = new FileReader();
preview.show();
reader.onload = function(e){
image_base64 = e.target.result;
preview.html("<div class='upload-preview-thumb' style='height:"+nh+"px;background-image:url("+image_base64+")'/><div>");
};
reader.readAsDataURL(file);
});
}
else
{
console.log("Your browser does not support File API");
}
}
above code save as one js file like file-upload.js
then link it to your file where you want perview.
i.e.
<script src="js/file-upload.js" type="text/javascript"></script>
use this kind of example for the input type
<input type="file" class="file2" name="page-image" id="page-image"/>
that works on the class that name is "file2" that class you given to the input field that able to create preview.
full structure something like below.
HTML Code you can try
<input type="file" class="file2" name="page-image[]" id="page-image"/>
<div class="clearfix"></div>
<div class="upload-preview" style="display: block;">
<div class="upload-preview-thumb">
// perview genereate here
// you can display image also here if uploaded throw the php condition in edit image part
</div>
</div>
<input type="file" class="file2" name="page-image[]" id="page-image"/>
<div class="clearfix"></div>
<div class="upload-preview" style="display: block;">
<div class="upload-preview-thumb">
// perview genereate here
// you can display image also here if uploaded throw the php condition in edit image part
</div>
</div>
CSS
.upload-preview {
border: 1px dashed #ccc;
display: block;
float: left;
margin-top: 10px;
padding: 5px;
}
.upload-preview-thumb {
background-position: 50% 25%;
background-size: cover;
float: left;
margin: 5px;
position: relative;
width: 139px;
}
Hope this works and in future it's helpful for you.
Thanks.
hello, i need your help for my codes. I want to preview multiple images before upload and there are remove button in each images. But my code doesn't work when i'm using div targetting in each remove button.
the first, my codes is like THIS FIDDLE 1.
and when i'm add some changes become THIS FIDDLE 2
my HTML :
<body>
<header>
<h1>File API - FileReader</h1>
</header>
<article>
<label for="files">Select multiple files: </label>
<input id="files" type="file" multiple/>
<output id="result" />
</article>
and CSS :
body{
font-family: 'Segoe UI';
font-size: 12pt;
}
header h1{
font-size:12pt;
color: #fff;
background-color: #1BA1E2;
padding: 20px;
}
article
{
width: 80%;
margin:auto;
margin-top:10px;
}
.thumbnail{
height: 100px;
margin: 10px;
}
it's my javascripts :
window.onload = function(){
//Check File API support
if(window.File && window.FileList && window.FileReader)
{
var filesInput = document.getElementById("files");
filesInput.addEventListener("change", function(event){
var files = event.target.files; //FileList object
var output = document.getElementById("result");
for(var i = 0; i< files.length; i++)
{
var file = files[i];
//Only pics
if(!file.type.match('image'))
continue;
var picReader = new FileReader();
picReader.addEventListener("load",function(event){
var picFile = event.target;
var div = document.createElement("div");
div.innerHTML = "<img class='thumbnail' src='" + picFile.result + "'" +
"title='" + picFile.name + "'/> <a href='#' class='remove_pict'>X</a>";
output.insertBefore(div,null);
});
//Read the image
picReader.readAsDataURL(file);
}
});
}
else
{
console.log("Your browser does not support File API");
}
}
thanks for advance. any suggestions much be appreciated ^^
Image and delete anchor are children of div object. Put click event on each a, then delete the parent. So when user click the x mark, selected image will be deleted.
div.children[1].addEventListener("click", function(event){
div.parentNode.removeChild(div);
});
see demo at http://jsfiddle.net/L45LW/5/
$("#result").on( "click",".remove_pict",function(){
$(this).parent().remove();
});
This may be help you