JS slider has one too many slides. Can't figure out why - javascript

I have a slider which is supposed to show only three slides, but it continues (both automatically or by click) to a fourth blank slide. I don't see where the number of slides is set in the code. Would really appreciate some educated eyes on this.
The JS
$(document).ready(function() {
var $slider = $(".slider"),
$slideBGs = $(".slide__bg"),
diff = 0,
curSlide = 0,
numOfSlides = $(".slide").length-1,
animating = false,
animTime = 500,
autoSlideTimeout,
autoSlideDelay = 6000,
$pagination = $(".slider-pagi");
function createBullets() {
for (var i = 0; i < numOfSlides+1; i++) {
var $li = $("<li class='slider-pagi__elem'></li>");
$li.addClass("slider-pagi__elem-"+i).data("page", i);
if (!i) $li.addClass("active");
$pagination.append($li);
}
};
createBullets();
function manageControls() {
$(".slider-control").removeClass("inactive");
if (!curSlide) $(".slider-control.left").addClass("inactive");
if (curSlide === numOfSlides) $(".slider-control.right").addClass("inactive");
};
function autoSlide() {
autoSlideTimeout = setTimeout(function() {
curSlide++;
if (curSlide > numOfSlides) curSlide = 0;
changeSlides();
}, autoSlideDelay);
};
autoSlide();
function changeSlides(instant) {
if (!instant) {
animating = true;
manageControls();
$slider.addClass("animating");
$slider.css("top");
$(".slide").removeClass("active");
$(".slide-"+curSlide).addClass("active");
setTimeout(function() {
$slider.removeClass("animating");
animating = false;
}, animTime);
}
window.clearTimeout(autoSlideTimeout);
$(".slider-pagi__elem").removeClass("active");
$(".slider-pagi__elem-"+curSlide).addClass("active");
$slider.css("transform", "translate3d("+ -curSlide*100 +"%,0,0)");
$slideBGs.css("transform", "translate3d("+ curSlide*50 +"%,0,0)");
diff = 0;
autoSlide();
}
function navigateLeft() {
if (animating) return;
if (curSlide > 0) curSlide--;
changeSlides();
}
function navigateRight() {
if (animating) return;
if (curSlide < numOfSlides) curSlide++;
changeSlides();
}
$(document).on("mousedown touchstart", ".slider", function(e) {
if (animating) return;
window.clearTimeout(autoSlideTimeout);
var startX = e.pageX || e.originalEvent.touches[0].pageX,
winW = $(window).width();
diff = 0;
$(document).on("mousemove touchmove", function(e) {
var x = e.pageX || e.originalEvent.touches[0].pageX;
diff = (startX - x) / winW * 70;
if ((!curSlide && diff < 0) || (curSlide === numOfSlides && diff > 0)) diff /= 2;
$slider.css("transform", "translate3d("+ (-curSlide*100 - diff) +"%,0,0)");
$slideBGs.css("transform", "translate3d("+ (curSlide*50 + diff/2) +"%,0,0)");
});
});
$(document).on("mouseup touchend", function(e) {
$(document).off("mousemove touchmove");
if (animating) return;
if (!diff) {
changeSlides(true);
return;
}
if (diff > -6 && diff < 6) {
changeSlides();
return;
}
if (diff <= -6) {
navigateLeft();
}
if (diff >= 6) {
navigateRight();
}
});
$(document).on("click", ".slider-control", function() {
if ($(this).hasClass("left")) {
navigateLeft();
} else {
navigateRight();
}
});
$(document).on("click", ".slider-pagi__elem", function() {
curSlide = $(this).data("page");
changeSlides();
});
});
The HTML
<div class="slider-container">
<div class="slider-control left inactive"></div>
<div class="slider-control right"></div>
<ul class="slider-pagi"></ul>
<div class="slider">
<div class="slide slide-0 active">
<div class="slide__bg"></div>
<div class="slide__content">
<!--<svg class="slide__overlay" viewBox="0 0 720 405" preserveAspectRatio="xMaxYMax slice">
<path class="slide__overlay-path" d="M0,0 150,0 500,405 0,405" />
</svg>-->
<div class="slide__text">
<h2 class="slide__text-heading"><b>New</b> featured products</h2>
<h3 class="slide__text-sub-head">Ives<sup>®</sup> hands-free door pulls</h3>
<p class="slide__text-desc">Ives offers hands-free pulls and door opening tools that enable pedestrians to operate the door with an arm or foot to avoid contacting surfaces with their hands. This is a cost-effective solution for retrofitting high-traffic mechanical applications to hands-free.<br><a class="slide__text-link">Learn More</a></p>
</div>
</div>
</div>
<div class="slide slide-1 ">
<div class="slide__bg"></div>
<div class="slide__content">
<!--<svg class="slide__overlay" viewBox="0 0 720 405" preserveAspectRatio="xMaxYMax slice">
<path class="slide__overlay-path" d="M0,0 150,0 500,405 0,405" />
</svg>-->
<div class="slide__text">
<h2 class="slide__text-heading"><b>New</b> featured products</h2>
<h3 class="slide__text-sub-head">LCN<sup>®</sup> touchless actuators</h3>
<p class="slide__text-desc">Allegion offers no-touch actuators that are installed in place of push buttons and comply with ANSI 156.19 low energy standards. A pedestrian simply waves a hand in front of the wall plate, the technology senses the motion and acknowledges intent to enter. No contact with the door or hardware is required.<br><a class="slide__text-link">Learn More</a></p>
</div>
</div>
</div>
<div class="slide slide-2">
<div class="slide__bg"></div>
<div class="slide__content">
<!--<svg class="slide__overlay" viewBox="0 0 720 405" preserveAspectRatio="xMaxYMax slice">
<path class="slide__overlay-path" d="M0,0 150,0 500,405 0,405" />
</svg>-->
<div class="slide__text">
<h2 class="slide__text-heading"><b>New</b> featured products</h2>
<h3 class="slide__text-sub-head">Schlage<sup>®</sup> mobile access solutions</h3>
<p class="slide__text-desc">Schlage Mobile Access Solutions provide comprehensive touchless offering, including mobile enabled multi-technology readers, mobile enabled wireless electronic locks and mobile access credentials.<br><a class="slide__text-link">Learn More</a></p>
</div>
</div>
</div>
</div>
</div>
TIA!

Just tried the following which seems to have corrected the issue.
I changed this line:
numOfSlides = $(".slide").length-1,
To this:
numOfSlides = $(".slide").length-2,
Getting the desired result now...only 3 slides as intended. Hopefully the code is fundamentally sound.

Related

Show different images, based on percentage of page scrolled

I'm looking to fade-in different images, based on the percentage of the total page scrolled.
The idea is that an image is shown at an even interval along the entire page.
Right now, I have the following code which is based on the amount of pixels scrolled. But since this doesn't work on different devices, it is not suited for my idea. Would anyone know how to pick up on what I have below and make it percentage of the entire page?
Thank you!
$("#c1").fadeIn(500);
$(document).scroll(function () {
var pos = $(document).scrollTop();
if (pos < 500) { hideAll("c1"); $("#c1").fadeIn(500); }
if (pos > 1000 && pos < 1500) { hideAll("c2"); $("#c2").fadeIn(500); }
if (pos > 2000 && pos < 2500) { hideAll("c3"); $("#c3").fadeIn(500); }
if (pos > 3000 && pos < 3500) { hideAll("c4"); $("#c4").fadeIn(500); }
if (pos > 4000 && pos < 4500) { hideAll("c5"); $("#c5").fadeIn(500); }
if (pos > 5000 && pos < 5500) { hideAll("c6"); $("#c6").fadeIn(500); }
});
function hideAll(exceptMe) {
$(".bg").each(function (i) {
if ($(this).attr("id") == exceptMe) return;
$(this).fadeOut();
});
}
body {height:9500px;}
.bg{width:25%;z-index:-1;display:none;position:fixed;margin:0;top:50%;left:50%;transform:translate(-50%,-50%)}
.bg img{max-height:100%}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div class="background">
<div id="c1" class="bg" style="display: block;"><img src="https://dummyimage.com/600x400/000/aaa" /></div>
<div id="c2" class="bg"><img src="https://dummyimage.com/600x400/d400d4/fff" /></div>
<div id="c3" class="bg"><img src="https://dummyimage.com/600x400/47d400/fff" /></div>
<div id="c4" class="bg"><img src="https://dummyimage.com/600x400/007cd4/fff" /></div>
<div id="c5" class="bg"><img src="https://dummyimage.com/600x400/00d463/fff" /></div>
<div id="c6" class="bg"><img src="https://dummyimage.com/600x400/a6d400/fff" /></div>
</div>
Ah, I see now ok, so I believe this should work for you, it uses the methods from
javascript scroll event for iPhone/iPad?
I tested it using browserstack.com's mobile emulators on android and Iso and both seemed to work
$("#c1").fadeIn(500);
//use touch move for ISO mobile
window.addEventListener("touchmove", Scroll, false);
window.addEventListener("scroll", Scroll, false);
function Scroll() {
var windowHeight = jQuery(document).height();
//Capture where the top of the page is after scroll
var currentPosition = jQuery(document).scrollTop();
//Capture how many pixels can be viewed by the user
var windowViewingArea = jQuery(window).height();
//Figure out the bottom of what the user has scrolled to
var bottomScrollPosition = currentPosition + windowViewingArea;
//Figure out the rounded percentage of how much was scrolled
var percentScrolled = parseInt((bottomScrollPosition / windowHeight * 100).toFixed(0));
//console.log(percentScrolled)
if (percentScrolled >= 15 && percentScrolled < 30) {
hideAll("c1");
$("#c1").fadeIn(500);
} else if (percentScrolled >= 30 && percentScrolled < 45) {
hideAll("c2");
$("#c2").fadeIn(500);
} else if (percentScrolled >= 45 && percentScrolled < 60) {
hideAll("c3");
$("#c3").fadeIn(500);
} else if (percentScrolled >= 60 && percentScrolled < 75) {
hideAll("c4");
$("#c4").fadeIn(500);
} else if (percentScrolled >= 75 && percentScrolled < 90) {
hideAll("c5");
$("#c5").fadeIn(500);
} else if (percentScrolled >= 90) {
hideAll("c6");
$("#c6").fadeIn(500);
}
}
function hideAll(exceptMe) {
$(".bg").each(function(i) {
if ($(this).attr("id") == exceptMe) return;
$(this).fadeOut();
});
}
body {
height: 9500px;
}
.bg {
width: 25%;
z-index: -1;
display: none;
position: fixed;
margin: 0;
top: 50%;
left: 50%;
transform: translate(-50%, -50%)
}
.bg img {
max-height: 100%
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div class="background">
<div id="c1" class="bg" style="display: block;"><img src="https://dummyimage.com/600x400/000/aaa" /></div>
<div id="c2" class="bg"><img src="https://dummyimage.com/600x400/d400d4/fff" /></div>
<div id="c3" class="bg"><img src="https://dummyimage.com/600x400/47d400/fff" /></div>
<div id="c4" class="bg"><img src="https://dummyimage.com/600x400/007cd4/fff" /></div>
<div id="c5" class="bg"><img src="https://dummyimage.com/600x400/00d463/fff" /></div>
<div id="c6" class="bg"><img src="https://dummyimage.com/600x400/a6d400/fff" /></div>
</div>
Is this what you were after ?
you could use the document scroll event which has cross-browser support:
https://developer.mozilla.org/en-US/docs/Web/API/Document/scroll_event#browser_compatibility
here is your code using that method:
$("#c1").fadeIn(500);
document.addEventListener('scroll', function(e) {
var pos = window.scrollY;
if (pos < 500) {
hideAll("c1");
$("#c1").fadeIn(500);
}
if (pos > 1000 && pos < 1500) {
hideAll("c2");
$("#c2").fadeIn(500);
}
if (pos > 2000 && pos < 2500) {
hideAll("c3");
$("#c3").fadeIn(500);
}
if (pos > 3000 && pos < 3500) {
hideAll("c4");
$("#c4").fadeIn(500);
}
if (pos > 4000 && pos < 4500) {
hideAll("c5");
$("#c5").fadeIn(500);
}
if (pos > 5000 && pos < 5500) {
hideAll("c6");
$("#c6").fadeIn(500);
}
});
function hideAll(exceptMe) {
$(".bg").each(function(i) {
if ($(this).attr("id") == exceptMe) return;
$(this).fadeOut();
});
}
body {
height: 9500px;
}
.bg {
width: 25%;
z-index: -1;
display: none;
position: fixed;
margin: 0;
top: 50%;
left: 50%;
transform: translate(-50%, -50%)
}
.bg img {
max-height: 100%
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div class="background">
<div id="c1" class="bg" style="display: block;"><img src="https://dummyimage.com/600x400/000/aaa" /></div>
<div id="c2" class="bg"><img src="https://dummyimage.com/600x400/d400d4/fff" /></div>
<div id="c3" class="bg"><img src="https://dummyimage.com/600x400/47d400/fff" /></div>
<div id="c4" class="bg"><img src="https://dummyimage.com/600x400/007cd4/fff" /></div>
<div id="c5" class="bg"><img src="https://dummyimage.com/600x400/00d463/fff" /></div>
<div id="c6" class="bg"><img src="https://dummyimage.com/600x400/a6d400/fff" /></div>
</div>
what browsers / devices are you having issues with? do you need help doing the image swapping based on the % of the page scrolled?
I hope this helps

HTML javascript, dragging method in canvas

I made a square grid using HTML canvas and I am implementing a drag mechanism, such that the user can draw only rectangles by dragging over the grid.
In the below solution, the user can draw non-rectangle shapes, depending on how the user drags.
An additional question : The grid can be of any size and the drag operation is laggy for large rectangles. Any performance improvement suggestions for that ?
Here are my code of html and javascript
function getSquare(canvas, evt) {
var rect = canvas.getBoundingClientRect();
return {
x: 1 + (evt.clientX - rect.left) - (evt.clientX - rect.left)%10,
y: 1 + (evt.clientY - rect.top) - (evt.clientY - rect.top)%10
};
}
function emptySquare(context) {
context.rect(0, 0, canvas.width, canvas.height);
context.fillStyle = "#ffffff"
context.fill();
context.strokeStyle = "#ddd";
context.stroke();
}
function range(start, end) {
var ans = [];
if (end > start) {
for (let i = start; i <= end; i += 10) {
ans.push(i);
}
} else {
emptySquare(context);
for (let i = start; i >= end; i -= 10) {
ans.push(i);
}}
return ans;
}
function drawBoard(context) {
for (var x = 0.5; x < 20001; x += 10) {
context.moveTo(x, 0);
context.lineTo(x,20000);
}
for (var y = 0.5; y < 20001; y += 10) {
context.moveTo(0, y);
context.lineTo(20000, y);
}
context.strokeStyle = "#ddd";
context.stroke();
}
function fillSquare(context, x, y){
context.fillStyle = "#70B7B5";
context.fillRect(x,y,9,9);
}
var canvas = document.getElementById('myBoard');
var context = canvas.getContext('2d');
var A;
drawBoard(context);
var isDrag= false;
// drawBoard(context);
canvas.addEventListener('mousedown', function(evt) {
var mousePos = getSquare(canvas, evt);
isDrag=true;
fillSquare(context, mousePos.x, mousePos.y);
previousPos = mousePos;
}, false);
canvas.addEventListener('mousemove', function(evt) {
if (isDrag) {
var mousePos = getSquare(canvas, evt);
var x_dist = range(previousPos.x, mousePos.x);
var y_dist = range(previousPos.y, mousePos.y);
for (x in x_dist) {
for (y in y_dist) {
fillSquare(context, x_dist[x], y_dist[y]);
}
}
}
}, false);
canvas.addEventListener('mouseup', function(evt) {
if (isDrag){
isDrag = false;
}
}, false);
var canvas = document.getElementById('myBoard');
var context = canvas.getContext('2d');
// drawBoard(context);
var isDrag=false;
canvas.addEventListener('mousedown', function(evt) {
var mousePos = getSquare(canvas, evt);
isDrag=true;
fillSquare(context, mousePos.x, mousePos.y);
previousPos = mousePos;
}, false);
canvas.addEventListener('mousemove', function(evt) {
if (isDrag) {
var mousePos = getSquare(canvas, evt);
var x_dist = range(previousPos.x, mousePos.x);
var y_dist = range(previousPos.y, mousePos.y);
for (x in x_dist) {
for (y in y_dist) {
fillSquare(context, x_dist[x], y_dist[y]);
}
}
}
}, false);
canvas.addEventListener('mouseup', function(evt) {
if (isDrag){
isDrag = false;
}
}, false);
<head>
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.5.1/jquery.min.js"></script>
<link href="https://cdn.jsdelivr.net/npm/bootstrap#5.1.3/dist/css/bootstrap.min.css" rel="stylesheet">
<link rel="stylesheet" href="./assets/css/style.css">
<meta charset="utf-8">
</head>
<body>
<nav class="navbar navbar-expand-lg navbar-dark bg-dark">
<div class="container-fluid">
<a class="navbar-brand" href="index.html">t</a>
<button class="navbar-toggler" type="button" data-bs-toggle="collapse" data-bs-target="#navbarNavAltMarkup" aria-controls="navbarNavAltMarkup" aria-expanded="false" aria-label="Toggle navigation">
<span class="navbar-toggler-icon"></span>
</button>
<div class="collapse navbar-collapse" id="navbarNavAltMarkup">
<div class="navbar-nav">
<a class="nav-link" aria-current="page" href="index.html">Home</a>
<a class="nav-link" href="#">About Us</a>
<a class="nav-link" href="Myblock.html">Mk</a>
</div>
<div class="navbar-nav ms-auto mb-2 mb-lg-0">
<a class="nav-link" href="login.html">Login</a>
</div>
</div>
</div>
</nav>
<div>
<div class="modal fade bd-example-modal-lg" id="exampleModal" tabindex="-1" aria-labelledby="exampleModalLabel" aria-hidden="true">
<div class="modal-dialog modal-lg">
<div class="modal-content">
<div class="modal-header">
<h5 class="modal-title" id="exampleModalLabel">간판 구입</h5>
<button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
</div>
<div class="modal-body">
<form action="" method="POST" enctype="multipart/form-data">
<div class="container">
<div class="row">
<div class="col-md-12">
<div class="form-group">
<div class="preview-zone hidden">
<div class="box box-solid">
<div class="box-header with-border">
<div><b>미리보기</b></div>
<!-- <div class="box-tools pull-right">
<button type="button" class="btn btn-danger btn-xs remove-preview">
<i class="fa fa-times"></i> 초기화
</button>
</div> -->
</div>
<div class="box-body"></div>
</div>
</div>
<div class="dropzone-wrapper">
<div class="dropzone-desc">
<i class="glyphicon glyphicon-download-alt"></i>
<p>광고 이미지 선택 or 드래그해 옮겨 오세요.</p>
</div>
<input type="file" name="img_logo" class="dropzone">
</div>
</div>
</div>
</div>
</div>
<div class="form-group">
<label for="exampleInputEmail1">닉네임/이름</label>
<input type="email" class="form-control" id="exampleInputEmail1" aria-describedby="emailHelp" placeholder="닉네임/이름">
<label for="exampleInputEmail1">연락처</label>
<input type="email" class="form-control" id="exampleInputEmail1" aria-describedby="emailHelp" placeholder="핸드폰 번호">
<label for="exampleInputEmail1">구매희망 면적</label>
<input type="email" class="form-control" id="exampleInputEmail1" aria-describedby="emailHelp" placeholder="ex) 10 x 10 OR 100x100 ">
</div>
</form>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-secondary" data-bs-dismiss="modal">닫기</button>
<button type="submit" class="btn btn-dark">적용하기</button>
</div>
</div>
</div>
</div>
<div>
<canvas id="myBoard" width="1440" height="1200"></canvas>
</div>
</hr>
<footer>
<p>© 2021 Nune Project</p>
</footer>
<script src="https://cdn.jsdelivr.net/npm/bootstrap#5.1.3/dist/js/bootstrap.bundle.min.js"></script>
<script type="text/javascript" src="./assets/js/mainBoard.js"></script>
<script type="text/javascript" src="./assets/js/drag_field.js"></script>
</body>
The issue is being seen because range function is not clearing the squares when end > start. Clearing the squares in both the cases resolves the issue.
Here's the snippet that fixes the issue.
function range(start, end) {
var ans = [];
emptySquare(context);
if (end > start) {
for (let i = start; i <= end; i += 10) {
ans.push(i);
}
} else {
for (let i = start; i >= end; i -= 10) {
ans.push(i);
}
}
return ans;
}
The Lag Issue
The callback function attached to mousemove clears and draws squares on every invocation - a time consuming operation. Given that JavaScript is single threaded and this function is called at a very high rate, it might be the cause of the lag.
Debouncing the mousemove callback can help reducing the lag.
Another approach to solve the lag issue is to make two canvases: one for the background grid lines and the other one for drawing the green rectangles.
<div>
<canvas id="bg" width="1440" height="1200"></canvas>
<canvas id="myBoard" width="1440" height="1200"></canvas>
</div>
Set the #bg canvas so that #myBoard is in front of it:
#bg {
position: absolute;
z-index: -1;
}
Then draw the grid lines on the #bg canvas:
const bg = document.getElementById('bg')
const bgContext = bg.getContext('2d')
drawBoard(bgContext)
Finally, move the emptySquare(context) function into the mousemove event callback and edit it as follows:
function emptySquare(context) {
context.clearRect(0, 0, canvas.width, canvas.height)
}
So it will only clear the #myBoard canvas while #bg stays the same without needing to redraw it each time.
Example:
const bg = document.getElementById('bg')
const bgContext = bg.getContext('2d')
drawBoard(bgContext)
function getSquare(canvas, evt) {
var rect = canvas.getBoundingClientRect()
return {
x: 1 + (evt.clientX - rect.left) - ((evt.clientX - rect.left) % 10),
y: 1 + (evt.clientY - rect.top) - ((evt.clientY - rect.top) % 10),
}
}
function emptySquare(context) {
context.clearRect(0, 0, canvas.width, canvas.height)
}
function range(start, end) {
var ans = []
if (end > start) {
for (let i = start; i <= end; i += 10) {
ans.push(i)
}
} else {
for (let i = start; i >= end; i -= 10) {
ans.push(i)
}
}
return ans
}
function drawBoard(context) {
for (var x = 0.5; x < 20001; x += 10) {
context.moveTo(x, 0)
context.lineTo(x, 20000)
}
for (var y = 0.5; y < 20001; y += 10) {
context.moveTo(0, y)
context.lineTo(20000, y)
}
context.strokeStyle = '#ddd'
context.stroke()
}
function fillSquare(context, x, y) {
context.fillStyle = '#70B7B5'
context.fillRect(x, y, 9, 9)
}
var canvas = document.getElementById('myBoard')
var context = canvas.getContext('2d')
var isDrag = false
canvas.addEventListener('mousedown', function(evt) {
var mousePos = getSquare(canvas, evt)
isDrag = true
fillSquare(context, mousePos.x, mousePos.y)
previousPos = mousePos
}, false)
canvas.addEventListener('mousemove', function(evt) {
if (isDrag) {
var mousePos = getSquare(canvas, evt)
var x_dist = range(previousPos.x, mousePos.x)
var y_dist = range(previousPos.y, mousePos.y)
emptySquare(context)
for (x in x_dist) {
for (y in y_dist) {
fillSquare(context, x_dist[x], y_dist[y])
}
}
}
}, false)
canvas.addEventListener('mouseup', function(evt) {
if (isDrag) {
isDrag = false
}
}, false)
#bg {
position: absolute;
z-index: -1;
}
<div>
<canvas id="bg" width="1440" height="1200"></canvas>
<canvas id="myBoard" width="1440" height="1200"></canvas>
</div>

Accordion JS hyperlink propagation

I am working on a website with multiple accordions on each page with download links. I found a beautiful accordion by Ahmet Aksungur, but the hyperlinks don’t work with his code. I’ve tried adding preventDefault() and stopPropagation() -- $.on('click', 'a', function (e) { e.stopPropegation();}) -- – this work great (once!) – but the problem is that after the initial download, none of the accordions or download links work.
Could anyone suggest a way to stopPropagation on an event and allow normal function of the rest of the accordions. Thanks.
codepen: https://codepen.io/doncroy/pen/abZBZyL
'''
<script>
(function () {
"use strict";
var jQueryPlugin = (window.jQueryPlugin = function (ident, func) {
return function (arg) {
if (this.length > 1) {
this.each(function () {
var $this = $(this);
if (!$this.data(ident)) {
$this.data(ident, func($this, arg));
}
});
return this;
} else if (this.length === 1) {
if (!this.data(ident)) {
this.data(ident, func(this, arg));
}
return this.data(ident);
}
};
});
})();
(function () {
"use strict";
function Accordion($roots) {
var element = $roots;
var accordion = $roots.first("[data-accordion]");
var accordion_target = $roots.find("[data-accordion-item]");
var accordion_content = $roots.find("[data-accordion-content]");
$(accordion_target).click(function () {
$(this).toggleClass("opened");
$(this).find(accordion_content).slideToggle("slow");
$(this).siblings().find(accordion_content).slideUp("slow");
$(this).siblings().removeClass("opened");
});
}
$.fn.Accordion = jQueryPlugin("Accordion", Accordion);
$("[data-accordion]").Accordion();
function Ripple_Button($root) {
var elements = $root;
var ripple_btn = $root.first("[data-ripple]");
$(ripple_btn).on("click", function (event) {
event.preventDefault();
var $div = $("<div/>"),
btnOffset = ripple_btn.offset(),
xPos = event.pageX - btnOffset.left,
yPos = event.pageY - btnOffset.top;
$div.addClass("ripple-effect");
$div.css({
height: ripple_btn.height(),
width: ripple_btn.height(),
top: yPos - $div.height() / 2,
left: xPos - $div.width() / 2,
background: ripple_btn.data("ripple") || "#ffffff26"
});
ripple_btn.append($div);
window.setTimeout(function () {
$div.remove();
}, 2000);
});
}
$.fn.Ripple_Button = jQueryPlugin("Ripple_Button", Ripple_Button);
$("[data-ripple]").Ripple_Button();
})();
</script>
'''
'''
<div class="container">
<div class="aks-accordion" itemscope itemtype="https://schema.org/FAQPage" data-accordion="">
<div class="aks-accordion-row">
<div class="aks-accordion-item" itemscope itemprop="mainEntity" itemtype="https://schema.org/Question" data-accordion-item="" data-ripple="#2c612c26">
<div class="aks-accordion-item-row">
<div class="aks-accordion-item-icon">
<svg class="aks-accordion-item-icon-open" viewBox="0 0 512 512">
<path d="M492,236H276V20c0-11.046-8.954-20-20-20c-11.046,0-20,8.954-20,20v216H20c-11.046,0-20,8.954-20,20s8.954,20,20,20h216
v216c0,11.046,8.954,20,20,20s20-8.954,20-20V276h216c11.046,0,20-8.954,20-20C512,244.954,503.046,236,492,236z" />
</svg>
<svg class="aks-accordion-item-icon-close" viewBox="0 0 512 512">
<path d="M492,236H20c-11.046,0-20,8.954-20,20c0,11.046,8.954,20,20,20h472c11.046,0,20-8.954,20-20S503.046,236,492,236z" />
</svg>
</div>
<div class="aks-accordion-item-title">
<h4 itemprop="name">Dropdown Title</h4>
</div>
</div>
<div class="aks-accordion-item-content" itemscope itemprop="acceptedAnswer" itemtype="https://schema.org/Answer" data-accordion-content="">
<li><div id="#" onclick='recordVisit(this.id, "link")'><i class="fas fa-file-download"></i>PLACEHOLDER</div></li>
<li><div id="#" onclick='recordVisit(this.id, "link")'><i class="fas fa-file-download"></i>PLACEHOLDER</div></li>
<li><div id="#" onclick='recordVisit(this.id, "link")'><i class="fas fa-file-download"></i>PLACEHOLDER</div></li>
</div>
</div>
</div>
</div>
</div>
'''
I found the answer. The problem with the stopPropagation() written into the JS was that it affected the accordions globally. The solution was to use an inline onclick event on each of the links.
<li><div id="#" onclick='recordVisit(this.id, "link"); event.stopPropagation();'><i class="fas fa-file-download"></i>PLACEHOLDER</div></li>

Effect typing when switching slider

In the slider need realize the effect of "typing" when you switch slides. I use Slick Slider for slider. Work example http://test2.hotweb.com.ua/webbit/.
HTML:
<div class="header-slider-wrap">
<div class="header-slider">
<div class="slider-nav__left nav-btn-slider">
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 477.175 477.175"><path d="M145.188 238.575l215.5-215.5c5.3-5.3 5.3-13.8 0-19.1s-13.8-5.3-19.1 0l-225.1 225.1c-5.3 5.3-5.3 13.8 0 19.1l225.1 225c2.6 2.6 6.1 4 9.5 4s6.9-1.3 9.5-4c5.3-5.3 5.3-13.8 0-19.1l-215.4-215.5z"/></svg>
</div>
<div class="slider-nav__right nav-btn-slider">
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 477.175 477.175"><path d="M360.73 229.075l-225.1-225.1c-5.3-5.3-13.8-5.3-19.1 0s-5.3 13.8 0 19.1l215.5 215.5-215.5 215.5c-5.3 5.3-5.3 13.8 0 19.1 2.6 2.6 6.1 4 9.5 4 3.4 0 6.9-1.3 9.5-4l225.1-225.1c5.3-5.2 5.3-13.8.1-19z"/></svg>
</div>
<ul class="slider-item-list">
<li class="slider-item" style="background-color: #6495ED">
<div class="slider-text-wrap">
<div class="slider-text" data-text='Example text 1'></div>
</div>
</li>
<li class="slider-item" style="background-color: #BA55D3">
<div class="slider-text-wrap">
<div class="slider-text" data-text='Example text 2'></div>
</div>
</li>
<li class="slider-item" style="background-color: #8DEEEE">
<div class="slider-text-wrap">
<div class="slider-text" data-text='Example text 3'></div>
</div>
</li>
</ul>
</div>
</div>
JavaScript:
printTextSlider();
function printTextSlider() {
var $btn = $('.nav-btn-slider'),
$ul = $('.slider-item-list'),
$activeLi = $ul.find('.slick-active'),
$text = $activeLi.find('.slider-text');
$text.addClass('is-active');
printText($text);
$btn.on('click', function() {
var $activeLi = $ul.find('.slick-active'),
$siblings = $activeLi.siblings().find('.slider-text'),
$text = $activeLi.find('.slider-text'),
id = $text.attr('id');
setTimeout(function() {
$siblings.removeClass('is-active');
}, 1000);
$text.addClass('is-active');
printText($('#'+id));
});
}
function printText(el) {
var a = el.data('text');
a = a.split('');
console.log(a);
el.text('');
var c = a.length;
j = 0;
setInterval(function() {
if(j < c) {
el.text(el.text() + a[j]);
j++;
}
else {
el.removeClass('after-line');
}
}, 100);
}
Style(sass):
.slider-text-wrap {
max-width: 700px;
width: 100%;
margin: 0 auto;
padding-top: 230px;
}
.slider-text {
font-size: 36px;
word-wrap: break-word;
opacity: 0;
}
Proble: when you switch slides, the text displayed is not correct.
Where I'm wrong?
UPDATE: I found some interesting plugin typed.js and rewrite js code for this:
printTextSlider();
function printTextSlider() {
var $btn = $('.nav-btn-slider'),
$ul = $('.slider-item-list'),
$active = $ul.find('.slick-active'),
$span = $active.find('.slider-text'),
text = $span.data('text');
$span.typed({
strings: [text],
typeSpeed: 100,
startDelay: 1300,
showCursor: false,
});
$btn.on('click', function() {
var $active = $ul.find('.slick-active'),
$span = $active.find('.slider-text'),
text = $span.data('text');
printText($span, text);
});
}
function printText(el, text) {
el.typed({
strings: [text],
typeSpeed: 100,
startDelay: 1800,
showCursor: false
});
}
It's work!

How do I stop clicking next too many times from breaking my image rotator?

Im new to jquery and have been trying to code a simple image rotator, it works well at the moment except for the fact that if you click the "next" of "prev" buttons too many times very quickly it will break the image rotator.
Here is the html:
<div id="viewport">
<div id="imageContainer">
<div class="image" style="background-color:red;">
<div class="title"><p>This is the title of the post</p></div>
</div>
<div class="image" style="background-color:green;">
<div class="title"><p>This is the title of the post</p></div>
</div>
<div class="image" style="background-color:yellow;">
<div class="title"><p>This is the title of the post</p></div>
</div>
<div class="image" style="background-color:brown;">
<div class="title"><p>This is the title of the post</p></div>
</div>
<div class="image" style="background-color:purple;">
<div class="title"><p>This is the title of the post</p></div>
</div>
</div>
</div>
<input type="button" name="prev" id="prev" value="prev" />
<input type="button" name="next" id="next" value="next" />
and jquery:
var ic = $('#imageContainer');
var numItems = $('.image').size();
var position = 0;
ic.css('left', '0px');
var inter;
var rotateTimeout;
function rotate(){
inter = setInterval(function(){
if (position == (numItems - 1)) {
console.log(position);
$('.image').first().insertAfter($('.image').last());
ic.css('left', '+=400px');
position--;
}
ic.animate({opacity: 0.2, left: "-=400px"}, 1500, function(){
ic.animate({opacity: 1.0}, 1000);
});
position += 1;
}, 6000);
}
rotate();
$('#prev').click(function () {
console.log(position);
if (position == 0) {
$('.image').last().insertBefore($('.image').first());
ic.css('left', '-=400px');
position++;
}
ic.animate({
left: "+=400px"
});
position -= 1;
clearInterval(inter);
clearTimeout(rotateTimeout);
rotateTimeout = setTimeout(rotate, 10000);
});
$('#next').click(function () {
if (position == (numItems - 1)) {
console.log(position);
$('.image').first().insertAfter($('.image').last());
ic.css('left', '-400px');
position--;
}
ic.animate({
left: "-=400px"
});
position += 1;
clearInterval(inter);
clearTimeout(rotateTimeout);
rotateTimeout = setTimeout(rotate, 10000);
});
Here is a demo of the rotator.
So how can I either stop the user from clicking the button too quickly, or perhaps only account for a click per two seconds to allow the rotator to do what it needs?
To limit function call frequency you can use some "Throttle" function. For example _.throttle from Underscore.js or any other implementation. It is not necessary to use whole library, only required function could be copied from there.
The event handler attachment will look like this:
$('#prev').click( _.throttle(function () { yours code... }, 2000) );

Categories