0

I have a disabled button and I want to display a message in the other side of the page (NOT A CHILD ELEMENT) when I hover this button. How to do that? I already tried using jquery and CSS but it doens't work:

#deleteManagerWarning{
  display: none;
  color: red;
  float: right;
}

#disabledCloseBtn:hover + #deleteManagerWarning{
  display: block;
}

and

  $("#disabledCloseBtn").hover(function(){
    $("#deleteManagerWarning").css("display", "block");
  });

This is the html button:

<button type="submit" 
class="btn-close" 
id="disabledCloseBtn" 
name="disabledCloseBtn" 
disabled 
aria-label="Close">

This is the html message:

<span id="deleteManagerWarning">Unable to delete Manager</span>
Cohiba
  • 23
  • 6
  • 2
    To help, I think we may well need to see more of your HTML; where - for example - are the elements in the DOM in relation to each other? Can you share enough of your "*[mcve]*" code (ideally as [a snippet](https://stackoverflow.blog/2014/09/16/introducing-runnable-javascript-css-and-html-code-snippets/) in your question) that we can reproduce your problem? – David Thomas Jun 02 '22 at 19:24
  • solution is a little trickier than I thought, it doesn't appear that disabled elements fire events. There are some tricks to work around this, see https://stackoverflow.com/questions/18113937/fire-onmouseover-event-when-element-is-disabled – Lucretius Jun 02 '22 at 19:28

2 Answers2

0

If the two elements are far separated from each other in the markup, CSS won't help you-- you need a relationship like descendent or adjacent. In this case, your jQuery would be working if the button were not disabled:

$(document).ready(() => {
 $("#disabledCloseBtn").hover(function(){
    console.log('hover');
    $("#deleteManagerWarning").css("display", "block");
  });
 });
#deleteManagerWarning {
  display: none;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div>
  <button type="submit" class="btn-close" id="disabledCloseBtn" name="disabledCloseBtn" aria-label="Close">
  Close
</button>
</div>
<div>
  <p>Dummy content</p>
  <p>Dummy content</p>
  <p>Dummy content</p>
  <span id="deleteManagerWarning">Unable to delete Manager</span>
</div>

However, it appears that jQuery does not (or cannot) fire the hover event for a disabled button-- the following example is exactly the same as the first except the button is disabled:

$(document).ready(() => {
 $("#disabledCloseBtn").hover(function(){
    console.log('hover');
    $("#deleteManagerWarning").css("display", "block");
  });
 });
#deleteManagerWarning {
  display: none;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div>
  <button type="submit" class="btn-close" id="disabledCloseBtn" name="disabledCloseBtn" disabled aria-label="Close">
  Close
</button>
</div>
<div>
  <p>Dummy content</p>
  <p>Dummy content</p>
  <p>Dummy content</p>
  <span id="deleteManagerWarning">Unable to delete Manager</span>
</div>

In this case, you have a few alternative options you can employ:

  1. Fake the disabled state on the button: reduce the opacity, remove click handlers, make sure you update the ARIA messaging to report the button as disabled. (You could also fake the button entirely using a <div> and wiring up all the accessibility and interactivity, but this would be much more difficult and to a similar effect). This may actually be more accessible, because a disabled button isn't focusable by keyboard.
  2. Use a different hover target: Instead of the button, try using the wrapper around the button, or float something invisible over the button.

Here is an example faking the disabled state:

$(document).ready(() => {
  $("#disabledCloseBtn").hover(
    function() {
      $("#deleteManagerWarning").css("display", "block");
    },
    function() {
      $("#deleteManagerWarning").css("display", "none");
    },
  );
});
#deleteManagerWarning {
  display: none;
}

.disabled {
  opacity: 0.5;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div>
  <button type="submit" class="btn-close disabled" id="disabledCloseBtn" name="disabledCloseBtn" aria-label="Close">
  Close
</button>
</div>
<div>
  <p>Dummy content</p>
  <p>Dummy content</p>
  <p>Dummy content</p>
  <span id="deleteManagerWarning">Unable to delete Manager</span>
</div>

Just make sure you are figuring out a way to communicate that it is disabled to assistive technologies -- and remember, content that is popping into the existence on the other side of the page probably needs to be appropriately announced to screen readers.

Alexander Nied
  • 12,804
  • 4
  • 25
  • 45
0

Problem

It appears that JavaScript and jQuery do not detect disabled tags (I learned something today).

CSS has no problem:

Figure I

<button class='A'>A</button>
<output class='A'>HELLO WORLD!</output>

Figure II

button.A:hover:disabled + output.A {
  display: inline-block;
} 
/*  */

Figure III

$('button.A').hover(enter, exit)
// OR
document.querySelector('button.A').addEventListener('mouseenter', enter);
document.querySelector('button.A').addEventListener('mouseleave', exit);
/*  */

If you need to use jQuery or JavaScript you'll need to wrap the disabled button in another tag (See Example C and D). Note, the JavaScript portion of Figure III is slightly different than the JavaScript in Example D. In Figure III the events used are "mouseenter" and "mouseleave" which are the equivalent of the jQuery .hover() method. In Example D the events "mouseover" and "mouseout" were used because Example D was setup to delegate the events which requires bubbling in which "mouseenter" and "mouseleave" do not do. At the bottom of this answer are links to everything either discussed or demonstrated.

Solutions

CSS: A combination of :hover, :disabled, and sibling combinators (+ and ~). If given the exact HTML layout, I could assist you in obtaining the exact selector. If it's too much HTML, a link to a Plunker, Pen, or Fiddle will be fine.

From what I already know, I believe the general sibling combinator will work (see Example B)

OR

jQ/JS: Wrap the disabled button in another tag and target that instead.

/**
* Example C - button wrapper (jQuery)
*/
$("button.C, menu.C").hover(jQEnter, jQExit);

function jQEnter(e) {
  /* DEMO =------------------= */
  console.clear();
  console.log(this.tagName);
  /* =-----------------------= */
  $("output.C").show();
}

function jQExit(e) {
  $("output.C").hide();
}

/**
* Example D - button wrapper (JavaScript)
*/
document.querySelector('fieldset.D').addEventListener('mouseover', JSEnter);
document.querySelector('fieldset.D').addEventListener('mouseout', JSExit);

function JSEnter(e) {
  /* DEMO =------------------= */
  console.clear();
  console.log(e.target.tagName);
  /* =-----------------------= */ 
  if (e.target.matches('button.D, menu.D')) {
      document.querySelector('output.D').style.display = 'inline-block';
  }
}

function JSExit(e) {
  if (e.target.matches('button.D, menu.D')) {
    document.querySelector('output.D').style.display = 'none';
  }
}
/**
* Example A - adjacent sibling combinator (CSS)
*/
button.A:disabled:hover+output.A {
  display: inline-block;
}

/**
* Example B - general sibling combinator (CSS)
*/
button.B:disabled:hover~output.B {
  display: inline-block;
}
<style>
  /* DEMO =----------------------=*/
  
  fieldset {
    position: relative;
    margin-bottom: 20px;
  }
  
  fieldset:nth-of-type(2) {
    padding-bottom: 25px;
  }
  
  fieldset fieldset {
    margin-bottom: 5px;
  }

  pre {
    outline: dashed blue 1px;
  }
  
  p {
    margin-top: -3px;
    margin-bottom: -3px;
  }
  
  output {
    position: absolute;
    z-index: 1;
    display: none;
    margin-bottom: 4px;
    color: red;
  }
  
  menu {
    max-width: max-content; 
    padding: 10px;
    outline: red dashed 1px;
  }
  
  .as-console-row::after {
    width: 0;
    font-size: 0;
  }
  
  .as-console-row-code {
    width: 100%;
    word-break: break-word;
  }
  
  .as-console-wrapper {
    min-height: 25% !important;
    max-width: 50%;
    margin-left: 50%;
  }
  /* =---------------------------= */
</style>

<fieldset class='A'>
  <legend>Example A - <code>output.A</code> is <b>directly</b> after <code>button.A</code></legend>
  <pre><code>
  button.A:disabled:hover + output.A {
    display: inline-block;
  }
  </code></pre>
  <button class="A" disabled>button A</button>
  <output class="A">output A</output>
</fieldset>

<fieldset class='B'>
  <legend>Example B - <code>output.B</code> is after <code>button.B</code></legend>
  <p><b>and</b> there could be other tags between them</p>
  <pre><code>
  button.B:disabled:hover ~ output.B {
    display: inline-block;
  }
  </code></pre>
  <button class="B" disabled>button B</button>
  <fieldset disabled>
    <legend>Manager</legend>
  </fieldset>
  <output class="B">output B</output>
</fieldset>

<fieldset class='C'>
  <legend>Example C - <code>output.C</code> is anywhere on page</legend>
  <output class="C">output C</output>
  <menu class='C'>
    <button class="C" disabled>button C</button>
  </menu>
  <button class="C" disabled>button C</button>
  <button class="C">button C ENABLED</button>
</fieldset>

<fieldset class='D'>
  <legend>Example D - <code>output.D</code> is anywhere on this page</legend>
  <output class="D">output D</output>
  <menu class='D'>
    <button class="D" disabled>button D</button>
  </menu>
  <button class="D" disabled>button D</button>
  <button class="D">button D ENABLED</button>
</fieldset>

<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>

References

zer00ne
  • 41,936
  • 6
  • 41
  • 68