2

I have been trying to make this thing that focuses an input inside it when its outer div is clicked. I really hope this is not a duplicate as I have searched everywhere and not found an answer to this. I am at risk of being blocked so I hope no one flags this as a duplicate.

Here is the code below, it works with focusing the input, but when it has to unfocus it does not seem to work.

window.onload = function() {
  var drop = document.getElementsByClassName("datadrop");
  var drops = document.getElementsByClassName("datadrop").length;

  for (x = 0; x < drops; x++) {
    var input = document.getElementById(drop[x].getAttribute("input"));
    drop[x].onclick = function(e) {
      e.preventDefault();
      clicked = 0
      if (this == document.activeElement) {
        input.blur();
      } else {
        input.focus();
      }
    }
  }
}
.datadrop {
  padding: 7.5px;
  width: 85px;
  display: flex;
  align-items: center;
  justify-content: center;
  color: white;
}

.datadrop .drop {
  width: 150px;
  position: fixed;
  display: none;
}

.datadrop .item {
  padding: 10px;
}

.datadrop .item:hover {
  background-color: #F1F3F4;
}

.datadrop .divider {
  padding: 5px;
  color: grey;
}

.datadrop .divider:hover {
  background-color: #ffffff;
}

.datadrop input {
  width: 60px;
  color: black;
}

.datadrop:hover {
  background-color: #F1F3F4;
  color: #5F6368;
}

.datadrop .click {
  color: #5F6368;
}

.datadrop input {
  background-color: transparent;
  border: 1px solid transparent;
  outline: none;
  padding: 5px;
}

.datadrop input:focus {
  background-color: white;
  border: 1px solid black;
  border-radius: 2.5px;
}
<div datadrop="scale" input="scales" class="datadrop">
  <input type="text" id="scales" value="100%"> &nbsp;&nbsp;|&nbsp; <i class="fa-solid fa-caret-down click"></i>
  <div class="drop" id="scale">
    <div class="item">Fit</div>
    <div class="item divider">
      <hr>
    </div>
    <div class="item">Fit</div>
    <div class="item">Fit</div>
    <div class="item">Fit</div>
  </div>
</div>
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.1.1/css/all.min.css" integrity="sha512-KfkfwYDsLkIlwQp6LFnl8zNdLGxu9YAA1QvwINks4PhcElQSvqcyVLLD9aMhXd13uQjoXtEKNosOWaZqXgel0g==" crossorigin="anonymous" referrerpolicy="no-referrer" />

I hope someone has an answer to this using only JavaScript, and I hope no one flags this as a duplicate, as I am trying to not do duplicates.

6
  • It looks like the code works as it is? What exactly are you expecting the code to do? Notice that focus is not the same as hover. Commented Apr 14, 2022 at 10:03
  • I am expecting it to unfocus as soon as I re-click it, I have looked up toggling focus but all of the other answers require me to use jQuery. Commented Apr 14, 2022 at 10:06
  • There's a lot going on in the script. Whenever it creates more than a single event listener, input variable goes to haywire. See stackoverflow.com/q/750486/1169519 Commented Apr 14, 2022 at 10:16
  • Do you by any chance know how I can resolve this? I would greatly appreciate it. Commented Apr 14, 2022 at 10:28
  • @topsoftwarepro check my answer, I have commented out my changes in it. Commented Apr 14, 2022 at 10:51

3 Answers 3

3

I edited your snippet. you used a loop so i supposed that you want to have multiple inputs. By the way, be careful the element does't have a "input" attribute. I tried to follow the logic of your code so i replaced the "input" -wrong- attribute with a data-input attribute.

I used two flags to check if the input is selected: "inputIsSelected" and "selectedDrop"

if inputIsSelected and clicked on same parent blur if inputnotSelected and same parent focus if parent changes then set the inputIsSelected to false

window.onload = function() {
  var drop = document.getElementsByClassName("datadrop");
  var drops = document.getElementsByClassName("datadrop").length;
  let selectedDrop = null // a flag the clicked drop
  let inputIsSelected = false;
  console.log({drops})
  var x;  

  
  for (x = 0; x < drops; x++) {
    //var input = document.getElementById(drop[x].getAttribute("input"));
    
    let inputId = drop[x].dataset.input; //select inputId using a data-* attribute
 
    let input = document.getElementById(inputId);
    
    drop[x].onclick = function(e) {
       
      e.preventDefault();
      clicked = 0
      
      if(this!==selectedDrop){
       selectedDrop = this;
       inputIsSelected = false;
      }
      
      if(!inputIsSelected){
      input.focus();
      inputIsSelected=true;
      }else{
      inputIsSelected=false;
      input.blur()
      }
      
       
      
      
     
    }
  }
}
.datadrop {
  padding: 7.5px;
  width: 85px;
  display: flex;
  align-items: center;
  justify-content: center;
  color: white;
}

.datadrop .drop {
  width: 150px;
  position: fixed;
  display: none;
}

.datadrop .item {
  padding: 10px;
}

.datadrop .item:hover {
  background-color: #F1F3F4;
}

.datadrop .divider {
  padding: 5px;
  color: grey;
}

.datadrop .divider:hover {
  background-color: #ffffff;
}

.datadrop input {
  width: 60px;
  color: black;
}

.datadrop:hover {
  background-color: #F1F3F4;
  color: #5F6368;
}

.datadrop .click {
  color: #5F6368;
}

.datadrop input {
  background-color: transparent;
  border: 1px solid transparent;
  outline: none;
  padding: 5px;
}

.datadrop input:focus {
  background-color: white;
  border: 1px solid black;
  border-radius: 2.5px;
}
<div datadrop="scale" data-input="scales-1" class="datadrop">
  <input type="text" id="scales-1" value="100%"> &nbsp;&nbsp;|&nbsp; <i class="fa-solid fa-caret-down click"></i>
  <div class="drop" id="scale">
    <div class="item">Fit</div>
    <div class="item divider">
      <hr>
    </div>
    <div class="item">Fit</div>
    <div class="item">Fit</div>
    <div class="item">Fit</div>
  </div>
</div>
<div datadrop="scale" data-input="scales-2" class="datadrop">
  <input type="text" id="scales-2" value="100%"> &nbsp;&nbsp;|&nbsp; <i class="fa-solid fa-caret-down click"></i>
  <div class="drop" id="scale">
    <div class="item">Fit</div>
    <div class="item divider">
      <hr>
    </div>
    <div class="item">Fit</div>
    <div class="item">Fit</div>
    <div class="item">Fit</div>
  </div>
</div>
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.1.1/css/all.min.css" integrity="sha512-KfkfwYDsLkIlwQp6LFnl8zNdLGxu9YAA1QvwINks4PhcElQSvqcyVLLD9aMhXd13uQjoXtEKNosOWaZqXgel0g==" crossorigin="anonymous" referrerpolicy="no-referrer" />

Sign up to request clarification or add additional context in comments.

Comments

2

Try this,

window.onload = function() {
  var drop = document.getElementsByClassName("datadrop");
  var drops = document.getElementsByClassName("datadrop").length;
  var focus_array = []; // lets log each focus and blur in this array
  
  for (x = 0; x < drops; x++) {
    var input = document.getElementById(drop[x].getAttribute("input"));
    drop[x].onclick = function(e) {
      e.preventDefault();
      clicked = 0
      if (focus_array[x]) { // just check focus array 
        input.blur();
        focus_array[x]=0; //update focus array for blur
      } else {
        input.focus();
        focus_array[x]=1; //update focus array for focus
      }
    }
  }
}
.datadrop {
  padding: 7.5px;
  width: 85px;
  display: flex;
  align-items: center;
  justify-content: center;
  color: white;
}

.datadrop .drop {
  width: 150px;
  position: fixed;
  display: none;
}

.datadrop .item {
  padding: 10px;
}

.datadrop .item:hover {
  background-color: #F1F3F4;
}

.datadrop .divider {
  padding: 5px;
  color: grey;
}

.datadrop .divider:hover {
  background-color: #ffffff;
}

.datadrop input {
  width: 60px;
  color: black;
}

.datadrop:hover {
  background-color: #F1F3F4;
  color: #5F6368;
}

.datadrop .click {
  color: #5F6368;
}

.datadrop input {
  background-color: transparent;
  border: 1px solid transparent;
  outline: none;
  padding: 5px;
}

.datadrop input:focus {
  background-color: white;
  border: 1px solid black;
  border-radius: 2.5px;
}
<div datadrop="scale" input="scales" class="datadrop">
  <input type="text" id="scales" value="100%"> &nbsp;&nbsp;|&nbsp; <i class="fa-solid fa-caret-down click"></i>
  <div class="drop" id="scale">
    <div class="item">Fit</div>
    <div class="item divider">
      <hr>
    </div>
    <div class="item">Fit</div>
    <div class="item">Fit</div>
    <div class="item">Fit</div>
  </div>
</div>
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.1.1/css/all.min.css" integrity="sha512-KfkfwYDsLkIlwQp6LFnl8zNdLGxu9YAA1QvwINks4PhcElQSvqcyVLLD9aMhXd13uQjoXtEKNosOWaZqXgel0g==" crossorigin="anonymous" referrerpolicy="no-referrer" />

Comments

0

If you want to change the value of the input based on the value of the keyboard input without giving the input focus, you can do this.

let element = document.getElementById("scales");

window.addEventListener("keydown", function () {

     element.value = String.fromCharCode(event.keyCode);

})

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.