I have a title that is in the h3 tag. My code works using slideUp but slideDown looks so bad. I want the slideDown animations smooth like in slideUp. Basically, slideDown from the last array to the first array, and then the cycle continues (an infinite). Here is my code: HTML:
<div class="services-slide-up">
<h3 class="services-it-consulting">IT Consulting</h3>
<h3 class="services-web-dev">Web Development</h3>
<h3 class="services-mobile-app-dev">Mobile App Development</h3>
<h3 class="services-ui-ux-design">UI/UX Design</h3>
<h3 class="services-team-dev">Team Development</h3>
<h3 class="services-software-testing">Software Testing</h3>
</div>
jQuery
$(document).ready(function() {
var divs = [$(".services-it-consulting"), $(".services-web-dev"), $(".services-mobile-app-dev"), $(".services-ui-ux-design"), $(".services-team-dev"), $(".services-software-testing")];
var i = 0;
function animateDivs() {
divs[i].slideDown(1000, function() {
divs[i].slideUp(1000, function() {
i++;
if (i >= divs.length) {
i = 0;
}
animateDivs();
});
});
}
animateDivs();
});
loop();
function loop()
{
let divs = [$(".services-it-consulting"), $(".services-web-dev"), $(".services-mobile-app-dev"), $(".services-ui-ux-design"), $(".services-team-dev")];
let counter = 0;
for(let i = 0; i < divs.length; i++) {
setTimeout(function(){ divs[i].slideUp('slow') }, 1000 * counter);
counter++;
}
var down=1;
for(let j = divs.length-1; j > 0; j--) {
setTimeout(function(){
divs[j].slideDown('slow');
down++;
// base case
if (down == divs.length) {
loop();
}
}, 1000 * counter);
counter++;
}
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div class="services-slide-up">
<h3 class="services-it-consulting">IT Consulting</h3>
<h3 class="services-web-dev">Web Development</h3>
<h3 class="services-mobile-app-dev">Mobile App Development</h3>
<h3 class="services-ui-ux-design">UI/UX Design</h3>
<h3 class="services-team-dev">Team Development</h3>
<h3 class="services-software-testing">Software Testing</h3>
</div>
I have used to setTimeout to slide up and slide own to call function in looping.see in the code
You have semantic issues and I find the nested slide up / down event very confusing. What you can do is to place a setTimeout on each event and multiply it by a counter. This counter should be consistent also for the slideDown event. A solution could look like the following.
However be aware of memory allocation issues since the setTimeout is executed immediately. So this will create 8 timeout functions in total. Not a big deal at this point but can become an issue, so please be aware of that.
let divs = [$(".services-it-consulting"), $(".services-web-dev"), $(".services-mobile-app-dev"), $(".services-ui-ux-design"), $(".services-team-dev")];
let counter = 0;
for(let i = 0; i < divs.length; i++) {
setTimeout(function(){ divs[i].slideUp('slow') }, 1000 * counter);
counter++;
}
for(let j = divs.length-1; j >= 0; j--) {
setTimeout(function(){ divs[j].slideDown('slow') }, 1000 * counter);
counter++;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div class="services-slide-up">
<h3 class="services-it-consulting">IT Consulting</h3>
<h3 class="services-web-dev">Web Development</h3>
<h3 class="services-mobile-app-dev">Mobile App Development</h3>
<h3 class="services-ui-ux-design">UI/UX Design</h3>
<h3 class="services-team-dev">Team Development</h3>
<h3 class="services-software-testing">Software Testing</h3>
</div>
Related
So far this is what I have tried. I cant seem to figure out how to reset the img src to the first image in the folder after the user does not click on a button for 5 seconds.
HTML
<div class="slider">
<div class="img-box">
<img src="images/a.jpg" class="slider-img">
</div>
<button id="first" class="btn" onclick="prev()">Prev</button>
<button id="second" class="btn" onclick="next()">Next</button>
</div>
JavaScript
var slider_img = document.querySelector('.slider-img');
var images = ['a.jpg', 'b.jpg', 'c.jpg', 'd.jpg', 'e.jpg'];
var i = 0;
function prev(){
if(i <= 0) i = images.length;
i--;
return setImg();
}
function next(){
if(i >= images.length-1) i = -1;
i++;
return setImg();
}
function setImg(){
return slider_img.setAttribute('src', "images/"+images[i]);
}
var btnDwn = document.onmousedown
function idk(){
return slider_img.setAttribute('src', "images/"+images[0]);
}
if(btnDwn == false){
setInterval(idk(),5000)
}
I'll define "inactivity/idleness" to if user stops moving mouse AND stops clicking
I do this by making a function that every time you call it, a timeout is set(and the previous timeout deleted) so that the content INSIDE the timeout ONLY activates AFTER 5 seconds of NOT BEING TRIGGERED
Do note that to be idle, stop using your mouse and do not click the functions for about 5 seconds and see it in action :D
var slider_img = document.querySelector('.slider-img');
var images = ['a.jpg', 'b.jpg', 'c.jpg', 'd.jpg', 'e.jpg'];
var i = 0; var timeout=0;
function prev(){
if(i <= 0) i = images.length;
i--; resetImg();
return setImg();
}
function next(){
if(i >= images.length-1) i = -1;
i++; resetImg();
return setImg();
}
function setImg(){
return slider_img.setAttribute('src', "images/"+images[i]);
}
function resetImg(){
clearTimeout(timeout);
timeout=setTimeout(()=>{slider_img.setAttribute('src', "images/"+images[0]);},5000);
}
//every time you click those buttons, you are 'active', now being active would also count as moving your mouse
document.body.addEventListener('mousemove',resetImg)
I have attempted to find an answer to my question here on Stack Overflow but have been unsuccessful in finding one.
As part of my JavaScript learning I am trying to create my own carousel slider. The problem is I am trying to allow for X number of sliders on the same page, each with their own automatic timers and controls. This is proving to be an issue when I try to control either one of them. For instance if I manually control one of them, the other one then stops playing as the paused variable is set to true.
I'm pretty sure that my issue is either the scope of the variables or not being more specific with targeting the slider elements (e). I may have been looking at this too long and have somewhat lost perspective on it. I would appreciate any advice with this or even just a nudge in the right direction.
Thanks.
HTML
<div id="slider-1" class="slider-wrap">
<div class="slider ">
<div class="slide-wrap" data-slide="0">
<div class="slider-slide" style="background-image: url(image1.png)">
<div class="slide-text text-background">
Slide 1
</div>
</div>
</div>
<div class="slide-wrap" data-slide="1">
<div class="slider-slide" style="background-image: url(image2.png)">
<div class="slide-text text-background">
Slide 2
</div>
</div>
</div>
<div class="slide-wrap current-slide" data-slide="2">
<div class="slider-slide" style="background-image: url(image3.png)">
<div class="slide-text text-background">
Slide 3
</div>
</div>
</div>
</div>
</div>
Javascript
// Setup variables
let helpers = require('./helpers.js')
let sliders = document.getElementsByClassName('slider-wrap')
let paused = false
//Get all sliders on page and start slider function
for (var i = 0; i < sliders.length; i++) {
let slideIndex = 0
let e = sliders[i]
slider(e, slideIndex)
autoChange(e, slideIndex)
}
// Slider function which adds indicator click listeners
function slider (e, slideIndex) {
let element = e
let interval
let indicators = e.getElementsByClassName('slide-indicator')
for (var i = 0; i < indicators.length; i++) {
indicators[i].addEventListener('click', function (e) {
let slideIndex = Number(e.target.dataset.slide)
paused = true
if (helpers.hasClass(e.target, 'current') === false) {
clearTimeout(interval)
sliderChange(element, slideIndex)
}
})
}
}
// Change slider based on index and update classes
function sliderChange (e, slideIndex) {
let slides = e.getElementsByClassName('slide-wrap')
let indicators = e.getElementsByClassName('slide-indicator')
let num = slides.length - 1
let prev = e.querySelector('.current-slide')
for (var i = 0; i < slides.length; i++) {
slides[i].classList.remove('current-slide')
indicators[i].classList.remove('current')
}
slides[slideIndex].classList.add('current-slide')
indicators[slideIndex].classList.add('current-indicator')
if (paused === false) {
autoChange(e, slideIndex)
}
}
// Automatically change slide
function autoChange (e, slideIndex) {
let slides = e.getElementsByClassName('slide-wrap')
let num = slides.length - 1
if (slideIndex === num) {
slideIndex = 0
} else {
slideIndex++
}
interval = setTimeout(function () {
sliderChange(e, slideIndex)
}, 3000)
}
Having paused as global variable is an issue at least. I would recommend you to create a javascript object for each slider so that each slider would have their own "paused" property.
let sliders = document.getElementsByClassName('slider-wrap')
var sliderObjects = []
for (i = 0; i < sliders.length; i++) {
var slider = {slider: sliders[i], paused: false}
sliderObjects[i] = slider
}
Here some useful reference on JavaScript Objects: https://www.w3schools.com/js/js_objects.asp
I have made a set of traffic lights that light in sequence but I want to load a timer when the web page is opened that changes the lights in sequence every 2 seconds, instead of clicking a button.
I attempted to do this but it's not working, if any of you know why and can help, please do. Thanks.
<html>
<body onload="timer()">
<div class="container">
<button class="btn" onclick="traffic_lights()">Change Lights</button>
<img id="traffic-light" src="" alt="traffic lights">
</div>
</body>
<script>
var traffic_light_img = [];
var i = 0;
function traffic_lights() {
if (i <= 3) {
i++;
document.getElementById("traffic-light").src = traffic_light_img[i];
} else {
i = 0;
document.getElementById("traffic-light").src = traffic_light_img[i];
}
}
function timer() {
setInterval(traffic_lights, 2000);
}
</script>
You code already affects the traffic lights automatically based on a timer. The only problem is that you don't include any images to load, and that you increment your index before loading the images. Remember, lists start at index 0!
Instead of:
if (i <= 3) {
i++;
document.getElementById("traffic-light").src = traffic_light_img[i];
}
You need:
if (i < 3) {
document.getElementById("traffic-light").src = traffic_light_img[i];
i++;
}
Here's the full code, complete with some placeholder images:
<html>
<body onload="timer()">
<div class="container">
<img id="traffic-light" src="http://placehold.it/100" alt="traffic lights">
</div>
</body>
<script>
var traffic_light_img = [
"http://placehold.it/200",
"http://placehold.it/300",
"http://placehold.it/100",
];
var i = 0;
function traffic_lights() {
if (i < 3) {
document.getElementById("traffic-light").src = traffic_light_img[i];
i++;
} else {
i = 0;
document.getElementById("traffic-light").src = traffic_light_img[i];
}
}
function timer() {
setInterval(traffic_lights, 2000);
}
</script>
I've also removed the button in the above sample, as it's not needed.
Hope this helps! :)
I am trying to implement anchor points to scroll to certain "Views" on my Jack-Scrolling home page. I have used an approach shown on CodePen or below. However, because of this approach any <a name="xyz"></a> tags in my code when referenced by www.domain.com#xyz just show the first "page" of my website. How can I work around this, or produce comparable results with an alternative tagging method?
<div id="projects">
<section id="project-0" class="slide active"> Test 1</section>
<section id="project-1" class="slide active"> testing 2</section>
<section id="project-2" class="slide active"> This is testing 3</section>
</div>
JS:
var delta = 0;
var currentSlideIndex = 0;
var scrollThreshold = 30;
var slides = $(".slide");
var numSlides = slides.length;
function elementScroll (e) {
console.log (Math.abs(delta));
// --- Scrolling up ---
if (e.originalEvent.detail < 0 || e.originalEvent.wheelDelta > 0) {
delta--;
if ( Math.abs(delta) >= scrollThreshold) {
prevSlide();
}
}
// --- Scrolling down ---
else {
delta++;
if (delta >= scrollThreshold) {
nextSlide();
}
}
// Prevent page from scrolling
return false;
}
function showSlide() {
delta = 0; // reset
slides.each(function(i, slide) {
$(slide).toggleClass('active', (i >= currentSlideIndex));
});
}
function prevSlide() {
currentSlideIndex--;
if (currentSlideIndex < 0) {
currentSlideIndex = 0;
}
showSlide();
}
function nextSlide() {
currentSlideIndex++;
if (currentSlideIndex > numSlides) {
currentSlideIndex = numSlides;
}
showSlide();
}
$(window).on({
'DOMMouseScroll mousewheel': elementScroll
});
Thanks very much, just to help you read the code, the approach is to place each of the slides on top of each other and then only show the one that is defined by the scroller index (which is incremented and decremented if the scroll is greater than our scroll threshold). - Possibly something using JQuery? Thanks for your help.
I have several sections like this:
<section class="one">
<div class="two over" element="myelement1">
<div class="front" >
<img src="element.jpg" width ="100%;" height ="100%;" alt="">
</div>
<div class="back">
</div>
</div>
</section>
<section class="one ">
<div class="two over" element="myelement2">
<div class="front" >
<img src="element2.jpg" width ="100%;" height ="100%;" alt="">
</div>
<div class="back">
</div>
</div>
</section>
Then I have a function like:
var i = j =0;
$(function () {
$('.over').hover(function () {
/*do something*/
}, function () {
if ( $(this).attr('element') == 'myelement1'){
img = $(this).find('img');
img.attr('src', arr_1[i]);
i++;
if(i > arr_1.length-1) i=0;
}
if ( $(this).attr('element') == 'myelement2'){
img = $(this).find('img');
img.attr('src', arr_2[j]);
j++;
if(j > arr_2.length-1) j=0;
}
});
})
How can I store in global variables or maybe a dictionary
the values of each img = $(this).find('img'); so I do this only once and not every time the user is in .hover?
First off, you probably don't need to solve the problem you're trying to solve. Modern computer are so fast that searching the children of an object for imgs is a very fast operation (unless perhaps there are thousands). So, you probably shouldn't be trying to optimize this at all unless you have actual performance data that says there really is a problem here.
Always measure before optimizing to know what problems are actually there and actually need solving. Then, measure any potential solution to see if it's actually doing what you need.
As to the actual question you ask, there are a couple options.
You can retrieve it the first time and then just save it in a global:
var i = j =0;
var imgs1, imgs2;
$(function () {
$('.over').hover(function () {
/*do something*/
}, function () {
if ( $(this).attr('element') == 'myelement1'){
if (!imgs1) {
imgs1 = $(this).find('img');
}
imgs1.attr('src', arr_1[i]);
i++;
if(i > arr_1.length-1) i=0;
}
else if ( $(this).attr('element') == 'myelement2'){
if (!imgs2) {
imgs2 = $(this).find('img');
}
imgs2.attr('src', arr_2[j]);
j++;
if(j > arr_2.length-1) j=0;
}
});
})
or, more in the spirit of jQuery, use .data() instead of globals:
var i = j =0;
$(function () {
$('.over').hover(function () {
/*do something*/
}, function () {
var imgs = $(this).data("imgList");
if (imgs) {
imgs = $(this).find('img');
$(this).data("imgList", imgs);
}
if ( $(this).attr('element') == 'myelement1'){
imgs.attr('src', arr_1[i]);
i++;
if(i > arr_1.length-1) i=0;
}
else if ( $(this).attr('element') == 'myelement2'){
imgs.attr('src', arr_2[j]);
j++;
if(j > arr_2.length-1) j=0;
}
});
})