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>
Related
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>
i have the following html structure:
<div id='main'>
<div id='612'>
</div>
...
<div id='1'>
</div>
</div>
As you can see i have several div going in a decreasing order and i wuold like to make a button that activate a jQuery script that can sort those div in both ways (decreasing and increasing).
I already created the button and linked it to the script but i can't find a way to sort the divs. Is possible?
Edit:
Posted the entire code on pastebin:
https://pastebin.com/DZWdNMZk
Edit:
Posted the entire code on Github if it any help:
https://github.com/mattiac02/divs
This is one option. Setting the display of the parent to flex, then using js to set the order property of the children. Hopefully the demonstration helps!
document.querySelector("#orderEm")
.addEventListener("click", () => {
document.querySelectorAll("div > div")
.forEach(div => {
div.style.order = div.id;
});
});
document.querySelector("#reverse")
.addEventListener("click", () => {
document.querySelector("#container")
.classList.toggle("reverse");
});
#container {
display: flex;
justify-content: space-around;
}
#container.reverse {
flex-direction: row-reverse;
}
div > div {
height: 50px;
width: 50px;
font-size: 15pt;
border: 1px solid black;
margin: 1em;
display: flex;
justify-content: center;
align-items: center;
}
<div id="container" data-sorted="unsorted">
<div id="2">2</div>
<div id="3">3</div>
<div id="1">1</div>
</div>
<button id="orderEm">Order 'Em!</button>
<button id="reverse">Reverse 'Em!</button>
One of of doing this is to get the elements into an array and sort the array and re-append them to the main div:
$('#btnAsc').click(function() {
//gets all div children of the main div, this returns a jQuery array with the elements
var divs = $('#main div');
//sorts the divs based on the id attribute
var ordered = divs.sort(function(a, b) {
return $(a).attr('id') - $(b).attr('id');
});
//empty the main div and re-append the ordered divs
$('#main').empty().append(ordered)
});
$('#btnDesc').click(function(){
var divs = $('#main div');
var ordered = divs.sort(function(a, b) {
return $(b).attr('id') - $(a).attr('id');
});
$('#main').empty().append(ordered)
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div id='main'>
<div id='612'>
612
</div>
<div id='1'>
1
</div>
<div id='2'>
2
</div>
<div id='3'>
3
</div>
<div id='5'>
5
</div>
</div>
<input type="button" id="btnAsc" value="Asc">
<input type="button" id="btnDesc" value="Desc">
I am trying to implement a different pop-up window when I click different divs. Here's an example:
<div class="column" onclick="togglePopup('popup', 2)">Residential cleaning</div> <!--Function used here. -->
<div id="overlay">
<div class="popup">
<div class="popup_content">
<div class="close_btn" onclick="closePopup('popup',2)">×</div>
<h1>Some heading</h1>
<p>SOME TEXT</p>
<img src="assets/some_image.jpg" alt="image" width="249">
</div>
</div> <!--END of the popup window -->
</div>
When I click on the div of class column, I should see the popup div, however it only works with the very first one. Here's the JavaScript:
function togglePopup(popup_class, div_num){
overlay.style.display="flex";
let all_divs = document.getElementsByClassName(popup_class);
let my_div = all_divs[div_num-1];
my_div.classList.toggle("active");
console.log(my_div)
}
function closePopup(popup_class, div_num){
overlay.style.display="none";
let all_divs = document.getElementsByClassName(popup_class);
let my_div = all_divs[div_num-1];
my_div.classList.toggle("active");
console.log(my_div)
}
The function saves all the divs of class popup in the let all_divs, then it uses the parameter div_num to select a specific div and finally toggle the class "active" (CSS will be below). But like I said it only works one time. By the way the id overlay is originally hidden.
CSS:
.popup.active .popup_content {
transition:all 300ms ease-in-out;
transform:translate(-50%,-50%) scale(1);
}
#overlay {
position:fixed;
top:0px;
left:0px;
width:100%;
height:100%;
background-color:rgba(0,0,0,0.7);
z-index:1;
display:none;
}
I really don't know why this happens, it works as intended only with the first element of the list "all_divs". Is there a way around this? I already tried many things and realized it only works on the first element of the list. I did not include the first div in the code, (the one that works) because it's the exact same thing, except instead of a 1 in onclick="togglePopup('popup', 1)" it has a 2.
You're attempting to access a HTMLCollection by an index that does not exist. e.g.
let all_divs = document.getElementsByClassName('popup');
let my_div = all_divs[2]; // undefined
Instead you should add data to the open button to explicitly describe which popup it should open by its unique id.
Also, you should:
use querySelectorAll to addEventListener to each of the relevant buttons
use html buttons instead of divs
const openBtns = document.querySelectorAll('.open_btn')
const closeBtns = document.querySelectorAll('.close_btn')
openBtns.forEach(openBtn => openBtn.addEventListener('click', (e) => {
const popupIdToOpen = e.currentTarget.dataset.popup;
const popupToOpen = document.querySelector(`#${popupIdToOpen}`)
if (popupToOpen) {
popupToOpen.classList.add('active')
}
}))
closeBtns.forEach(closeBtn => closeBtn.addEventListener('click', (e) => {
const popupToClose = e.currentTarget.closest(".overlay")
if (popupToClose) {
popupToClose.classList.remove('active')
}
}))
.overlay {
color: white;
position: fixed;
top: 0;
background-color: #000;
display: none;
}
.active {
display: block;
}
<button class="open_btn" data-popup="popup1">Popup 1</button>
<div class="overlay" id="popup1">
<button class="close_btn">×</button >
<h1>Popup 1 heading</h1>
<p>Popup 1 Content</p>
</div>
<button class="open_btn" data-popup="popup2">Popup 2</button>
<div class="overlay" id="popup2">
<button class="close_btn">×</button >
<h1>Popup 2 heading</h1>
<p>Popup 2 Content</p>
</div>
<button class="open_btn" data-popup="popup3">Popup 3</button>
<div class="overlay" id="popup3">
<button class="close_btn">×</button >
<h1>Popup 3 heading</h1>
<p>Popup 3 Content</p>
</div>
I have a list of items displayed in a container with a dropdown associated with every container.A snippet of how the container list looks:
http://jsfiddle.net/jHpKB/2/
When I click on the button , the dropdown menu shows up, however, when I try to click on any other button button, the dd stays and does not hide. the list is dynamically created. What I was trying to do is if the current clicked element is same as that of the previous clicked elemnt, then hide the first dd menu
Is there way to check if a clicked element is equal to the previous clicked element in javascript(no jquery)
code:
afterRender: function() {
this.el.on('click', function(e) {
//here i want to check (if e.getTarget() === secondClickedEment) { //do something}
},this);
}
is this possible?
Thanks
You can test object equality with jQuery using the is function. Requires 1.6 or higher.
var stuff = $('#stuff');
var thing = stuff;
if (stuff.is(thing)) {
// the same
}
So for your situation this should work:
afterRender: function() {
this.el.on('click', function(e) {
var clickedElm = $(e.getTarget());
var secondElm = $(secondClickedElm);
if (clickedElm.is(secondElm)){
// same elements
}
},this);
}
jQuery example:
use var lastClicked; to hold the last clicked element, then each click check if the same one clicked then reset the lastclicked, otherwise update the lastclicked.
var lastClicked;
$('.container').on('click', function(e) {
if (this == lastClicked) {
lastClicked = '';
$(this).children('.menu').hide();
} else {
lastClicked = this;
$('.menu').hide();
$(this).children('.menu').show();
}
});
.container {
border: 1px solid #333;
height: 300px;
width: 200px;
float: right;
margin-right: 20px;
}
.menu {
display: none;
}
.button {
border: 1px solid #333;
background: #333;
float: right;
height: 20px;
width: 20px;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="container">
<div class="button">
</div>
<div class="menu">
<div class="option1 option">option1</div>
<div class="option2 option">option2</div>
</div>
</div>
<div class="container">
<div class="button">
</div>
<div class="menu">
<div class="option1 option">option1</div>
<div class="option2 option">option2</div>
</div>
</div>
<div class="container">
<div class="button">
</div>
<div class="menu">
<div class="option1 option">option1</div>
<div class="option2 option">option2</div>
</div>
</div>
One way to do this would be to dynamically add/remove a class to the div, indicating if it's open or not. Then on click, you could just toggle that class.
Example:
let containers = document.getElementsByClassName('container');
for (let i=0; i<containers.length; i++) {
let button = containers.item(i).getElementsByClassName('button')[0];
let menu = containers.item(i).getElementsByClassName('menu' )[0];
button.addEventListener('click', function() {
menu.classList.toggle('open');
});
}
Then in your CSS:
.open {
display: block;
}
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/