user2970179
user2970179

Reputation:

Browse Image and Insert into Iframe

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?

Upvotes: 3

Views: 9955

Answers (2)

zero298
zero298

Reputation: 26877

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:

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:

enter image description here

And the DOM:

enter image description here

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);
    }
 }

Upvotes: 2

cubitouch
cubitouch

Reputation: 1937

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.

Upvotes: 0

Related Questions