I have this HTML code in which I want to display two images in parallel. It should work like a change slider image with scroll option:
The problem is that I can't scroll down into the div with class .image-comparison-slider.
#image-comparison-slider {
margin: auto;
position: relative;
width: var(--image-comparison-slider-width);
overflow: auto;
border-radius: 0.5rem;
box-shadow: -7px 5px 16px 1px rgba(56, 86, 122, 0.6);
cursor: col-resize;
}
#image-comparison-slider img {
display: block;
width: var(--image-comparison-slider-width);
height: auto;
max-height: 80vh;
object-fit: cover;
pointer-events: none;
user-select: none;
}
<div id="image-comparison-slider">
<img class="overflow-auto" width="100%" src="../../static/img/screenshot.png" alt="before">
<div class="img-wrapper">
<img width="100%" alt="after" src="../../static/img/screenshot1.png" />
</div>
<span class="label label-before">Before</span>
<span class="label label-after">After</span>
<div class="handle">
<div class="handle-line"></div>
<div class="handle-circle">
<i class="fas fa-chevron-left"></i>
<i class="fas fa-chevron-right"></i>
</div>
<div class="handle-line"></div>
</div>
</div>
The js code related to the problem is here :
const slider = document.querySelector("#image-comparison-slider");
const sliderImgWrapper = document.querySelector("#image-comparison-slider .img-wrapper");
const sliderHandle = document.querySelector("#image-comparison-slider .handle");
slider.addEventListener("mousemove", sliderMouseMove);
slider.addEventListener("touchmove", sliderMouseMove);
function sliderMouseMove(event) {
if(isSliderLocked) return;
const sliderLeftX = slider.offsetLeft;
const sliderWidth = slider.clientWidth;
const sliderHandleWidth = sliderHandle.clientWidth;
let mouseX = (event.clientX || event.touches[0].clientX) - sliderLeftX;
if(mouseX < 0) mouseX = 0;
else if(mouseX > sliderWidth) mouseX = sliderWidth;
sliderImgWrapper.style.width = `${((1 - mouseX/sliderWidth) * 100).toFixed(4)}%`;
sliderHandle.style.left = `calc(${((mouseX/sliderWidth) * 100).toFixed(4)}% - ${sliderHandleWidth/2}px)`;
}
let isSliderLocked = false;
slider.addEventListener("mousedown", sliderMouseDown);
slider.addEventListener("touchstart", sliderMouseDown);
slider.addEventListener("mouseup", sliderMouseUp);
slider.addEventListener("touchend", sliderMouseUp);
slider.addEventListener("mouseleave", sliderMouseLeave);
function sliderMouseDown(event) {
if(isSliderLocked) isSliderLocked = false;
sliderMouseMove(event);
}
function sliderMouseUp() {
if(!isSliderLocked) isSliderLocked = true;
}
function sliderMouseLeave() {
if(isSliderLocked) isSliderLocked = false;
}
Here are some functions that helps me to move the slider above the images to be able to see the differences between them.
It works properly but I need to scroll in the parent div and I can't do that.
Related
I created class based functions in my project. Scroll class is to create smooth scroll behaviour using translateY property. The second one called SideNavigation generate bullet list navigation based on projects elements length. I want to achive smooth scroll effect also on click on those bullets, but can't find solution for this. Code snippet included. Hope anyone can help with this.
const config = {
ease: 0.1,
current: 0,
previous: 0,
rounded: 0
}
class Scroll {
constructor(velocity) {
this.velocity = velocity
}
setBodyHeight() {
document.body.style.height = document.getElementById('projects').getBoundingClientRect().height + 'px'
}
isMobile() {
return 'ontouchstart' in document.documentElement && navigator.userAgent.match(/Mobi/)
}
onScroll() {
config.current = window.scrollY
config.previous += (config.current - config.previous) * config.ease
config.rounded = Math.round(config.previous * 100) / 100
const difference = config.current - config.rounded
const acceleration = difference / document.body.clientWidth
const velocity = +acceleration
const skew = velocity * this.velocity
const element = document.getElementById('projects')
this.isMobile() ? element.style.transform = `skewY(${skew}deg)` : element.style.transform = `translateY(-${config.rounded}px)`
requestAnimationFrame(() => this.onScroll())
}
}
class SideNavigation {
constructor() {
createBullets()
}
}
function createBullets() {
const bulletWrapper = document.createElement('div')
const bulletList = document.createElement('ul')
bulletWrapper.classList.add('side-nav')
for (let i = 0; i < document.getElementsByClassName('project').length; i++) {
const bullet = document.createElement('li')
bullet.setAttribute('id', '' + i)
bullet.addEventListener('click', event => {
console.log(document.getElementsByClassName('project')[parseInt(event.target.id)].offsetTop)
// scroll to current section
})
bulletList.append(bullet)
bulletWrapper.append(bulletList)
document.body.append(bulletWrapper)
}
}
window.addEventListener('load', () => {
const scrollInstance = new Scroll(8, true)
const sideNav = new SideNavigation()
scrollInstance.setBodyHeight()
requestAnimationFrame(() => scrollInstance.onScroll())
})
html,
body {
height: 100%;
}
main {
position: fixed;
left: 0;
top: 0;
height: 100%;
width: 100%;
overflow: hidden;
}
#projects {
width: 80%;
}
.project {
height: 500px;
width: 100%;
background: #333;
color: #fff;
}
.side-nav {
position: fixed;
right: 20px;
top: 20%;
z-index: 10;
}
.side-nav li {
width: 30px;
height: 30px;
display: block;
background: #333;
margin-bottom: 20px;
border-radius: 50%;
cursor: pointer;
}
<body>
<main>
<div id="projects">
<div class="project">
<p>Some text example</p>
</div>
<div class="project">
<p>Some text example</p>
</div>
<div class="project">
<p>Some text example</p>
</div>
<div class="project">
<p>Some text example</p>
</div>
<div class="project">
<p>Some text example</p>
</div>
</div>
</main>
</body>
I hope I understood your question correctly. Is this what you're looking for?
const config = {
ease: 0.1,
current: 0,
previous: 0,
rounded: 0
}
class Scroll {
constructor(velocity) {
this.velocity = velocity
}
setBodyHeight() {
document.body.style.height = document.getElementById('projects').getBoundingClientRect().height + 'px'
}
isMobile() {
return 'ontouchstart' in document.documentElement && navigator.userAgent.match(/Mobi/)
}
onScroll() {
config.current = window.scrollY
config.previous += (config.current - config.previous) * config.ease
config.rounded = Math.round(config.previous * 100) / 100
const difference = config.current - config.rounded
const acceleration = difference / document.body.clientWidth
const velocity = +acceleration
const skew = velocity * this.velocity
const element = document.getElementById('projects')
this.isMobile() ? element.style.transform = `skewY(${skew}deg)` : element.style.transform = `translateY(-${config.rounded}px)`
requestAnimationFrame(() => this.onScroll())
}
}
class SideNavigation {
constructor() {
createBullets()
}
}
function createBullets() {
const bulletWrapper = document.createElement('div')
const bulletList = document.createElement('ul')
bulletWrapper.classList.add('side-nav')
for (let i = 0; i < document.getElementsByClassName('project').length; i++) {
const bullet = document.createElement('li')
bullet.setAttribute('id', '' + i)
bullet.addEventListener('click', event => {
console.log(document.getElementsByClassName('project')[parseInt(event.target.id)].offsetTop)
// scroll to current section
window.scrollBy(0, document.getElementsByClassName('project')[parseInt(event.target.id)].offsetTop - window.pageYOffset);
})
bulletList.append(bullet)
bulletWrapper.append(bulletList)
document.body.append(bulletWrapper)
}
}
window.addEventListener('load', () => {
const scrollInstance = new Scroll(8, true)
const sideNav = new SideNavigation()
scrollInstance.setBodyHeight()
requestAnimationFrame(() => scrollInstance.onScroll())
})
html,
body {
height: 100%;
}
main {
position: fixed;
left: 0;
top: 0;
height: 100%;
width: 100%;
overflow: hidden;
}
#projects {
width: 80%;
}
.project {
height: 500px;
width: 100%;
background: #333;
color: #fff;
}
.side-nav {
position: fixed;
right: 20px;
top: 20%;
z-index: 10;
}
.side-nav li {
width: 30px;
height: 30px;
display: block;
background: #333;
margin-bottom: 20px;
border-radius: 50%;
cursor: pointer;
}
<body>
<main>
<div id="projects">
<div class="project">
<p>Some text example</p>
</div>
<div class="project">
<p>Some text example</p>
</div>
<div class="project">
<p>Some text example</p>
</div>
<div class="project">
<p>Some text example</p>
</div>
<div class="project">
<p>Some text example</p>
</div>
</div>
</main>
</body>
The scrollBy function's second parameter allows to modify the window's Y axis. But as we want each bullet to jump to the start of it's project, we decrease the current Y axis of the page from the Y axis of the project window.scrollBy(0, document.getElementsByClassName('project')[parseInt(event.target.id)].offsetTop - window.pageYOffset).
I am hacking together an experimental pagination interface called wigi(board) but have run into an issue.
The interface works by any l1 (subject) class or l2 (subheading) class running vertical down the left. Pages (l3 class nodes) are represented as points attached to the side of an l1 or l2.
Mousing over any node will move the selector to that node and call a db query to display a specific page's contents. This works fine. It moves like it should.
Right now I have buttons that will also move between the next and previous li in the navigation list. These are filler for future swiping and other interaction to demonstrate the issue.
Right now these buttons work to a point, until the jquery .next() hits a <br> node, which I am using in order to break the l3 lines and continue the menu vertical to the next l1 or l2. When the .next hits the last node before one of these, it stops dead and wont jump down to the next row. Why? What is the best strategy to fix it?
JS fiddle: http://jsfiddle.net/93g786jp/
The issue with next is in here. It is running over an li list (best to look at JSfiddle)
function nextAndBack(e) {
var cur = $('.dots .selected'),
next = cur.next('li'),
prev = cur.prev('li');
if (e.target.id == 'nextButton') {
if (next.length == 1) {
newSelected(next);
console.log("Next Node:")
console.log(next);
$(next).trigger("mouseover");
}
} else if (e.target.id == 'prevButton') {
if (prev.length == 1) {
newSelected(prev);
console.log("Previous Node:")
console.log(prev);
$(prev).trigger("mouseover");
}
}
}
Note this is based on the gooey interface by Lucas Bebber # https://codepen.io/lbebber/pen/lFdHu which was the closet match I could find for an interface like what I wanted. For the posted example, I stripped out any effects and other extras so some stubs exist.
As the <br /> gets in the way of selecting siblings you can instead use nextAll() or prevAll() and then get the first() of the selected items:
next = cur.nextAll('li').first(),
prev = cur.prevAll('li').first();
function wigiBoardMove() {
var cur = $(this);
var desty = cur.position().top;
var destx = cur.position().left;
var t = 0.6;
gsap.to($(".select"), t, {
y: desty,
ease: Back.easeOut
});
gsap.to($(".select"), t, {
x: destx,
ease: Back.easeOut
});
newSelected(cur);
}
function newSelected(newTarget) {
$('.selected').removeClass('selected');
newTarget.addClass('selected');
}
function nextAndBack(e) {
var cur = $('.dots .selected'),
next = cur.nextAll('li').first(),
prev = cur.prevAll('li').first();
if (e.target.id == 'nextButton') {
if (next.length == 1) {
newSelected(next);
$(next).trigger("mouseover");
}
} else if (e.target.id == 'prevButton') {
if (prev.length == 1) {
newSelected(prev);
$(prev).trigger("mouseover");
}
}
}
/* Modified from gooey pagnation code published by Lucas Bebber # https://codepen.io/lbebber/pen/lFdHu */
$(function() {
$(".dot").on("mouseenter", wigiBoardMove);
var lastPos = $(".select").position().top;
function updateScale() {
var pos = $(".select").position().top;
var speed = Math.abs(pos - lastPos);
var d = 44;
var offset = -20;
var hd = d / 2;
var scale = (offset + pos) % d;
if (scale > hd) {
scale = hd - (scale - hd);
}
scale = 1 - ((scale / hd) * 0.35);
gsap.to($(".select"), 0.1, {
scaleY: 1 + (speed * 0.06),
scaleX: scale
})
lastPos = pos;
requestAnimationFrame(updateScale);
}
requestAnimationFrame(updateScale);
$(".dot:eq(0)").trigger("mouseover");
// Back and Forward Node Logic
$('#nextButton, #prevButton').on('click', nextAndBack);
})
#container {}
.dots {
list-style-type: none;
padding: 0;
margin: 0;
padding-top: 20px;
padding-bottom: 20px;
padding-left: 20px;
margin-left: -10px;
padding-right: 10px;
position: absolute;
top: 0px;
width: 150px;
right: 0px;
}
.dot {
display: inline-block;
vertical-align: middle;
margin-left: 5px;
margin-right: 5px;
cursor: pointer;
color: white;
position: relative;
z-index: 2;
}
.l1 {
border-radius: 100%;
width: 10px;
height: 10px;
background: blue;
border: none;
}
.l3 {
border-radius: 100%;
width: 7px;
height: 7px;
border: none;
background: blue;
}
.select {
display: block;
border-radius: 100%;
width: 15px;
height: 15px;
background: #daa520;
position: absolute;
z-index: 3;
top: -4px;
left: 1px;
pointer-events: none;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.4.1/jquery.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/gsap/3.5.1/gsap.min.js"></script>
<div id="container">
<ul class="dots">
<li class="select"></li>
<li class="dot l1"></li>
<li class="dot l3"></li>
<li class="dot l3"></li>
<li class="dot l3"></li><br>
<li class="dot l1"></li>
<li class="dot l3"></li>
<li class="dot l3"></li><br>
<li class="dot l1"></li>
<li class="dot l3"></li><br>
</ul>
<img id="nextButton" height="10" width="10" alt="Next Node" /><br>
<img id="prevButton" height="10" width="10" alt="Previous Node" />
</div>
I have a dynamic slider with two buttons left and right.
that means for each slide, the slide parent width increases by 100%. 2 slides * 100% = 200%. In example class="slider"; width:'200%'
I want to center each slide's text in the middle of the page. But i want the text to slide not in just slides container, but in its parent-parent width (class='carousel' in example).
Code below, is example how the slider is looking right now.
JavaScript, you should ignore this. Implemented it, for the code to work.
document.addEventListener('DOMContentLoaded', function() { //Display function after HTML is loaded
const left = document.querySelector('.left');
const right = document.querySelector('.right');
var slider = document.getElementById('slider');
var leftImg = document.getElementById('left');
var rightImg = document.getElementById('right');
var sections = document.querySelectorAll('.slide').length; // get number of slides
var sectionIndex = 1;
slider.style.width = ' ' + 100 * sections + '%';
function changeOpacity() {
if (sectionIndex == 1) {
leftImg.style.opacity = '0.4';
} else {
leftImg.style.opacity = '1';
}
if (sectionIndex == sections) {
rightImg.style.opacity = '0.4';
} else {
rightImg.style.opacity = '1';
}
}
left.addEventListener('click', function() {
var leftImg = document.getElementById('left');
sectionIndex = (sectionIndex > 1) ? sectionIndex - 1 : 1;
slider.style.transform = 'translate(' + (sectionIndex - 1) * (-100 / sections) + '%)';
changeOpacity();
});
right.addEventListener('click', function() {
sectionIndex = (sectionIndex < sections) ? sectionIndex + 1 : sections;
slider.style.transform = 'translate(' + (sectionIndex - 1) * (-100 / sections) + '%)';
changeOpacity();
});
})
.slider-container {
padding: 25px 0px;
width: 40%;
margin: auto;
}
.slider-container .carousel {
overflow: hidden;
height: 260px;
width: 100%;
border:solid 2px black;
position:relative;
}
.slider-container .slider {
display: -webkit-box;
display: -ms-flexbox;
display: flex;
height: 100%;
-webkit-transition: .5s;
transition: .5s;
}
.slider-container .slider .slide {
width: 100%;
}
.slider-container .arrow-container {
width: 70px;
position: absolute;
bottom: 0;
}
<div class="slider-container mobile-container text-left">
<div class="carousel relative">
<div id="slider" class="slider">
<div class="slide">
<div class="author d-flex flex-column">
<h3>Ken Ludden</h3>
<span class="regularText">Director, Margot Fonteyn Academy of Ballet</span>
</div>
</div>
<div class="slide">
<div class="author d-flex flex-column">
<h3>Ken Ludden</h3>
<span class="regularText">Director, Margot Fonteyn Academy of Ballet</span>
</div>
</div>
</div>
</div>
<div class="controls">
<div class="arrow-container d-flex justify-content-between ">
<div>
<button class="left" id="left" style="opacity: 0.4;">Left </button>
</div>
<div>
<button class="right" id="right">Right</button>
</div>
</div>
</div>
</div>
</div>
The Snippet below is what i want. But i should be centered, and i don't know how.
I have tried using fl
document.addEventListener('DOMContentLoaded', function() { //Display function after HTML is loaded
const left = document.querySelector('.left');
const right = document.querySelector('.right');
var slider = document.getElementById('slider');
var leftImg = document.getElementById('left');
var rightImg = document.getElementById('right');
var sections = document.querySelectorAll('.slide').length; // get number of slides
var sectionIndex = 1;
slider.style.width = ' ' + 100 * sections + '%';
function changeOpacity() {
if (sectionIndex == 1) {
leftImg.style.opacity = '0.4';
} else {
leftImg.style.opacity = '1';
}
if (sectionIndex == sections) {
rightImg.style.opacity = '0.4';
} else {
rightImg.style.opacity = '1';
}
}
left.addEventListener('click', function() {
var leftImg = document.getElementById('left');
sectionIndex = (sectionIndex > 1) ? sectionIndex - 1 : 1;
slider.style.transform = 'translate(' + (sectionIndex - 1) * (-100 / sections) + '%)';
changeOpacity();
});
right.addEventListener('click', function() {
sectionIndex = (sectionIndex < sections) ? sectionIndex + 1 : sections;
slider.style.transform = 'translate(' + (sectionIndex - 1) * (-100 / sections) + '%)';
changeOpacity();
});
})
.slider-container {
margin: auto;
padding: 25px 0px;
}
.slider-container .carousel {
overflow: hidden;
height: 260px;
width: 80%; /* the width i want */
border: solid 2px black; /* the border for your understading */
position: relative;
}
.slider-container .slider {
display: -webkit-box;
display: -ms-flexbox;
display: flex;
height: 100%;
-webkit-transition: .5s;
transition: .5s;
}
.slider-container .slider .slide {
width: 100%;
}
.slider-container .comment {
max-width: 352px;
padding: 30px 0px;
}
.slider-container .arrow-container {
width: 70px;
position: absolute;
bottom: 0;
}
<div class="slider-container mobile-container text-left">
<div class="carousel relative">
<div id="slider" class="slider">
<div class="slide">
<div class="author d-flex flex-column">
<h3>Ken Ludden</h3>
<span class="regularText">Director, Margot Fonteyn Academy of Ballet</span>
</div>
</div>
<div class="slide">
<div class="author d-flex flex-column">
<h3>Ken Ludden</h3>
<span class="regularText">Director, Margot Fonteyn Academy of Ballet</span>
</div>
</div>
</div>
<div class="controls">
<div class="arrow-container d-flex justify-content-between ">
<div>
<button class="left" id="left" style="opacity: 0.4;">Left </button>
</div>
<div>
<button class="right" id="right">Right</button>
</div>
</div>
</div>
</div>
</div>
</div>
You can see in this snippet that text is sliding from a lot further right than the previous example.
I need to center the slide, because i want the same for left side.
I have tried using flex-column, align-items:center on class="slide". And it works fine, but the class="controls" aren't centering because they are position:absolute and i tried to putting them elsewhere, but it didnt work..
I really hope you guys did understand what i want and really hope that i recieve atleast some suggestions. This is my 1st question, sorry for long code.
Thank you anyway :)
Your carousel is 80% of the width, so if you want that to be centered, you can do: margin: 0 auto on the carousel class.
How to use scrollIntoView on container which has overflow:hidden and it shouldn't scroll the page?
Here is an example: at the bottom of the page text in container <div class="cnt'> which has fixed width and overflow hidden. I want to scroll items in this container without scrolling the page.
At the top of the page two buttons to scroll to first and last element. If i click on button it will scroll text in the container and scroll to that container at the bottom of the page.
I can't use scrollLeft because overflow is hidden. :(
Does anybody know how to solve it?
const cnt = document.querySelector('.cnt')
const spanElements = cnt.querySelectorAll('span');
const lastSpan = spanElements[spanElements.length - 1]
const firstSpan = spanElements[0]
lastSpan.scrollIntoView()
const buttons = Array.from(document.querySelectorAll('button'))
const [buttonToFirstEl, buttonToLastEl] = buttons;
buttonToFirstEl.onclick = function() {
firstSpan.scrollIntoView()
}
buttonToLastEl.onclick = function() {
lastSpan.scrollIntoView()
}
.cnt {
width: 90px;
overflow: hidden;
white-space: nowrap;
padding: 8px;
border: solid #ccc 1px;
}
.filler {
width: 100%;
height: 200px;
border: dashed 2px #ccc;
margin: 20px;
}
.root {
border: solid 1px;
}
<div class="root">
<button id="button">scroll to first element</button>
<button id="button">scroll to last element</button>
<div class="filler">
</div>
<div class="filler">
</div>
<div class="filler">
</div>
<div class="filler">
</div>
<div class="cnt">
<span>
first:tessst
</span>
<span>
2:dddd
</span>
<span>
3:cccddd
</span>
<span>
4:rreeee
</span>
<span>
last:dddrreddd
</span>
</div>
</div>
https://codepen.io/geeny273/pen/bGpxYqG
if you want scrolled element in .cnt class
you need to style every span in .cnt
.cnt span{
/* relative + block for make elements solid & listed*/
position : relative;
display : block;
color: red;
font-size : 16px;
}
and in .cnt parent you need to defined height for making scroll working
.cnt {
width: 90px;
/* for example 28px */
height : 28px;
overflow: hidden;
white-space: nowrap;
padding: 4px;
border: solid black 1px;
/* overflow y or x for making scroll*/
overflow-y : scroll;
}
i hope this steps help you
To get this correctly, (i.e with support for all writing-mode, direction and block-inline options) you'd basically have to rewrite scrollIntoView from scratch, while omitting the loop that goes up the tree of scrolling-boxes. This is not a trivial task.
If you don't need a bullet proof solution though, you can simply get the nearest scrolling-box and check by how much it should be scrolled to show the start of your element:
const cnt = document.querySelector('.cnt')
const spanElements = cnt.querySelectorAll('span');
const lastSpan = spanElements[spanElements.length - 1]
const firstSpan = spanElements[0]
const buttons = Array.from(document.querySelectorAll('button'))
const [buttonToFirstEl, buttonToLastEl] = buttons;
buttonToFirstEl.onclick = function() {
scrollIntoParentView( firstSpan );
}
buttonToLastEl.onclick = function() {
scrollIntoParentView( lastSpan );
}
function scrollIntoParentView( elem, options ) {
const directions = getSimpleScrollIntoViewDirections( elem, options );
const left = directions.inline_direction || 0;
const top = directions.block_direction || 0;
const new_options = {
left,
top,
behavior: (options && options.behavior) || "auto"
};
directions.scrolling_box.scrollBy( new_options );
}
function getSimpleScrollIntoViewDirections( elem, { block = "start", inline = "start" } = {} ) {
const element_bbox = elem.getBoundingClientRect();
const scrolling_box = getNearestScrollingBox( elem );
const scrolling_box_bbox = scrolling_box.getBoundingClientRect();
const block_direction = Math.round( element_bbox.top - scrolling_box_bbox.top);
const inline_direction = Math.round( element_bbox.left - scrolling_box_bbox.left);
return {
scrolling_box,
block_direction,
inline_direction
};
}
function getNearestScrollingBox( elem ) {
if( !elem.isConnected ) { return null; }
const elem_computed_styles = getComputedStyle( elem );
// not in specs, but that seems to be what browser implementations do
if( elem_computed_styles.getPropertyValue( 'position' ) === "fixed" ) {
return null;
}
const scrolling_box = elem.parentElement;
if( !scrolling_box ) {
return elem === document.scrollingElement ? null : document.scrollingElement;
}
const computed_styles = getComputedStyle( scrolling_box );
const scroll_x = computed_styles.getPropertyValue( "overflow-x");
const scroll_y = computed_styles.getPropertyValue( "overflow-y");
if(
(scroll_x === 'clip' && scroll_y === 'clip') ||
(scrolling_box.offsetHeight <= scrolling_box.scrollingHeight) ||
(scrolling_box.offsetWidth <= scrolling_box.scrollingWidth)
) {
return getNearestScrollingBox( scrolling_box );
}
return scrolling_box;
}
.cnt {
width: 90px;
overflow: hidden;
white-space: nowrap;
padding: 8px;
border: solid #ccc 1px;
}
.filler {
width: 100%;
height: 200px;
border: dashed 2px #ccc;
margin: 20px;
}
.root {
border: solid 1px;
}
<div class="root">
<button id="button">scroll to first element</button>
<button id="button">scroll to last element</button>
<div class="filler">
</div>
<div class="filler">
</div>
<div class="filler">
</div>
<div class="filler">
</div>
<div class="cnt">
<span>
first:tessst
</span>
<span>
2:dddd
</span>
<span>
3:cccddd
</span>
<span>
4:rreeee
</span>
<span>
last:dddrreddd
</span>
</div>
</div>
scrollLeft and scrollTop work well with overflow:hidden. I check scrollLeft property on first span element instead of its container
changing scrollLeft on parent element of span, solve this issue
firstSpan.parentElement.scrollLeft = 0;
const cnt = document.querySelector('.cnt')
const spanElements = cnt.querySelectorAll('span');
const lastSpan = spanElements[spanElements.length - 1]
const firstSpan = spanElements[0]
lastSpan.scrollIntoView()
const buttons = Array.from(document.querySelectorAll('button'))
const [buttonToFirstEl, buttonToLastEl] = buttons;
buttonToFirstEl.onclick = function() {
firstSpan.parentElement.scrollLeft = 0;
}
buttonToLastEl.onclick = function() {
const cnt = lastSpan.parentElement;
cnt.scrollLeft = cnt.scrollWidth;
}
.cnt {
width: 90px;
overflow: hidden;
white-space: nowrap;
padding: 8px;
border: solid #ccc 1px;
}
.filler {
width: 100%;
height: 200px;
border: dashed 2px #ccc;
margin: 20px;
}
.root {
border: solid 1px;
}
<div class="root">
<button id="button">scroll to first element</button>
<button id="button">scroll to last element</button>
<div class="filler">
</div>
<div class="filler">
</div>
<div class="filler">
</div>
<div class="filler">
</div>
<div class="cnt">
<span>
first:tessst
</span>
<span>
2:dddd
</span>
<span>
3:cccddd
</span>
<span>
4:rreeee
</span>
<span>
last:dddrreddd
</span>
</div>
</div>
<div class="game">
<div class="hole hole1">
<div class="mole"></div>
</div>
<div class="hole hole2">
<div class="mole"></div>
</div>
<div class="hole hole3">
<div class="mole"></div>
</div>
<div class="hole hole4">
<div class="mole"></div>
</div>
<div class="hole hole5">
<div class="mole"></div>
</div>
<div class="hole hole6">
<div class="mole"></div>
</div>
<div class="hole hole7">
<div class="mole"></div>
</div>
<div class="hole hole8">
<div class="mole"></div>
</div>
<div class="hole hole9">
<div class="mole"></div>
</div>
</div>
.game {
width: 300px;
height: 600px;
display: flex;
flex-wrap: wrap;
margin: 0 auto;
}
.hole {
flex: 1 0 33.33%;
overflow: hidden;
width: 100%;
position: relative;
}
.hole:after {
display: block;
background: url('gaura1.png') bottom center no-repeat;
background-size: 100%;
content: '';
width: 100%;
height:100%;
position: absolute;
z-index: 2;
}
.mole {
background: url('flowAlb.png') bottom center no-repeat;
background-size: 100%;
position: absolute;
width: 100%;
height:100%;
top:100%;
transition: all 0.4s;
}
.hole.up .mole {
top: -20px;
z-index:3;
}
I'm trying to learn web development with CSS, HTML and JAVASCRIPT(i'm new to all of them) and I'm working on some whack-a-mole game code that was free to work with. I understood what the code does, but I'm not sure how to work with. I have an event listener on click for each mole, but I wanna do something if the mole isn't clicked and I don't know how to check that. I tried different methods, using boolean variables or trying to check if the click was outside the element, but none of them worked. I'm pretty sure I didn't used them right, so I would really appreciate some help or information. I'll leave here the JS code. Thanks so much!
const holes = document.querySelectorAll('.hole');
const scoreBoard = document.querySelector('.score');
const moles = document.querySelectorAll('.mole');
const mySound=document.getElementById("sound");
const joc=document.getElementsByClassName("game");
let lastHole;
let timeUp = false;
let score = 0;
function randomTime(min, max) {
return Math.round(Math.random() * (max - min) + min);
}
function randomHole(holes) {
const index = Math.floor(Math.random() * holes.length);
const hole = holes[index];
if (hole === lastHole) {
return randomHole(holes);
}
lastHole = hole;
return hole;
}
function peep() {
const time = randomTime(500, 1000);
const hole = randomHole(holes);
hole.classList.add('up');
setTimeout(() => {
hole.classList.remove('up');
if (!timeUp) {
peep();
}
}, time);
}
function startGame() {
scoreBoard.textContent = 0;
timeUp = false;
score = 0;
peep();
setTimeout(() => timeUp = true, 90000)
}
function wack(e) {
if (!e.isTrusted) return;
score = score + 100;
this.parentNode.classList.remove('up');
scoreBoard.textContent = score;
}
moles.forEach(mole => mole.addEventListener('click', wack));
You can add a click event to the documentElement and check its target. Consequently you could also remove your other click handlers while doing this and check for the class mole.
;document.documentElement.onclick = function(event){
//REM: Target element of the click
var tTarget = event.srcElement || event.target;
//REM: Check which element was targted.
if(tTarget.id === 'sample'){
alert('You clicked on #sample')
}
else{
alert('You clicked on "' + tTarget.tagName + '"')
}
};
html, body{
height: 100%;
position: relative;
width: 100%
}
body{
background: yellow
}
div{
background: red
}
.sample{
background: lime;
height: 100%;
position: relative;
width: 100%
}
<div class = 'sample'>
<div id = 'sample'>click me or not</div>
</div>