gaurav5430
gaurav5430

Reputation: 13917

pointer-events:none but capture click

is it possible to allow only click and disable all other pointer-events

top-layer has a search bar

bottom-layer has a word cloud

I have set pointer-events:none on top-layer, so all words in the word cloud can be hovered over even if they are below the search bar.

but I want the click event on the input text to be enabled, so that when the user wants to type in something, he can.

enter image description here

Here is a related fiddle

The text is behind the input, but it should be hoverable, the input is above the text, but it should be focusable using mouse, to allow the user to type in.

Note: it looks like a placeholder thing, but it is not. please see the original image to see what i am trying to achieve.

Upvotes: 25

Views: 43712

Answers (6)

mkupiniak
mkupiniak

Reputation: 127

Wouldn't it be easiest to set input's z-index to a higher value than the element with pointer-events: 'none'?

Upvotes: 0

la_petite_kozel
la_petite_kozel

Reputation: 890

I had the same problem in the past. I managed to solve it in a bit tricky way, just added parent division with button inside and applied click event on parent element and pointer-events: none to child button element.

Upvotes: 0

user3342816
user3342816

Reputation: 1263

If layout permits it you could use the adjacent sibling combinator, given that you re-order the elements:

Tested on FireFox and Chrome.

.backText:hover {
  color           : red;
}
.cl1 {
  opacity         : 0.7;
  position        : absolute;
}
/* adjacent sibling combinator */
.wrap-input:hover + div {
  color           : red;
}
.cl1:focus {
  opacity         : 1;
}
<div>
  <div class="wrap-input">
    <input type="text" class="cl1" value="aa" />
  </div>
  <div class="backText">
     Some text to be hovered even if input is above
  </div>
</div>


Other options

The following only works on FireFox. Tested on Chrome and it flickers when pointer is moved, - but could perhaps give some ideas.

Instead of setting pointer-events on the input-element directly, set it using the :hover pseudo-class.

Example, based on your fiddle:

.cl1 {
  position        : absolute;
  top             : 0px;
  opacity         : 0.7;
  height          : 30px;
}
/* Move pointer-events here */
.cl1:hover {
  pointer-events  : none;
}
.cl1:focus {
  opacity         : 1;
}

.backText:hover {
  color           : red;
}
<div>
  <div class="backText">
     Some text to be hovered even if input is above
  </div>
  <div>
    <input type="text" class="cl1" />
  </div>
</div>

Upvotes: 0

DavidDomain
DavidDomain

Reputation: 15303

I think this should work. Listening to the click event on the parent container, getting the event.clientX and event.clientY values to check if they are within the bounds of the input element. If so, you can then set the focus to the input element. You can still determine if one of the random words underneath the input element has been clicked.

var d = document,
    c = d.getElementsByClassName('container').item(0),
    inp = d.createElement('input'),
    a = 50,
    i = 0;


/*
 | get the clientBoundingRect of the input element
 | and if the mouse x and mouse y positions are within
 | the bounds set the focus on to the input element.
------------------------------------------------------------- */
function inpClickHndl (evt) {
  var inpRect = inp.getBoundingClientRect(),
      x = evt.clientX,
      y = evt.clientY,
      l = inpRect.left,
      w = l + inpRect.width,
      t = inpRect.top,
      h = t + inpRect.height;

  if (x >= l && x <= w && y >= t && y <= h) {
    inp.focus();
  }
}

/* 
 | ignore this, it's just to create the random words.
------------------------------------------------------------- */
function wordClickHndl (evt) {
  this.style.color = "yellow";
}

for (i; i < a; i++) {
  var p = d.createElement('p'),
      t = d.createTextNode('Random Word');
  p.appendChild(t);
  p.addEventListener('click', wordClickHndl, false);
  p.style.position = 'absolute';
  p.style.top = Math.floor(Math.random() * (window.innerHeight - 80)) + -40 + 'px';
  p.style.left = Math.floor(Math.random() * (window.innerWidth - 80)) + -40 + 'px';
  p.style.fontSize = Math.floor(Math.random() * (38 - 8)) + 8 + 'px';
  p.style.fontWeight = 'bold';
  c.appendChild(p);
}

inp.setAttribute('type', 'text');
c.appendChild(inp);

/*------------------------------------------------------------- */

// add a click handler to your parent element.
c.addEventListener('click', inpClickHndl, false);
body {
  margin: 0;
  font-family: sans-serif;
}

.container {
  position: relative;
  height: 100vh; width: 100vw;
  background-color: #1a1a1a;
}

.container p {
  color: green;
}

.container p:hover {
  color: red;
  cursor: pointer;
}

.container input {
  position: absolute;
  top: 50%; left: calc(50% - 85px);
  pointer-events:none;
  opacity: .75;
}
<div class="container"></div>

Upvotes: 3

Yoram de Langen
Yoram de Langen

Reputation: 5509

Because pointer-events is blocking interactieve events(click, hover, mouseenter etc.) it would be only accessible with javascript (through focus for example).

It's maybe not the best solution but it will do I guess in your case?

(function($) {
  var focus = false;
  $(document).on('click', function(e) {
    console.log(focus);
    e.preventDefault();
    if (focus) {
      focus = false;
      $('.cl1').trigger('blur');
    } else {
      focus = true;
      $('.cl1').focus();
    }
  });
})(jQuery);

a fiddle with this working solution: https://jsfiddle.net/cob02bpv/1/

Edit: you could check on which element was clicked, only elements under the input will be tricky.

If its not the solution the only one would be to calculate the coordinates from the input box and check where the click event was triggered. But still you would have problems for your elements under the input box.

Upvotes: 3

user5066707
user5066707

Reputation:

Just add the pointer-events CSS3 property, setting as initial to the text box. Using !important is recommended also, so because another property can pass that added.

In CSS3:

pointer-events:initial !important

In JavaScript:

document.querySelector('input[type=text]').style.pointerEvents="initial"

Upvotes: 1

Related Questions