5

I need to fire onblur event when I click outside "aside panel", in order to make the panel close if user clicks outside navigation panel.
Though I'm using React JS - but for simplicity I've written example in pure JavaScript. Lately I've written something similar and everything works fine, but in this case it's not working, may be because of position fixed.

var d = document.getElementById("fname");

d.addEventListener("blur", myFunction);

function myFunction() {
  alert("Input field lost focus.");
}
var state = true;

function myFunction2() {
  state = !state;
  if (state) {
    d.className = "header__aside";
  } else {
    d.className += " header__aside--open";
  }

}
.main {
  background-color: violet;
  padding: 50px;
}

.header__aside {
  background-color: #cfcfcf;
  box-shadow: 0 19px 38px rgba(0, 0, 0, 0.3), 0 15px 12px rgba(0, 0, 0, 0.22);
  font-size: 1.2rem;
  height: 100%;
  opacity: 0.9;
  position: fixed;
  right: -30%;
  top: 0;
  transition: right 0.5s ease-out;
  width: 30%;
  z-index: 10;
}

.header__aside--open {
  right: 0;
}
<p class='main'>This example</p>
<button type="button" onClick="myFunction2()">
&#9776;
</button>
<div class="header__aside" id="fname">
  <div class="aside-nav">
    <div class="aside-nav__header">
      <button type="button" class="aside-nav__header-button" onClick="myFunction2()">x</button>
    </div>
    <nav class="nav nav__aside">
      <a class="nav__aside-link active" aria-current="true" href="/">Main</a>
    </nav>
  </div>
</div>
Taras Yaremkiv
  • 3,440
  • 7
  • 32
  • 54
  • You can't attach `onblur` event on a div, AFAIK it's generally used with inputs and form elements. – cнŝdk Nov 15 '17 at 13:01
  • @chsdk Weird but in React it's working 100% comething like this:
    – Taras Yaremkiv Nov 15 '17 at 13:03
  • 1
    @chsdk Ok I'll rewrite question using React JS – Taras Yaremkiv Nov 15 '17 at 13:10
  • But I think what you need is a `click` event and check if the taget is not your div. – cнŝdk Nov 15 '17 at 13:16
  • @chsdk I've took example from [detect-click-outside-react-component](https://stackoverflow.com/questions/32553158/detect-click-outside-react-component) question. It's not that simple because I detect if user clicks outside sidepanel area which is dynamic – Taras Yaremkiv Nov 15 '17 at 13:23
  • Yes it would be a little difficult, regarding react, I can't help you with it. I am sorry I am not familiar with ReactJS. – cнŝdk Nov 15 '17 at 13:32

3 Answers3

12

To have Onblur on an element it should receive focus first, Div elements don't receive focus by default. You can add tabindex="0"

<div tabindex="0" ....

Thanks to Emil, for react you can use

tabIndex={0}
shakeel
  • 1,609
  • 1
  • 14
  • 14
  • 1
    This hack works even with React. You can add `tabIndex={0}` to outermost div in order to dismiss keyboard from input. – emil Feb 19 '19 at 09:03
  • If the element that has the `onBlur` effect and `tabindex` is created `onClick` of another element, it does not automatically gets focus when it appears. Thus, you may need to focus it using `element.focus()` after creating the element. – Christopher K. Aug 04 '21 at 05:19
0

You will have to set a tabindex on the div and manually focus it to get the blur handler invoked

var d = document.getElementById("fname");

d.addEventListener("blur", myFunction);

function myFunction() {
  alert("Input field lost focus.");
}
var state = true;

function myFunction2() {
  state = !state;
  d.focus();
  if (state) {
    d.className = "header__aside";
  } else {
    d.className += " header__aside--open";
  }

}
.main {
  background-color: violet;
  padding: 50px;
}

.header__aside {
  background-color: #cfcfcf;
  box-shadow: 0 19px 38px rgba(0, 0, 0, 0.3), 0 15px 12px rgba(0, 0, 0, 0.22);
  font-size: 1.2rem;
  height: 100%;
  opacity: 0.9;
  position: fixed;
  right: -30%;
  top: 0;
  transition: right 0.5s ease-out;
  width: 30%;
  z-index: 10;
}

.header__aside--open {
  right: 0;
}
<p class='main'>This example</p>
<button type="button" onClick="myFunction2()">
&#9776;
</button>
<div class="header__aside" id="fname" tabindex="0">
  <div class="aside-nav">
    <div class="aside-nav__header">
      <button type="button" class="aside-nav__header-button" onClick="myFunction2()">x</button>
    </div>
    <nav class="nav nav__aside">
      <a class="nav__aside-link active" aria-current="true" href="/">Main</a>
    </nav>
  </div>
</div>
Joschi
  • 2,874
  • 1
  • 18
  • 23
0

Add tabindex=0 to the panel-html and focus() to the JS opening the panel:

<div id=panel tabindex=0></div>

document.getElementById('panel').onclick = function(){ 
  document.getElementById('panel').style.display = 'block';
  document.getElementById('panel').focus();
  document.getElementById('panel').onblur = function(){ 
    document.getElementById('panel').style.display = 'none';
  }
}
Sebastian H
  • 109
  • 1
  • 6