0

I am doing some self taught html/js. I am trying to make a simple image uploader, the tutorial I am following gives the following html,

<section id="image" class="button">
    <button>Add image</button>
    <input type="file" accept="image/*">
  </section>

In the CSS I have

section.button input[type="file"] {
    display: none;
  }

To hide the choose file button. It asks to set up the javascript so that when the add image button is clicked it calls the .click method for the hidden button.

It says this can be done by obtaining a reference to the hidden element. I cannot find anything in the videos supplied which explain how to do this. I have looked on youtube at videos but they all seem to give the hidden input an id such as,

<input type="file" id = "file" accept="image/*">

Is there an error in the supplied html file or is it possible to get obtain a reference to the hidden element without giving it an id?

Thank you

Joe Pasquale
  • 27
  • 1
  • 1
  • 5

3 Answers3

2

Your CSS selector string

section.button input[type="file"]

already selects the input you need - all you need to do is pass that selector string to querySelector, and you'll be returned a reference to that <input>:

const input = document.querySelector('section.button input[type="file"]');
input.click();

What that selector string means is: select an input with an attribute type whose value is file, which is a descendant of a section whose class is button. (Just for an example, if you wanted to select the <button> instead of the <input>, you can follow the exact same pattern - just use button instead of input: section.button button)

CertainPerformance
  • 356,069
  • 52
  • 309
  • 320
2

You can use nextElementSibling to find the hidden input from the button:

document.querySelector('#image button').addEventListener('click', function() {
  this.nextElementSibling.click();
})
section.button input[type="file"] {
  display: none;
}
<section id="image" class="button">
  <button type="button">Add image</button>
  <input type="file" accept="image/*">
</section>
connexo
  • 53,704
  • 14
  • 91
  • 128
1

There are multiple ways to get a reference to your DOM element from JavaScript. You can use document.querySelector() and give it a CSS selector. This will give you the first element matching your selector. That way you can fetch by id using a selector like #myId or by input type with a selector like input[type="file"].

Or you can directly use document.getElementById() and give it the unique id of your element.

To attach an event listener to the button and call the click method of the hidden input, use addEventListener('click', handler), in the handler, find the input using the above methods, and call the click() method on it:

console.log(document.getElementById('file'));
console.log(document.querySelector('#file'));
console.log(document.querySelector('input[type="file"]'));

document.querySelector('#image button').addEventListener('click', event => {
  document.querySelector('input[type="file"]').click();
});
section.button input[type="file"] {
  display: none;
}
<section id="image" class="button">
  <button>Add image</button>
  <input type="file" accept="image/*" id="file">
</section>
jo_va
  • 13,504
  • 3
  • 23
  • 47
  • No need to query the DOM again, the input is the `this.nextElementSibling` inside your click handler (unless you use an arrow function, then it's got to be `event.target.nextElementSibling`). – connexo Mar 05 '19 at 09:45
  • @connexo, you are totally right, I upvoted your answer, but if an element is inserted between the button and the input, it won't work anymore, I prefer to give explicit references to the elements to avoid any breaking change with future changes. And when performance is a problem, then optimize for that. – jo_va Mar 05 '19 at 09:53