2

When I have focus on the input field and I click in any open area of the body, the body becomes the document.activeElement , Is there a way to prevent the body focus completely. What I am looking for is :

  1. To prevent focus the body and maintain focus on the input field.
  2. To avoid the firing of the blur event on the input field.

I've tried adding tabindex=-1 but I believe its for Tab functionality and hence does not work in this case.

document.querySelector("#inpdontlosefocus")
  .addEventListener("blur",function(){
    
  const $log = document.querySelector("#log");
  $log.innerText += "\r\nLost focus";
})
html,body {
  width:100vw;
    height: 100vh;
}
<body id="notokaytogetfocus">
  <input id="inpdontlosefocus" type="" placeholder="dont lose focus to body">  
  
  <input id="inpokaytofocus" type="" placeholder="allow focus">  
  <div id="log"></div>
</body>

2 Answers2

0

I'd added more html elements for a more accurate demonstration, the logic here is if the event source in body is not focus-able then we set focus back to the input we want, other wise the its a focusable element thus will get the focus(e.g. button, link, input, ...); notice that click event is attached to body and clicking outside body won't have this behavior.

document.querySelector('.notokaytogetfocus').addEventListener("click",function (e){
  if(e.target == document.activeElement){
    console.log("focusable element");
  }else{
    console.log("not focusable element");
    // we'll set foucs on desired input
    document.querySelector("#inpdontlosefocus").focus()
  }
})
.notokaytogetfocus{height: 100vh; width:100vw;}
<div class="notokaytogetfocus">
  <input id="inpdontlosefocus" type="" placeholder="dont lose focus to body">  
  <input id="inpokaytofocus" type="" placeholder="allow focus"> 
  <button>do!(focusable)</button>
  <p>lorem ipsum</p>
  <div>some text</div>
</div>
Mechanic
  • 5,015
  • 4
  • 15
  • 38
  • thank you, If we remove the .maincontent div, the body still gets focus and it seems to defeat the purpose. Is there something I'm missing? – Royston dsouza May 18 '20 at 06:25
  • @Roystondsouza in a real life situation `body` tag contains your elements and will be big enough; but in this snippet `body` is not behaving like real `body` in `html` document so I'd added that `div` to simulate more realistic situation; this `height: 100vh;` is key here not `div`; you can apply it to body itself – Mechanic May 18 '20 at 06:51
  • you're right about the body height. I've corrected the code snippet,thanks. But the body still get focus. (e.g. in your code view if i click the top right corner, beside the button, the body tag is the active element and blur is fired). – Royston dsouza May 18 '20 at 14:53
  • @Roystondsouza I'd said that before; *if you click outside body ...* and I said that this usually never happens in real use-cases; and the code inside this snippet can't be exactly like real world since its a **snippet**. btw I'd `width: 100vw` to ensure container's width (i.e. `body` tag in real code) will be as big as the result screen inside the snippet and made the snippet simpler to you would be able to use it; – Mechanic May 18 '20 at 17:00
  • This is looks much better thank you for taking the time.But to get the originally focused input there's no way i guess other than to store it in a variable like @th31 mentioned. I am hoping to get a windows app like sturdy functionality. That will prevent a blur event. is there any way i could achieve that ? – Royston dsouza May 19 '20 at 14:58
0

Here is a solution that will always keep the focus on input fields in your document:

  • you will be able to switch the focus between input fields.

  • if you clicked outside an element that is not input, it will get the lastest input blurred and will apply focus on it.

var blurred, focused;
const $log = document.querySelector("#log");
var els = document.querySelectorAll('input');
Array.prototype.forEach.call(els, function(el) {
  el.addEventListener('focus', function() {
    focused = this;
  });
  el.addEventListener('blur', function() {
    $log.innerText += "\r\nLost focus;"
    blurred = this;
  });
});

document.addEventListener("click", function(e) {
  e.preventDefault();
  if (focused && focused.tagName == "INPUT") {
    $log.innerText += "\r\nactiveElement= " + document.activeElement.id;
    focused.focus();
  } else if (blurred) blurred.focus();
})
html,
label {
  width: 100%;
  height: 100%;
}
<body id="notokaytogetfocus">
  <input id="inpdontloosefocus" placeholder="dont loose focus to body">

  <input id="inpokaytofocus" placeholder="allow focus">
  <div id="log"></div>

</body>
h3t1
  • 1,126
  • 2
  • 18
  • 29
  • Thank you th31,+ 1 as this is the closest.But I was hoping to get a windows app like sturdy functionality. That will prevent a blur event as we also use a lot of custom element so its not just input fields but the elements encapsulating it that are permitted to be clicked. – Royston dsouza May 18 '20 at 14:32