0

I am trying to open a window and process the file in the calling JavaScript. I can pass the file name using localStorage but if I return the file I can't get it right. I can't use this solution due to restrictions of the system I am calling the JavaScript from:

var fileSelector = document.createElement('input');
fileSelector.setAttribute('type', 'file');
fileSelector.click();

Can a file object be passed using localStorage or should I use another method? My code is:

<!DOCTYPE html>
<html>
<script language="JavaScript">
function testInjectScript2(){
try {
    var myhtmltext =
    '<input type="file" id="uploadInput3" name=\"files[]" onchange=\'localStorage.setItem("myfile",document.getElementById("uploadInput3").files[0]);\' multiple />';
    console.log("myhtmltext="+myhtmltext);
    var newWin2 = window.open('',"_blank", "location=200,status=1,scrollbars=1, width=500,height=200");
    newWin2.document.body.innerHTML = myhtmltext;

newWin2.addEventListener("unload", function (e) {
   if(localStorage.getItem("myfile")) {
        var f = localStorage.getItem("myfile");
        alert ('in function.f='+f);
        alert ('in function.f.name='+(f).name);
        localStorage.removeItem("myfile");
    }                           
});
    } catch (err) {
                alert(err);
    }
}
</script>
<body>
    <input type="button" text="testInjectScript2" onclick="testInjectScript2()" value="testInjectScript2" />

</body>
</html>
K. A. Buhr
  • 45,621
  • 3
  • 45
  • 71
Ness
  • 3
  • 2

1 Answers1

0

First of all, welcome to SO. If I get you right, you want to upload a file using a new window and get that file using localStorage onto your main page. This is a possible solution. However, please do also note that the maximum size of the localStorage can vary depending on the user-agent (more information here). Therefore it is not recommend to use this method. If you really want to do this, please have a look at the first snippet.

var read = document.getElementById("read-value"), open_win = document.getElementById("open-win"), win, p = document.getElementById("file-set");

open_win.addEventListener("click", function(){
    win = window.open("", "", "width=200,height=100");
    win.document.write(
 '<input id="file-input" type="file"/>' +
 '<script>' +
  'var input = document.getElementById("file-input");' +
  'input.addEventListener("change", function(){window.localStorage.setItem("file", input.files[0]);})'+
 '<\/script>'
    );
})

read.addEventListener("click", function(){
  var file = window.localStorage.getItem("file");
  if(file){
    p.innerText = "file is set";
  }else{
    p.innerText = "file is not set";
  }
})
<button id="open-win">Open window</button>

<br><br>
<!-- Check if file is set in localStorage -->
<button id="read-value">Check</button>

<p id="file-set" style="margin: 10px 0; font-family: monospace"></p>

<i style="display: block; margin-top: 20px">Note: This only works locally as SO snippets lack the 'allow same origin' flag. i.e. just copy the html and js into a local file to use it.</i>

However, why not use a more elegant solution: Simply using a modal. When the input value changes you can simply close the modal and get the file value without all the hassle of a localStorage.

// Get the modal, open button and close button
var modal = document.getElementById('modal'),
    btn = document.getElementById("open-modal"),
    span = document.getElementById("close"),
    input = document.getElementById("file-input"),
    label = document.getElementById("input-label"), file;

// When the user clicks the button, open the modal 
btn.addEventListener("click", function() {
    modal.style.display = "block";
})

// When the user clicks on <span> (x), close the modal
span.addEventListener("click", function() {
    modal.style.display = "none";
})

input.addEventListener("change", function(){
  file = input.files[0];
  modal.style.display = "none";
  
  //Change value of the label for nice styling ;)
  label.innerHTML = input.files[0].name;
  
  //do something with your value
  
})

// When the user clicks anywhere outside of the modal, close it
window.addEventListener("click", function(event) {
    if (event.target == modal) {
        modal.style.display = "none";
    }
})
.modal {
    display: none; /* Hidden by default */
    position: fixed; /* Stay in place */
    z-index: 1; /* Sit on top */
    padding-top: 10px; /* Location of the box */
    left: 0;
    top: 0;
    width: 100%; /* Full width */
    height: 100%; /* Full height */
    overflow: auto; /* Enable scroll if needed */
    background-color: rgb(0,0,0); /* Fallback color */
    background-color: rgba(0,0,0,0.4); /* Black w/ opacity */
}

.modal h2 {
    font-family: sans-serif;
    font-weight: normal;
}

/* Modal Content */
.modal-content {
    background-color: #fefefe;
    margin: auto;
    padding: 20px;
    border: 1px solid #888;
    width: 80%;
}

/* The Close Button */
.close {
    color: #aaaaaa;
    float: right;
    font-size: 28px;
    font-weight: bold;
}

.close:hover,
.close:focus {
    color: #000;
    text-decoration: none;
    cursor: pointer;
}


/* Input styles, added bonus */

.file-input {
 width: 0.1px;
 height: 0.1px;
 opacity: 0;
 overflow: hidden;
 position: absolute;
 z-index: -1;
}

.file-input + label {
    font-size: 1.25em;
    font-weight: 700;
    padding: 10px 20px;
    border: 1px solid #888;
    display: inline-block;
    cursor: pointer;
    font-family: sans-serif;
}

.file-input:focus + label,
.file-input + label:hover {
    background-color: #f7f7f7;
}
<!-- Trigger/Open The Modal -->
<button id="open-modal">Open Modal</button>

<!-- The Modal -->
<div id="modal" class="modal">

  <!-- Modal content -->
  <div class="modal-content">
    <span id="close" class="close">&times;</span>
    <h2><i>Upload a file?</i></h3>
    <input id="file-input" name="file-input" class="file-input" type="file"/>
    <label id="input-label" for="file-input">Upload a file</label>
  </div>

</div>

Hope it helps! Let me know!

Cheers!

Evochrome
  • 1,205
  • 1
  • 7
  • 20
  • Thanks for the detailed answer. It works great when I copy it to an html file and open it in google chrome. I still have to figure out how to use it from the software I am using. The JavaScript code should be run from a software that allows me to write only pure JavaScript. I can't use any html tags as – Ness Sep 11 '18 at 19:23
  • Could you provide some more information on why it is not possible to use div tags? Is it because the pages are fixed? In that case you could simply append the tags using javascript. – Evochrome Sep 11 '18 at 20:33
  • Sure . I am working with enterprise Project and Portfolio Management (PPM) software called Sciforma. I can declare a button in the software and when the user click on this button I can perform some Sciforma commands or execute what is declared in the software as html script . This html script can contain JavaScript and also some Sciforma commands that allows me to get data from Sciforma (such as project id , project name etc.). In this “html script” I can use only pure java and I managed to use also ajax but no html tag is allowed. – Ness Sep 12 '18 at 14:16
  • .I tried to append the tags using JavaScript and looks like it is also not supported inside Sciforma. – Ness Sep 12 '18 at 14:16
  • Originally I used: var fileSelector = document.createElement('input'); fileSelector.setAttribute('type', 'file'); fileSelector.click(); to get file selector and it worked fine until I started to use Sciforma commands . The “.click” stopped working so the Choose file windows explorer window was not displayed. That is why I tried to overcome this by opening a new window and asking the user to click on “Choose file”. – Ness Sep 12 '18 at 14:17
  • Ah okay that is a pity. What problem are you exactly facing right now / What part of your code does not work? – Evochrome Sep 12 '18 at 21:09
  • I noticed the the "fileSelector.click()" is not working in various situation from Sciforma. I am trying to find out why and fix the existing code. – Ness Sep 13 '18 at 11:16
  • What about doing it on `change`? Thus, `fileSelector.addEventListener("change", function(){})`. Also, it could be that Sciforma simply does not support the `.click()`. In the last case you could try to call the `onclick` function directly using `fileSelector.onclick();`. Let me know how it works out for you – Evochrome Sep 14 '18 at 22:26
  • Already tried… change event is triggered after the user choose a file and my issue is that the file explorer is not displayed. fileSelector.onclick(); returns error message “fileSelector.onclick is not a function”. The “.click()” is supported because if it is the only thing in the script it works. It also works from IE and EDG. The issue is only with Chrome. – Ness Sep 16 '18 at 10:09
  • Managed to append the modal to my JavaScript inside Sciforma! Working perfect and returns the file . Only issue I have now is that it does not support UTF-8 characters in the file. I'm sure there is a simple solution. Thanks for all the help – Ness Sep 16 '18 at 15:02
  • Glad to hear that it did work in the end! I would appreciate it if you could upvote and/or mark my answer as the right answer if it did help you a bit. Good luck and cheers! – Evochrome Sep 17 '18 at 00:50