komalr 10 Posted July 23, 2020 Share Posted July 23, 2020 This is not my code, found it and is quite useful in my line of work. I've never dabbled with html scripting so don't know where to even start. Here, I just wanted to add a new feature but am not able to. Can someone please help me with this? This script allows me to drag gif file on to the page and build a gallery but I also want to add the names of the files below the image. The script right now shows the names but not correctly. <!DOCTYPE html> <html><head><meta http-equiv="Content-Type" content="text/html; charset=UTF-8"> <div id="holder" class=""> <style> #holder {background-color: white; width: 100%; height: 100%;} #holder.hover {background-color: lightgray;} .center {text-align:center;} .agif {width: 196px; vertical-align:middle;} .agif {width: auto; vertical-align:middle; margin: 2px;} body {border: 0px solid red;margin:0; padding: 0;height:100%} html {height:98%} </style> <article> <p id="status"></p> <p>Drag images (gif/jpg/png/bmp) from your desktop into this window to build a gallery.</p> <p>Save as complete web page with your images embedded in the page. Then reload into a browser to see your gallery again.</p> <p id="pics"><img class="agif" </article> </div> <script> var holder = document.getElementById('holder'), state = document.getElementById('status'); if (typeof window.FileReader !== 'undefined') { state.innerHTML = 'File API & FileReader available'; } holder.ondragover = function () { this.className = 'hover'; return false; }; holder.ondragend = function () { this.className = ''; return false; }; holder.ondragleave = holder.ondragend; holder.ondrop = function (e) { this.className = ''; e.preventDefault(); for (var i = 0; i < e.dataTransfer.files.length; i++ ) { var reader = new FileReader(); var f = e.dataTransfer.files[i]; reader.onload = function (event) { var pics = document.getElementById('pics'); pics.innerHTML = pics.innerHTML + "<img class='agif' src='" + event.target.result + "'>" + f.name +"/>"; }; reader.readAsDataURL(f); }; return false; }; </script> </body></html> Link to post Share on other sites
K^2 2,173 Posted July 23, 2020 Share Posted July 23, 2020 <!DOCTYPE html> <html><head><meta http-equiv="Content-Type" content="text/html; charset=UTF-8"> <div id="holder" class=""> <style> #holder {background-color: white; width: 100%; height: 100%;} #holder.hover {background-color: lightgray;} .center {text-align:center;} .agif {width: auto; vertical-align:middle; margin: 2px; display: inline-block;} body {border: 0px solid red;margin:0; padding: 0;height:100%} html {height:98%} </style> <article> <p id="status"></p> <p>Drag images (gif/jpg/png/bmp) from your desktop into this window to build a gallery.</p> <p>Save as complete web page with your images embedded in the page. Then reload into a browser to see your gallery again.</p> <p id="pics"></p> </article> </div> <script> var holder = document.getElementById('holder'), state = document.getElementById('status'); if (typeof window.FileReader !== 'undefined') { state.innerHTML = 'File API & FileReader available'; } holder.ondragover = function () { this.className = 'hover'; return false; }; holder.ondragend = function () { this.className = ''; return false; }; holder.ondragleave = holder.ondragend; holder.ondrop = function (e) { this.className = ''; e.preventDefault(); for (var i = 0; i < e.dataTransfer.files.length; i++ ) { var reader = new FileReader(); var f = e.dataTransfer.files[i]; reader.onload = function (event) { var pics = document.getElementById('pics'); pics.innerHTML += `<div class='agif'><img src='${event.target.result}'/></br>${f.name}</div>`; }; reader.readAsDataURL(f); }; return false; }; </script> </body></html> I only fixed things that seemed to matter, so it's not great, but it seems to work. Note that I've enclosed the image and text into a separate div, moved the agif class to that, and gave that class a display: inline-block, which makes it work the same way the images used to, but now it's the entire image + title block. Hope that helps. 1 Link to post Share on other sites
komalr 10 Posted July 23, 2020 Author Share Posted July 23, 2020 (edited) Thanks a lot, this does seems to work except for the names. All the images I drag seem to have the same name until and unless I drag them one by one. Edited July 23, 2020 by komalr Link to post Share on other sites
komalr 10 Posted July 23, 2020 Author Share Posted July 23, 2020 (edited) So, I've got this. This fixes the issue of name but it's assigning the wrong names whenever i'm dropping multiple files. So, I've got this. This fixes the issue of name but it's assigning the wrong names. <!DOCTYPE html> <html><head><meta http-equiv="Content-Type" content="text/html; charset=UTF-8"> <div id="holder" class=""> <style> #holder {background-color: white; width: 100%; height: 100%;} #holder.hover {background-color: lightgray;} .center {text-align:center;} .agif {width: auto; vertical-align:middle; margin: 10px; display: inline-block;} body {border: 0px solid red;margin:0; padding: 0;height:100%} html {height:98%} </style> <article> <p id="status"></p> <p>Drag images (gif/jpg/png/bmp) from your desktop into this window to build a gallery.</p> <p>Save as complete web page with your images embedded in the page. Then reload into a browser to see your gallery again.</p> <p id="pics"><img class="agif"></img></p> </article> </div> <script> var holder = document.getElementById('holder'), state = document.getElementById('status'); if (typeof window.FileReader !== 'undefined') { state.innerHTML = 'File API & FileReader available'; } holder.ondragover = function () { this.className = 'hover'; return false; }; holder.ondragend = function () { this.className = ''; return false; }; holder.ondragleave = holder.ondragend; holder.ondrop = function (e) { this.className = ''; e.preventDefault(); var files=[]; var results=[]; var no=0; for (var i = 0; i < e.dataTransfer.files.length; i++ ) { var reader = new FileReader(); var f = e.dataTransfer.files[i]; //console.log("i ki value "+i); //console.log("file name "+f.name); files.push(f); results.push(event.target.result); // if(i==1){ reader.onload = function (event) { for(var j=0;j<files.length;j++){ if(j==no){ //console.log(j+". "+i); // if(j==i){ var pics = document.createElement('pics'+j); // var pic=document.getElementById('pics'+i); //console.log('pics'+j); //pics.innerHTML = "<br><br><img class='agif' src='" + event.target.result + "'></img><br>" + files[j].name +""; pics.innerHTML += `<div class='agif'><img src='${event.target.result}'/></br>${files[j].name}</div>`; holder.appendChild(pics); }} no+=1; }; reader.readAsDataURL(f); }; // holder.style.height="10%"; return false; }; Edited July 23, 2020 by komalr Link to post Share on other sites
K^2 2,173 Posted July 24, 2020 Share Posted July 24, 2020 Ah, yes, that's a common problem in old style handler functions. They had no concept of bound context. And because in your code the onload can get called in arbitrary order, names can get switched around. You can resolve that with a new ES6 style lambdas. So this should work. <!DOCTYPE html> <html><head><meta http-equiv="Content-Type" content="text/html; charset=UTF-8"> <div id="holder" class=""> <style> #holder {background-color: white; width: 100%; height: 100%;} #holder.hover {background-color: lightgray;} .center {text-align:center;} .agif {width: auto; vertical-align:middle; margin: 2px; display: inline-block;} body {border: 0px solid red;margin:0; padding: 0;height:100%} html {height:98%} </style> <article> <p id="status"></p> <p>Drag images (gif/jpg/png/bmp) from your desktop into this window to build a gallery.</p> <p>Save as complete web page with your images embedded in the page. Then reload into a browser to see your gallery again.</p> <p id="pics"></p> </article> </div> <script> var holder = document.getElementById('holder'), state = document.getElementById('status'); if (typeof window.FileReader !== 'undefined') { state.innerHTML = 'File API & FileReader available'; } holder.ondragover = function () { this.className = 'hover'; return false; }; holder.ondragend = function () { this.className = ''; return false; }; holder.ondragleave = holder.ondragend; holder.ondrop = function (e) { this.className = ''; e.preventDefault(); for (var i = 0; i < e.dataTransfer.files.length; i++ ) { var reader = new FileReader(); var f = e.dataTransfer.files[i]; const name = f.name; const pics = document.createElement('pics' + i); reader.onload = (event) => { pics.innerHTML = `<div class='agif'><img src='${event.target.result}'/></br>${name}</div>`; holder.appendChild(pics); }; reader.readAsDataURL(f); }; return false; }; </script> </body></html> I'm not an expert on JS by any means, but the way I understand it, with the ()=>{} style lambdas you create a new instance of it every time it's bound in that loop, and along with the lambda itself, it binds the values of all the variables it uses inside. In this case, the string name and pointer to element pics. Use of const over var is purely syntactic sugar. Modern JS style is to use const or let instead of var. But afaik, this should have worked with var just the same. Link to post Share on other sites
komalr 10 Posted July 24, 2020 Author Share Posted July 24, 2020 Hey! Thanks a lot, K^2. This works perfectly. Link to post Share on other sites