I was wondering if this is possible.
I want to create a function to retrieve an image and insert into an iframe. The user must be able to choose a file (image/video) and it will be inserted into an iframe.
main.html
<input type="file" id="addImage"> I have used this for the user to choose a file.
<iframe class="frame" id="frame" src="insert.html"></iframe> And this for the iframe. The iframe src is another html document.
insert.html
<span id="edit"></span> is within the insert.html where the image needs to be inserted to.
I don't quite understand how javascript can be used to retrieve the image from the users selection and insert into the iframe.
Is this possible?
Yes, here is an example. The key is to hook onto the iframe and then use its contentWindow.
EDIT
Additionally, I don't know if you meant the browse for file or the drag'n'drop API so I implemented both.
Lots of help from these sources:
file-api : How to interact with the file-api
drag-drop events : Events to key off of when dragging and dropping
And here is a fiddle:
JSFiddle
CSS
*{
font-family: Arial;
}
.section{
width: 400px;
padding: 20px;
margin: auto;
}
#dragDiv{
background-color: #ffffcc;
}
#browseDiv{
background-color: #ccffcc;
}
#iframeDiv{
background-color: #ffcccc;
}
#dropTarget{
width: 300px;
height: 300px;
border-style: dashed;
border-width: 5px;
}
.dropEnabled{
border-color: #999999;
}
.dropEnabled:hover{
border-color: #ff9933;
}
.dropMe{
border-color: #99ff99;
}
JS
/**
* I set up the listeners for dragging and dropping as well
* as creating an iFrame for holding dragged in images
* #returns {undefined}
*/
function main() {
// The div that receives drops and the new iFrame
var targetDiv = document.getElementById("dropTarget"),
iframe = document.createElement("iframe");
// Set the iframe to a blank page
iframe.src = "about:blank";
// Append it to the target
document.getElementById("iframeTarget").appendChild(iframe);
// Drag over is when an object is hovering over the div
// e.preventDefault keeps the page from changing
targetDiv.addEventListener("dragover", function(e) {
e.preventDefault();
this.className = "dropMe";
}, false);
// Drag leave is when the object leaves the div but isn't dropped
targetDiv.addEventListener("dragleave", function(e) {
e.preventDefault();
this.className = "dropEnabled";
}, false);
// Drop is when the click is released
targetDiv.addEventListener("drop", function(e) {
e.preventDefault();
this.className = "dropEnabled";
loadFile(e.dataTransfer.files[0], iframe);
}, false);
document.getElementById("upload").addEventListener("click", function() {
var file = document.getElementById("browsedFile").files[0];
loadFile(file, iframe);
}, false);
}
/**
* Load a file and then put it on an ifrmae
* #param {Element} f The file that needs to get loaded
* #param {Element} destination The iframe that the file is appended to
* #returns {undefined}
*/
function loadFile(f, destination) {
// Make a file reader to interpret the file
var reader = new FileReader();
// When the reader is done reading,
// Make a new image tag and append it to the iFrame
reader.onload = function(event) {
var newImage = document.createElement("img");
newImage.src = event.target.result;
destination.contentWindow.document.getElementsByTagName("body")[0].appendChild(newImage);
};
// Tell the reader to start reading asynchrounously
reader.readAsDataURL(f);
}
// Run the main script
window.onload = main;
HTML
<!DOCTYPE html>
<html>
<head>
<title>I framed it</title>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width">
</head>
<body>
<div id="dragDiv" class="section">
<div>The div below receives dragged in files</div>
<div id="dropTarget" class="dropEnabled"></div>
</div>
<div id="browseDiv" class="section">
<div>I upload stuff the boring way</div>
<input type="file" id="browsedFile"><button id="upload">Upload</button>
</div>
<div id="iframeDiv" class="section">
<div>And below me, an iFrame gets created</div>
<div id="iframeTarget"></div>
</div>
</body>
</html>
And here is the result:
And the DOM:
EDIT
A comment was made about how to do this with videos as well. There are several ways to do it, but here is one way that I would do it using the HTML5 <vido> tag which you can find more information on here: HTML Videos.
One tricky thing that I'm sure is rather cludgy is how to say what kind of file you should be loading. I use a switch() on the file's type attribute which usually evaluates to something like: image/png or video/mp4 for MP4 videos. However, this ties you to a specific file format. A better way to do it would be to make a regular expression that figures out if it's just an image or a video and ignore the format since the process is rougly the same for all files of those types.
I added my own regular expression implementation. Probably, not the best, but it allows all appropriate image types to come through now.
Also, I tried using some sample videos from Apple which can be found here: Sample QuickTime Movies. However, those did not work for some reason. So after that, I just downloaded the sample videos that W3Schools uses in their tutorial. I'm telling you this so that in case you try it and it doesn't work, it might be the file itself and not your code.
Edited loadFile() Function
/**
* Load a file and then put it on an ifrmae
* #param {Element} f The file that needs to get loaded
* #param {Element} destination The iframe that the file is appended to
* #returns {undefined}
*/
function loadFile(f, destination) {
// Make a file reader to interpret the file
var reader = new FileReader(),
loaderFunc = null,
typeRegEx = /^(\w+)\//,
contentType = f.type.match(typeRegEx)[1];
// Figure out how to load the data
switch (contentType) {
case "video":
loaderFunc = function(event) {
var newVideo = document.createElement("video"),
newVideoSource = document.createElement("source");
newVideo.width = 300;
newVideo.height = 300;
newVideo.setAttribute("controls");
newVideoSource.src = event.target.result;
newVideoSource.type = f.type;
destination.contentWindow.document.getElementsByTagName("body")[0].appendChild(newVideo);
newVideo.appendChild(newVideoSource);
};
break;
case "image":
loaderFunc = function(event) {
var newImage = document.createElement("img");
newImage.src = event.target.result;
destination.contentWindow.document.getElementsByTagName("body")[0].appendChild(newImage);
};
break;
default:
console.log("Unknown file type");
return;
}
// We should have returned, but just make sure
if (loaderFunc) {
// When the reader is done reading,
// Make a new image tag and append it to the iFrame
reader.onload = loaderFunc;
// Tell the reader to start reading asynchrounously
reader.readAsDataURL(f);
}
}
You can manipulate directly an iframe from an other if they are from same domain.
See jQuery/JavaScript: accessing contents of an iframe
What you can do if this is not the case is :
Setting up a communication process between both pages (see How to communicate between iframe and the parent site?)
or
Uploading your file to a server, and refresh the "insert.html" page to display the uploaded image.
Related
With this code, I get only the URL. So I have to call this URL to restore the image.
Is it possible to get the image data itself directly without calling this URL again?
That's to avoid CORS depending on some server.
var dropbox = document.getElementById('dropbox');
dropbox.addEventListener('dragenter', noopHandler, false);
dropbox.addEventListener('dragexit', noopHandler, false);
dropbox.addEventListener('dragover', noopHandler, false);
dropbox.addEventListener('drop', drop, false);
function noopHandler(evt) {
evt.stopPropagation();
evt.preventDefault();
}
function drop(evt) {
evt.stopPropagation();
evt.preventDefault();
var imageUrl = evt.dataTransfer.getData('URL');
console.log(imageUrl)
alert(imageUrl);
}
#dropbox {
border: solid 1px red;
width: 200px;
height: 200px;
}
<div>Drag this image to the drop zone:</div>
<img src="http://www.google.com/logos/2012/Julia_Child-2012-hp.jpg" alt="" />
<div id="dropbox">
DropZone => you could drop any image from any page here
</div>
That's to avoid CORS
It sounds rather like you are trying to avoid Same-Origin-Policy (SOP).
CORS is a way to relax SOP, so it doesn't block some domains to access resources on your server.
SOP is a protection, if you find a way to avoid it that's a security issue, and you should probably report this to browser vendors since they can be generous with such bug reports.
So to answer your question, No, you can't.
As you have already thought, having the image's data passed into the DataTransfer would mean that a cross-origin script would be able to read the content of a cross-domain resource, and we don't want this to happen.
What you can do, as you already found too, is to fetch again that resource using the URL that has been passed into the DataTransfer, but if the server there doesn't allow you to read that content, you still won't be able to do so.
Ps: If the image on the other page was served through CORS, or simply same-origin, and you had access to that page, you could then append the data as a File in the DataTransfer. But I guess if you were in that situation, you could also simply setup your server so that it allows your other ones to read the data there.
Please, run the snippet below.
Before the "ev.target.appendChild(document.getElementById(data))" over this code, you must to follow this instructions:
How can I convert an image into Base64 string using JavaScript?
...It's possible inside<Canvas>
function DopHere(ev) {
ev.preventDefault();
}
function image_drags(ev) {
ev.dataTransfer.setData("text", ev.target.id);
}
function drop(ev,div_id) {
ev.preventDefault();
var hasImages =hasImage(div_id);
var data = ev.dataTransfer.getData("text");
if(hasImages==false){
var data = ev.dataTransfer.getData("text");
ev.target.appendChild(document.getElementById(data));
}else{
alert('div already have an image.');
}
}
function hasImage(id) {
var arrival_div=document.getElementById(id);
var childElements = document.getElementById(id).childNodes;
for (var i = 0; i < childElements.length; i++) {
if (childElements[i].localName != null && childElements[i].localName.toLowerCase() == "img") {
return true;
}
}
return false;
}
#drop_container{border:1px solid #000; width:170px; height:100px; padding:5px; float:left; margin:20px;}
#dropback_container{border:1px solid #000; width:170px; height:100px; padding:5px;float:left; margin:20px;}
img{
max-width:170px;
height:auto;
}
<div id="drop_container" ondrop="drop(event,'drop_container')" ondragover="DopHere(event)"><img id="image_drag" src="http://www.google.com/logos/2012/Julia_Child-2012-hp.jpg" draggable="true"
ondragstart="image_drags(event)"></div>
<div id="dropback_container" ondrop="drop(event,'dropback_container')" ondragover="DopHere(event)"></div>
https://jsfiddle.net/b7p8k5cf/1/
i working on this code that the objective is to: check if is a PNG, check if is 256X256, and transform img to base64 to upload to the server.
so if i select a 256 x 256 img it's loads but,if i load another img that is not a 256 x 256 after selecting a 256 x 256 it's loads and i don't know why!
Video Showing
How can i resolve it?
function isFileImage(file) {
const acceptedImageTypes = ['image/png'];
return file && acceptedImageTypes.includes(file['type'])
}
function importFileandPreview() {
var preview = document.querySelector('img');
var file = document.querySelector('input[type=file]').files[0];
var reader = new FileReader();
if (file) {
//read img
reader.readAsDataURL(file);
//verify type
var text = file.type;
if (text === "image/png") {
//load img
reader.addEventListener("load", function () {
//put img on <img> src
//console logs
//console.log(preview);
//console.log("pre_nat_height:"+preview.naturalHeight);
// console.log("pre_nat_width:"+preview.naturalWidth);
//technically check if img is 256 x 256
var old = preview.src;
preview.src = reader.result;
if(preview.naturalHeight === 256 && preview.naturalWidth === 256){
//create a hidden input (works but value is not from last img)
var element = document.getElementById("imga");
if(typeof(element) != 'undefined' && element != null){
document.getElementById("imga").remove();
}
input = document.createElement('input');
input.setAttribute("type","hidden");
input.setAttribute("id","imga");
input.setAttribute("name","img")
input.setAttribute("value",preview.src);
document.getElementById('count').appendChild(input);
delete preview;
}
//else if img is not 256 x 256
else {
preview.src = old;
alert("Must be a PNG and have 256px X 256px!");
delete preview;
}
}, false);// i don't know why false but ye
}
}
}
<input type="file" id="file" accept="image/PNG" onchange="importFileandPreview()"><br>
<img src=" data:image/png;base64,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" height="256" width="256">
<form id="count">
</form>
tl;dr: You need to perform the check against the natural dimensions of the image inside the handler for the preview's load event.
The problem you're facing is a consequence of bad timing rather than poor logic. More specifically, it lies in that you set the new src of your preview and then check against the loaded image's natural dimensions synchronously.
This approach is wrong because an image loads asynchronously and, therefore, your code doesn't wait for it to load before proceeding with your check. As a result, when, after selecting a valid image, you select an invalid one, you're still checking against the dimensions of the former as the latter hasn't yet loaded.
To correct this error, you have to perform your check inside the handler for the preview's load event, just as shown below.
Working Snippet:
(I've rewritten the function to make it easier to read)
function isFileImage (file) {
const acceptedImageTypes = ["image/png"];
return file && acceptedImageTypes.includes(file["type"])
}
function importFileandPreview () {
var preview = document.querySelector("img");
var file = document.querySelector("input[type=file]").files[0];
var reader = new FileReader();
/* Terminate the function prematurely if the file isn't an image. */
if (!isFileImage(file)) return;
/* Load the file into the reader. */
reader.readAsDataURL(file);
/* Set the 'load' event of the reader. */
reader.addEventListener("load", function () {
/* Create a temporary image to use for the check to avoid flashing. */
var tempPreview = new Image();
/* Set the 'load' event of the temporary preview. */
tempPreview.addEventListener("load", function () {
/* Check whether the selected image isn't 256x256 pixels. */
if (this.naturalHeight != 256 || this.naturalWidth != 256) {
/* Alert the user. */
alert("Must be a PNG and have 256px X 256px!");
/* Restore the default src to the preview. */
preview.src = preview.dataset.defaultSrc;
/* Terminate the function prematurely. */
return;
}
/* Set the result of the reader as the source of the preview. */
preview.src = reader.result;
/* Save the image to the form. */
saveImageToInput(reader.result);
});
/* Set the result of the reader as the source of the image. */
tempPreview.src = reader.result;
});
/* Save the default image in a data-* attribute to use again if needed. */
preview.dataset.defaultSrc = preview.dataset.defaultSrc || preview.src;
}
function saveImageToInput (image) {
/* Find the hidden input. */
var input = document.getElementById("imga");
/* Check whether the input doesn't exist. */
if (!input) {
/* Create a new hidden input. */
input = document.createElement("input");
input.setAttribute("id", "imga");
input.setAttribute("name", "img");
input.setAttribute("type", "hidden");
/* Place the input in the form. */
document.getElementById("count").appendChild(input);
}
/* Save the image as the input's value. */
input.setAttribute("value", image);
}
<input type="file" id="file" accept="image/PNG" onchange="importFileandPreview()"><br>
<img src=" data:image/png;base64,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" height="256" width="256">
<form id="count">
</form>
Notes:
It's a good idea to use a temporary preview to check if the selected image fulfils your criteria because, if you load it in the visible preview and then alert the user, the loaded image will show.
delete preview: Don't do this. Variables in JavaScript aren't supposed to be deleted like this.
The third argument passed to addEventListener determines whether the event is caught in the bubbling or the capturing phase. By default, it's false, so you can omit it.
EDIT: I have half answered my own question, but still need assistance. Please see Dynamically load HTML from other files onto page as you scroll below.
Original post:
I am working on revamping a site for members that contains an image gallery of photos that can be used for marketing purposes. Previously each category was split into sub-categories, resulting in a couple hundred pages and some pages with one image only. I've ditched the sub-categories and contained all the images on each category page. When you click on a thumbnail it the full size image opens in a lightbox with additional info
This is fine for most categories, but some categories are large and contain a couple hundred images. The problem is that on these pages, most of the time not all the thumbnails will load. Instead of using pagination to separate these large categories into multiple pages I want to have more content load dynamically as you scroll down. I do not know how to do this.
The code snippet on jQuery load more data on scroll looks like it could work, but is there a way to replace
html += '<p class="dynamic">Dynamic Data : This is test data.<br />Next line.</p>';
with something that will put the contents of file1.html in its place, followed by file2.html, and so on?
If not, is there some way of creating some sort of file that would have the thumbnail locations that could be referred to and loaded as a user scrolls down?
This YouTube video seemed like a good starting point, but it requires an AJAX call or some other call. I am not sure what this means and where it's calling to.
So I found a potential solution using IntersectionObserver thanks to deanhume.com. It works beautifully in Chrome and newer versions of Firefox.
Sadly, we still code our site work work with IE 11 as our standard. I don't know why, but we do so I have to deal with that. The problem is this solution does not work with an older version of Firefox I use for validation nor does it work with IE 11. So I want to use a polyfill.
The GitHub page for the polyfill talks about using <script src="https://polyfill.io/v3/polyfill.min.js?features=IntersectionObserver"></script> for older browser support, but it does not seem to work. I also placed the polyfill JavaScript file on the site and referenced it in the page head before any other Javascript, but it also does not seem to work.
What is the proper way to load a polyfill file?
The first line referencing it is: <script src="../pathto/polyfills/intersectionobserver.js"></script>
Then there is some unrelated stuff before getting to the Intersection Observer bit; CSS for the fade in and calling in the lazy-load script:
<style>
.fade-in {
animation-name: fadeIn;
animation-duration: 1.3s;
animation-timing-function: cubic-bezier(0, 0, 0.4, 1);
animation-fill-mode: forwards;
}
#keyframes fadeIn {
from {
opacity: 0;
}
to {
opacity: 1;
}
}
.centered {
display:block;
margin:0 auto;
}
</style>
<script type="module">
import LazyLoad from "../pathto/lazy-load.js";
LazyLoad.init();
</script>
Below is the lazy-load.js file.
const defaults = {
imageLoadedClass: 'js-lazy-image--handled',
imageSelector: '.js-lazy-image',
// If the image gets within 100px in the Y axis, start the download.
rootMargin: '100px 0px',
threshold: 0.01
};
let config,
images,
imageCount,
observer;
/**
* Fetches the image for the given URL
* #param {string} url
*/
function fetchImage(url) {
return new Promise((resolve, reject) => {
const image = new Image();
image.src = url;
image.onload = resolve;
image.onerror = reject;
});
}
/**
* Preloads the image
* #param {object} image
*/
function preloadImage(image) {
const src = image.dataset.src;
if (!src) {
return;
}
return fetchImage(src).then(() => { applyImage(image, src); });
}
/**
* Load all of the images immediately
* #param {NodeListOf<Element>} images
*/
function loadImagesImmediately(images) {
// foreach() is not supported in IE
for (let i = 0; i < images.length; i++) {
let image = images[i];
preloadImage(image);
}
}
/**
* Disconnect the observer
*/
function disconnect() {
if (!observer) {
return;
}
observer.disconnect();
}
/**
* On intersection
* #param {array} entries
*/
function onIntersection(entries) {
// Disconnect if we've already loaded all of the images
if (imageCount === 0) {
disconnect();
return;
}
// Loop through the entries
for (let i = 0; i < entries.length; i++) {
let entry = entries[i];
// Are we in viewport?
if (entry.intersectionRatio > 0) {
imageCount--;
// Stop watching and load the image
observer.unobserve(entry.target);
preloadImage(entry.target);
}
}
}
/**
* Apply the image
* #param {object} img
* #param {string} src
*/
function applyImage(img, src) {
// Prevent this from being lazy loaded a second time.
img.classList.add(config.imageLoadedClass);
img.src = src;
}
let LazyLoad = {
init: (options) => {
config = {...defaults, ...options};
images = document.querySelectorAll(config.imageSelector);
imageCount = images.length;
// If we don't have support for intersection observer, loads the images immediately
if (!('IntersectionObserver' in window)) {
loadImagesImmediately(images);
} else {
// It is supported, load the images
observer = new IntersectionObserver(onIntersection, config);
// foreach() is not supported in IE
for (let i = 0; i < images.length; i++) {
let image = images[i];
if (image.classList.contains(config.imageLoadedClass)) {
continue;
}
observer.observe(image);
}
}
}
};
export default LazyLoad;
And just in case it's needed, a sample of the image code on the page:
<img class="js-lazy-image" data-src="url/members/thumbs/ab_banff_np.jpg" alt="rockies, rocky mountains, trees, summer" aria-describedby="image_g2">
Now you can do lazy loading native on html using tag loading="lazy"
Example:
<img src="image.png" loading="lazy" width="200" height="200">
More information: https://css-tricks.com/native-lazy-loading/
To load more content in Javascript (and using jQuery), you can use the following:
$.ajax("path/to/your/file/file1.html")
.done((data) => {
$('body').append(data);
});
What this does:
Get the content of file1.html
Add the content to the body of your current website
More info:
https://api.jquery.com/Jquery.ajax/
https://developer.mozilla.org/en-US/docs/Web/Guide/AJAX
I have a metro app (WinJS) in VS2012 which loads an image inside a by using an a from my local disk like which next function
function loadPictureFromFile(event) {
var selectedFile = event.target.files[0];
var reader = new FileReader();
imageElement = document.createElement("img"); //creates <img id="img"> element
imageElement.title = selectedFile.name; //set photo's name
reader.onload = function (event) {
imageElement.setAttribute("src", event.target.result); //picture's source
_divPicture.appendChild(imageElement); //Add's <img> element to Div element
};
reader.readAsDataURL(selectedFile);
}
but sometimes my image is too big to display on screen, it requires a scroll for viewing it completely, how to add it from javascript or WinJS after loading picture??
in your default.css simply add
body {
overflow-x:auto;
overflow-y:auto;
}
I am using ASP.NET C# 4.0, my web form consist of input type file to upload images.
i need to validate the image on client side, before saving it to my SQL database
since i am using input type= file to upload images, i do not want to post back the page for validating the image size, dimensions.
Needs your assistance
Thanks
you can do something like this...
You can do this on browsers that support the new File API from the W3C, using the readAsDataURL function on the FileReader interface and assigning the data URL to the src of an img (after which you can read the height and width of the image). Currently Firefox 3.6 supports the File API, and I think Chrome and Safari either already do or are about to.
So your logic during the transitional phase would be something like this:
Detect whether the browser supports the File API (which is easy: if (typeof window.FileReader === 'function')).
If it does, great, read the data locally and insert it in an image to find the dimensions.
If not, upload the file to the server (probably submitting the form from an iframe to avoid leaving the page), and then poll the server asking how big the image is (or just asking for the uploaded image, if you prefer).
Edit I've been meaning to work up an example of the File API for some time; here's one:
<!DOCTYPE HTML>
<html>
<head>
<meta http-equiv="Content-type" content="text/html;charset=UTF-8">
<title>Show Image Dimensions Locally</title>
<style type='text/css'>
body {
font-family: sans-serif;
}
</style>
<script type='text/javascript'>
function loadImage() {
var input, file, fr, img;
if (typeof window.FileReader !== 'function') {
write("The file API isn't supported on this browser yet.");
return;
}
input = document.getElementById('imgfile');
if (!input) {
write("Um, couldn't find the imgfile element.");
}
else if (!input.files) {
write("This browser doesn't seem to support the `files` property of file inputs.");
}
else if (!input.files[0]) {
write("Please select a file before clicking 'Load'");
}
else {
file = input.files[0];
fr = new FileReader();
fr.onload = createImage;
fr.readAsDataURL(file);
}
function createImage() {
img = document.createElement('img');
img.onload = imageLoaded;
img.style.display = 'none'; // If you don't want it showing
img.src = fr.result;
document.body.appendChild(img);
}
function imageLoaded() {
write(img.width + "x" + img.height);
// This next bit removes the image, which is obviously optional -- perhaps you want
// to do something with it!
img.parentNode.removeChild(img);
img = undefined;
}
function write(msg) {
var p = document.createElement('p');
p.innerHTML = msg;
document.body.appendChild(p);
}
}
</script>
</head>
<body>
<form action='#' onsubmit="return false;">
<input type='file' id='imgfile'>
<input type='button' id='btnLoad' value='Load' onclick='loadImage();'>
</form>
</body>
</html>
Works great on Firefox 3.6. I avoided using any library there, so apologies for the attribute (DOM0) style event handlers and such.
function getImgSize(imgSrc) {
var newImg = new Image();
newImg.onload = function() {
var height = newImg.height;
var width = newImg.width;
alert ('The image size is '+width+'*'+height);
}
newImg.src = imgSrc; // this must be done AFTER setting onload
}