How to display another element when hover disabled button? - javascript

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>

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:
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.
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.

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
HTML Attribute
disabled
CSS Selectors
:disabled
:hover
Child & Sibling Combinators
jQuery Methods
.hover()
.show() & .hide()
JavaScript Events
Events
Event Delegation

Related

jQuery multiple button show and hide elements when click

I have a multiple buttons has show and hide class. Which is also activate the elements every toggle click. I want to make it a shorter code and make it globally. Please help me how to do it. All I want is to achieve a lesser code and same with the result.. Thank you.
$('.show').on('click', function () {
$(this).addClass('inactive');
$('.hide').removeClass('inactive');
$('.helloworld').removeClass('inactive')
})
$('.hide').on('click', function () {
$(this).addClass('inactive');
$('.show').removeClass('inactive');
$('.helloworld').addClass('inactive')
})
$('.ok').on('click', function () {
$(this).addClass('inactive');
$('.cancel').removeClass('inactive');
$('.thanks').removeClass('inactive')
})
$('.cancel').on('click', function () {
$(this).addClass('inactive');
$('.ok').removeClass('inactive');
$('.thanks').addClass('inactive')
})
<style>
.inactive{
display:none;
}
button{
padding:5px 25px;
color: #fff;
background-color:#1d9bf0;
margin-top: 10px;
}
</style>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<button class="show"> + Show </button>
<button class="hide inactive"> - Hide </button>
<p class="helloworld inactive">Hello WOrld</p>
<br>
<button class="ok"> + Ok </button>
<button class="cancel inactive"> - Cancel </button>
<p class="thanks inactive">Thank you</p>
The technique you're looking for here is DRY, or Don't Repeat Yourself. To do this, look for the common patterns in the logic you have.
In this case each button has its text updated, and it changes the state of it's following sibling. Therefore you can place common class attributes on the elements so that the same JS logic can be applied to them all. From there you can use jQuery's DOM traversal methods to relate the elements to each other, and also data attributes to store custom metadata about the elements which can be used when the click event occurs.
Finally you can use toggleClass() to add/remove the classes to display/hide the elements as necessary.
Here's a working example:
$('.toggle').on('click', e => {
let $btn = $(e.target);
$btn
.text(() => $btn.data($btn.hasClass('show') ? 'hide-text' : 'show-text')).toggleClass('show') // update text
.next().toggleClass('inactive'); // toggle related content
})
<style>
.inactive {
display: none;
}
button {
padding: 5px 25px;
color: #fff;
background-color: #1d9bf0;
margin-top: 10px;
}
</style>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div class="toggle-container">
<button class="toggle show" data-show-text="+ Show" data-hide-text="- Hide">+ Show</button>
<p class="content inactive">Hello WOrld</p>
</div>
<div class="toggle-container">
<button class="toggle show" data-show-text="+ Ok" data-hide-text="- Cancel">+ Ok</button>
<p class="content inactive">Thank you</p>
</div>

Javascript - show a button inside of a DIV when clicked (and hide all others)

I have a list of DIVS that have buttons inside. By default, all buttons are hidden. When I click within a DIV area, the current button inside of this clicked DIV are should show (class='.db') AND all previously clicked/shown buttons should be hidden (class='.dn'). In other words, at any time there should be only one button (currently clicked) shown and all other should be hidden.
I want to use vanilla Javascript and tried this below, but it won't work. I feel there is some small error but don't know where.. Note - the DIVS and buttons don't have their own unique IDs (they only have the same CSS (.posted) classes.
PS - maybe it'd be better not to add this onClick="t();" to each DIV and use an 'addEventListener' function, but this is way too much for me ; )
CSS:
.dn {display:none}
.db {display:block}
.posted {
height: 50px;
width: 100px;
background-color: green;
border: 2px solid red;
}
HTML:
<div class="posted" onClick="t();">
<button class="dn">Reply</button>
</div>
<div class="posted" onClick="t();">
<button class="dn">Reply</button>
</div>
<div class="posted" onClick="t();">
<button class="dn">Reply</button>
</div>
JAVASCRIPT:
function t()
{
var x=document.getElementsByClassName("posted"),i,y=document.getElementsByTagName("button");
for(i=0;i<x.length;i++)
{
x[i].y[0].className="dn";
};
x.y[0].className='db';//make sure the currently clicked DIV shows this button (?)
}
You might want to read more about selector, how to select class, block level etc.
some link might be helpful:
CSS selector:
https://www.w3schools.com/cssref/css_selectors.asp
jQuery selector:
https://api.jquery.com/category/selectors/
Solution - Using jQuery:
$('.posted').on('click', function() {
//find all class called posted with child called dn, then hide them all
$('.posted .dn').hide();
//find this clicked div, find a child called dn and show it
$(this).find('.dn').show();
});
.dn {
display: none
}
.db {
display: block
}
.posted {
height: 50px;
width: 100px;
background-color: green;
border: 2px solid red;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="posted">
<button class="dn">Reply1</button>
</div>
<div class="posted">
<button class="dn">Reply2</button>
</div>
<div class="posted">
<button class="dn">Reply3</button>
</div>
Solution - Pure js version:
//get list of div block with class="posted"
var divlist = Array.prototype.slice.call(document.getElementsByClassName('posted'));
//for each div
divlist.forEach(function(item) {
//add click event for this div
item.addEventListener("click", function() {
//hide all button first
divlist.forEach(function(el) {
el.getElementsByTagName('button')[0].classList.add('dn');
});
//show button of the div clicked
this.getElementsByTagName('button')[0].classList.remove('dn');
}, false);
});
.dn {
display: none
}
.db {
display: block
}
.posted {
height: 50px;
width: 100px;
background-color: green;
border: 2px solid red;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="posted">
<button class="dn">Reply1</button>
</div>
<div class="posted">
<button class="dn">Reply2</button>
</div>
<div class="posted">
<button class="dn">Reply3</button>
</div>
You can do this with with plain JavaScript using Event Bubbling, querySelector and the element classList attribute like this.
Change your HTML to look like this:
<div class="posts">
<div class="posted">
<button class="dn">Reply</button>
</div>
<div class="posted" >
<button class="dn">Reply</button>
</div>
<div class="posted" >
<button class="dn">Reply</button>
</div>
</div>
Then use JavaScript like this:
var posts = document.querySelector('.posts');
var allPosted = document.querySelectorAll('.posted');
//clicks bubble up into the posts DIV
posts.addEventListener('click', function(evt){
var divClickedIn = evt.target;
//hide all the buttons
allPosted.forEach(function(posted){
var postedBtn = posted.querySelector('button');
postedBtn.classList.remove('db');
});
// show the button in the clicked DIV
divClickedIn.querySelector('button').classList.add('db')
});
You can find a working example here: http://output.jsbin.com/saroyit
Here is very simple example using jQuery .siblings method:
$(function () {
$('.posted').click(function () {
$('button', this).show();
$(this).siblings().find('button').hide();
});
});
https://jsfiddle.net/3tg6o1q7/

how to display div on mouseover on disabled button

I have been working on the requirement that is to perform operations on a disabled button.I want to display a text on a disabled button, i tried in Jquery but its not working, below is the code which i tried.
$(function(){
$(window).on("load", function () {
$('#btn').prop("disabled", true);
$("#btn[disabled]").mouseover(function(){
$(".main").css({ "display": "block" });
})
$("#btn[disabled]").mouseout(function(){
$(".main").css({ "display": "none" });
})
});
})
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.0.0/jquery.min.js"></script>
<button id="btn" disabled>Search</button>
<div class="main" style="display:none">
this is a div
</div>
You could do this with CSS instead like below:
#hiddenDiv { display: none; }
#btn[disabled]:hover + #hiddenDiv { display: block; }
<button id="btn" disabled>Search</button>
<div class="main" id="hiddenDiv">
this is a div
</div>
What this is doing is initially setting hiddenDiv to display: none; and then on hover of the button it sets it to display: block;
Disabling buttons means turning their interactiveness off. While this is a different approach, you may want to achieve desired effect with CSS for browser speed.
button[disabled] + .main {
display: none;
}
button[disabled]:hover + .main {
display: block;
}
<button id="btn" disabled>Search</button>
<div class="main">this is a div</div>
Situation:
In HTML disabled elements don't fire any event and doesn't react to user actions, they are just shown with a grayed-out text.
You can see in the disabled MDN specification that :
If the element is disabled, it does not respond to user actions, it cannot be focused, and the command event will not fire.
Solution:
Why don't you simply use the title attribute title="this is a div"?!
<button id="btn" title="this is a div" disabled>Search</button>
Here's a simple Demo snippet:
<button id="btn" title="this is a div" disabled>Search</button>

Changing Parent Class With Child's Button Using Javascript

What i'm basically asking is if i could do this?
function Close(){
// what the furry mermaids should i put in here!?
}
.vissible {
display: block;
}
.hidden {
display: none;
}
#parentDiv1{
background-color: red;
}
#parentDiv2{
background-color:blue;
}
<div id="parentDiv1" class="visible">
<button id="closebtn" onclick="Close()">close</button>
<p> This is div 1 </p>
</div>
<div id="parentDiv2" class="visible">
<button id="closebtn" onclick="Close()">close</button>
<p> This is div 2 </p>
</div>
There are two divs that contain the same button but each button changes their parent div's class to hidden. Their parent's div only.
This is because i want to make a lot of pages but they close one by one with the same code and the same button. I'm wanting a minimalist solution here.
Oh and please don't be vague with your answers. If you are going to present it please explain how it works and how to apply it. A working code example is desired.
Note: Only one function may be used and is used by two identical buttons that are separated by two Divs.
Please and Thank You! :D
You can pass the current element context this to method. Then parent div can be accessed using parentNode property. To manipulate element's class use Element.classList property.
function Close(elem) {
elem.parentNode.classList.add('hidden')
elem.parentNode.classList.remove('visible')
}
function Close(elem) {
elem.parentNode.classList.add('hidden')
elem.parentNode.classList.remove('visible')
}
.vissible {
display: block;
}
.hidden {
display: none;
}
#parentDiv1 {
background-color: red;
}
#parentDiv2 {
background-color: blue;
}
<div id="parentDiv1" class="visible">
<button id="closebtn" onclick="Close(this)">close</button>
<p>This is div 1</p>
</div>
<div id="parentDiv2" class="visible">
<button id="closebtn" onclick="Close(this)">close</button>
<p>This is div 2</p>
</div>
I would recommend you to use unobtrusive event handler. Instead of using ugly inline click handler.
document.addEventListener("DOMContentLoaded", function(event) {
var elements = document.querySelectorAll('.closebtn');
elements.forEach(function(element) {
element.addEventListener('click', function() {
this.parentNode.classList.add('hidden');
this.parentNode.classList.remove('visible');
})
});
});
.vissible {
display: block;
}
.hidden {
display: none;
}
#parentDiv1 {
background-color: red;
}
#parentDiv2 {
background-color: blue;
}
<div id="parentDiv1" class="visible">
<button type="button" class="closebtn">close</button>
<p>This is div 1</p>
</div>
<div id="parentDiv2" class="visible">
<button type="button" class="closebtn">close</button>
<p>This is div 2</p>
</div>
Pass event in close function and access to parent with event.target.parentNode;
function Close(event){
const parent= event.target.parentNode
parent.classList.remove('vissible');
parent.classList.add('hidden');
// what the furry mermaids should i put in here!?
}
.vissible {
display: block;
}
.hidden {
display: none;
}
#parentDiv1{
background-color: red;
}
#parentDiv2{
background-color:blue;
}
<div id="parentDiv1" class="visible">
<button id="closebtn" onclick="Close(event)">close</button>
<p> This is div 1 </p>
</div>
<div id="parentDiv2" class="visible">
<button id="closebtn" onclick="Close(event)">close</button>
<p> This is div 2 </p>
</div>
Here you go :)
https://jsfiddle.net/
$('#parentDiv1 #closebtn').on('click', function(){
$(this).parent().addClass('hidden')
})
$('#parentDiv2 #closebtn').on('click', function(){
$(this).parent().addClass('hidden')
})
This is how i would do it. Use something like this.
$(".closebtn").click(function(){
$(this).parent().removeClass("visible");
$(this).parent().addClass("hidden");
});
Also in your css your class is spelled vissible and in your html the class it spelled visible

Toggle and untoggle three buttons

I have three buttons and I want to toggle between them. How can I add and remove the toggle and untoggle classes to have to toggle appropriately.
Right now, both buttons can be selected/toggled on. There should only be one button toggled at a time but I also want to be able to deselect/untoggle all of the buttons. So that I have
an option of not toggling the buttons on.
Here's the buttons in my view:
<div id="drawing">
<div style="margin-top: 12px; padding-left: 8px; margin-bottom: 8px">
<button class="small-button" onclick="Drawing.AngleClick()" data-val-btnname="Angle" style="width: 70px; height: 20px;"><span>#Culture.GetString("Angle")</span></button>
</div>
<div style="margin-top: 12px; padding-left: 8px;">
<button class="small-button" onclick="Drawing.PointClick()" data-val-btnname="Point" style="width: 70px; height: 20px;"><span style="font-size:10px !important">#Culture.GetString("Point")</span></button>
<button class="small-button" data-val-btnname="ClearAll" style="width: 70px;" onclick="Drawing.Delete()"><span>#Culture.GetString("ClearAll")</span></button>
</div>
</div>
Here's the js function so far for one of the buttons (I have the same if statement in my other button):
AngleClick: function () {
var button = $('body').find("button[data-val-btnname='Angle']");
if (button.hasClass('small-toggled-button')) {
button.removeClass('small-toggled-button').addClass('small-button');
} else {
button.removeClass('small-button').addClass('small-toggled-button');
}
}
This is an easy method for toggling buttons. Run the snippet to see it work. I simplified your HTML only for the sake of shortening the example--I'm not suggesting you change it.
$(document).ready(function() {
$("#drawing button").click(function(e) {
var isActive = $(this).hasClass('active');
$('.active').removeClass('active');
if (!isActive) {
$(this).addClass('active');
}
});
});
.active {
background: #555555;
color: #ffffff;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<div id="drawing">
<button class="small-button">Angle</button>
<button class="small-button">Point</button>
<button class="small-button">ClearAll</button>
</div>

Categories

Resources