skip to Main Content

I have a button that when it has focus will make a div containing an input become visible:

function makeFocus() {
    //document.getElementById('in').focus();
}
.edit-path-container {
    display: none;
    height: 100%;
}
.edit-path-btn:focus + .edit-path-container {
    display: block;
}
.edit-path-container:focus-within, .edit-path-container:active {
    display: block !important;
}
<button class="edit-path-btn " style="float:right" onfocus='makeFocus()'>click to show</button>
<div class="edit-path-container ">
    <input id="in" type="text" value="test">
</div>

Here you can click in the input and edit the text, if you click away the container will disappear as intended.
I have added some JavaScript to give the input focus so the user can start typing straight away but the container never becomes visible. Is there a way to fix this?

3

Answers


  1. I think you can do like that :

    function switchFocus() {
      const input = document.getElementById('in');
      input.parentElement.classList.toggle('invisible');
      if (!input.parentElement.classList.contains('invisible')) {
        input.focus();
      }
    }
    .invisible {
        display: none;
    }
    <button class="edit-path-btn " style="float:right" onclick='switchFocus()'>click to show</button>
    <div id="in-container" class="edit-path-container invisible">
        <input id="in" type="text" value="test" onblur="switchFocus()">
    </div>
    Login or Signup to reply.
  2. The problem with how it works is the blur event fires before the focus happens so the element hides as you try to focus it.

    Only way I can see to get around it with how your HTML code is written is to add a temp class that makes it visible and you can then remove that temp class after you focus it or use all JavaScript.

    function makeFocus() {
      var inp = document.getElementById('in');
      inp.classList.add('active');
      inp.focus();
      inp.classList.remove('active');
    }
    .edit-path-container {
      display: none;
      height: 100%;
    }
    
    .edit-path-btn:focus+.edit-path-container {
      display: block;
    }
    
    .edit-path-container:focus-within,
    .edit-path-container:active,
    .edit-path-container:has(.active) {
      display: block !important;
    }
    <button class="edit-path-btn " style="float:right" onfocus='makeFocus()'>click to show</button>
    <div class="edit-path-container ">
      <input id="in" type="text" value="test">
    </div>
    Login or Signup to reply.
  3. Basic CSS I simplified but then added some more to remove the problematic float when placed on a page.
    Change summary:

    • Used events on the elements
    • Removed event attachment from HTML and put it in code
    • Used a custom event just for clarity
    • Focus out/blur on the text fields will hide it using the 'blur' event
    • Key part Used an attribute on the element to show/hide its container wrapper as a toggle mechanism
    • Can also have multiple values for "custom" effects. For example add a new value to both show it and show a related for example to show an adjacent sibling when the blur happens; things like that. ref: https://developer.mozilla.org/en-US/docs/Web/CSS/Adjacent_sibling_combinator
    • Lots of excess console logs to show what happens when/where
    let editPathButton = document.querySelector('.edit-path-btn');
    let textInputFoFocus = document.querySelector('.text-input-for-focus');
    const focusEvent = new Event("focus");
    const makeVisibleEvent = new Event("makevisible");
    editPathButton.addEventListener('click', makeFocus, false);
    
    function makeFocus(event) {
      console.log("here");
      textInputFoFocus.dispatchEvent(makeVisibleEvent);
    }
    
    textInputFoFocus.addEventListener("blur", (event) => {
      console.log("here in blur");
      event.target.dataset.showonfocus = "hide";
    });
    textInputFoFocus.addEventListener("makevisible", event => {
      console.log("here in custom");
      event.target.dataset.showonfocus = "show";
      event.target.focus()
      console.log(event.target.outerHTML);
    });
    textInputFoFocus.addEventListener("focus", (event) => {
      console.log("here in focus; start typing");
    });
    body {
      font-size: 16px;
      margin: 0;
      padding: 0;
      box-sizing: border;
    }
    
    .container-wrapper {
      display: grid;
      grid-template: columns: 1fr auto;
      justify-content: space-between;
      height: 3rem;
      padding: 1rem;
    }
    
    .edit-path-btn {
      grid-column: 2;
      grid-row: 1;
      height: 1.5rem;
    }
    
    .edit-path-container {
      grid-column: 1;
      grid-row: 1;
      display: none;
      height: 100%;
    }
    
    .edit-path-container:has(> .text-input-for-focus[data-showonfocus="show"]) {
      display: block;
    }
    <div class="container-wrapper">
      <button class="edit-path-btn">Click to show and focus text edit</button>
      <div class="edit-path-container">
        <label for="in">Edit Me:</label>
        <input class="text-input-for-focus" id="in" type="text" value="test" data-showonfocus="hide">
      </div>
    </div>
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search