I have a product card that I would like to be able to change the main image src of when the user hovers over a 'colour swatch' however, I'm finding this difficult using the answer from here: Change Image Source from Div with onmouseover.
My current code is as follows:
(function() {
var img1 = "https://picsum.photos/300";
var img2 = "https://picsum.photos/300";
var myimg = document.getElementById('img');
myimg.src = img1;
var hoverables = document.getElementsByClassName('hoverme');
for (var i = hoverables.length; i--;) {
hoverables[i].addEventListener("mouseover", hoverMe, false);
hoverables[i].addEventListener("mouseout", unhoverMe, false);
}
function hoverMe() {
myimg.src = img2;
}
function unhoverMe() {
myimg.src = img1;
}
})();
.product-card{
height: auto;
width: auto;
border-radius: 25px;
box-shadow: 0px 0px 15px 5px rgba(0,0,0,0.1);
-webkit-box-shadow: 0px 0px 15px 5px rgba(0,0,0,0.1);}
.card-body{
height: auto;
width: 100%;
text-align: left;
position: relative;}
.card-image{
max-width:350px;
max-height:350px;
padding: 10px;}
.card-sidebar{
height: 100%;
width: 50px;
display: flex;
align-items: center;
position: absolute;
right: 0;
top: 0;
border-radius: 0 25px 0 0;
background-color: rgba(255, 255, 255, .15);
backdrop-filter: blur(2.5px);}
.swatch-contain{
height: auto;
width: 100%;
display: flex;
flex-direction: column;
align-items: center;
justify-content: space-evenly;}
.swatch{
height: 25px;
width: 25px;
background-color: aqua;
border: 1px solid whitesmoke;
border-radius: 100%;
margin: 5px;}
.swatch.black{
background-color: black;}
.card-foot{
height: 100px;
width: 100%;
border-top: 1px solid whitesmoke;
}
<div class="product-card">
<div class="card-body">
<img src="https://picsum.photos300" alt="Aqua Evo22 Backpack" class="card-image" id="img">
<div class="card-sidebar">
<div class="swatch-contain">
<div class="swatch black hoverme" id=""></div>
<div class="swatch" id=""></div>
<div class="swatch" id=""></div>
</div>
</div>
</div>
<div class="card-foot">
<p></p>
</div>
</div>
I'm going to have this function for multiple 'swatches' on over around 100 products so I need a solution that is a minimal and easily replicable as possible. what I currently have doesn't function as expected and is very long to keep copying to replace for each product I'll list.
Related
For this Slider to work I have set pointer-events: none; . But I want to have a clickable Button within the slide. Thats not possible right now, since pointer-events: none;. Since I only know a bare minimum about JS I need help.
const sliderContainer = document.querySelector(".slider-container");
const slider = document.querySelector(".slider");
const onButton = document.querySelector(".btn");
let clicked = false;
let xAxis;
let x;
sliderContainer.addEventListener("mouseup", () => {
sliderContainer.style.cursor = `grab`;
});
sliderContainer.addEventListener("mousedown", (e) => {
clicked = true;
xAxis = e.offsetX - slider.offsetLeft;
// tells the current position
sliderContainer.style.cursor = `grabbing`;
});
window.addEventListener("mouseup", () => {
clicked = false;
});
sliderContainer.addEventListener("mousemove", (e) => {
if (!clicked) return;
e.preventDefault();
x = e.offsetX;
slider.style.left = `${x - xAxis}px`;
// but we dont want it to scroll forever
checkSize();
});
function checkSize() {
let sliderContainerOut = sliderContainer.getBoundingClientRect();
let sliderIn = slider.getBoundingClientRect();
if (parseInt(slider.style.left) > 0) {
slider.style.left = `0px`;
} else if (sliderIn.right < sliderContainerOut.right) {
slider.style.left = `-${sliderIn.width - sliderContainerOut.width}px`;
}
}
#import url("//fonts.googleapis.com/css?family=Raleway");
:root {
--item-height: 80vh;
--item-witdh: 80vw;
--item-spacing: 300px;
--item-count: 4;
--starting-slide-distance-left: 40vw;
--blur: 3.5px;
--spread: -2.5px;
--horiz: 1.3616px;
--vert: 2.09668px;
}
.wrapper {
height: 100vh;
width: 100vw;
}
/*----------------------------Slider Start-----------------------------*/
.slider-container {
position: absolute;
width: 100vw;
min-height: var(--item-height);
overflow: hidden;
cursor: grab;
padding: 50px;
}
.slider {
position: absolute;
width: auto;
height: auto;
display: grid;
grid-template-columns: repeat(var(--item-count), 1fr);
column-gap: var(--item-spacing);
pointer-events: none;
transform: translatex(var(--starting-slide-distance-left));
}
.slider-item {
width: var(--item-witdh);
height: var(--item-height);
border: 2px solid green;
border-radius: 20px;
overflow: hidden;
align-content: center;
}
.item-shadow {
box-shadow: calc(clamp(0px, var(--horiz), 2px)) calc(clamp(0px, var(--vert), 2px)) 2px calc(var(--spread)) rgba(0, 0, 0, 0.233), calc(2 * var(--horiz)) calc(2 * var(--vert)) calc(var(--blur)) calc(var(--spread)) rgba(0, 0, 0, 0.2), calc(3 * var(--horiz)) calc(3 * var(--vert)) calc(var(--blur)) calc(var(--spread)) rgba(0, 0, 0, 0.123), calc(5 * var(--horiz)) calc(5 * var(--vert)) calc(var(--blur)) calc(var(--spread)) rgba(0, 0, 0, 0.076), calc(8 * var(--horiz)) calc(8 * var(--vert)) calc(var(--blur)) calc(var(--spread)) rgba(0, 0, 0, 0.047), calc(13 * var(--horiz)) calc(13 * var(--vert)) calc(var(--blur)) calc(var(--spread)) rgba(0, 0, 0, 0.028);
border: 1px solid rgba(0, 0, 0, 0.068);
}
/*----------------------------Slider end-----------------------------*/
/*------------------------Item Content Start-------------------------*/
h2 {
color: #fff;
font-family: Raleway;
text-align: center;
font-size: 35px;
padding: 30px;
}
.slide1 {
background-image: url(https://www.memorabilien.org/wp-content/uploads/pexels-pixabay-220201.webp);
background-size: cover;
display: grid;
grid-template-columns: auto auto auto auto;
grid-template-rows: auto auto;
justify-content: space-around;
}
.images:hover {}
img {
max-height: var(--item-height);
width: auto;
}
.img:hover {
cursor: pointer!important;
}
.colnum-wrapper {
border: 2px solid yellow;
align-content: center;
display: flex;
flex-wrap: wrap;
align-content: center;
}
.colnum-wrapper2 {
border: 2px solid purple;
}
/*----------------Button Start------------------*/
.btn-wrapper {
border: 2px solid cyan;
text-align: center;
padding: 30px;
}
.btn {
border-radius: 20px;
padding: 15px;
border: 5px solid #aa80ff;
background: transparent;
font: Raleway, bold;
font-size: 30px;
color: #fff;
position: relative;
}
.btn:hover {
background: #aa80ff;
color: black;
}
<div class="wrapper" style="border: 2px dotted green;">
<div class="slider-container" style="border: 2px dotted green;">
<div class="slider" style="border: 2px dotted green;">
<div class="slider-item item-shadow slide1" style="border: 2px dotted red;">
<div class="colnum-wrapper">
<div class="colnum-wrapper2">
<div class="headline" style="border: 3px solid red;">
<h2>The Space and Universe Poster Collection</h2>
</div>
<div class="btn-wrapper"><button class="btn item-shadow" id="btn">Explore</button></div>
</div>
</div>
<div class="images" style="border: 2px solid green">
<img src="https://www.memorabilien.org/wp-content/uploads/Untitled-2-1.webp"></img>
</div>
</div>
<div class="slider-item item-shadow">item</div>
<div class="slider-item item-shadow">item</div>
<div class="slider-item item-shadow">item</div>
</div>
</div>
</div>
Here is a Codepen-Link: https://codepen.io/memorabilien/pen/MWVKmaB
Add onclick event listener to container div.
I tried the following, and as you can see, the event does not seem to be registered. How can I add the listener to this div?
The div id I want is "engineersContainer."
document.getElementById("engineersContainer").addEventListener("click", function(e) {
console.log("It was clicked");
alert("It was clicked");
});
.barContainer {
margin: 2px;
border: 2px solid black;
border-radius: 20px;
width: 200px;
//width:-moz-fit-content;
//width: fit-content;
padding: 5px;
overflow: hidden;
position: relative;
background: #34e8eb;
z-index: -1;
}
.containerHeader:before {
content:"";
background: skyblue;
position: absolute;
inset: 0;
z-index: -1;
height:45px
}
<div id="engineersContainer" class="barContainer">
<div id="engineerList" class="containerHeader" style="font-size:1.5em; text-align:center">Current Engineer </div>
<div> Engineer's Name</div>
<div id="clickText" style="padding-bottom: 10px; font-size:0.75em; text-align:center "> (Click to See All Permits) </div>
</div>
Remove the -1 z-index, otherwise it will be under the rest of the page
Add the event listener in the page load event
See second example for a workaround
window.addEventListener("load", function() {
document.getElementById("engineersContainer")
.addEventListener("click", function(e) {
console.log("It was clicked");
});
});
.barContainer {
margin: 2px;
border: 2px solid black;
border-radius: 20px;
width: 200px;
//width:-moz-fit-content;
//width: fit-content;
padding: 5px;
overflow: hidden;
position: relative;
background: #34e8eb;
/* z-index: -1 */
}
.containerHeader:before {
content: "";
background: skyblue;
position: absolute;
inset: 0;
z-index: -1;
height: 45px
}
.containerHeader {
font-size: 1.5em;
text-align: center
}
#clickText {
padding-bottom: 10px;
font-size: 0.75em;
text-align: center
}
<div id="engineersContainer" class="barContainer">
<div id="engineerList" class="containerHeader">Current Engineer </div>
<div> Engineer's Name</div>
<div id="clickText"> (Click to See All Permits) </div>
</div>
Otherwise add another div on top of it
window.addEventListener("load", function() {
document.getElementById("engineersContainerClick").addEventListener("click", function(e) {
console.log("It was clicked");
});
});
.barContainer {
margin: 2px;
border: 2px solid black;
border-radius: 20px;
width: 200px;
//width:-moz-fit-content;
//width: fit-content;
padding: 5px;
overflow: hidden;
position: relative;
background: #34e8eb;
z-index: -1
}
#engineersContainerClick {
margin: 2px;
border-radius: 20px;
width: 200px;
height:70px;
padding: 5px;
border:none;
overflow: hidden;
position: absolute;top:0;
background-color: transparent;
z-index:999;
}
.containerHeader:before {
content: "";
background: skyblue;
position: absolute;
inset: 0;
z-index: -1;
height: 45px
}
.containerHeader {
font-size: 1.5em;
text-align: center
}
#clickText {
padding-bottom: 10px;
font-size: 0.75em;
text-align: center
}
<div id="engineersContainer" class="barContainer">
<div id="engineerList" class="containerHeader">Current Engineer </div>
<div> Engineer's Name</div>
<div id="clickText"> (Click to See All Permits) </div>
</div>
<div id="engineersContainerClick" class="barContainer">
You need to remove the z-index: -1 in your CSS.
Any user clicks are not making contact with the element, but with the document above the element.
Working Example:
document.getElementById("engineersContainer").addEventListener("click", function(e) {
console.log("It was clicked");
alert("It was clicked");
});
.barContainer {
margin: 2px;
border: 2px solid black;
border-radius: 20px;
width: 200px;
/* width:-moz-fit-content; */
/* width: fit-content; */
padding: 5px;
overflow: hidden;
position: relative;
background: #34e8eb;
}
.containerHeader:before {
content:"";
background: skyblue;
position: absolute;
inset: 0;
z-index: -1;
height:45px
}
<div id="engineersContainer" class="barContainer">
<div id="engineerList" class="containerHeader" style="font-size:1.5em; text-align:center">Current Engineer </div>
<div> Engineer's Name</div>
<div id="clickText" style="padding-bottom: 10px; font-size:0.75em; text-align:center "> (Click to See All Permits) </div>
</div>
document.getElementById("engineersContainer").onclick=function(){
console.log("your event");
}
.barContainer {
margin: 2px;
border: 2px solid black;
border-radius: 20px;
width: 200px;
//width:-moz-fit-content;
//width: fit-content;
padding: 5px;
overflow: hidden;
position: relative;
background: #34e8eb;
}
.containerHeader:before {
content:"";
background: skyblue;
position: absolute;
inset: 0;
z-index: -1;
height:45px
}
<body>
<div id="engineersContainer" class="barContainer">
<div id="engineerList" class="containerHeader" style="font-size:1.5em; text-align:center">Current Engineer </div>
<div> Engineer's Name</div>
<div id="clickText" style="padding-bottom: 10px; font-size:0.75em; text-align:center "> (Click to See All Permits) </div>
</div>
</body>
ng-js -->
document.getElementById("engineersContainer").onclick=function(){
console.log("your event");
}
<div id="engineersContainer"> Here is the Engineers Container
</div>
I would use an anonymous function for this. You must call the script after your div has been created, as Javascript is read top to bottom and will not have a reference if it is run before the div has been placed.
Beware that if you have a listener on the container div, it will impact your ability to introduce any clickable options within the divs child elements such as buttons later on. Could this cause you problems in the future? If so rethink the design possibly to save you some trouble later. Also, the negative Z index needs to be removed as it is being drawn beneath the layer that Javascript detects the clicks. Sorry for the edits I'm new to StackO.
I need to create a pyramid figure with 4 levels division something like this:
Although I have achieved the same with the following code set:
const PyramidChart = () => {
return (
<div className="d-flex flex-column align-items-center pyramid_wrap">
<div className="category_one">
<h6>2</h6>
</div>
<div className="category_two">
<h6>8</h6>
</div>
<div className="category_three">
<h6>11</h6>
</div>
<div className="category_four">
<h6>16</h6>
</div>
</div>
);
};
ReactDOM.render(
<PyramidChart />,
document.getElementById('root')
);
.pyramid_wrap {
height: 100%;
text-align: center;
}
.category_one {
width: 70px;
height: 30px;
border-left: 35px solid transparent;
border-right: 35px solid transparent;
border-bottom: 50px solid tomato;
}
.category_two {
width: 116px;
height: 30px;
border-left: 22px solid transparent;
border-right: 22px solid transparent;
border-bottom: 28px solid orange;
}
.category_three {
width: 162px;
height: 30px;
border-left: 22px solid transparent;
border-right: 22px solid transparent;
border-bottom: 28px solid cyan;
}
.category_four {
width: 208px;
height: 30px;
border-left: 22px solid transparent;
border-right: 22px solid transparent;
border-bottom: 28px solid teal;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.8.4/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.8.4/umd/react-dom.production.min.js"></script>
<div id="root"></div>
And got something like this:
But the issue I am unable to resolve is to align the text in top-level pyramid area to center. It is somehow always out of sync with the it is aligned in.
Any help to rectify this issue is appreciated :)
Let's try moving from CSS Triangle to :before and :after with skew transform property.
I haven't changed your HTML, just add a .value class to your <h6> to style them.
Basically all you have to do is to set to every <div> a :before with a negative degree angle and a :after with a positive degree angle and give them the same background color, in order to match.
Only for the top-level <div> I used a CSS Triangle, so you already know how it works.
In order to make the values horizontally and vertically aligned I used flexbox on the parent, combined with justify-content: center; (horizontal align) and align-items: center; (vertical align). Don't forget to always add a line-height:1em; and remove margin to the element you want to be vertical aligned. If the line-height is not equal to its actual height it will always be some pixels up or down the middle axe.
.pyramid_wrap {
margin-top: 200px;
height: 100%;
text-align: center;
}
.category_one,
.category_two,
.category_three,
.category_four {
position: relative;
margin: 6px auto;
display: flex;
justify-content: center;
align-items: center;
}
.category_one:before,
.category_one:after,
.category_two:before,
.category_two:after,
.category_three:before,
.category_three:after,
.category_four:before,
.category_four:after {
position: absolute;
top: 0;
display: block;
width: 30px;
height: 100%;
content: "";
}
.category_one:before,
.category_two:before,
.category_three:before,
.category_four:before {
left: -15px;
transform: skew(-25deg);
}
.category_one:after,
.category_two:after,
.category_three:after,
.category_four:after {
right: -15px;
transform: skew(25deg);
}
.category_one {
width: 20px;
height: 40px;
background: tomato;
}
.category_one:before,
.category_one:after {
width: 30px;
height: 40px;
background: tomato;
}
.category_one:before {
left: -16px;
top: 0;
}
.category_one:after {
right: -16px;
top: 0;
}
.category_one .value:after {
position: absolute;
z-index: -1;
top: -55px;
left: 50%;
transform: translateX(-50%);
content: "";
display: block;
width: 0;
height: 0;
border-style: solid;
border-width: 0 28px 70px 28px;
border-color: transparent transparent tomato transparent;
}
.category_two {
width: 70px;
height: 40px;
background: orange;
}
.category_two:before,
.category_two:after {
width: 40px;
background: orange;
}
.category_two:before {
left: -12px;
}
.category_two:after {
right: -12px;
}
.category_three {
width: 120px;
height: 40px;
background: cyan;
}
.category_three:before,
.category_three:after {
background: cyan;
}
.category_three:before {
left: -9px;
}
.category_three:after {
right: -9px;
}
.category_four {
width: 150px;
height: 40px;
background: teal;
}
.category_four:before,
.category_four:after {
background: teal;
}
.value {
margin: 0;
position: relative;
z-index: 3;
color: #fff;
font-size: 16px;
font-family: Arial, sans-serif;
font-weight: normal;
line-height: 1em;
}
<div class="d-flex flex-column align-items-center pyramid_wrap">
<div class="category_one">
<h6 class="value">2</h6>
</div>
<div class="category_two">
<h6 class="value">8</h6>
</div>
<div class="category_three">
<h6 class="value">11</h6>
</div>
<div class="category_four">
<h6 class="value">16</h6>
</div>
</div>
One of the possible solutions is to use CSS mask over the entire pyramid's wrapper. It may be not well supported as of now, yet provides genuine way of shaping your pyramid with SVG path (triangle):
In order not to let the mask shrink (hiding upper and lower layers), you may need to preserve the min-width of a wrapper (equal to number of layers multiplied by layer height - 3em).
To avoid layer labels falling outside of the mask, you may need to center the mask according to labels position (mask-position: center)
Live-demo, implementing that concept, might look as follows:
const { render } = ReactDOM,
rootNode = document.getElementById('root')
const pyramidItems = [{label:'2', color: '#f47660'}, {label:'8', color:'#fcae60'}, {label:'11', color:'#a7e6db'}, {label:'16',color:'#79d4c5'}]
const Pyramid = ({items}) => (
<div
className="wrapper"
style={{minWidth:`${items.length}*3em`}}
>
{
items.map(({label,color},key) => (
<div
key={key}
className="layer"
style={{backgroundColor:color}}
>
{label}
</div>
))
}
</div>
)
render (
<Pyramid items={pyramidItems} />,
rootNode
)
.wrapper {
--triangle-shape: url("data:image/svg+xml;base64,PHN2ZyB2aWV3Qm94PSIwIDAgMTAwIDEwMCIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj48cGF0aCBkPSJNNTAsMCBMMTAwLDEwMCBMMCwxMDAgeiIvPjwvc3ZnPg==");
-webkit-mask-image: var(--triangle-shape);
-webkit-mask-repeat: no-repeat;
-webkit-mask-position: center;
mask-image: var(--triangle-shape);
mask-repeat: no-repeat;
mask-position: center;
display: flex;
flex-direction: column;
}
.layer {
height: 3em;
color: #fff;
font-size: 15px;
display: flex;
justify-content: center;
align-items: center;
border: .2em solid #fff;
margin: -.2em 0px;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.12.0/umd/react.production.min.js"></script><script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.11.0/umd/react-dom.production.min.js"></script><div id="root"></div>
I work with statick creation elements, and for this i need to have slider.
I just create slider, but elements are not fit in to slider container.
Example:
var htmlElements;
var userName = "Jonny Programmer"
var id = "6656"
function createUserCard() {
htmlElements = `<div class="user-card">
<img src="https://source.unsplash.com/user/erondu" class="userImage" />
<div class="info">
<div class="name">${userName}</div>
<div class="handle">
<div class="idPersone">${id}</div>
</div>
</div>
</div>`
$('.cardsCreation').append(htmlElements);
}
$('#plus-button').on('click', function () {
createUserCard();
});
(function () {
var sliderImages = document.querySelectorAll('.image'),
arrowLeft = document.querySelector('#left-arrow'),
arrowRight = document.querySelector('#right-arrow'),
currentImg = 0;
function initSlider() {
resetSlider();
sliderImages[0].style.display = 'block';
}
function resetSlider() {
for (var i = 0; i < sliderImages.length; i++) {
sliderImages[i].style.display = 'none';
}
}
function toLeft() {
resetSlider();
sliderImages[currentImg - 1].style.display = 'block';
currentImg--;
}
function toRight() {
resetSlider();
sliderImages[currentImg + 1].style.display = 'block';
currentImg++;
}
arrowLeft.addEventListener('click', function () {
if (currentImg === 0) {
currentImg = sliderImages.length;
}
toLeft();
});
arrowRight.addEventListener('click', function () {
if (currentImg === sliderImages.length - 1) {
currentImg = -1;
}
toRight();
});
initSlider();
})();
.user-card, userImage {
box-shadow: 0px 2px 5px 0 rgba(0,0,0,0.25);
}
.user-card {
margin: 12px;
padding: 10px 10px 10px 10px;
border-radius: 12px;
width: 160px;
text-align: center;
float: left;
background-color: #fff;
}
.userImage {
border-radius: 50%;
height: 140px;
width: 140px;
border: 5px solid #eee;
}
.name {
font-size: 20px;
margin: 5px;
font-weight: bold;
}
.progress {
color: #25af53;
font-size: 48px;
}
#plus-button {
width: 55px;
height: 55px;
border-radius: 50%;
background: #428bca;
position: absolute;
top: 33%;
margin-left: 20px;
cursor: pointer;
box-shadow: 0px 2px 5px #666;
border: none;
outline: none;
}
.plus {
color: white;
position: absolute;
top: 0;
display: block;
bottom: 0;
left: 0;
right: 0;
text-align: center;
padding: 0;
margin: 0;
line-height: 55px;
font-size: 38px;
font-family: 'Roboto';
font-weight: 300;
}
#plus-button:hover {
box-shadow: 0 6px 14px 0 #666;
transform: scale(1.05);
}
.wrapper {
position: relative;
}
.arrow {
cursor: pointer;
position: absolute;
width: 0;
height: 0;
border-style: solid;
top: 50%;
margin-top: 160px;
}
#left-arrow {
border-width: 50px 40px 50px 0;
border-color: transparent #000 transparent transparent;
left: 0;
margin-left: 25px;
}
#right-arrow {
border-width: 50px 0 50px 40px;
border-color: transparent transparent transparent #000;
right: 0;
margin-right: 25px;
}
.image {
background-size: cover;
background-position: center;
background-repeat: no-repeat;
}
.vertical-align-wrapper {
display: table;
overflow: hidden;
text-align: center;
}
.vertical-align-wrapper span {
display: table-cell;
vertical-align: middle;
font-size: 5rem;
color: #ffffff;
}
#media only screen and (max-width : 992px) {
.vertical-align-wrapper span {
font-size: 2.5rem;
}
#left-arrow {
border-width: 30px 20px 30px 0;
margin-left: 15px;
}
#right-arrow {
border-width: 30px 0 30px 20px;
margin-right: 15px;
}
.arrow {
margin-top: -30px;
}
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div class="wrapper">
<div id="left-arrow" class="arrow"></div>
<div id="slider">
<div class="image image-one">
<div class="vertical-align-wrapper">
<div class="cardsCreation"></div>
<button id="plus-button">
<p class="plus">+</p>
</button>
</div>
</div>
<div class="image image-two">
<div class="vertical-align-wrapper">
<span>Slide 2</span>
</div>
</div>
<div class="image image-three">
<div class="vertical-align-wrapper">
<span>Slide 3</span>
</div>
</div>
</div>
<div id="right-arrow" class="arrow"></div>
</div>
So as u can see affter tapping "+" i add new ellement in to html.
And from two sides i have arrows which are changing slider.
After tapping arrows go down, and this is not good.
And after i will reach limit of adding element in one slider it's add new element to new slider page.
What i want ex:
If you are using toggle of display CSS property that happened because it remove whole element from the DOM so, I suggest you to use visibility or opacity properties to done your task.
When I select each colour tab, the image changes colour. However, when you miss the tab or select just off the colour tab or any other part of the “nav” container for the “a” element it adds the is-select class to this also; meaning there is no image. Very frustrated, and would like some help please as to how I can stop the “nav” element being given the is-select classname, as I just need the “a” elements.
HTML
<div class="tab-pane__swatch-container">
<div class="tab-pane__swatch-content">
<div class="tab-pane is-selected" id="red">
<img src="https://www.bristolstreetversa.com/images/colour_swatches/Grand-Tourneo-Connect/Red.png" alt="Red Versa" class="tab-pane__swatch-image">
</div>
<div class="tab-pane" id="black">
<img src="https://www.bristolstreetversa.com/images/colour_swatches/Grand-Tourneo-Connect/Black.png" alt="Red Versa" class="tab-pane__swatch-image">
</div>
</div>
<nav class="row-1 tab-pane__swatch-selector" id="js-swatch">
</nav>
</div>
CSS
.tab-pane__swatch-image {
width: 90%;
}
.row-1 {
display: flex;
flex-flow: wrap;
justify-content: center;
list-style: none;
}
.tab-pane__swatch-link {
width: 40px;
height: 40px;
cursor: pointer;
margin: 0 20px 10px 0;
background-color: blue;
border: 2px solid #fff;
box-shadow: 3px 1px 10px #a9a9a9;
border-radius: 50%;
}
.tab-pane__swatch-link--red {
background: #ff0000;
}
.tab-pane__swatch-link--black {
background: #000;
}
.tab-pane {
display: none;
}
.tab-pane.is-selected {
display: table;
}
a.is-selected::before {
content: '';
color: #fff;
position: absolute;
display: initial;
margin: 8px 0 0 15px;
border-style: solid;
border-width: 0 3px 3px 0;
transform: rotate(45deg);
height: 1rem;
width: 0.5rem;
}
JS
function onSwatchClick(event) {
let selectedSwatches = document.querySelectorAll('.is-selected');
for(let i = 0; i < selectedSwatches.length; i++) {
selectedSwatches[i].className = selectedSwatches[i].className.replace('is-selected', '');
}
event.preventDefault();
event.target.className += ' is-selected';
document.getElementById(event.target.href.split('#')[1]).className += ' is-selected';
}
const elswatchClick = document.getElementById('js-swatch');
elswatchClick.addEventListener('click', onSwatchClick, false);
Hope you can help thank you.
Your event handler is targeting the tab parent element, not the individual tab triggers. As such, it's not updating the element classes correctly.
Instead, I targeted the class of tab-pane__swatch-link and looped through them, attaching the event listener to each one.
function onSwatchClick(event) {
let selectedSwatches = document.querySelectorAll('.is-selected');
for(let i = 0; i < selectedSwatches.length; i++) {
selectedSwatches[i].className = selectedSwatches[i].className.replace('is-selected', '');
}
event.preventDefault();
event.target.className += ' is-selected';
document.getElementById(event.target.href.split('#')[1]).className += ' is-selected';
}
const elswatchClick = document.querySelectorAll('.tab-pane__swatch-link');
for (var i = 0; i < elswatchClick.length; i++) {
elswatchClick[i].addEventListener('click', onSwatchClick, false);
}
.tab-pane__swatch-image {
width: 90%;
}
.row-1 {
display: flex;
flex-flow: wrap;
justify-content: center;
list-style: none;
}
.tab-pane__swatch-link {
width: 40px;
height: 40px;
cursor: pointer;
margin: 0 20px 10px 0;
background-color: blue;
border: 2px solid #fff;
box-shadow: 3px 1px 10px #a9a9a9;
border-radius: 50%;
}
.tab-pane__swatch-link--red {
background: #ff0000;
}
.tab-pane__swatch-link--black {
background: #000;
}
.tab-pane {
display: none;
}
.tab-pane.is-selected {
display: table;
}
a.is-selected::before {
content: '';
color: #fff;
position: absolute;
display: initial;
margin: 8px 0 0 15px;
border-style: solid;
border-width: 0 3px 3px 0;
transform: rotate(45deg);
height: 1rem;
width: 0.5rem;
}
<div class="tab-pane__swatch-container">
<div class="tab-pane__swatch-content">
<div class="tab-pane is-selected" id="red">
<img src="https://www.bristolstreetversa.com/images/colour_swatches/Grand-Tourneo-Connect/Red.png" alt="Red Versa" class="tab-pane__swatch-image">
</div>
<div class="tab-pane" id="black">
<img src="https://www.bristolstreetversa.com/images/colour_swatches/Grand-Tourneo-Connect/Black.png" alt="Red Versa" class="tab-pane__swatch-image">
</div>
</div>
<nav class="row-1 tab-pane__swatch-selector" id="js-swatch">
</nav>
</div>
EDIT: Ryan's answer is much cleaner than this.
You could make sure that the element that was actually clicked was an "A" tag. Here's how you could do that:
if (event.target.tagName === "A") {
// An <a> tag was clicked
}