Chaining this effect sequentially - javascript

This is probably really simple to do. Everything works, this is a horizontal slider that slides one image after another. The issue is, one image slides up, but once that image has slide up, then starts the previous one. My questions is. How do you chain this so that one, slides up but you see the other slide up after the last one.
This function moves the completed slide at the end of the last LI.
function cloneView(){
$('.complete').each(function(){
$(this).clone().insertAfter('.slide_img ul li:last').addClass('slides',function(){
//$('.slides').css({display : "block"});
}).removeClass('complete');
$('.complete').first().remove();
});
}
This function checks how many LI's there are(totalSlides). It also slidesup the current li and sets it as class="complete" (which is how the cloneView knows to move it).
$(function () {
var slideS = $('.slide_img ul li');
var comp = $('.slide_img ul li.viewing');
slideHeight = $('.slide_img').height();
totalSlides = slideS.length;
slideLength = totalSlides * slideHeight;
slideS.addClass('slides').css({
display: "none"
});
slideS.first().addClass('viewing').removeClass('slides').css({
display: "block"
});
slideS.last().addClass('last_img').removeClass('slides');
slideInterval = setInterval(function () {
$('.viewing').delay(1000).slideUp("slow", function () {
$(this).addClass('complete').removeClass('viewing');
$(this).next('li').addClass('viewing', function () {
$(this).removeClass('slides').effect('slide', {
direction: 'down',
mode: 'show'
});
cloneView();
});
});
}, 10000);
});
I plan to turn this into a plugin (even though I am sure there are hundreds of them).
Here is a jsfiddle.

Here is a much easier way of doing what you want
http://jsfiddle.net/LCDXj/3/
Made sure that only the .current-slide class is visible via CSS:
.slide_img {
height: 445px;
overflow: hidden;
position: fixed;
text-align: center;
top: 60px;
width: 100%;
}
.slide_img ul li img {
width: 100%;
}
.slide_img ul li{
position: relative;
display: none;
}
.slide_img > ul {
list-style: none outside none;
margin: 0;
padding: 0;
}
.slide_img ul li.current-slide
{
display: block;
}
Set the first element in the slider to be .current-slide
Every X seconds, slide the current slide up then append it to the back of
the list
Immediately after queueing up the action to slide the first
slide up, also queue up the action to slide the next slide in the
DOM structure down.
$(function()
{
var slideS = $('.slide_img ul li');
slideHeight = $('.slide_img').height();
totalSlides = slideS.length;
var imgSize = $('.slide_img ul li img').height();
slideLength = totalSlides * slideHeight;
slideS.first().addClass('current-slide');
slideInterval=setInterval(function()
{
slideS.filter('.current-slide').slideUp(function()
{
$(this).appendTo($(this).parent()).removeClass('current-slide');
}).next().slideDown().addClass('current-slide');;
}, 5000);
});
The key thing to note that I am doing that you were not is that I am not waiting for the first slide to finish sliding up to start sliding the next one down.
Additionally, by simply appending the element to the end of the <ul /> afterwards, we don't need to worry about any kind of fancy cloning.

Related

jQuery: Add / Remove style while scrolling past div's

I have this page (https://www.datacoral.com/architecture/) that has a left sidebar with five bullet points. What I want to happen is as the user scrolls past these five div's on the right hand column, the text in one of these bullet points adds a class called 'bolder' and the text become a font-weight of 700 to let the user know what point they are in on the page. As the pass by that same div, the class disappears and ends up in the next bullet point since you're now passing by another div.
I've got it partially working but it's not hitting the right point of the div at all. Seems to add the class as you are passing the bottom of the div instead of the top.
This is the code I'm currently working with. Anyone know what I might be doing wrong so this can function properly?
Note: Should mention I'm basically duplicating this code five times and just swapping out the numbers.
jQuery(function(){
jQuery(window).scroll(function() {
var scroll = jQuery(window).scrollTop(); // how many pixels you've scrolled
var os = jQuery('#guide_body-0').offset().top; // pixels to the top of div1
var ht = jQuery('#guide_body-0').height(); // height of guide_body-0 in pixels
if(scroll > os + ht){
jQuery('.scroll-nav-0').addClass('bolder');
}
});
});
I think firing a function on scroll like that gets a little bit crazy. I always delay the function until the scrolling has stopped.
As far as the catch point, i think your code is applying the classes when the element has moved out of view. i would use the bottom of the browser screen as a reference point.
Think about it like this:
$(window).scrollTop() returns 0 at the top of the page.
$('#guide_body-0').offset().top returns 1000px.
So $(window).scrollTop() is equal to $('#guide_body-0').offset().top when that element is at the top of the screen.
Add $('#guide_body-0').height() to the equation and that puts the scroll position (the top of the screen) at the bottom of the element.
What you need to do is check if the offset.top property of the element is in a scroll position which puts it above the bottom of the screen.
UPDATE
The code here is for a custom solution. But if you are looking for a way to just add simple animations to elements as they scroll into view, check out wow.js and animate.css
https://wowjs.uk/
https://animate.style/
// Init variable for timer
let timer;
// Get target element
const el = $("#4");
// Get viewport height
const screen = window.innerHeight;
// Fire callback on window scroll
$(window).scroll(function() {
// Clear timeout just in case
clearTimeout(timer);
// Check if the element already has the class
if (!el.hasClass("active")) {
// Set a delay timer then run the function
timer = setTimeout(check_el_pos, 300);
}
});
function check_el_pos() {
// Clear the timer
clearTimeout(timer);
// Get current scroll position
let scroll_pos = $(window).scrollTop();
// This is the math here. Add scroll position to screen height and you get the bottom of the screen. When that value equals the top offset of the element, we are there.
if (scroll_pos + screen > el.offset().top) {
console.log(scroll_pos + screen);
console.log(el.offset().top);
// Add the classes to the element. Boom, we're done.
el.removeClass("active").addClass("active");
}
}
body,
html {
padding: 0;
margin: 0;
}
.example-grid {
list-style: none;
padding: 0;
margin: 0;
width: 100%;
display: grid;
grid-gap: 40px;
}
.example-grid>li {
list-style: none;
padding: 0;
margin: 0;
width: 100%;
height: 65vh;
background: slategray;
display: flex;
justify-content: center;
align-items: center;
text-align: center;
color: #fff;
font-size: 2em;
line-height: 1em;
transition: background-color 1s;
transition-timing-function: ease-out;
}
.example-grid>li:nth-child(even) {
background: coral;
}
.example-grid>li.active {
background: aquamarine;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<ul class="example-grid">
<li id="1">1</li>
<li id="2">2</li>
<li id="3">3</li>
<li id="4">4</li>
<li id="5">5</li>
<li id="6">6</li>
<li id="7">7</li>
</ul>

how to set a scroll bar size without having content

I am trying to create a data-grid where I am not displaying all the records in the beginning and want to render them when scrolled. Is there a way I can set a scroll size based on the amount of data that I have and change the data in the dev when user scrolls.
I know there are grid's out there but I do not want to use them and want to know what are the different ways to do it.
I have tried looking into the scroll event and I did not find anything about the scroll direction or the current offset. Is there any documentation I can find. or even a technical name to search for would help me.
You can search for a "infinity scroll" with javascript and html.
EXAMPLE HTML: `<ul id='infinite-list'></ul>`
EXAMPLE CSS: `#infinite-list {
/* We need to limit the height and show a scrollbar */
width: 200px;
height: 300px;
overflow: auto;
/* Optional, only to check that it works with margin/padding */
margin: 30px;
padding: 20px;
border: 10px solid black;
}
/* Optional eye candy below: */
li {
padding: 10px;
list-style-type: none;
}
li:hover {
background: #ccc;
}`
EXAMPLE JAVASCRIPT: `var listElm = document.querySelector('#infinite-list');
// Add 20 items.
var nextItem = 1;
var loadMore = function() {
for (var i = 0; i < 20; i++) {
var item = document.createElement('li');
item.innerText = 'Item ' + nextItem++;
listElm.appendChild(item);
}
}
// Detect when scrolled to bottom.
listElm.addEventListener('scroll', function() {
if (listElm.scrollTop + listElm.clientHeight >= listElm.scrollHeight) {
loadMore();
}
});
// Initially load some items.
loadMore();
`

Trying to do a horizontal slide nav with endless loop

Trying to do a regular horizontal nav with arrow that has a endless loop. Tried figuring it out and some how I can't get it to loop back to "all" div.
tried slick carousel but it has this glitch when the page loads
HTML
<div id="second-navigation">
<div id="slider">
<li>All</li>
<li>slide1</li>
<li>slide2</li>
</div>
</div>
JS
var W = $('#second-navigation').width();
var N = $('#slider li').length;
var C = 0;
$('#slider').width( W*N );
$('#left, #right').click(function(){
var myID = this.id=='right' ? C++ : C-- ;
C= C===-1 ? N-1 : C%N ;
$('#slider').stop().animate({left: -C*W }, 1000 );
});
CSS
#second-navigation{
width:300px;
height:150px;
position:relative;
overflow:hidden;
}
#slider{
position:absolute;
height:150px;
left:0;
width:9999px;
}
#slider li{
float:left;
}
One approach would be to as follows:
When a direction button (ie left or right) is clicked, clone the list item that will be moved out of view by the animation (ie the first <li> for the <ul> when the "left" button is clicked)
attach the cloned <li> to the opposite end of the <ul> list (ie append the cloned first to the end of <ul> when "left" is clicked
animate the margin of the <ul> element to hide the original <li> that was cloned (ie for the "left" case, animate the <ul> left margin to "-150px", which is the width of your <li> items)
On completion of the animation, ensure the <ul> margin is reset, and that the now hidden <li> element has been removed
This can be written in code as shown below. There are a few extra things going on here:
The <ul> needs to be the direct parent of <li> items (a <div> cannot parent <li> items)
Flex box is used to achieve horizontal layout of <li> items, which simplifies CSS styling
Compounded animations need to be prevented (ie the case where button click happens during an existing animation). Below, I'm just ignoring clicks if an animation is underway
$("#left").click(function() {
/* If currently animated, early exit */
if($("#second-navigation ul:animated").length) {
return;
}
/* Clone the element that will be hidden */
var firstClone = $("li:first-child").clone();
$("#second-navigation ul")
.animate({
/* Animate ul container left margin to left */
"marginLeft": "-150px"
}, {
done: function() {
/* Reset ul container left margin */
$(this).css("marginLeft", "0px");
/* Remove element that is now hidden */
$("li:first-child", "#second-navigation ul").remove();
}
})
/* Add cloned element to end of list */
.append(firstClone);
});
$("#right").click(function() {
if($("#second-navigation ul:animated").length) {
return;
}
var lastClone = $("li:last-child").clone();
$("ul")
.css({
"marginLeft": "-150px"
})
.animate({
"marginLeft": "0"
}, {
done: function() {
$("li:last-child", "#second-navigation ul").remove();
}
})
.prepend(lastClone);
});
#second-navigation {
position: relative;
overflow: hidden;
width: 300px;
height: 150px;
}
ul {
display: flex;
width: fit-content;
flex-direction: row;
padding: 0;
margin: 0;
}
li {
position: relative;
height: 150px;
width: 150px;
top: 0;
left: 0;
transition: left ease-in-out 1s;
background: linear-gradient(45deg, black, transparent);
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/2.0.0/jquery.min.js"></script>
<div id="second-navigation">
<ul>
<li>All</li>
<li>slide1</li>
<li>slide2</li>
</ul>
</div>
<button id="left">Move left</button>
<button id="right">Move right</button>
Hope this helps!

Get jQuery dropdown to load and drop gracefully

I am trying to get this jQuery dropdown to work properly: http://jsfiddle.net/a2geG/2/
The first problem is that both .bounce-summary div elements are open by default. I'd like them to be closed by default and have included the following to achieve that, but it doesnt seem to work:
.bounce-summary {
width: 75%;
height: 100px;
background: #ccc;
position: relative;
display: none;
}
The second issue is that when then first li element is clicked, the bottom one doesn't transition smoothly but seems to jump a bit as well. How can I prevent this behavior?
Thanks!
Try setting easing: 'swing', it makes it much smoother and just set toggle to false later after defining toggle. Fiddle
$(document).ready(function () {
$("ol.rounded-list li").click(function () {
$(this).find("div.bounce-summary").toggle("slide", {
duration: 700,
easing: 'swing',
direction: 'up'
});
});
$(this).find("div.bounce-summary").toggle(false);
});
Update 1
I just added to .rounded-list the following css:
div.enumerate {
display: block;
margin: .5em 0;
}
while removing margin: .5em 0; from the main div:
Updated Fiddle: Fiddle
The boxes are both expanded because you define:
.rounded-list {
...
div {
display: block;
}
...
}
which takes precedence over the display: none defined in your .bounce-summary, as the aforementioned selector is more specific.
I ll tell you what the problem is :
when you add margin to div then it adds to all the divs.
So when you try clicking to have the bounce effect, the resulting div will have margins on top and bottom as well as the original div which is already present.
added
li{
margin: .5em 0;
}
.bounce-summary{
margin-top: 10px;
}
and removed the margin from the div.
fiddle here

How to trigger the layout to change?

I've a sticked element which gets the top-alignment from current scroll-offset. Problem is, that the layout is not "retriggerd" if the space from it is free. So there stays a ghost-gap where the sticked element was...
http://fiddle.jshell.net/pPc4V/
The markup is pretty simple:
...
as well as the js:
var $win = $(this);
var sticked = document.querySelector('a.sticked');
$win.on('scroll', function () {
var scrollTop = $win.scrollTop();
sticked.style.top = scrollTop + 'px';
// $win.resize();
});
...and the css looks good so far:
a {
display: inline-block;
width: 90px;
height: 90px;
background: deepskyblue;
}
.sticked {
position: relative;
top: 0;
left: 0;
background: tomato;
}
I tried to trigger the resize-event on scroll (as you see above uncommented), but no success! Any ideas, how to retrigger the layout so that the free-gap is filled with the next floated element?
Update
To clarify what I mean I made a simple image-timelime:
Step 1
Step 2
Step 3
The issue is that you are setting position fixed on an element which is displayed inline. That will cause that space to occur. I have redid your jsFiddle with proper alignment.
To fix it, I added the class "stuck" only when the document's scrollTop position is greater than the scrollTop position of your target element.
jsFiddle: http://fiddle.jshell.net/pPc4V/44/
HMTL:
<div id="grid">
etc...
</div>
CSS:
#grid {
height:1000px;
overflow:hidden;
float:left
}
#grid > a {
display: inline-block;
width: 90px;
height: 90px;
background: deepskyblue;
}
.stuck {
position: fixed;
background: navy !important;
}
JS:
$(window).on('scroll', function () {
var $doc = $(document),
parentElement = $('#grid'),
childToGetStuck = parentElement.find('a:nth-child(5)');
if ($doc.scrollTop() > childToGetStuck.scrollTop()) {
childToGetStuck.addClass('stuck');
//console.log($('.stuck').scrollTop())
} else {
childToGetStuck.removeClass('stuck');
}
});

Categories