JavaScript - Div Elements Appending Twice on One Click - javascript

//Global variables
let count = 1;
let canvas = document.querySelector('#canvas');
let canvasContainer = document.querySelector('.canvas-container');
let designBtn = document.querySelector('#design-btn');
let editBtn = document.querySelector('#edit-btn');
let isDesign = false;
let isEdit = false;
let circleArray = [];
let offset = [];
//Click event listener for design button
designBtn.addEventListener('click', (event)=>{
isDesign = true;
isEdit = false;
designBtn.style.backgroundColor = '#BA4A00'
designBtn.style.color = '#17202A'
editBtn.style.backgroundColor = null;
editBtn.style.color = null
//Invoke being_design function
begin_design()
})
//Click event listener for edit button
editBtn.addEventListener('click', (event)=>{
isDesign = false;
isEdit = true;
editBtn.style.backgroundColor = '#BA4A00'
editBtn.style.color = '#17202A'
designBtn.style.backgroundColor = null;
designBtn.style.color = null
//Invoke edit_design function
edit_design()
})
//Function creates new element and then appends it to the parent div
function create_circle_element(x, y){
let circle = document.createElement('div')
const circleHeight = 40;
const circleWidth = 40;
circle.style.position = 'absolute';
circle.style.backgroundColor = 'orange';
circle.style.height = `${circleHeight}px`;
circle.style.width = `${circleWidth}px`;
circle.style.borderRadius = '50%'
circle.style.textAlign = 'center';
circle.style.lineHeight = `${circleHeight}px`;
circle.style.cursor = 'pointer';
circle.style.left = `${(x - (canvas.offsetLeft + canvasContainer.offsetLeft - window.scrollX)) - (circleWidth/2)}px`;
circle.style.top = `${(y -(canvas.offsetTop + canvasContainer.offsetTop - window.scrollY)) - (circleHeight/2)}px`
circle.textContent = `${count}`;
canvas.append(circle)
circleArray.push(circle)
count++
}
//Function responsible for adding circles to the canvas
//Function is invoked when design button is clicked
function begin_design(){
let mousePosition;
canvas.addEventListener('mousedown', (event)=>{
if(isDesign){
mousePosition = {
x: event.clientX,
y: event.clientY
}
create_circle_element(mousePosition.x, mousePosition.y);
}
})
}
//Function responsible for editing the circles on the canvas i.e moving them around on mousedown/mousemove event
//Function is invoked when edit button is clicked
function edit_design(){
if(isEdit){
let mouseDown = false;
let offset = [];
let circleClickedOn = [];
//Set mouseDown to false
canvas.addEventListener('mouseup', ()=>{
mouseDown = false
})
//Loop through the newly created circles and attached 'mousedown' event to each
circleArray.forEach((circleElement)=>{
circleElement.addEventListener('mousedown', (event)=>{
mouseDown = true;
offset = [
circleElement.offsetLeft - event.clientX,
circleElement.offsetTop - event.clientY
]
circleClickedOn = [circleElement]
})
})
//Move circles around
canvas.addEventListener('mousemove', (event)=>{
if(mouseDown){
let mousePosition;
mousePosition = {
x: event.clientX,
y: event.clientY
}
circleClickedOn[0].style.left = `${offset[0] + mousePosition.x}px`
circleClickedOn[0].style.top = `${offset[1] + mousePosition.y}px`
}
})
}
}
*{
margin: 0;
padding: 0;
box-sizing: border-box;
}
body{
position: relative;
width: 100%;
min-height: 100vh;
}
.sidebar{
position: fixed;
top: 0;
left: 0;
background-color: #17202A;
width: 50px;
min-height: 100vh;
}
.sidebar .sidebar-top{
position: relative;
height: 35px;
}
.sidebar .sidebar-top #toggle-btn{
position: absolute;
display: flex;
height: 35px;
width: 100%;
justify-content: center;
align-items: center;
font-size: 18px;
cursor: pointer;
color: #808B96
}
.sidebar .sidebar-center{
position: relative;
width: 100%;
margin-top: 15px;
}
.sidebar .sidebar-center ul li{
position: relative;
height: 35px;
margin-bottom: 5px;
list-style: none;
}
.sidebar .sidebar-center ul li a{
position: relative;
display: flex;
justify-content: center;
align-items: center;
height: 35px;
text-decoration: none
}
.sidebar .sidebar-center ul li a{
font-size: 18px;
color: #808B96
}
.sidebar .sidebar-center ul li a:hover{
background-color: #2e4053
}
.canvas-container{
position: absolute;
top: 0;
width: calc(100% - 50px);
min-height: 100vh;
left: 50px;
padding: 20px;
background-color: #2E4053
}
.canvas-container #canvas{
position: relative;
width: 100%;
min-height: 100vh;
}
<!DOCTYPE html>
<html lang="en" dir="ltr">
<head>
<meta charset="utf-8">
<title>testing</title>
<link rel="stylesheet" href="style.css">
<!-- Boxicons CDN Link -->
<link href='https://unpkg.com/boxicons#2.0.7/css/boxicons.min.css' rel='stylesheet'>
<meta name="viewport" content="width=device-width, initial-scale=1.0">
</head>
<body>
<div class="sidebar">
<div class="sidebar-top">
<i class='bx bx-menu' id="toggle-btn"></i>
</div>
<div class="sidebar-center">
<ul class="nav-list">
<li>
<a href="#" id="design-btn">
<i class='bx bx-pyramid'></i>
</a>
</li>
<li>
<a href="#" id="edit-btn">
<i class='bx bxs-edit-alt'></i>
</a>
</li>
</ul>
</div>
</div>
<div class="canvas-container">
<div id="canvas"></div>
<script src="script.js"></script>
</body>
</html>
Objective - When user clicks design button, the circles are added to the canvas on mousedown event. When user clicks the edit button, they are able to move the circles around. When the design button is clicked again, user is able to continue adding circles and incrementing the number from where it was left off.
Error to resolve - When design is first clicked, I am able to successfully add circles to the canvas. If I click on edit button and move the circles around and then click on design button right after, it appends two circles on on click. Why is it appending two circles? This only happens after I click on edit.
***JAVASCRIPT***
//Global variables
let count = 1;
let canvas = document.querySelector('#canvas');
let canvasContainer = document.querySelector('.canvas-container')
let designBtn = document.querySelector('#design-btn');
let editBtn = document.querySelector('#edit-btn');
let isDesign = false;
let isEdit = false;
let circleArray = [];
let offset = []
//Click event listener for design button
designBtn.addEventListener('click', (event)=>{
isDesign = true;
isEdit = false;
designBtn.style.backgroundColor = '#BA4A00'
designBtn.style.color = '#17202A'
editBtn.style.backgroundColor = null;
editBtn.style.color = null
//Invoke being_design function
begin_design()
})
//Click event listener for edit button
editBtn.addEventListener('click', (event)=>{
isDesign = false;
isEdit = true;
editBtn.style.backgroundColor = '#BA4A00'
editBtn.style.color = '#17202A'
designBtn.style.backgroundColor = null;
designBtn.style.color = null
//Invoke edit_design function
edit_design()
})
//Function creates new element and then appends it to the parent div
function create_circle_element(x, y){
let circle = document.createElement('div')
const circleHeight = 40;
const circleWidth = 40;
circle.style.position = 'absolute';
circle.style.backgroundColor = 'orange';
circle.style.height = `${circleHeight}px`;
circle.style.width = `${circleWidth}px`;
circle.style.borderRadius = '50%'
circle.style.textAlign = 'center';
circle.style.lineHeight = `${circleHeight}px`;
circle.style.cursor = 'pointer';
circle.style.left = `${(x - (canvas.offsetLeft + canvasContainer.offsetLeft - window.scrollX)) - (circleWidth/2)}px`;
circle.style.top = `${(y -(canvas.offsetTop + canvasContainer.offsetTop - window.scrollY)) - (circleHeight/2)}px`
circle.textContent = `${count}`;
canvas.append(circle)
circleArray.push(circle)
count++
}
//Function responsible for adding circles to the canvas
//Function is invoked when design button is clicked
function begin_design(){
let mousePosition;
canvas.addEventListener('mousedown', (event)=>{
if(isDesign){
mousePosition = {
x: event.clientX,
y: event.clientY
}
create_circle_element(mousePosition.x, mousePosition.y)
}
})
}
//Function responsible for editing the circles on the canvas i.e moving them around on mousedown/mousemove event
//Function is invoked when edit button is clicked
function edit_design(){
if(isEdit){
let mouseDown = false;
let offset = [];
let circleClickedOn = [];
//Set mouseDown to false
canvas.addEventListener('mouseup', ()=>{
mouseDown = false
})
//Loop through the newly created circles and attached 'mousedown' event to each
circleArray.forEach((circleElement)=>{
circleElement.addEventListener('mousedown', (event)=>{
mouseDown = true;
offset = [
circleElement.offsetLeft - event.clientX,
circleElement.offsetTop - event.clientY
]
circleClickedOn = [circleElement]
})
})
//Move circles around
canvas.addEventListener('mousemove', (event)=>{
if(mouseDown){
let mousePosition;
mousePosition = {
x: event.clientX,
y: event.clientY
}
circleClickedOn[0].style.left = `${offset[0] + mousePosition.x}px`
circleClickedOn[0].style.top = `${offset[1] + mousePosition.y}px`
}
})
}
}
***HTML***
<!DOCTYPE html>
<html lang="en" dir="ltr">
<head>
<meta charset="utf-8">
<title>Testing</title>
<link rel="stylesheet" href="style.css">
<!-- Boxicons CDN Link -->
<link href='https://unpkg.com/boxicons#2.0.7/css/boxicons.min.css' rel='stylesheet'>
<meta name="viewport" content="width=device-width, initial-scale=1.0">
</head>
<body>
<div class="sidebar">
<div class="sidebar-top">
<i class='bx bx-menu' id="toggle-btn"></i>
</div>
<div class="sidebar-center">
<ul class="nav-list">
<li>
<a href="#" id="design-btn">
<i class='bx bx-pyramid'></i>
</a>
</li>
<li>
<a href="#" id="edit-btn">
<i class='bx bxs-edit-alt'></i>
</a>
</li>
</ul>
</div>
</div>
<div class="canvas-container">
<div id="canvas"></div>
<script src="script.js"></script>
</body>
</html>
***CSS***
*{
margin: 0;
padding: 0;
box-sizing: border-box;
}
body{
position: relative;
width: 100%;
min-height: 100vh;
}
.sidebar{
position: fixed;
top: 0;
left: 0;
background-color: #17202A;
width: 50px;
min-height: 100vh;
}
.sidebar .sidebar-top{
position: relative;
height: 35px;
}
.sidebar .sidebar-top #toggle-btn{
position: absolute;
display: flex;
height: 35px;
width: 100%;
justify-content: center;
align-items: center;
font-size: 18px;
cursor: pointer;
color: #808B96
}
.sidebar .sidebar-center{
position: relative;
width: 100%;
margin-top: 15px;
}
.sidebar .sidebar-center ul li{
position: relative;
height: 35px;
margin-bottom: 5px;
list-style: none;
}
.sidebar .sidebar-center ul li a{
position: relative;
display: flex;
justify-content: center;
align-items: center;
height: 35px;
text-decoration: none
}
.sidebar .sidebar-center ul li a{
font-size: 18px;
color: #808B96
}
.sidebar .sidebar-center ul li a:hover{
background-color: #2e4053
}
.canvas-container{
position: absolute;
top: 0;
width: calc(100% - 50px);
min-height: 100vh;
left: 50px;
padding: 20px;
background-color: #2E4053
}
.canvas-container #canvas{
position: relative;
width: 100%;
min-height: 100vh;
}

The issue is you're registering the mouse-down event handler in design mode every time user switches to the design mode.
However you never unregister the mouse-down event handler upon switching to edit mode.
This results in multiple event handler to be registered for canvas click event(mouse-down).
So whenever you switch back to the design mode and click upon the canvas, it fires click handler for previously registered listener as well as the newly registered listener.
Check the updated snippet
Comment lines marked with // Solution :
//Global variables
let count = 1;
let canvas = document.querySelector('#canvas');
let canvasContainer = document.querySelector('.canvas-container');
let designBtn = document.querySelector('#design-btn');
let editBtn = document.querySelector('#edit-btn');
let isDesign = false;
let isEdit = false;
let circleArray = [];
let offset = [];
//Click event listener for design button
designBtn.addEventListener('click', (event)=>{
isDesign = true;
isEdit = false;
designBtn.style.backgroundColor = '#BA4A00'
designBtn.style.color = '#17202A'
editBtn.style.backgroundColor = null;
editBtn.style.color = null
//Invoke being_design function
begin_design()
})
//Click event listener for edit button
editBtn.addEventListener('click', (event)=>{
isDesign = false;
isEdit = true;
editBtn.style.backgroundColor = '#BA4A00'
editBtn.style.color = '#17202A'
designBtn.style.backgroundColor = null;
designBtn.style.color = null
//Invoke edit_design function
edit_design()
})
//Function creates new element and then appends it to the parent div
function create_circle_element(x, y){
let circle = document.createElement('div')
const circleHeight = 40;
const circleWidth = 40;
circle.style.position = 'absolute';
circle.style.backgroundColor = 'orange';
circle.style.height = `${circleHeight}px`;
circle.style.width = `${circleWidth}px`;
circle.style.borderRadius = '50%'
circle.style.textAlign = 'center';
circle.style.lineHeight = `${circleHeight}px`;
circle.style.cursor = 'pointer';
circle.style.left = `${(x - (canvas.offsetLeft + canvasContainer.offsetLeft - window.scrollX)) - (circleWidth/2)}px`;
circle.style.top = `${(y -(canvas.offsetTop + canvasContainer.offsetTop - window.scrollY)) - (circleHeight/2)}px`
circle.textContent = `${count}`;
canvas.append(circle)
circleArray.push(circle)
count++
}
// Solution : Define a click handler
var designClickHandler = (event)=>{
if(isDesign){
mousePosition = {
x: event.clientX,
y: event.clientY
}
create_circle_element(mousePosition.x, mousePosition.y);
}
}
//Function responsible for adding circles to the canvas
//Function is invoked when design button is clicked
function begin_design(){
let mousePosition;
// Solution : Register click handler
canvas.addEventListener('mousedown', designClickHandler)
}
//Function responsible for editing the circles on the canvas i.e moving them around on mousedown/mousemove event
//Function is invoked when edit button is clicked
function edit_design(){
if(isEdit){
// Solution : unregister click handler
canvas.removeEventListener('mousedown', designClickHandler)
let mouseDown = false;
let offset = [];
let circleClickedOn = [];
//Set mouseDown to false
canvas.addEventListener('mouseup', ()=>{
mouseDown = false
})
//Loop through the newly created circles and attached 'mousedown' event to each
circleArray.forEach((circleElement)=>{
circleElement.addEventListener('mousedown', (event)=>{
mouseDown = true;
offset = [
circleElement.offsetLeft - event.clientX,
circleElement.offsetTop - event.clientY
]
circleClickedOn = [circleElement]
})
})
//Move circles around
canvas.addEventListener('mousemove', (event)=>{
if(mouseDown){
let mousePosition;
mousePosition = {
x: event.clientX,
y: event.clientY
}
circleClickedOn[0].style.left = `${offset[0] + mousePosition.x}px`
circleClickedOn[0].style.top = `${offset[1] + mousePosition.y}px`
}
})
}
}
*{
margin: 0;
padding: 0;
box-sizing: border-box;
}
body{
position: relative;
width: 100%;
min-height: 100vh;
user-select: none;
}
.sidebar{
position: fixed;
top: 0;
left: 0;
background-color: #17202A;
width: 50px;
min-height: 100vh;
}
.sidebar .sidebar-top{
position: relative;
height: 35px;
}
.sidebar .sidebar-top #toggle-btn{
position: absolute;
display: flex;
height: 35px;
width: 100%;
justify-content: center;
align-items: center;
font-size: 18px;
cursor: pointer;
color: #808B96
}
.sidebar .sidebar-center{
position: relative;
width: 100%;
margin-top: 15px;
}
.sidebar .sidebar-center ul li{
position: relative;
height: 35px;
margin-bottom: 5px;
list-style: none;
}
.sidebar .sidebar-center ul li a{
position: relative;
display: flex;
justify-content: center;
align-items: center;
height: 35px;
text-decoration: none
}
.sidebar .sidebar-center ul li a{
font-size: 18px;
color: #808B96
}
.sidebar .sidebar-center ul li a:hover{
background-color: #2e4053
}
.canvas-container{
position: absolute;
top: 0;
width: calc(100% - 50px);
min-height: 100vh;
left: 50px;
padding: 20px;
background-color: #2E4053
}
.canvas-container #canvas{
position: relative;
width: 100%;
min-height: 100vh;
}
<!DOCTYPE html>
<html lang="en" dir="ltr">
<head>
<meta charset="utf-8">
<title>hiveport</title>
<link rel="stylesheet" href="style.css">
<!-- Boxicons CDN Link -->
<link href='https://unpkg.com/boxicons#2.0.7/css/boxicons.min.css' rel='stylesheet'>
<meta name="viewport" content="width=device-width, initial-scale=1.0">
</head>
<body>
<div class="sidebar">
<div class="sidebar-top">
<i class='bx bx-menu' id="toggle-btn"></i>
</div>
<div class="sidebar-center">
<ul class="nav-list">
<li>
<a href="#" id="design-btn">
<i class='bx bx-pyramid'></i>
</a>
</li>
<li>
<a href="#" id="edit-btn">
<i class='bx bxs-edit-alt'></i>
</a>
</li>
</ul>
</div>
</div>
<div class="canvas-container">
<div id="canvas"></div>
<script src="script.js"></script>
</body>
</html>

Related

how to make a carousel(sliding) stop when the mouse pointer hovers over on the images

How to make carousel (slider) stop when the mouse pointer has hovered over on the image in GSAP?
I made a huge try in many ways on the internet but nothing suit for my code.
// wrapping the code with onload to execute JS immediately
window.onload = function() {
//variables for slide animation time
var slideDelay = 1.2; //the slides flow in every 1.5 seconds
var slideDuration = 0.2;
var slides = document.querySelectorAll(".slide");
var prevButton = document.querySelector("#prevButton");
var nextButton = document.querySelector("#nextButton");
var numSlides = slides.length;
//infinite slide rotation
for (var i = 0; i < numSlides; i++) {
TweenLite.set(slides[i], {
xPercent: i * 100
});
}
// auto animation (the timer can be added to auto animate after a certain idle-time)
var wrap = wrapPartial(-100, (numSlides - 1) * 100);
var timer = TweenLite.delayedCall(3, autoPlay);
var animation = TweenMax.to(slides, 1, {
xPercent: "+=" + (numSlides * 100),
ease: Linear.easeNone,
paused: true,
repeat: -1,
modifiers: {
xPercent: wrap
}
});
var proxy = document.createElement("div");
TweenLite.set(proxy, { x: "+=0" });
var transform = proxy._gsTransform;
var slideAnimation = TweenLite.to({}, 0.1, {});
var slideWidth = 0;
var wrapWidth = 0;
resize();
window.addEventListener("resize", resize);
// navigation with buttons
prevButton.addEventListener("click", function() {
animateSlides(1);
});
nextButton.addEventListener("click", function() {
animateSlides(-1);
});
function animateSlides(direction) {
timer.restart(true);
slideAnimation.kill();
var x = snapX(transform.x + direction * slideWidth);
slideAnimation = TweenLite.to(proxy, slideDuration, {
x: x,
onUpdate: updateProgress
});
}
// auto-play function for auto animation
function autoPlay() {
animateSlides(-1);
}
function updateProgress() {
animation.progress(transform.x / wrapWidth);
}
function snapX(x) {
return Math.round(x / slideWidth) * slideWidth;
}
//calculating the necessary width for slide animation
function resize() {
var norm = (transform.x / wrapWidth) || 0;
slideWidth = slides[0].offsetWidth;
wrapWidth = slideWidth * numSlides;
TweenLite.set(proxy, {
x: norm * wrapWidth
});
animateSlides(0);
slideAnimation.progress(1);
}
//returns the difference between the passed function's max and min value
function wrapPartial(min, max) {
var diff = max - min;
return function(value) {
var v = value - min;
return ((diff + v % diff) % diff) + min;
}
}
}
* {
box-sizing: border-box;
}
/* the main wrapper box */
main {
display: flex;
position: relative;
flex-direction: column;
width: 300px;
height: 250px;
overflow: hidden;
border: 3px solid #000000;
}
/* the header and navigations */
.controls {
padding: 10px;
display: flex;
align-items: center;
justify-content: space-between;
height: 60px;
min-height: 60px;
border-bottom: 2px solid #000000;
}
.controls button {
width: 30px;
height: 30px;
border-radius: 50%;
border: none;
outline: none;
background-repeat: no-repeat;
background-size: 70%;
cursor: pointer;
background-color: #000;
background-position: center center;
}
.slides-container {
border-top: 2px solid ;
position: relative;
overflow: hidden;
display: flex;
flex: 1;
}
.slide {
position: absolute;
font-size: 90px;
font-weight: 700;
color: rgba(255,255,255,0.9);
display: flex;
align-items: center;
justify-content: center;
height: 100%;
width: 100%;
background-size: cover;
background-repeat: no-repeat;
}
.slides-inner {
position: relative;
height: 100%;
width: 100%;
overflow: hidden;
}
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<link rel="stylesheet" type="text/css" href="style.css">
<title>Varshath Gupta Solution</title>
<script src="https://cdnjs.cloudflare.com/ajax/libs/gsap/1.20.2/TweenMax.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/gsap/1.20.2/plugins/ModifiersPlugin.min.js"></script>
<script type="text/javascript" src="./script.js">
</script>
</head>
<body>
<!-- Main wrapper div for the header and slider components. -->
<div class="wrapper">
<main>
<!-- the header that includes the navigation buttons and the logo -->
<div class="controls">
<button id="prevButton" style="background-image: url(https://drive.google.com/uc?export=view&id=1o6S3UjO-DQFLXAGShYeN4bQXoI0yuxP0);"></button>
<div class="logo"><img width="80" src="https://logos.textgiraffe.com/logos/logo-name/Cartoon-designstyle-cartoon-m.png"/></div>
<button id="nextButton" style="background-image: url( https://drive.google.com/uc?export=view&id=1aptD-5krbPTtFRjZk_b2O8Ikx2x0F2TC);"></button>
</div>
<!-- the slider -->
<div class="slides-container">
<div class="slides-inner">
</div>
</div>
</div>
<div class="slide" style="background-image: url( https://drive.google.com/uc?export=view&id=1ngTIZMgHFHTSQO9vinuB666ruA3l-Vgq)"></div>
</div>
</div>
</div>
</main>
</div>
</body>
</html>

DOM Element Not Rendering on Page Until After JS Transition Completion

The title says it all. To see the issue, copy this code to the following online compiler: https://www.w3schools.com/php/phptryit.asp?filename=tryphp_compiler
<!DOCTYPE HTML>
<html>
<style>
/*MAIN*/
* {
margin: 0;
padding: 0;
user-select: none;
overflow: hidden;
}
body {
background-color: #FF0000;
margin: 0;
padding: 0;
}
/*ELEMENTS*/
div {
width: 100vw;
height: 100vh;
float: left;
margin-left: 0vw;
}
h1 {
font-family: verdana;
font-size: 5vh;
text-transform: uppercase;
}
h1.white {
color: #F4F4F4;
}
</style>
<body>
<div id = "main" style = "width: auto; margin-left: 0vw;">
<div id = "home" class = "container" style = 'background-color: #000000;'>
<h1 class = "white">click arrow to see how the next page doesn't appear until after the transition is complete</h1>
<!--ARROW BUTTON-->
<p id = 'arrowButton' style = 'color: #FFFFFF; position: absolute; height: 10vh; width: auto; margin: 45vh 0 0 75vw; font-size: 3vh;' onMouseDown = 'NextButtonClick();'>--></p>
</div>
<div id = "welcome" class = "container" style = 'background-color: #FFFFFF;'>
<h1 style = 'margin: 47.5vh 0 0 50vw'>welcome to my portfolio</h1>
</div>
</div>
<script>
var mainDiv, welcomeDiv;
var transitionSeconds = 0.5;
var isTransitioning = false;
function NextButtonClick() {
if(!isTransitioning) {
isTransitioning = true;
i = 0;
thisInterval = setInterval(function() {
mainDiv.style.marginLeft = (100 / i) - 101 + "vw";
i++;
if(i == 100) {
clearInterval(thisInterval);
mainDiv.style.marginLeft = "-100vw";
isTransitioning = false;
}
}, transitionSeconds);
}
}
window.onload = function() {
mainDiv = document.getElementById("main");
welcomeDiv = document.getElementById("welcome");
var arrowButton = document.getElementById("arrowButton");
var arrowButtonX, arrowButtonY;
var arrowButtonGlowDistance = 100;
arrowButtonX = arrowButton.getBoundingClientRect().left + arrowButton.getBoundingClientRect().width/2;//center
arrowButtonY = arrowButton.getBoundingClientRect().top + arrowButton.getBoundingClientRect().height/2;//center
document.onmousemove = function(e) {
x = e.clientX; y = e.clientY;
};
};
</script>
</body>
</html>
The background is red on purpose so that you can see how, even though the "welcome" div should be rendered over top the background, it is not being rendered until the very last second after the transition is completed and 100% of the element is on the screen.
I am stumped, and I'm not sure why this is since HTML usually doesn't seem to behave this way. Even when I highlight the element in Inspect Element, the Inspector doesn't show me where the element is on the screen until the final moment when it is rendered.
Any help would be greatly appreciated, and I look forward to hearing your feedback!
The problem here is that your DIVs are placed under each other and while one is moving horizontally, the next div is still underneath of it until first one is completely out of the way (just like Jenga game in reverse).
To solve this, you can try add display: flex, to place them horizontally instead:
var mainDiv, welcomeDiv;
var transitionSeconds = 0.5;
var isTransitioning = false;
function NextButtonClick() {
if (!isTransitioning) {
isTransitioning = true;
i = 0;
thisInterval = setInterval(function() {
mainDiv.style.marginLeft = (100 / i) - 101 + "vw";
i++;
if (i == 100) {
clearInterval(thisInterval);
mainDiv.style.marginLeft = "-100vw";
isTransitioning = false;
}
}, transitionSeconds);
}
}
window.onload = function() {
mainDiv = document.getElementById("main");
welcomeDiv = document.getElementById("welcome");
var arrowButton = document.getElementById("arrowButton");
var arrowButtonX, arrowButtonY;
var arrowButtonGlowDistance = 100;
arrowButtonX = arrowButton.getBoundingClientRect().left + arrowButton.getBoundingClientRect().width / 2; //center
arrowButtonY = arrowButton.getBoundingClientRect().top + arrowButton.getBoundingClientRect().height / 2; //center
document.onmousemove = function(e) {
x = e.clientX;
y = e.clientY;
};
};
* {
margin: 0;
padding: 0;
user-select: none;
overflow: hidden;
}
body {
background-color: #FF0000;
margin: 0;
padding: 0;
}
/*ELEMENTS*/
div {
width: 100vw;
height: 100vh;
float: left;
margin-left: 0vw;
display: flex; /* added */
}
h1 {
font-family: verdana;
font-size: 5vh;
text-transform: uppercase;
}
h1.white {
color: #F4F4F4;
}
<div id="main" style="width: auto; margin-left: 0vw;">
<div id="home" class="container" style='background-color: #000000;'>
<h1 class="white">click arrow to see how the next page doesn't appear until after the transition is complete</h1>
<!--ARROW BUTTON-->
<p id='arrowButton' style='color: #FFFFFF; position: absolute; height: 10vh; width: auto; margin: 45vh 0 0 75vw; font-size: 3vh;' onMouseDown='NextButtonClick();'>--></p>
</div>
<div id="welcome" class="container" style='background-color: #FFFFFF;'>
<h1 style='margin: 47.5vh 0 0 50vw'>welcome to my portfolio</h1>
</div>
</div>

Building a custom volume slider

I've found this and tried to fix it as the logic behind it is similar to what I'm trying to achieve. I've manage to get it working with minimal editing. but it isn't working as expected.
note: I have commented out the click feature as it is working fine.
What is happening
If you click on the volumeBtn and accidentally move the cursor out of the volumeRange div height or width while sliding either left or right, the mouseup event listener doesn't get executed when you stop clicking the mouse.
Like 1, after clicking the volumeBtn you cannot drag the volumeBtn left or right once it goes outside the `volumeRange' div.
There is a flicker from the zeroth position to the desired position.
What I Want to happen
If you click on the volumeBtn then stop clicking the mouse, the mouseup event should be executed even if the cursor is no longer on the volumeRange.
If you click on the volumeBtn you should be able to drag the volumeBtn left or right even if the cursor is no longer on the volumeRange.
const volume = document.querySelector('.volume');
const volumeRange = document.querySelector('.volume-range');
const volumeBtn = document.querySelector('.volume-button');
// volumeRange.addEventListener("click", volumeClick );
// function volumeClick(event) {
// let x = event.offsetX;
// volume.style.width = (Math.floor(x) + 10) + 'px';
// }
let mouseIsDown = false;
volumeBtn.addEventListener("mouseup", up);
volumeBtn.addEventListener("mousedown", down);
volumeRange.addEventListener("mousemove", volumeSlide);
function down(){ mouseIsDown = true; }
function up(){ mouseIsDown = false; }
function volumeSlide(event) {
if (mouseIsDown) {
let x = event.offsetX;
console.log(x);
volume.style.width = Math.floor(x + 10) + 'px';
}
}
body {
background-color: #2a2a2a;
}
.volume-range {
margin-top: 80px;
height: 5px;
width: 250px;
background: #555;
border-radius: 15px;
}
.volume-range>.volume {
height: 5px;
width: 50px;
background: #2ecc71;
border: none;
border-radius: 10px;
outline: none;
position: relative;
}
.volume-range>.volume>.volume-button {
width: 20px;
height: 20px;
border-radius: 20px;
background: #FFF;
position: absolute;
right: 0;
top: 50%;
transform: translateY(-50%);
cursor: pointer;
outline: none;
}
<!DOCTYPE html>
<html lang="en" dir="ltr">
<head>
<meta charset="utf-8">
<title>Volume</title <link rel="stylesheet" href="https://use.fontawesome.com/releases/v5.6.3/css/all.css" integrity="sha384-UHRtZLI+pbxtHCWp1t77Bi1L4ZtiqrqD80Kn4Z8NTSRyMA2Fd33n5dQ8lWUE00s/" crossorigin="anonymous">
</head>
<style>
</style>
<body>
<div class="volume-range">
<div class="volume">
<div class="volume-button"></div>
</div>
</div>
</body>
</html>
Why it doesn't work
This is working the way you described it because mouse events will only be fired when the mouse is inside the element that have the listeners attached.
An immediate (but not very good) solution to this will be to move the listener for "mouseup" and "mousemove" from the volumeBtn/volumeRange to the window object. This is not very good because if you will later need to remove this element, you should also remove the listeners from the window object.
Better solution
It would be better to encapsulate the slider inside another element that will give it some padding, and then put the event listeners on that "container" element. It will still stop moving when you go outside the element, but at least everything is self-contained.
This is shown in the following snippet:
const volume = document.querySelector('.volume');
const volumeRange = document.querySelector('.volume-range');
const volumeContainer = document.querySelector('.volume-container');
const volumeBtn = document.querySelector('.volume-button');
// volumeRange.addEventListener("click", volumeClick );
// function volumeClick(event) {
// let x = event.offsetX;
// volume.style.width = (Math.floor(x) + 10) + 'px';
// }
let mouseIsDown = false;
volumeContainer.addEventListener("mouseup", up);
volumeBtn.addEventListener("mousedown", down);
volumeContainer.addEventListener("mousemove", volumeSlide, true);
function down(){ mouseIsDown = true; }
function up(){ mouseIsDown = false; }
const volumeRangeWidth = volumeRange.getBoundingClientRect().width; // This will be the volume limit (100%)
function volumeSlide(event) {
if (mouseIsDown) {
let x = event.offsetX;
if (event.target.className == "volume-container") {
x = Math.floor(x);
if (x < 0) x = 0; // check if it's too low
if (x > volumeRangeWidth) x = volumeRangeWidth; // check if it's too high
volume.style.width = (x+10) + 'px';
}
}
}
body {
background-color: #2a2a2a;
}
.volume-container {
padding: 40px 0px;
margin: 0px 20px;
}
.volume-range {
height: 5px;
width: 250px;
background: #555;
border-radius: 15px;
}
.volume-range>.volume {
height: 5px;
width: 50px;
background: #2ecc71;
border: none;
border-radius: 10px;
outline: none;
position: relative;
}
.volume-range>.volume>.volume-button {
width: 20px;
height: 20px;
border-radius: 20px;
background: #FFF;
position: absolute;
right: 0;
top: 50%;
transform: translateY(-50%);
cursor: pointer;
outline: none;
}
<!DOCTYPE html>
<html lang="en" dir="ltr">
<head>
<meta charset="utf-8">
<title>Volume</title>
<link rel="stylesheet" href="https://use.fontawesome.com/releases/v5.6.3/css/all.css" integrity="sha384-UHRtZLI+pbxtHCWp1t77Bi1L4ZtiqrqD80Kn4Z8NTSRyMA2Fd33n5dQ8lWUE00s/" crossorigin="anonymous">
</head>
<style>
</style>
<body>
<div class="volume-container">
<div class="volume-range">
<div class="volume">
<div class="volume-button"></div>
</div>
</div>
</div>
</body>
</html>
Other problems
In the fiddle it is also shown how to avoid the volume to go outside the container.

Activating the "onmousemove" event only when the "onmousedown" event is activated

After discovering the difficulties of styling inputs of type range, I though it best to simply create one using css and hiding the original. I'm trying to Make a volume slider, but I don't think I fully understand how to connect onmousemove and onmousedown. I tried following the following post
How to connect onmousemove with onmousedown?
but my volumeSlider function - the javascript code that is commented out - still isn't working;
What I want is that onmousemove is only activated on onmousedown and not by simply moving the mouse.
const volume_div = document.querySelector('.volume');
const volumeBtn_div = document.querySelector('.volume-button');
function volumeClick(event) {
let x = event.offsetX;
volume_div.style.width = (Math.floor(x) + 10) + 'px';
}
/*
volumeBtn_div.onmousedown = function() {
volumeBtn_div.onmousemove = volumeSlide;
};
function volumeSlide(event) {
let x = event.offsetX;
volume_div.style.width = Math.floor(x) + 'px';
}*/
body {
background-color: #2a2a2a;
}
.volume-range {
margin-top: 80px;
height: 5px;
width: 250px;
background: #555;
border-radius: 15px;
}
.volume-range>.volume {
height: 5px;
width: 50px;
background: #2ecc71;
border: none;
border-radius: 10px;
outline: none;
position: relative;
}
.volume-range>.volume>.volume-button {
width: 20px;
height: 20px;
border-radius: 20px;
background: #FFF;
position: absolute;
right: 0;
top: 50%;
transform: translateY(-50%);
cursor: pointer;
outline: none;
}
<!DOCTYPE html>
<html lang="en" dir="ltr">
<head>
<meta charset="utf-8">
<title>Volume</title <link rel="stylesheet" href="https://use.fontawesome.com/releases/v5.6.3/css/all.css" integrity="sha384-UHRtZLI+pbxtHCWp1t77Bi1L4ZtiqrqD80Kn4Z8NTSRyMA2Fd33n5dQ8lWUE00s/" crossorigin="anonymous">
</head>
<body>
<div class="volume-range" onclick="volumeClick(event)">
<div class="volume">
<div class="volume-button"></div>
</div>
</div>
If I understand your question correctly, I think you could just set a flag onmousedown and reset it onmouseup. Something like:
let mouseIsDown = false;
volumeBtn_div.onmousedown = function() { mouseIsDown = true };
volumeBtn_div.onmouseup = function() { mouseIsDown = false };
volumeBtn_div.onmousemove = volumeSlide;
function volumeSlide(event) {
if(mouseIsDown){
let x = event.offsetX;
volume_div.style.width = Math.floor(x) + 'px';
}
}
...
In response to your comment, this similar example works in Chrome. I changed the EventListener syntax. It should get you on the right track.
<!DOCTYPE html>
<html>
<head>
<style>
div { width: 200px; height: 100px; border: 1px solid black; }
</style>
</head>
<body>
<div id="input"></div>
<p id="output"></p>
<script>
const input = document.getElementById("input");
const output = document.getElementById("output");
let mouseIsDown = false;
input.addEventListener("mouseup", up);
input.addEventListener("mousedown", down);
input.addEventListener("mousemove", slide);
function down(){ mouseIsDown = true; }
function up(){ mouseIsDown = false; }
function slide(e) {
if(mouseIsDown){
var x = e.clientX;
var pos = "pos: " + x;
output.innerHTML = pos;
}
}
</script>
</body>
</html>

How to Create Image-Video Thumbnail Slider With Previous and Next Button dynamically using Javascript only?

I want to make Thumbnail Image-Video Slider dynamic using javascript only, here i created a container in which i added some images through javascript, but now i want to slide this images with Next and Previous Buttons and also on swipe mouse slider should slide.
This is the Latest Code whatever i did now i am getting problem in NEXT & PREVIOUS Buttons. i want onclick of NEXT & PREVIOUS image slider should slide Backward and Forward
This is the Output what i am getting from this code
and images should come in only one Row
Please Help me !!
$(document).ready(function ()
{
function PhotoGallery()
{
this.index = 0;
this.holder = [];
var container = document.getElementById('thumbs_container');
var nextButton = document.createElement('button');
nextButton.className = 'next';
nextButton.innerHTML = '❯';
container.appendChild(nextButton);
var prevButton = document.createElement('button');
prevButton.className = 'previous';
prevButton.innerHTML = '❮';
container.appendChild(prevButton);
container = $(window).width();
nextButton.addEventListener('click', this.next);
prevButton.addEventListener('click', this.previous);
this.create = function (name, src) {
var container = document.getElementById('thumbs_container');
var img = document.createElement('img');
img.src = src;
img.alt = name;
img.className = 'thumb';
img.style.width = '300px';
img.style.height = '150px;';
container.appendChild(img);
this.holder.push({
index: ++this.index,
ele: img
})
}
this.next = function () {
this.holder[this.index].ele.style.display = 'none';
this.holder[++this.index].ele.style.display = block;
}
this.previous = function () {
this.holder[this.index].ele.style.display = 'none';
this.holder[--this.index].ele.style.display = 'block';
}
}
var photoGallery = new PhotoGallery();
photoGallery.create('1', 'img/1.jpg');
photoGallery.create('2', 'img/2.jpg');
photoGallery.create('3', 'img/3.jpg');
photoGallery.create('4', 'img/4.jpg');
photoGallery.create('5', 'img/5.jpg');
photoGallery.create('6', 'img/6.jpg');
photoGallery.create('7', 'img/7.jpg');
photoGallery.create('8', 'img/8.jpg');
photoGallery.create('9', 'img/9.jpg');
photoGallery.create('10','img/10.jpg');
#thumbs_container {
margin: 400px auto; /*center-aligned*/
width: 100%; /*width:400px;*/
padding: 4px 40px; /*Gives room for arrow buttons*/
box-sizing: border-box;
position: relative;
background-color: red;
-webkit-user-select: none;
user-select: none;
/*max-width: 1600px;
max-height: 600px;*/
overflow:hidden;
}
.thumb{
margin-right: 1px;
}
.previous {
background-color: #4CAF50;
border: none;
color: white;
padding: 10px 10px;
text-align: center;
text-decoration: none;
display: inline-block;
font-size: 16px;
cursor: pointer;
position: absolute;
margin-left: -33px;
margin-top: 63px;
}
.next {
background-color: #4CAF50;
border: none;
color: white;
padding: 10px 10px;
text-align: center;
text-decoration: none;
display: inline-block;
font-size: 16px;
cursor: pointer;
position: absolute;
margin-left: 1822px;
margin-top: 63px;
}
<div id='thumbs_container'></div>
This is not a comprehensive answer but it should point you in the right direction.
(function() {
function PhotoGallery() {
this.index = 0;
this.holder = [];
this.setIndexVisible = true;
// When next funtion is called swap the display properties accordingly
this.next = function() {
console.log(this.index);
this.holder[this.index].ele.style.display = 'none';
this.holder[this.index+1].ele.style.display = 'block';
this.index+=1;
}
// Ditto as above according the requirement
this.previous = function() {
this.holder[this.index].ele.style.display = 'none';
this.holder[this.index-1].ele.style.display = 'block';
this.index-=1;
}
//create a button each for previous and next
var container = document.getElementById('thumbs_container');
let nextButton = document.createElement('button');
nextButton.className="next";
nextButton.id = "next";
container.appendChild(nextButton);
//style the button
// Listen to the click event and call the corresponsing function
nextButton.addEventListener('click', this.next.bind(this));
this.create = function(name, src) {
var container = document.getElementById('thumbs_container');
var img = document.createElement('img');
img.src = src;
img.alt = name;
img.className = 'thumb';
img.style.width = '200px';
if(this.setIndexVisible && this.index===0)
img.style.display = 'block';
else
img.style.display = 'none';
container.appendChild(img);
this.holder.push({
index: this.holder.length,
ele: img
})
}
}
var photoGallery = new PhotoGallery();
photoGallery.create('RED SQUARE', 'https://upload.wikimedia.org/wikipedia/commons/thumb/2/25/Red.svg/2000px-Red.svg.png');
photoGallery.create('BLUE SQUARE', 'https://upload.wikimedia.org/wikipedia/commons/thumb/f/fd/000080_Navy_Blue_Square.svg/600px-000080_Navy_Blue_Square.svg.png')
})();
UPDATE : Please try and understand the code and modify it to fulfill your requirements. You might have to update the next and previous functions and also some of the logic to make it a]usable. This is just a blueprint of how to do it.
Here is a jsbin link : https://jsbin.com/ginuvonusi/edit?html,css,js,console,output
var leftFrom = 10;
var scrollPosition = 0;
var scrollOffSet = 400;
$(document).ready(function () {
function PhotoGallery() {
$('#thumbs_container').css('width', '100%');
$('#thumbs_container').css('position', 'absolute');
$('#thumbs_container').css('overflow-y', 'hidden');
//$('#thumbs_container').css('left', '1.9%')
$('#thumbs_container').css('float', 'left');
$('#thumbs_container').css('height', '215px')
var container = document.getElementById('thumbs_container');
var nextButton = document.createElement('button');
nextButton.className = 'next';
nextButton.innerHTML = '❯';
container.appendChild(nextButton);
var next = function () {
console.log("Next Clicked" + " " + $('#thumbs_container').width());
if ((scrollPosition + scrollOffSet) < $('#thumbs_container').width()) {
scrollPosition = scrollPosition + scrollOffSet;
$('#thumbs_container').animate({ scrollLeft: scrollPosition }, 750);
}
else {
if ((scrollPosition + scrollOffSet) > $('#thumbs_container').width())
scrollPosition = scrollPosition + scrollOffSet;
$('#thumbs_container').animate({ scrollLeft: scrollPosition }, 750);
}
}
var prevButton = document.createElement('button');
prevButton.className = 'previous';
prevButton.innerHTML = '❮';
container.appendChild(prevButton);
var previous = function ()
{
console.log('Clicked Left');
var leftOffSet = $('#thumbs_container').scrollLeft();
console.log("leftOffset" + " " + leftOffSet);
if ((leftOffSet - scrollOffSet) > 0) {
scrollPosition = scrollPosition - scrollOffSet;
$('#thumbs_container').animate({ scrollLeft: scrollPosition }, 750);
} else {
if (leftOffSet > 0)
$('#thumbs_container').animate({ scrollLeft: 0 }, 750);
}
}
this.imagecreate = function (name, src) {
var container = document.getElementById('thumbs_container');
var img = document.createElement('img');
img.src = src;
img.alt = name;
img.className = 'thumb';
img.style.width = '300px';
img.style.height = '150px';
img.style.position = 'absolute';
img.style.left = leftFrom + 'px';
leftFrom = leftFrom + 310;
container.appendChild(img);
}
this.videocreate = function (src, type) {
var container = document.getElementById('thumbs_container');
var video = document.createElement('video');
var source = document.createElement('source');
source.src = src;
source.type = type;
video.autoplay = true;
video.loop = true;
video.controls = false;
video.style.display = 'inline-block';
video.style.width = '260px';
video.style.height = '260px';
video.style.position = 'absolute';
video.style.top = '-41px';
video.style.left = leftFrom + 'px';
leftFrom = leftFrom + 270;
video.appendChild(source);
container.appendChild(video);
}
nextButton.addEventListener('click', next);
prevButton.addEventListener('click', previous);
}
var photoGallery = new PhotoGallery();
photoGallery.imagecreate('1', 'img/1.jpg');
photoGallery.imagecreate('2', 'img/2.jpg');
photoGallery.imagecreate('3', 'img/3.jpg');
photoGallery.imagecreate('4', 'img/4.jpg');
photoGallery.videocreate('img/mcvideo.mp4', 'video/mp4');
photoGallery.imagecreate('5', 'img/5.jpg');
photoGallery.imagecreate('6', 'img/6.jpg');
photoGallery.imagecreate('7', 'img/7.jpg');
photoGallery.imagecreate('8', 'img/8.jpg');
photoGallery.videocreate('img/SampleVideo_640x360_1mb.mp4', 'video/mp4');
photoGallery.imagecreate('9', 'img/9.jpg');
photoGallery.imagecreate('10', 'img/10.jpg');
photoGallery.imagecreate('11', 'img/006.jpg');
photoGallery.videocreate('img/small.mp4', 'video/mp4');
photoGallery.imagecreate('12', 'img/007.jpg');
});
#thumbs_container {
width: 100%; /*width:400px;*/
padding: 14px 40px; /*Gives room for arrow buttons*/
box-sizing: border-box;
position: relative;
background-color: red;
-webkit-user-select: none;
user-select: none;
/*max-width: 1600px;
max-height: 600px;*/
overflow:hidden;
}
.thumb{
margin-right: 1px;
}
button{position: fixed;
top: 40%;
z-index: 99999;
left: 50%;
background-color: #4CAF50;
color: #fff;
border: none;
height: 30px;
width: 30px;
line-height: 30px;}
.previous {
background-color: #4CAF50;
border: none;
color: white;
text-align: center;
text-decoration: none;
display: inline-block;
font-size: 16px;
cursor: pointer;
position: fixed;
margin-left: -33px;
top: 7%;
left: 2%;
}
.next {
background-color: #4CAF50;
border: none;
color: white;
padding: 2px 10px;
text-align: center;
text-decoration: none;
display: inline-block;
font-size: 16px;
cursor: pointer;
position: fixed;
left: 98%;
top: 7%;
}
.round {
border-radius: 50%;
}
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<title>DynamicSlider</title>
<!--<link href="css/thumbs2.css" rel="stylesheet" />
<link href="css/thumbnail-slider.css" rel="stylesheet" />
<script src="js/thumbnail-slider.js" type="text/javascript"></script>
<script src="js/readImages.js"></script>-->
<!--<script src="http://ajax.googleapis.com/ajax/libs/jquery/1.7.1/jquery.min.js" type="text/javascript"></script>-->
<script src="js/jquery1.6.2.js"></script>
<script src="js/jquery-1.7.1.min.js"></script>
<link href="css/DynamicSlider.css" rel="stylesheet" />
<script src="js/DynamicSlider.js"></script>
</head>
<body>
<div id='thumbs_container'>
</div>
</body>
</html>

Categories