Making a jquery carousel from scratch - javascript

I know there are a ton of questions on here about jquery image carousel, but they all refer to a plugin. I would like to make one from scratch. It's a pretty simple one, there are 2 buttons, one left and one right. when you click the left button, the position of the overall container that has all the images shifts to the left, and the right makes it go right.
This is what I have so far... Right now the problem is only the left button works. (the right button works only once you slide the image to the left once) And I also want it to animate across all the images, and go to the last image when you get to the end of the set of images
JS:
total_entries = $("image-entry").length;
var current_index = 0;
var slider_entries = $('#slider-entries');
$('#home-slider #left').click(function(){
go_to_index(current_index-1);
return false;
});
$('#home-slider #right').click(function(){
go_to_index(current_index+1);
return false;
});
var go_to_index = function(index){
if(index < 0)
index = total_entries - 1;
if(index > total_entries - 1)
index = 0;
if(current_index == index)
return;
var left_offset = -1 * index * 720;
slider_entries.stop().animate({"left": left_offset}, 250);
//description_container.stop().animate({"left":left_offset}, 250);
current_index = index;
};
HTML:
<div id="slider">
<div id="slider-entries">
<div class="image-entry">
<img src="http://placekitten.com/720/230" />
</div>
<div class="image-entry">
<img src="http://placedog.com/720/230" />
</div>
<div class="image-entry">
<img src="http://placedog.com/720/230" />
</div>
</div>
</div>
total width of each image is 720px
total with of slider-entries is
Thanks

You have a problem with the total_entries variable.
First of all you need a "var" in front, to define that it's a new variable.
Second, you forgot a "." (dot) to search for the class in your HTML code..
your first line should be:
var total_entries = $(".image-entry").length;
Hope it works ;-)

Related

In pure JS, I am trying to set two similar classes but with different numbers or to set the same class to two different elemnts

I tried to set the same class imagens-giratorias to two elements or to set imagens-giratorias and imagens-giratorias-2. The class worked in first element, and the same class stopped of animating in the second element.
[I provide the JSFiddle at the end.]
Check the #rafaelcastrocouto's original code at https://stackoverflow.com/a/59524483/8041366. If you prefer reading the complete code here, here is the code taken from there, but with a bit modified:
var counter = 1;
var div = document.querySelector('.imagens-giratorias');
var imagens = document.querySelectorAll('.imagens-giratorias img');
var showNext = function () {
counter++;
if (counter > 3) counter = 1;
div.classList.remove('imagem1', 'imagem2', 'imagem3')
div.classList.add('imagem'+counter);
};
for (var img of imagens) {
img.addEventListener('animationend', showNext);
}
And small CSS snippet:
<div class="section-2">
<div class="item-2">
<div class="imagens-giratorias imagem1">
</div>
</div>
</div>
<div class="section-3">
<div class="item-2">
<div class="imagens-giratorias imagem1">
</div>
</div>
Or
<div class="section-3">
<div class="item-2">
<div class="imagens-giratorias-2 imagem1">
</div>
</div>
1st solution, that same original code above I am referring.
2nd solution:
var div = document.querySelector('.imagens-giratorias, .imagens-giratorias-2');
var imagens = document.querySelectorAll('.imagens-giratorias img, .imagens-giratorias-2 img');
3rd solution
var div = document.querySelector('[class^=imagens-giratorias]');
var imagens = document.querySelectorAll('[class^=imagens-giratorias] img');
4th solution
const contador = 1;
const div = document.querySelector('.imagens-giratorias');
const imagens = document.querySelectorAll('.imagens-giratorias img');
I also tried to use from multiple selectors with document.querySelectorAll. No luck.
But all these solutions did not work.
JSFiddle
Please pay attention to two elements. While one element will always animate, another will stop of animating.
https://jsfiddle.net/gusbemacbe/mbp84u6r/2/
If I understand you correctly you're trying to grab elements that have a class name starting with imagens-giratorias. If that's the case, use the ^ attribute selector as shown below:
document.querySelectorAll("[class^="imagens-giratorias"]")
Update:
Based on your update it appears that only one of your two divs' images is animating but in reality they're stacked on top of each of other. Feel free to use whatever layout method you want but for demonstration's sake I floated one left and the other right. Other that it was a matter of looping through your divs and assigning your function to their child images as so:
var divs = document.querySelectorAll('.imagens-giratórias');
var contador = 1;
var mostrarPróximo = function(div) {
contador++;
if (contador > 3) contador = 1;
div.classList.remove('imagem1', 'imagem2', 'imagem3')
div.classList.add('imagem' + contador);
};
Array.from(divs).forEach(function(div, index) {
var images = div.querySelectorAll('img');
Array.from(images).forEach(function(img) {
img.addEventListener('animationend', mostrarPróximo.bind(null, div));
});
});
https://jsfiddle.net/1r6yjf5s/

jQuery select DIV by class name starting from top

I have a structure like the following to create a one page web application, using some scroll functionalities:
<div class="home_section"></div> <!-- 1 -->
<div class="home_section"></div> <!-- 2 -->
<div class="home_section"></div> <!-- 3 -->
<div class="home_section"></div> <!-- 4 -->
I need to scroll to each of the above DIVs when the scroll event starts.
So, for example, when the scroll starts, if the first DIV visible from top is <!-- 2 -->, the body will have to scroll to the DIV <!-- 3 --> automatically.
This is what I am doing:
if ($(this).attr('id') == 'home') {
$(document).on("scrollstart", function (e) {
console.log('scrolling started on home');
e.preventDefault();
var next = $(this).find(".home_section"); //here I need to calculate which is the next DIV to scroll to
$('html, body').animate({
scrollTop: next.offset().top
});
});
}
The problem is that I do not know how to check which is the first .home_section DIV visibile starting from top, so I am unable to calculate which is the next target DIV to scroll to.
Thanks for ay help
I would loop through all the .home_sections divs, and get the first :visible like this
var divs = $(".home_section");
for(var x = 0; x < divs.length; x++){
if($(divs[x]).is(":visible")){
//do what you need here
var me = divs[x];
var next = x < divs.length - 1 ? divs[x] : undefined;
if(next){
//do the scroll
}
//then break the for loop
break;
}
}
This way you have an array of divs, you find the first visible and then you have the reference to the nth+1 div.
Another solution that should work:
var firstVisible = $(".home_section:visible:eq(0)");
var next = $(firstVisible).next();
hope this helps
next div would be $(this).next();
var next = $(this).next();
But you would need to modify this line for it to work for all divs:
if ($(this).attr('id') == 'home')
Modify the line var next = $(this).find(".home_section"); as below to get first div with class "home_section".
var next = $(this).getElementsByClassName("home_section")[0];

Randomised variable grid

I'm working on a website that needs to have a variable grid. It's based on Tumblr so unfortunately we can't use any PHP to solve our problem. We want to make some posts wider than other, but this should be done randomly and photo posts should be excluded from this.
The current markup for each of the text blocks is:
<article class="post text cf post-3">
<a href="#">
<div class="post-overview-header" style="background-image: url(https://31.media.tumblr.com/d4134dd4d2c48674e311ca0bb411d5cc/tumblr_inline_n3v11hGjI61s3vyc9.jpg); background-size: cover; background-position: 50% 0%; background-repeat: no-repeat no-repeat;">
<div class="hoverOverlay"></div>
<div class="post-overview-title">
<span class="post-title">posts adden</span>
<span class="post-date">
April 11, 2014
</span>
<span class="post-readingtime"><span aria-hidden="true" class="icon-readingtimesmall"></span><span class="eta">3 min</span></span>
</div>
</div>
<div class="post-content">
<p>this is the post's content</p>
</div>
</a>
</article>
My best shot at this grid is the following code but I wasn't able to check whether the wide post on the previous row is on the same level because that looks odd but I do want to do that.
var i = 0;
$('.post').each(function() {
// determine whether the count has to be reseted or not
if(i === 3){
i = 1;
}else{
i++;
}
$(this).addClass('post-' + i); // add one so the each post is properly named for this grid to work
if($(this).is(':first-of-type') || $(this).hasClass('text')){
$(this).not('.post-3').addClass('wide');
}
// in case the first of 2 posts is a wide one
if($(this).is('.wide.post-1')){
i = 2;
}
});
Desired effect: http://c.davey.im/Uzq9
Current effect http://c.davey.im/Uzsv
thanks in advance!
Thought I'd have a play and have come up with this: http://jsfiddle.net/andyface/7KCGJ/
Think it does the job you're after.
var i = 0,
prevRowWide = 0;
$('.post').each(function () {
//GENERATE POST POSITIONING INDEX
i === 3 ? i = 1 : i++;
// RANDOMLY GENERATE VALUE TO SAY IF POST SHOULD BE WIDE OR NOT
// CACHE CURRENT OBJECT, AIDDS PERFORMANCE
var addWide = Boolean(Math.round(Math.random())),
$elem = $(this);
$elem.addClass('post-' + i);
// MAKE SURE IT'S NOT A PHOTO
if( ! $elem.hasClass('photo')) {
// IF IT'S CHOSEN TO BE WIDE, THE PREVIOUS ROW DOESN'T HAVE A WIDE AT
// THAT POSITION AND IT'S IN POSITION 3 THEN ADD .wide AND UPDATE VARS
if(addWide && prevRowWide != i && i != 3) {
$elem.addClass('wide');
// STORES THE POSITION OF THE PREVIOUS ROWS WIDE SO YOU DON'T GET CLASHES
prevRowWide = i;
i++;
}
else if (i == prevRowWide) {
// IF WE'VE GOT BACK ROUND TO THE SAME ROW NUMBER AND IT'S NOT JUST
// BEEN SET ABOVE THEN WE CAN GET RID OF IT AS IT'S DONE IT'S JOB AND
// WE DON'T WANT IT AFFECTING THE NEXT ROW AS WELL
prevRowWide = 0;
}
}
});

Find respective divs, create new divs and append the ones that were found

so i am in a bit of a jam here and having a really hard time trying to solve this dilemma.
Here is what i am trying to do:
There is a container div (id=posts) full of other divs (name=posts).
I want it to grab in those divs and, by even/odd position, append them inside 2 other divs.
These 2 other divs are generated by javascript, one floats left and the other floats right.
Then i want it to empty the container div and insert the floating divs.
So far i have managed everything but one thing; it is only using the first found div...
Here is the HTML code:
<div id="posts">
<div name="posts">
left
</div>
<div name="posts">
right
</div>
<div name="posts">
left
</div>
<div name="posts">
right
</div>
<div name="posts">
left
</div>
<div name="posts">
right
</div>
<div name="posts">
left
</div>
<div name="posts">
right
</div>
</div>
Here is the script that i have been working with so far:
<script type="text/javascript">
var container = document.getElementById("posts");
var posts = document.getElementsByName("posts");
var rdiv = document.createElement("div");
rdiv.style.backgroundColor = "#0F0";
rdiv.style.cssFloat = "right";
rdiv.style.clear = "right";
var ldiv = document.createElement("div");
ldiv.style.backgroundColor = "#F00";
ldiv.style.cssFloat = "left";
ldiv.style.clear = "left";
for (i=0; i<posts.length; i++){
if (i%2){
rdiv.appendChild(posts[i]);
}else{
ldiv.appendChild(posts[i]);
}
}
container.innerHTML = "";
container.appendChild(rdiv);
container.appendChild(ldiv);
</script>
Now what this is doing is that it creates the left and right floating divs normally, but it only appends the first div inside both, the rest goes kabluey, can anyone help me with this one?
The main issue you are having is: appending a live element to another element, removes the element from its original location, causing problems with the loop.
To fix this, store the elements into a temporary array, appending them to their corresponding div's only once the looping is done:
var temp1 = [], temp2 = [];
for (i=0; i<posts.length; i++){
if (i%2){
temp1.push(posts[i]);
}else{
temp2.push(posts[i]);
}
}
for(var i = 0; i < temp1.length; i++) {
rdiv.appendChild(temp1[i]);
}
for(var i = 0; i < temp2.length; i++) {
ldiv.appendChild(temp2[i]);
}
You can see the full working example here: http://jsfiddle.net/FqSMw/

Carousel with image map linked to next image

The long and short of it is I'm trying to use a carousel, and instead of using next and previous buttons to navigate to other images, I want to use image mapping to link to other images. I'm quite stuck, so I appreciate any advice!
My carousel is from this site's tutorial (https://christianheilmann.com/2015/04/08/keeping-it-simple-coding-a-carousel/
). Here's my html code:
<ol class="content">
<li>
<img src="http://lorempixel.com/200/200" alt="mag" usemap="#map" class="img-responsive">
<map name="map">
<area shape=poly coords="500,80,1080,80,1080,550,500,550" href="img2" title="vent1" > <!--where should href link to?? -->
</map>
</li>
<li><img src="http://lorempixel.com/199/200" alt="2"></li>
<li><img src="http://lorempixel.com/200/199" alt="3"></li>
</ol>
My javascript:
carousel = (function(){
// Read necessary elements from the DOM once
var box = document.querySelector('.simbox');
var next = box.querySelector('.next');
var prev = box.querySelector('.prev');
// Define the global counter, the items and the
// current item
var counter = 0;
var items = box.querySelectorAll('.content li');
var amount = items.length;
var current = items[0];
box.classList.add('active');
// navigate through the carousel
function navigate(direction) {
// hide the old current list item
current.classList.remove('current');
// calculate the new position
counter = (counter + direction) % amount;
counter = counter < 0 ? amount - 1 : counter;
// set new current element
// and add CSS class
current = items[counter];
current.classList.add('current');
}
// add event handlers to buttons
next.addEventListener('click', function(ev) {
navigate(1);
});
prev.addEventListener('click', function(ev) {
navigate(-1);
});
// show the first element
// (when direction is 0 counter doesn't change)
navigate(0);})();
You asked "where should href link to?"
you can link it to href="javascript:navigate(1)" that way, when you click on the area, it will fire the navigate(1) function that will cause the carousel go to the next item.

Categories

Resources