jQuery multiple button show and hide elements when click - javascript

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>

Related

How to display another element when hover disabled button?

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

Use onclick in button to add a border to another div

Basically explained : click button A to add a border to card A, click button B to add a border to card B and remove border from card A etc. (these "cards" are also set up to be side scrolling so having the "highlighted card" scroll into view if it is out of view, so if you have any advice on how to do that too, I'm all ears)
This is what I have so far, but I keep getting an error that says the highlight function is not defined. I have it called on the button as onclick="highlight()"
function highlight() {
var item = document.getElementById('item-id')
var unhighlight = document.getElementsByClassName('item-class')
unhighlight.removeClass('border');
item.addClass('border');
}
Here's a simplified version that uses data attributes on the buttons and the divs to update the DOM.
Move your inline code to its own script.
Cache your elements.
Add an event listener to each button
Inside your highlight function: get the id from the button's data attribute, remove the borders from all the other divs, use the id to identify which div should now be highlighted, and then scroll it into view.
const buttons = document.querySelectorAll('button');
const items = document.querySelectorAll('div');
buttons.forEach(button => button.addEventListener('click', highlight, false));
function highlight(e) {
const button = e.target;
const id = button.dataset.id;
items.forEach(item => item.classList.remove('border'));
const div = document.querySelector(`div[data-id="${id}"]`);
div.classList.add('border');
div.scrollIntoView({behavior: "smooth", block: "end", inline: "nearest"});
}
#container { display: flex; flex-direction: row; }
div { padding: 1em; margin: 0.5em; width: 1500px; }
.border { border: 2px solid black; }
<button data-id="1">Click 1</button>
<button data-id="2">Click 2</button>
<button data-id="3">Click 3</button>
<div id="container">
<div data-id="1">Hallo 1</div>
<div data-id="2">Hallo 2</div>
<div data-id="3">Hallo 3</div>
</div>
Consider the following example.
$(function() {
$("button").click(function() {
var target = $(this).data("rel");
$(target).toggleClass("highlight");
});
});
.highlight {
border: 1px solid yellow;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<button id="button-a" data-rel="#card-a">A</button>
<button id="button-b" data-rel="#card-b">B</button>
<button id="button-c" data-rel="#card-c">C</button>
<div id="card-a" class="card">
<div class="card-title">Card A</div>
</div>
<div id="card-b" class="card">
<div class="card-title">Card B</div>
</div>
<div id="card-c" class="card">
<div class="card-title">Card C</div>
</div>

How to use toggleClass on multiple elements but not at the same time

so the problem I have is quite simple.
I have a span <span class=""spDetails>Show More</span> and with this element I am expanding a section to show more text.
The problem I have is that I want to use this function in other sections of the page.
This is the jquery code which I am using to toggleClass active.
$(".spDetails").click(function() {
$(".divFees").toggleClass("feesActive");
});
My question is: I don't want to write this line of code for every element using this toggle, is there a way to create this for multiple elements with different class names or IDs? Thanks.
Right, so here is my HTML: (shortened version!)
<div id="optionOne" class="elementOne">
<div class="divFees">
<p>Text Text</p>
</div>
<span class="showMore">Show More</span>
</div>
<div id="optionTwo" class="elementTwo">
<div class="divFees">
<p>Text Text</p>
</div>
<span class="showMore">Show More</span>
</div>
I m trying to hide and display <div class="divFees"></div> only when there child <span> is clicked.
You can just append your desired elements in the selector using ,.
$(".divFees , .otherOnes , #otherOneWithId").toggleClass("feesActive");
If the toggleable section comes after the toggling span :
$(".spDetails").on("click", function(e) {
$(this).next().toggleClass("active");
});
[id*='div'] {
height: 60px;
background: #f2f2f2;
border: #f6f6f6;
}
.active {
background: #555555;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<section>
<span class="spDetails" data-toggle="#div1">Toggle 1</span>
<div id="div1"></div>
<span class="spDetails" data-toggle="#div2">Toggle 2</span>
<div id="div2"></div>
</section>
Or with extra attributes to specify the target:
$(".spDetails").on("click", function(e) {
var target = $($(this).data("toggle"));
target.toggleClass("active");
});
[id*='div'] {
height: 60px;
background: #f2f2f2;
border: #f6f6f6;
}
.active {
background: #555555;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<section>
<span class="spDetails" data-toggle="#div1">Toggle 1</span>
<div id="div1"></div>
<span class="spDetails" data-toggle="#div2">Toggle 2</span>
<div id="div2"></div>
</section>
I imagine two ways:
Easy way:
Make function with args for your event. Example:
function setToogleClass(button, toggleElement, toggleClass) {
$('.' + button).click(function() {
$('.' + toggleElement).toggleClass(toggleClass);
});
}
setToggleClass("spDetails", "divFees", "feesActive")
Hard way:
Set event function by all classes who has className and who found child or parent or current elements.
function initToggleEvents() {
var toggleButtons = $('toggle-button');
var activeClassName = 'toggle-active';
toggleButtons.forEach(function(toggleButton) {
toggleButton.click(function(event) {
// if event.target has parentNode that toggleClass(activeClassName)
// else another rules
}
}
}

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/

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

Categories

Resources