Make these slides loop? - javascript

I have been working on this for a little while, and I think I'm stuck at this point.
I made a div slider with arrows. Each div slide is set to a min-width of 80px.
The code works just fine, except, when I navigate either to the left or the right, it stops at the last item. I want this slider to loop (as in endlessly), instead of ending at the last item.
let buttonLeft = document.getElementById('slide_left')
let buttonRight = document.getElementById('slide_right')
buttonLeft.addEventListener('click', function() {
document.getElementById('slider').scrollLeft -= 90
})
buttonRight.addEventListener('click', function() {
document.getElementById('slider').scrollLeft += 90
})
body{
background-color: #555;
height: 100vh;
display: grid;
align-items: center;
justify-items: center;
font-family: 'Helvetica';
}
div#slide_wrapper{
width: 440px;
display: flex;
justify-content: space-between;
height: fit-content;
}
div#slider{
width: 350px;
display: flex;
height: fit-content;
flex-wrap: nowrap;
overflow: hidden;
}
div.thumbnail{
min-width: 80px;
min-height: 80px;
cursor: pointer;
display: grid;
place-items: center;
font-size: 30px;
}
div.thumbnail:not(:last-child){
margin-right: 10px;
}
div.thumbnail:nth-child(1){
background-color: darkturquoise;
}
div.thumbnail:nth-child(2){
background-color: goldenrod;
}
div.thumbnail:nth-child(3){
background-color: rebeccapurple;
}
div.thumbnail:nth-child(4){
background-color: powderblue;
}
div.thumbnail:nth-child(5){
background-color: firebrick;
}
div.thumbnail:nth-child(6){
background-color: sienna;
}
div.thumbnail:nth-child(7){
background-color: bisque;
}
div.thumbnail:nth-child(8){
background-color: navy;
}
div#slide_wrapper > button{
height: fit-content;
align-self: center;
font-size: 24px;
font-weight: 800;
border: none;
outline: none;
}
div#slide_wrapper > button:hover{
cursor: pointer;
background-color: dodgerblue;
color: #fff;
}
<div id="slide_wrapper">
<button id="slide_left" class="slide_arrow">❮</button>
<div id="slider">
<div class="thumbnail active">1</div>
<div class="thumbnail">2</div>
<div class="thumbnail">3</div>
<div class="thumbnail">4</div>
<div class="thumbnail">5</div>
<div class="thumbnail">6</div>
<div class="thumbnail">7</div>
<div class="thumbnail">8</div>
</div>
<button id="slide_right" class="slide_arrow">❯</button>
</div>

Nice slider! There are several ways to achieve what you want. In my opinion, the simplest solution would be to work with some if conditions and a counter variable. Once the number of thumbnails is reached, set the counter back to 0.
Update
Regarding to your comment. "How about doing the same for the left arrow.". In the if condition block: if (0 == slideCount) { i add these lines:
slideCount = thumbnail.length // set the slideCounter to maximum
document.getElementById('slider').scrollLeft = slideCount * 90 // calculate the scroll distance
slideCount--; // decrease slidecount
setActive(); // set the red border on the current slide
const buttonLeft = document.getElementById('slide_left')
const buttonRight = document.getElementById('slide_right')
const thumbnail = document.querySelectorAll(".thumbnail");
let slideCount = 0;
setActive();
buttonLeft.addEventListener('click', function() {
if (0 == slideCount) {
slideCount = thumbnail.length
document.getElementById('slider').scrollLeft = slideCount * 90
slideCount--;
setActive();
return;
}
slideCount--;
document.getElementById('slider').scrollLeft -= 90
setActive();
})
buttonRight.addEventListener('click', function() {
slideCount++;
if ( 8 == slideCount) {
document.getElementById('slider').scrollLeft = 0
slideCount = 0;
} else {
document.getElementById('slider').scrollLeft += 90
}
setActive();
})
function setActive() {
thumbnail.forEach(t => {
t.classList.remove("active");
})
thumbnail[slideCount].classList.add("active")
}
function count() {
console.log(slideCount);
}
body{
background-color: #555;
height: 100vh;
display: grid;
align-items: center;
justify-items: center;
font-family: 'Helvetica';
}
div#slide_wrapper{
width: 440px;
display: flex;
justify-content: space-between;
height: fit-content;
}
div#slider{
width: 350px;
display: flex;
height: fit-content;
flex-wrap: nowrap;
overflow: hidden;
}
div.thumbnail{
min-width: 80px;
min-height: 80px;
cursor: pointer;
display: grid;
place-items: center;
font-size: 30px;
}
div.thumbnail:not(:last-child){
margin-right: 10px;
}
div.thumbnail:nth-child(1){
background-color: darkturquoise;
}
div.thumbnail:nth-child(2){
background-color: goldenrod;
}
div.thumbnail:nth-child(3){
background-color: rebeccapurple;
}
div.thumbnail:nth-child(4){
background-color: powderblue;
}
div.thumbnail:nth-child(5){
background-color: firebrick;
}
div.thumbnail:nth-child(6){
background-color: sienna;
}
div.thumbnail:nth-child(7){
background-color: bisque;
}
div.thumbnail:nth-child(8){
background-color: navy;
}
div#slide_wrapper > button{
height: fit-content;
align-self: center;
font-size: 24px;
font-weight: 800;
border: none;
outline: none;
}
div#slide_wrapper > button:hover{
cursor: pointer;
background-color: dodgerblue;
color: #fff;
}
.active {
border: 2px solid red;
}
<div id="slide_wrapper">
<button id="slide_left" class="slide_arrow">❮</button>
<div id="slider">
<div class="thumbnail active">1</div>
<div class="thumbnail">2</div>
<div class="thumbnail">3</div>
<div class="thumbnail">4</div>
<div class="thumbnail">5</div>
<div class="thumbnail">6</div>
<div class="thumbnail">7</div>
<div class="thumbnail">8</div>
</div>
<button id="slide_right" class="slide_arrow">❯</button>
</div>

Just find the width of the slider and compare it with the scroll left like
let buttonLeft = document.getElementById('slide_left')
let buttonRight = document.getElementById('slide_right')
buttonLeft.addEventListener('click', function() {
document.getElementById('slider').scrollLeft -= 90
})
buttonRight.addEventListener('click', function() {
const elem = document.getElementById('slider');
const ElemWidth = elem.getClientRects()[0].width
if(document.getElementById('slider').scrollLeft > ElemWidth ){
document.getElementById('slider').scrollLeft = 0
}else{
document.getElementById('slider').scrollLeft += 90
}
console.log(ElemWidth, document.getElementById('slider').scrollLeft , document.getElementById('slider').scrollLeft > ElemWidth)
})

Related

disable left or right arrow at the last item

Just made a simple div slider with navigation arrows. The div slider works just fine, except, I want some sort of CSS styling to be applied to the arrows.
That is, when a user clicks the left or right arrow, up to the last item, apply CSS styling telling the user they've reached the end of the slider.
let buttonLeft = document.getElementById('slide_left')
let buttonRight = document.getElementById('slide_right')
let container = document.getElementById('slider')
buttonLeft.addEventListener('click', function() {
container.scrollLeft -= 90
})
buttonRight.addEventListener('click', function() {
container.scrollLeft += 90
})
body {
background-color: #555;
height: 100vh;
display: grid;
align-items: center;
justify-items: center;
font-family: 'Helvetica';
}
div#slide_wrapper {
width: 440px;
display: flex;
justify-content: space-between;
height: fit-content;
}
div#slider {
width: 350px;
display: flex;
height: fit-content;
flex-wrap: nowrap;
overflow: hidden;
}
div.thumbnail {
min-width: 80px;
min-height: 80px;
cursor: pointer;
display: grid;
place-items: center;
font-size: 30px;
}
div.thumbnail:not(:last-child) {
margin-right: 10px;
}
div.thumbnail:nth-child(1) {
background-color: darkturquoise;
}
div.thumbnail:nth-child(2) {
background-color: goldenrod;
}
div.thumbnail:nth-child(3) {
background-color: rebeccapurple;
}
div.thumbnail:nth-child(4) {
background-color: powderblue;
}
div.thumbnail:nth-child(5) {
background-color: firebrick;
}
div.thumbnail:nth-child(6) {
background-color: sienna;
}
div.thumbnail:nth-child(7) {
background-color: bisque;
}
div.thumbnail:nth-child(8) {
background-color: navy;
}
div#slide_wrapper>button {
height: fit-content;
align-self: center;
font-size: 24px;
font-weight: 800;
border: none;
outline: none;
}
div#slide_wrapper>button:hover {
cursor: pointer;
}
<div id="slide_wrapper">
<button id="slide_left" class="slide_arrow">❮</button>
<div id="slider">
<div class="thumbnail active">1</div>
<div class="thumbnail">2</div>
<div class="thumbnail">3</div>
<div class="thumbnail">4</div>
<div class="thumbnail">5</div>
<div class="thumbnail">6</div>
<div class="thumbnail">7</div>
<div class="thumbnail">8</div>
</div>
<button id="slide_right" class="slide_arrow">❯</button>
</div>
Simply check to see if you need to disable each button based on the position of the scroll. Then if there is a need to disable a button, add the disabled class to the button, otherwise remove it.
Future enhancements.
Remove the hardcoded 360 value for the scroll end. This should be calculated from the size of the carousel items and the width of the viewport.
Allow more than one carousel to work with the same code. This could be achieved by using a javascript class that would hold the elements inside an object, separate from other carousels.
See the demo:
let buttonLeft = document.getElementById('slide_left')
let buttonRight = document.getElementById('slide_right')
let container = document.getElementById('slider')
let checkScroll = function() {
if (container.scrollLeft <= 0)
buttonLeft.classList.add("disabled");
else
buttonLeft.classList.remove("disabled");
if (container.scrollLeft >= 360)
buttonRight.classList.add("disabled");
else
buttonRight.classList.remove("disabled");
}
checkScroll();
buttonLeft.addEventListener('click', function() {
container.scrollLeft -= 90;
checkScroll();
})
buttonRight.addEventListener('click', function() {
container.scrollLeft += 90;
checkScroll();
})
body {
background-color: #555;
height: 100vh;
display: grid;
align-items: center;
justify-items: center;
font-family: 'Helvetica';
}
div#slide_wrapper {
width: 440px;
display: flex;
justify-content: space-between;
height: fit-content;
}
div#slider {
width: 350px;
display: flex;
height: fit-content;
flex-wrap: nowrap;
overflow: hidden;
}
div.thumbnail {
min-width: 80px;
min-height: 80px;
cursor: pointer;
display: grid;
place-items: center;
font-size: 30px;
}
div.thumbnail:not(:last-child) {
margin-right: 10px;
}
div.thumbnail:nth-child(1) {
background-color: darkturquoise;
}
div.thumbnail:nth-child(2) {
background-color: goldenrod;
}
div.thumbnail:nth-child(3) {
background-color: rebeccapurple;
}
div.thumbnail:nth-child(4) {
background-color: powderblue;
}
div.thumbnail:nth-child(5) {
background-color: firebrick;
}
div.thumbnail:nth-child(6) {
background-color: sienna;
}
div.thumbnail:nth-child(7) {
background-color: bisque;
}
div.thumbnail:nth-child(8) {
background-color: navy;
}
div#slide_wrapper>button {
height: fit-content;
align-self: center;
font-size: 24px;
font-weight: 800;
border: none;
outline: none;
}
div#slide_wrapper>button:hover {
cursor: pointer;
}
.slide_arrow.disabled {
opacity: 0.2;
cursor: auto !important;
}
<div id="slide_wrapper">
<button id="slide_left" class="slide_arrow">❮</button>
<div id="slider">
<div class="thumbnail active">1</div>
<div class="thumbnail">2</div>
<div class="thumbnail">3</div>
<div class="thumbnail">4</div>
<div class="thumbnail">5</div>
<div class="thumbnail">6</div>
<div class="thumbnail">7</div>
<div class="thumbnail">8</div>
</div>
<button id="slide_right" class="slide_arrow">❯</button>
</div>
a simple solution to this is to actually create a css class that defines the style of arrows when there are no more items and then just add/remove class based on current index of items

Convert this slide to a loop?

I made a div slider with arrows, each div is set to a min-width of 60px.
The code works just fine, except, when I navigate with the arrow either to the left or to the right, it stops at the last item. I want it to loop (as in endlessly). Instead of stopping at the last item.
let rightArrow = document.getElementById('right')
rightArrow.onclick = function() {
let container = document.getElementById('box')
sideScroll(container, 'right', 25, 80, 10)
}
let leftArrow = document.getElementById('left')
leftArrow.onclick = function() {
let container = document.getElementById('box')
sideScroll(container, 'left', 25, 80, 10)
}
function sideScroll(element, direction, speed, distance, step) {
// body...
scrollAmount = 0
let slideTimer = setInterval(function() {
// body...
if (direction == 'left') {
element.scrollLeft -= step
} else {
element.scrollLeft += step
}
scrollAmount += step
if (scrollAmount >= distance) {
window.clearInterval(slideTimer)
}
}, speed)
}
* {
margin: 0;
padding: 0;
box-sizing: border-box;
}
body {
background-color: #efefef;
width: 100%;
height: 100vh;
background-image: radial-gradient(circle, #2196f3, #3f51b5);
font-family: 'Nirmala UI';
display: grid;
place-items: center;
}
div.main {
position: relative;
background-color: #fff;
border-radius: 10px;
}
div.main div.item_div {
width: 300px;
overflow: auto;
display: flex;
}
div.main div.item_div::-webkit-scrollbar {
display: none;
}
div.main div.item_div div.item {
min-width: 60px;
min-height: 60px;
border-radius: 10px;
background-color: grey;
display: grid;
place-items: center;
font-size: 40px;
text-transform: uppercase;
scroll-behavior: smooth;
user-select: none;
}
div.main div.item_div div.item:not(:last-child) {
margin-right: 20px;
}
div.arrow {
position: absolute;
width: 40px;
height: 40px;
background-color: #f0f0f0;
border-radius: 50%;
display: flex;
align-items: center;
justify-content: center;
top: 50%;
transform: translateY(-50%);
}
div#left {
left: -60px;
}
div#right {
right: -60px;
}
div.arrow span {
font-size: 20px;
user-select: none;
}
div.arrow:hover {
cursor: pointer;
}
<div class="main">
<div class="item_div" id="box">
<div class="item">1</div>
<div class="item">2</div>
<div class="item">3</div>
<div class="item">4</div>
<div class="item">5</div>
<div class="item">6</div>
<div class="item">7</div>
<div class="item">8</div>
<div class="item">9</div>
<div class="item">10</div>
</div>
<div class="arrow" id="left"><span>❮</span></div>
<div class="arrow" id="right"><span>❯</span></div>
</div>
Can anyone help me out? Please?
You can you scrollLeft to check the position of scrollbar and move the bar to the start or end accordingly.
I have highlighted the changes I made to the code using comments
let rightArrow = document.getElementById('right')
rightArrow.onclick = function() {
let container = document.getElementById('box')
//check if the scrollbar is located at the end and reset it to starting position
if (container.scrollLeft == container.scrollWidth - container.offsetWidth) {
sideScroll(container, 'left', 10, container.scrollWidth, 20)
} else {
sideScroll(container, 'right', 25, 80, 10)
}
}
let leftArrow = document.getElementById('left')
leftArrow.onclick = function() {
let container = document.getElementById('box')
//check if the scrollbar is located at the start and reset it to ending position
if (container.scrollLeft == 0) {
sideScroll(container, 'right', 10, container.scrollWidth, 20)
} else {
sideScroll(container, 'left', 25, 80, 10)
}
}
function sideScroll(element, direction, speed, distance, step) {
// body...
scrollAmount = 0
let slideTimer = setInterval(function() {
// body...
if (direction == 'left') {
element.scrollLeft -= step
} else {
element.scrollLeft += step
}
scrollAmount += step
if (scrollAmount >= distance) {
window.clearInterval(slideTimer)
}
}, speed)
}
* {
margin: 0;
padding: 0;
box-sizing: border-box;
}
body {
background-color: #efefef;
width: 100%;
height: 100vh;
background-image: radial-gradient(circle, #2196f3, #3f51b5);
font-family: 'Nirmala UI';
display: grid;
place-items: center;
}
div.main {
position: relative;
background-color: #fff;
border-radius: 10px;
}
div.main div.item_div {
width: 300px;
overflow: auto;
display: flex;
}
div.main div.item_div::-webkit-scrollbar {
display: none;
}
div.main div.item_div div.item {
min-width: 60px;
min-height: 60px;
border-radius: 10px;
background-color: grey;
display: grid;
place-items: center;
font-size: 40px;
text-transform: uppercase;
scroll-behavior: smooth;
user-select: none;
}
div.main div.item_div div.item:not(:last-child) {
margin-right: 20px;
}
div.arrow {
position: absolute;
width: 40px;
height: 40px;
background-color: #f0f0f0;
border-radius: 50%;
display: flex;
align-items: center;
justify-content: center;
top: 50%;
transform: translateY(-50%);
}
div#left {
left: -60px;
}
div#right {
right: -60px;
}
div.arrow span {
font-size: 20px;
user-select: none;
}
div.arrow:hover {
cursor: pointer;
}
<div class="main">
<div class="item_div" id="box">
<div class="item">1</div>
<div class="item">2</div>
<div class="item">3</div>
<div class="item">4</div>
<div class="item">5</div>
<div class="item">6</div>
<div class="item">7</div>
<div class="item">8</div>
<div class="item">9</div>
<div class="item">10</div>
</div>
<div class="arrow" id="left"><span>❮</span></div>
<div class="arrow" id="right"><span>❯</span></div>
</div>

How to change a global variable within a function using click eventListener function?

I try to change the variable of passLength using 4 different buttons. This will affect the length of the string result of the function. The problem I'm noticing is that when I press for example the "24" button, then run the main function with the (now commented out) console log, passLength still logs as the default of 16. I believe this is because it was declared globally at the beginning, and my changes on button click are not taking place since they are happening locally within functions. Because when I console log within the buttonclick functions, it always puts out the value I need.
So my question is: How do I change this global passLength variable with button clicks?
let passLength = 16; //Default lngth of password. This will be changable later on
document.getElementById('btn8').addEventListener('click', function(){
let passLength = 8;
console.log(passLength)
return passLength;
});
document.getElementById('btn16').addEventListener('click', function(){
let passLength = 16;
console.log(passLength)
return passLength;
});
document.getElementById('btn20').addEventListener('click', function(){
let passLength = 20;
console.log(passLength)
return passLength;
});
document.getElementById('btn24').addEventListener('click', function(){
let passLength = 24;
console.log(passLength)
return passLength;
});
randomString(passLength)
function randomString(passLength){
//console.log(passLength)
var randomPassword = '';
var characters = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890-=+?!$/><)(%&*'
for(var i, i = 0; i < passLength; i++){
randomPassword += characters.charAt(Math.floor(Math.random() * characters.length))
};
console.log(randomPassword)
return randomPassword;
};
document.getElementById('btn').addEventListener('click', function(){
document.getElementById('string').textContent = randomString(passLength);
});
HTML:
<div id="contentWrapper">
<div class="row">
<h2>Generate a Secure Password</h2>
</div>
<div class="row">
<div id="stringContainer">
<p id="string">Click the button to start!</p> <!--password inside-->
</div>
</div>
<div class="btnRow">
<div id="generateButton">
<button id="btn">Generate</button>
</div>
</div>
<div class="row">
<!--empty row-->
</div>
<div class="h3Row">
<h3>Select Number of Characters:</h3>
</div>
<div class="selectingRow">
<div class="selectorBtn">
<button id="btn8" class="slctBtn">8</button>
</div>
<div class="selectorBtn">
<button id="btn16" class="slctBtn">16</button>
</div>
<div class="selectorBtn">
<button id="btn20" class="slctBtn">20</button>
</div>
<div class="selectorBtn">
<button id="btn24" class="slctBtn">24</button>
</div>
</div>
</div>
CSS
html, body {
font-family: sans-serif;
height: 100%;
margin: 0;
padding: 0;
}
#contentWrapper {
display: flex;
flex-direction: column;
height: 100vh;
justify-content: center;
align-items: center;
background-color: rgb(177, 192, 177);
}
h2 {
padding: 0;
margin: 0;
display: flex;
justify-content: center;
}
.row {
display: flex;
justify-content: center;
align-items: center;
padding: 4px 0;
width: 100%;
min-height: 50px;
}
.btnRow {
display: flex;
justify-content: center;
align-items: center;
width: 100%;
min-height: 35px;
}
.h3Row {
display: flex;
justify-content: center;
align-items: center;
width: 100%;
max-height: 25px;
}
.selectingRow {
display: flex;
justify-content: center;
align-items: center;
width: 100%;
min-height: 25px;
}
.slctBtn {
min-height: 20px;
min-width: 20px;
border-radius: 4px;
border: none;
color: rgb(0, 0, 0);
background-color: rgb(255, 168, 168);
transition: all 0.07s linear;
font-weight: bold;
margin-left: 5px;
margin-right: 5px;
}
.slctBtn:hover { /*give this an animation later, maybe a little shake*/
background-color: rgb(201, 99, 99);
}
.slctBtn:active { /*give this an animation too*/
background-color: rgb(201, 99, 99);
border: 2px solid black;
}
#generateButton {
display: flex;
justify-content: center;
align-items: center;
}
#btn {
min-height: 50px;
min-width: 110px;
border-radius: 4px;
border: none;
color: rgb(0, 0, 0);
font-weight: bold;
font-size: large;
background-color: rgb(255, 168, 168);
transition: all 0.07s linear;
}
#btn:hover { /*give this an animation later, maybe a little shake*/
background-color: rgb(201, 99, 99);
}
#btn:active { /*give this an animation too*/
background-color: rgb(201, 99, 99);
border: 2px solid black;
}
#stringContainer { /*Box*/
width: 300px;
height: 50px;
background-color: #636161;
color: #fff;
border-radius: 5px;
border: none;
text-align: center;
display: flex;
justify-content: center;
align-items: center;
}
#string {
display: flex;
letter-spacing: 2.1px;
}
You are re-declaring passLength with let (block scope) within each event handler which creates new variables, rather than affecting the global one. Remove all the let declarations in each callback to affect the one Global.
let passLength = 16; //Default lngth of password. This will be changable later on
document.getElementById('btn8').addEventListener('click', function(){
passLength = 8;
console.log(passLength)
return passLength;
});
document.getElementById('btn16').addEventListener('click', function(){
passLength = 16;
console.log(passLength)
return passLength;
});
document.getElementById('btn20').addEventListener('click', function(){
passLength = 20;
console.log(passLength)
return passLength;
});
document.getElementById('btn24').addEventListener('click', function(){
passLength = 24;
console.log(passLength)
return passLength;
});
randomString(passLength)
function randomString(passLength){
//console.log(passLength)
var randomPassword = '';
var characters = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890-=+?!$/><)(%&*'
for(var i, i = 0; i < passLength; i++){
randomPassword += characters.charAt(Math.floor(Math.random() * characters.length))
};
console.log(randomPassword)
return randomPassword;
};
document.getElementById('btn').addEventListener('click', function(){
document.getElementById('string').textContent = randomString(passLength);
});
html, body {
font-family: sans-serif;
height: 100%;
margin: 0;
padding: 0;
}
#contentWrapper {
display: flex;
flex-direction: column;
height: 100vh;
justify-content: center;
align-items: center;
background-color: rgb(177, 192, 177);
}
h2 {
padding: 0;
margin: 0;
display: flex;
justify-content: center;
}
.row {
display: flex;
justify-content: center;
align-items: center;
padding: 4px 0;
width: 100%;
min-height: 50px;
}
.btnRow {
display: flex;
justify-content: center;
align-items: center;
width: 100%;
min-height: 35px;
}
.h3Row {
display: flex;
justify-content: center;
align-items: center;
width: 100%;
max-height: 25px;
}
.selectingRow {
display: flex;
justify-content: center;
align-items: center;
width: 100%;
min-height: 25px;
}
.slctBtn {
min-height: 20px;
min-width: 20px;
border-radius: 4px;
border: none;
color: rgb(0, 0, 0);
background-color: rgb(255, 168, 168);
transition: all 0.07s linear;
font-weight: bold;
margin-left: 5px;
margin-right: 5px;
}
.slctBtn:hover { /*give this an animation later, maybe a little shake*/
background-color: rgb(201, 99, 99);
}
.slctBtn:active { /*give this an animation too*/
background-color: rgb(201, 99, 99);
border: 2px solid black;
}
#generateButton {
display: flex;
justify-content: center;
align-items: center;
}
#btn {
min-height: 50px;
min-width: 110px;
border-radius: 4px;
border: none;
color: rgb(0, 0, 0);
font-weight: bold;
font-size: large;
background-color: rgb(255, 168, 168);
transition: all 0.07s linear;
}
#btn:hover { /*give this an animation later, maybe a little shake*/
background-color: rgb(201, 99, 99);
}
#btn:active { /*give this an animation too*/
background-color: rgb(201, 99, 99);
border: 2px solid black;
}
#stringContainer { /*Box*/
width: 300px;
height: 50px;
background-color: #636161;
color: #fff;
border-radius: 5px;
border: none;
text-align: center;
display: flex;
justify-content: center;
align-items: center;
}
#string {
display: flex;
letter-spacing: 2.1px;
}
<div id="contentWrapper">
<div class="row">
<h2>Generate a Secure Password</h2>
</div>
<div class="row">
<div id="stringContainer">
<p id="string">Click the button to start!</p> <!--password inside-->
</div>
</div>
<div class="btnRow">
<div id="generateButton">
<button id="btn">Generate</button>
</div>
</div>
<div class="row">
<!--empty row-->
</div>
<div class="h3Row">
<h3>Select Number of Characters:</h3>
</div>
<div class="selectingRow">
<div class="selectorBtn">
<button id="btn8" class="slctBtn">8</button>
</div>
<div class="selectorBtn">
<button id="btn16" class="slctBtn">16</button>
</div>
<div class="selectorBtn">
<button id="btn20" class="slctBtn">20</button>
</div>
<div class="selectorBtn">
<button id="btn24" class="slctBtn">24</button>
</div>
</div>
</div>

How to download customisable color change box as image with the background image?

I have a box that can change color once you select the box and then select the color.
However, there is also a background image that shows the outline of the box. I have used HTML2canvas and jquery as libraries so I can download the customise color change box as an image, but it could only be downloaded locally if the image is hidden - as shown on the CSS.
My question is, how do I download the customisable color change box with the background outline box image? - or - Is there an alternative way to save the background image and the SVG locally with download button?
//////// carousel ////////
let sliderImages = document.querySelectorAll('.slide'),
arrowLeft = document.querySelector('#arrow-left'),
arrowRight = document.querySelector('#arrow-right'),
current = 0;
//Clear all images
function reset() {
for (let i = 0; i < sliderImages.length; i++) {
sliderImages[i].style.display = 'none';
}
}
// initialize slider
function startSlide() {
reset();
sliderImages[0].style.display = "block";
}
//show previous
function slideLeft() {
reset();
sliderImages[current - 1].style.display = "block";
current--;
}
//show next
function slideRight() {
reset();
sliderImages[current + 1].style.display = "block";
current++;
}
//left arrow click
arrowLeft.addEventListener('click', function() {
if (current === 0) {
current = sliderImages.length;
}
slideLeft();
});
//right arrow click
arrowRight.addEventListener('click', function() {
if (current === sliderImages.length - 1) {
current = -1;
}
slideRight();
});
startSlide();
const overlays = [];
document.querySelectorAll(".product").forEach(function(path) {
path.onclick = chooseProduct;
})
function chooseProduct(e) {
overlays.push(e.target);
overlays.forEach((overlay) => overlay.classList.add('highlight'));
}
//////// remove highlight when clicking outside of image ////////
var removeHighlight = function(e) {
var products = document.querySelectorAll('.product');
if (!e.target.classList.contains('product') && !e.target.classList.contains('color')) {
overlays.length = 0;
document.querySelectorAll('.product').forEach(function(prod) {
prod.classList.remove('highlight');
});
}
}
document.onclick = removeHighlight;
//////// remove highlight of a specific shape ////////
function chooseProduct(e) {
for (let i = 0; i < overlays.length; i += 1) {
let currentOverlay = overlays[i];
if (currentOverlay.isSameNode(e.target)) {
overlays.splice(i, 1);
e.target.classList.remove('highlight')
return;
}
}
overlays.push(e.target);
overlays.forEach((overlay) => overlay.classList.add("highlight"));
}
//////// get and set colours ////////
// Click on a color
var el = document.getElementsByClassName("color");
for (var i = 0; i < el.length; i++) {
el[i].onclick = changeColor;
}
function changeColor(e) {
// get the hex color
let hex = e.target.getAttribute("data-hex");
// set the hex color
overlays.forEach((overlay) => overlay.style.fill = hex);
}
$(document).ready(function() {
function saveScreenshot(canvas) {
var downloadLink = document.createElement('a');
downloadLink.download = 'download.jpg';
canvas.toBlob(function(blob) {
downloadLink.href = URL.createObjectURL(blob)
downloadLink.click();
});
}
$(".download-btn").on("click", function(e) {
e.preventDefault();
html2canvas(document.querySelector(".download-container"), {
scrollX: 0,
scrollY: 0
}).then(function(canvas) {
var image = canvas.toDataURL('image/jpeg');
document.getElementById("created-element").src = image;
$(this).attr('href', image);
saveScreenshot(canvas);
});
});
});
.grid-container {
display: grid;
grid-template-columns: auto 5% 1fr auto 1fr;
grid-template-rows: 128px auto 1fr auto auto auto auto 100px;
gap: 0px 0px;
grid-auto-flow: row;
grid-template-areas:
"header . . . ."
"main main main color-select color-select"
"main main main color-select color-select"
"about about about about about"
"howto howto howto howto howto"
"faqs faqs faqs faqs faqs"
"social social social social social"
"footer footer footer footer footer";
}
.header {
grid-area: header;
}
.logo {
display: inline-block;
padding-top: 20px;
padding-left: 65px;
}
.navbar {
display: inline-block;
padding-top: 50px;
padding-right: 20px;
font-family: 'Roboto Condensed', sans-serif;
line-height: 38px;
font-weight: 400;
font-size: 18px;
float: right;
}
.nav-link {
margin: 18px;
color: #212529;
text-decoration: none;
}
.main {
grid-area: main;
background-color: #f8f8f8;
padding-top: 20px;
padding-bottom: 50px;
display: flex;
text-align: center;
position: relative;
margin-top: 2.5px;
margin-left: 78px;
}
#slider,
.wrap,
.slide-content {
max-width: 1000px;
position: relative;
margin: auto;
}
.slide-content {
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
text-align: center;
}
.arrow {
cursor: pointer;
position: absolute;
top: 101%;
width: 60%;
height: 0;
z-index: 1;
font-size: 20px;
color: #cccccc;
}
#arrow-left {
left: 0;
}
#arrow-right {
right: 0;
}
/* Caption text */
.text {
position: relative;
color: #212529;
font-size: 18px;
top: 28px;
width: 100%;
text-align: center;
font-family: 'Roboto Condensed', sans-serif;
font-weight: 400;
}
.lion-number {
color: #8f8f8f;
}
.color-select {
display: flex;
align-items: center;
grid-area: color-select;
background-color: #f8f8f8;
margin-top: 2.5px;
margin-right: 78px;
padding: 10px;
}
body,
html {
margin: 0;
padding: 0;
height: 100%;
width: 100%;
}
#container {
width: 100%;
height: auto;
}
#product-svg {
position: absolute;
z-index: 2;
background-size: 100%;
background-repeat: no-repeat;
background-position: 50%;
mix-blend-mode: multiply;
width: 85%;
height: auto;
}
path {
fill: #8f8f8f;
}
.background-image {
position: relative;
z-index: 1;
width: 85%;
height: auto;
}
[data-test] {
display: flex;
flex-wrap: wrap;
justify-content: space-between;
align-items: start;
padding-left: 15px;
padding-right: 15px;
}
[data-test] span.color {
flex-shrink: 0;
display: flex;
flex-wrap: wrap;
justify-content: center;
width: 60px;
padding-bottom: 9px;
}
[data-test] span.color span {
height: 23px;
width: 20px;
background: var(--color);
clip-path: polygon(50% 0, 100% 25%, 100% 75%, 50% 100%, 0 75%, 0 25%);
margin-bottom: -6px;
}
[data-test] span.color span:first-child {
margin-left: 1px;
}
.highlight {
stroke-width: 10px;
stroke: #000;
}
img {
visibility: hidden;
}
button {
font-size: 1.25em;
padding: 1em;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.6.0/jquery.js" integrity="sha512-n/4gHW3atM3QqRcbCn6ewmpxcLAHGaDjpEBu4xZd47N0W2oQ+6q7oc3PXstrJYXcbNU1OHdQ1T7pAP+gi5Yu8g==" crossorigin="anonymous" referrerpolicy="no-referrer"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/html2canvas/1.2.2/html2canvas.js" integrity="sha512-Alb3nvf6wRVUhs6H8foMA8fuWAKFFretiYkk2WbrMSbAtTtNBOjKLbDIagmFVypIi4wT1pRhHwz+R/W7nU31wg==" crossorigin="anonymous" referrerpolicy="no-referrer"></script>
<div class="grid-container">
<header class="header">
<img class="logo" src="logo.png" alt="">
<nav class="navbar">
About
How to
FAQs
Contact
</nav>
</header>
</div>
</div>
<main class="main">
<div class="wrap">
<div id="arrow-left" class="arrow"><span>❮</span></div>
<div id="arrow-right" class="arrow"><span>❯</span></div>
<div id="slider">
<div class="slide slide1">
<div class="slide-content">
<div id="container">
<div class="download-container">
<svg id="product-svg" viewBox="0 0 256 256">
<path id="box1" class="product" d="M24 130.25L24 235L233 235L233 25.5L24 25.5L24 130.25Z" />
</svg>
<img class="background-image" src="https://images.vexels.com/media/users/3/139342/isolated/lists/61cddf9cfe50f4baaa8f472c253d1cb4-basic-square-outline.png" alt="">
</div>
</div>
<div class="text">image1</div>
</div>
</div>
<div class="slide slide1">
<div class="slide-content"
<div id="container">
<div class="download-container">
<svg id="product-svg" viewBox="0 0 256 256">
<path id="box2" class="product" d="M24 130.25L24 235L233 235L233 25.5L24 25.5L24 130.25Z" />
</svg>
<img class="background-image" src="https://images.vexels.com/media/users/3/139342/isolated/lists/61cddf9cfe50f4baaa8f472c253d1cb4-basic-square-outline.png" alt="">
</div>
</div>
<div class="text">image2</div>
</div>
</div>
<button class="download-btn">Download element!</button>
<img src="" id="created-element" />
</main>
<section class="color-select">
<div data-test>
<span class="color red">
<span class="color-selected" style="--color: #ff6666 " data-hex="#ff6666"></span>
</span>
</div>
</section>
</div>
If you want to download an image with the background changes that you have made then you first need to convert HTML(Image and the background together) into an image using libraries like HTML2Canvas.
Libarary: https://github.com/niklasvh/html2canvas
Tutorial: https://codepedia.info/convert-html-to-image-in-jquery-div-or-table-to-jpg-png
Which would take a screenshot of the HTML that is changed on the page that you have then the image would be downloaded.

how to know child divs on container div center on scroll event right and left?

trying to do event 'scroll' and when in the callback function the record of position div only record of last position, i want to know if that div in the center target i want
const slide = document.querySelector(".slides")
slide.addEventListener('scroll', function(e) {
const slide2 = document.querySelector("#slide-2")
console.log(slide2.offsetLeft)
})
<div class="slider">
1
2
3
4
5
<div class="slides">
<div id="slide-1">1</div>
<div id="slide-2">2</div>
<div id="slide-3">3</div>
<div id="slide-4">4</div>
<div id="slide-5">5</div>
</div>
</div>
my goal here I want to know if a user on that div to Right and Left for my slider
so i can make active dots , i am trying to just use native javascript here :)
here is my Codepen example
https://codepen.io/lpllplp222/pen/BaRvwKm
I have used jQuery to achieve the same.
position() function from the jQuery provides the current position of an element from its top and left, I am using the left value to calculate the current active element and get its index, thereby providing an active class to the corresponding dot.
const slide = document.querySelector(".slides")
$('#slider-dots a').on('click', function(event) {
event.stopPropagation();
})
slide.addEventListener('scroll', function(e) {
var scrollLeft = $('#slides-wrapper').scrollLeft();
var currIndex = -1;
$('#slider-dots a').removeClass('active');
for(var i = 0; i<$('#slides-wrapper div').length; i++) {
if($($('#slides-wrapper div')[i]).position().left >= 0 && currIndex === -1) {
currIndex = i;
}
}
$($('#slider-dots a')[currIndex]).addClass('active');
})
* {
box-sizing: border-box;
}
.slider {
width: 400px;
text-align: center;
overflow: hidden;
}
.slides {
display: flex;
overflow-x: auto;
scroll-snap-type: x mandatory;
scroll-behavior: smooth;
-webkit-overflow-scrolling: touch;
/*
scroll-snap-points-x: repeat(300px);
scroll-snap-type: mandatory;
*/
}
.slides::-webkit-scrollbar {
width: 10px;
height: 10px;
}
#slider-dots a.active {
color: violet;
background-color: #000;
}
.slides::-webkit-scrollbar-thumb {
background: black;
border-radius: 10px;
}
.slides::-webkit-scrollbar-track {
background: transparent;
}
.slides > div {
scroll-snap-align: start;
flex-shrink: 0;
width: 300px;
height: 200px;
margin-right: 50px;
border-radius: 10px;
background: #eee;
transform-origin: center center;
transform: scale(1);
transition: transform 0.5s;
position: relative;
display: flex;
justify-content: center;
align-items: center;
font-size: 100px;
}
.slides > div:target {
/* transform: scale(0.8); */
}
.author-info {
background: rgba(0, 0, 0, 0.75);
color: white;
padding: 0.75rem;
text-align: center;
position: absolute;
bottom: 0;
left: 0;
width: 100%;
margin: 0;
}
.author-info a {
color: white;
}
img {
object-fit: cover;
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
}
.slider > a {
display: inline-flex;
width: 1.5rem;
height: 1.5rem;
background: white;
text-decoration: none;
align-items: center;
justify-content: center;
border-radius: 50%;
margin: 0 0 0.5rem 0;
position: relative;
}
.slider > a:active {
top: 1px;
}
.slider > a:focus {
background: #000;
}
/* Don't need button navigation */
#supports (scroll-snap-type) {
.slider > a {
display: none;
}
}
html,
body {
height: 100%;
overflow: hidden;
}
body {
display: flex;
align-items: center;
justify-content: center;
background: linear-gradient(to bottom, #74abe2, #5563de);
font-family: "Ropa Sans", sans-serif;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div class="slider" id='slider-dots'>
1
2
3
4
5
<div id='slides-wrapper' class="slides">
<div id="slide-1">
1
</div>
<div id="slide-2">
2
</div>
<div id="slide-3">
3
</div>
<div id="slide-4">
4
</div>
<div id="slide-5">
5
</div>
</div>
</div>

Categories

Resources