Adding pagination links to onclick change image - javascript

I have a javascript that changes the image scr when you click on the image and it will cycle through. I want to add pagination links to this script. I want a Previous & Next text link but I don't know how to make the Previous link to go back a image and the Next link to go to the next image.
Here's the live demo http://jsfiddle.net/08p52h59/3/
html:
<div id="container">
<div class="nav">
<img src="http://i.imgur.com/tL6nW.gif">
<img src="http://i.imgur.com/BfZ5f.gif">
<img src="http://i.imgur.com/mR7wo.gif">
</div>
</div>
<div id="d"></div>
javascript:
$(function() {
var $images = $("#container > .nav > a").clone();
var $length = $images.length;
var $imgShow = 0;
$("#container > .nav").html( $("#container > .nav > a:first") );
$("#container > .nav > a:first").click(function(event) {
$(this).children().attr("src",
$("img", $images).eq(++$imgShow % $length).attr("src") );
$("#container > .nav > a:last").attr("href", $($images).eq($imgShow % $length).attr("href"));
event.preventDefault();
});
});
Can anyone tell me how to add these pagination links?

I was playing around with something similar and thought I'd share it in case it's of any use to you, different ideas on how to do it.
/* set first image in frame from shoebox on document.ready */
$(function() {
var leadOff = $('shoebox img:first-child').attr('source');
$('.picture').attr({'src' : leadOff, 'imageposition' : '1'});
});
/* load next image from shoebox (click on image and/or next button) */
$('pictureframe, buttonright').click(function() {
var imageTally = $('shoebox img').length;
var imagePosition = $('.picture').attr('imageposition');
var plusOne = parseInt(imagePosition) + 1;
var nextUp = $('shoebox img:nth-child(' + plusOne + ')').attr('source');
if (imagePosition == imageTally) {
var leadOff = $('shoebox img:first-child').attr('source');
$('.picture').attr({'src' : leadOff, 'imageposition' : '1'});
} else {
$('.picture').attr({'src' : nextUp, 'imageposition' : plusOne});
}
});
/* load previous image from shoebox (click on prev button) */
$('buttonleft').click(function() {
var imageTally = $('shoebox img').length;
var imagePosition = $('.picture').attr('imageposition');
var minusOne = parseInt(imagePosition) - 1;
var nextUp = $('shoebox img:nth-child(' + minusOne + ')').attr('source');
if (imagePosition == '1') {
var lastPic = $('shoebox img:last-child').attr('source');
$('.picture').attr({'src' : lastPic, 'imageposition' : imageTally});
} else {
$('.picture').attr({'src' : nextUp, 'imageposition' : minusOne});
}
});
body {
display: flex;
justify-content: center;
align-items: center;
height: 100vh;
width: 100%;
}
wall {
display: flex;
flex-direction: column;
padding: 6px;
background-color: hsla(0, 0%, 20%, 1);
}
pictureframe {
display: flex;
padding: 6px;
background-color: hsla(0, 0%, 40%, 1);
}
pictureframe img {
display: flex;
width: 100px;
height: 100px;
}
buttonswrapper {
display: flex;
flex-grow: 1;
}
buttonleft, buttonright {
display: flex;
justify-content: center;
align-items: center;
flex-grow: 1;
padding: 6px;
color: hsla(40, 20%, 70%, 1);
font-variant: small-caps;
font-weight: bold;
font-family: Verdana, sans-serif;
background-color: hsla(0, 0%, 40%, 1);
cursor: pointer;
}
buttonleft:hover, buttonright:hover {
background-color: hsla(50, 50%, 40%, 1);
}
shoebox {
display: none;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min.js"></script>
<wall>
<pictureframe>
<img class="picture" src="">
</pictureframe>
<buttonswrapper>
<buttonleft>prev</buttonleft>
<buttonright>next</buttonright>
</buttonswrapper>
</wall>
<shoebox>
<!-- prevent loading all images by changing src to source -->
<img source="http://i.imgur.com/tL6nW.gif">
<img source="http://i.imgur.com/BfZ5f.gif">
<img source="http://i.imgur.com/mR7wo.gif">
</shoebox>
fiddle
http://jsfiddle.net/Hastig/bjw9rpo0/8/
Let me know if annotations are needed and if you need the href's I have some ideas for that as well.

You could add data-id=NUMBER param and get $(this).attr('data-id') when it's clicked and showing +1 (next) or -1 (previous). Current showed image need a class too to know where's the pointer. Check when you'll go over to get the first / last one.
Full example
HTML
<div id="container">
<div class="nav">
<a class="current" data-id="1" href="http://stackoverflow.com/"><img src="http://i.imgur.com/tL6nW.gif"></a>
<a data-id="2" href="http://meta.stackoverflow.com/"><img src="http://i.imgur.com/BfZ5f.gif"></a>
<a data-id="3" href="http://chat.meta.stackoverflow.com/"><img src="http://i.imgur.com/mR7wo.gif"></a>
</div>
</div>
<div id="d">
<a class="prev" href="">Prev</a>
<a class="next" href="">Next</a></div>
CSS
a img {
display: none;
}
a.current img {
display: block;
}
JS
$(function() {
$("a").click(function(event) {
event.preventDefault();
var pointer = $(this).attr('data-id');
var alength = $('.nav a').length;
if ( !$(this).hasClass('current') ) {
var pointer = $('a.current').attr('data-id');
$('a.current').removeClass('current');
}
if ($(this).hasClass('prev')){
$('a.current').removeClass('current');
pointer--;
if (pointer < 1) { pointer = alength; }
} else {
$(this).removeClass('current');
pointer++;
if (pointer > alength) { pointer = 1; }
}
$('a[data-id="'+pointer+'"]').addClass('current');
});
});
Codepen: https://codepen.io/anon/pen/AXGGPJ?editors=1011

Related

How Can I make this touch Slider move atomically?

I am trying to make this touch slider, which move between slides automatically.
I tried many ways but nothing helped, this bellow is my Code:
.slider-container {
height: 100vh;
display: inline-flex;
overflow: hidden;
scrollbar-width: none;
transform: translateX(0);
will-change: transform;
transition: transform 0.3s ease-out;
cursor: grab;
}
.slide{
max-height: 100vh;
width: 100vw;
display: flex;
align-items: center;
justify-content: center;
padding: 1rem;
}
<div class="slider-container">
<div class="slide">
<img src="pics/slider/127616685-multi-colored-samples-of-marble-granite-and-travertine-chips-and-pebbles-for-landscape-design-close-.jpg"/>
</div>
<div class="slide">
<img src="pics/slider/1554689647283.jpg"/>
</div>
</div>
Just add this code at the bottom of your JS code.
This code changes the value of currentTranslate every 1 second and then calls the touchEnd(); function.
**I added the variable "loop" if the value is true when the last slide is reached... the script will call the first one again and so on indefinitely. If it has a value of false when the last slide is reached, the interval will be removed. And scrolling the slides will stop.
var loop = true; //<-- "true" Loop or "false" Stop on the End
var slideShw = setInterval(() => {
currentTranslate = currentTranslate - 101;
touchEnd();
if (currentIndex === slides.length - 1) {
if (loop) {
currentIndex -= slides.length;
} else {
stop_slideShw();
}
}
}, 1000);
function stop_slideShw() {
clearInterval(slideShw);
}
Example:
// get our elements
const slider = document.querySelector('.slider-container'),
slides = Array.from(document.querySelectorAll('.slide'))
// set up our state
let isDragging = false,
startPos = 0,
currentTranslate = 0,
prevTranslate = 0,
animationID,
currentIndex = 0
// add our event listeners
slides.forEach((slide, index) => {
const slideImage = slide.querySelector('img')
// disable default image drag
slideImage.addEventListener('dragstart', (e) => e.preventDefault())
// touch events
slide.addEventListener('touchstart', touchStart(index))
slide.addEventListener('touchend', touchEnd)
slide.addEventListener('touchmove', touchMove)
// mouse events
slide.addEventListener('mousedown', touchStart(index))
slide.addEventListener('mouseup', touchEnd)
slide.addEventListener('mousemove', touchMove)
slide.addEventListener('mouseleave', touchEnd)
})
// make responsive to viewport changes
window.addEventListener('resize', setPositionByIndex)
// // prevent menu popup on long press
// window.oncontextmenu = function (event) {
// event.preventDefault()
// event.stopPropagation()
// return false
// }
function getPositionX(event) {
return event.type.includes('mouse') ? event.pageX : event.touches[0].clientX
}
// use a HOF so we have index in a closure
function touchStart(index) {
return function (event) {
currentIndex = index
startPos = getPositionX(event)
isDragging = true
animationID = requestAnimationFrame(animation)
slider.classList.add('grabbing')
}
}
function touchMove(event) {
if (isDragging) {
const currentPosition = getPositionX(event)
currentTranslate = prevTranslate + currentPosition - startPos
}
}
var movedBy;
function touchEnd() {
cancelAnimationFrame(animationID)
isDragging = false
movedBy = currentTranslate - prevTranslate
// if moved enough negative then snap to next slide if there is one
if (movedBy < -100 && currentIndex < slides.length - 1) currentIndex += 1
// if moved enough positive then snap to previous slide if there is one
if (movedBy > 100 && currentIndex > 0) currentIndex -= 1
setPositionByIndex()
slider.classList.remove('grabbing')
}
function animation() {
setSliderPosition()
if (isDragging) requestAnimationFrame(animation)
}
function setPositionByIndex() {
currentTranslate = currentIndex * -window.innerWidth
prevTranslate = currentTranslate
setSliderPosition()
}
function setSliderPosition() {
slider.style.transform = `translateX(${currentTranslate}px)`
}
// NEW LINES /////////////////////////////////////////
var loop = true; //<-- "true" Loop or "false" Stop on the End
var slideShw = setInterval(() => {
currentTranslate = currentTranslate - 101;
touchEnd();
if (currentIndex === slides.length - 1) {
if (loop) {
currentIndex -= slides.length;
} else {
stop_slideShw();
}
}
}, 1000);
function stop_slideShw() {
clearInterval(slideShw);
}
/* :root {
--shadow: rgba(0, 0, 0, 0.8)
}
* {
box-sizing: border-box;
padding: 0;
margin: 0;
}
*/
.slider-container {
height: 100vh;
display: inline-flex;
overflow: hidden;
scrollbar-width: none;
transform: translateX(0);
will-change: transform;
transition: transform 0.3s ease-out;
cursor: grab;
}
.slide {
max-height: 100vh;
width: 100vw;
display: flex;
align-items: center;
justify-content: center;
padding: 1rem;
}
#media(min-width: 1200px) {
.slide {
padding: 3rem;
}
}
.slide img {
max-width: 100%;
max-height: 100%;
transition: transform 0.3s ease-in-out;
box-shadow: 5px 5px 50px -1px var(--shadow);
border-radius: 4px;
user-select: none;
}
.grabbing {
cursor: grabbing;
}
.grabbing .slide img {
transform: scale(0.9);
box-shadow: 5px 5px 40px -1px var(--shadow);
}
<div class="slider-container">
<div class="slide">
<img
src="https://images.pexels.com/photos/145939/pexels-photo-145939.jpeg?auto=compress&cs=tinysrgb&dpr=3&h=750&w=1260" />
</div>
<div class="slide">
<img
src="https://images.pexels.com/photos/47547/squirrel-animal-cute-rodents-47547.jpeg?auto=compress&cs=tinysrgb&dpr=2&h=650&w=940" />
</div>
<div class="slide">
<img
src="https://thumbor.forbes.com/thumbor/960x0/https%3A%2F%2Fspecials-images.forbesimg.com%2Fimageserve%2F5faad4255239c9448d6c7bcd%2FBest-Animal-Photos-Contest--Close-Up-Of-baby-monkey%2F960x0.jpg%3Ffit%3Dscale" />
</div>
</div>
To move your slider automatically you should use the animation property.
Its difficult to work on slider without Javascript. I am giving some fresh codes, you can check them and rewrite your codes accordingly.
var photos = ["1.png","2.png","3.png"]
var time = 3000;
var imgTag = document.querySelector("img")
var count = 0;
function changeImg() {
document.slide.src = photos[count];
count++;
if(count==3){
count=0;
imgTag.src = photos[count];
}
else{
imgTag.src = photos[count];
}
console.log("lap");
setTimeout("changeImg()",time);
}
window.onload = changeImg;
function next(){
count++;
time=3000;
if(count==3){
count=0;
imgTag.src = photos[count];
}
else{
imgTag.src = photos[count];
}
console.log("next");
}
function prev(){
count--;
time=3000;
if(count==-1){
count=2;
imgTag.src = photos[count];
}
else{
imgTag.src = photos[count];
}
console.log("prev");
}
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Stack Overflow</title>
<link rel="stylesheet" href="style.css">
</head>
<body>
<button onclick="prev()">Prev</button>
<img src="1.png" name="slide" alt="" height="300" width="300">
<button onclick="next()">Next</button>
<script type="text/javascript" src="index.js"></script>
</body>
</html>
Put any 3 images named "1.png" "2.png" "3.png". And then run the code. Hopefully it will run, and you will get an idea. Here I have used a setTimeout function that will fire up after 3 seconds to change your slides.
Thank you.

<br> mucking up .next() in JQuery

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>

How to change the text color of a transparent header on scroll, depending on the div it overlaps

I have a header with a transparent backgrounsd, and I am trying to get the text of the header to change colour between white and black depending on the background of the div it's overlapping.
So far I have managed to add a class of .color-menu to all the divs where I want the header to be black.
I then have it add a class of .dark-menu to the header when the .color-menu div reaches the top of the page.
The problem is that it only works for the first .colour-menu div. It will change to black when it is in the viewport and back to white for the next div but then when the next .color-menu div gets to the top it doesn't change.
So, it seems like the .each function isn't working but I am not sure how to fix it.
$(window).scroll(function() {
$('.color-menu').each(function(i){
var top_of_element = $(".color-menu").offset().top;
var bottom_of_element = $(".color-menu").offset().top + $(".color-menu").outerHeight();
var top_of_screen = $(window).scrollTop();
if ((top_of_screen > top_of_element) && (top_of_screen < bottom_of_element)) {
$(".header").addClass("dark-menu");
} else {
$(".header").removeClass("dark-menu");
}
});
});
UPDATE: I have also tried using $(this) but it really throws off when it changes color.
$(window).scroll(function() {
$('.color-menu').each(function(i){
var top_of_element = $(this).offset().top;
var bottom_of_element = $(this).offset().top + $(this).outerHeight();
var top_of_screen = $(window).scrollTop();
if ((top_of_screen > top_of_element) && (top_of_screen < bottom_of_element)) {
$(".header").addClass("dark-menu");
} else {
$(".header").removeClass("dark-menu");
}
});
});
Here is a simplified version of my code as an example:
$(document).ready(function() {
$(".white").addClass("color-menu");
$(".white-bold").addClass("color-menu");
$(".light").addClass("color-menu");
$(".light-bold").addClass("color-menu");
$(".bright").addClass("color-menu");
});
$(window).scroll(function() {
$('.color-menu').each(function(i){
var top_of_element = $(".color-menu").offset().top;
var bottom_of_element = $(".color-menu").offset().top + $(".color-menu").outerHeight();
var top_of_screen = $(window).scrollTop();
if ((top_of_screen > top_of_element) && (top_of_screen < bottom_of_element)) {
$(".header").addClass("dark-menu");
} else {
$(".header").removeClass("dark-menu");
}
});
});
.header {
width: 100%;
background: rgba(0,0,0,0);
margin: 0;
padding:10px;
position: fixed;
text-align: center;
}
.header a {
color: white;
font-size: 2rem;
text-transform: uppercase;
}
.dark-menu a{
color: black;
}
.black {
background-color: black;
height: 200px;
}
.white, .white-bold, .light, .light-bold, .bright {
background-color: white;
height: 200px;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div class="header">
<a>This is the header</a>
</div>
<div class ="black"></div>
<div class ="white"></div>
<div class ="black"></div>
<div class ="white-bold"></div>
<div class ="black"></div>
<div class ="light"></div>
<div class ="black"></div>
<div class ="light-bold"></div>
<div class ="black"></div>
<div class ="bright"></div>
What is happening in your code is that on scroll, you loop through every color-menu div and add the class if it is the current one... but then the code continues to loop though the remaining elements in the array and removes it again because the page is not in the other div.
I've explained step-by-step the changes you need to get this to work after the example, but first you can see it working here:
Working Example:
$(document).ready(function() {
$(".white").addClass("color-menu");
$(".white-bold").addClass("color-menu");
$(".light").addClass("color-menu");
$(".light-bold").addClass("color-menu");
$(".bright").addClass("color-menu");
$(window).scroll(function() {
var inColorMenu = false; /* initialise var to store if we are in color-menu */
var top_of_screen = $(window).scrollTop(); /* just get this once outside loop */
/* Loop through each color-menu element and check if we are in one */
$('.color-menu').each(function(i) {
var top_of_element = $(this).offset().top;
var bottom_of_element = top_of_element + $(this).outerHeight();
/* if we are in a color-menu element, set our var to true and stop processing */
if ((top_of_screen > top_of_element) && (top_of_screen < bottom_of_element)) {
inColorMenu = true;
return false; /* N.B. need to return "false" to break from the "each" loop */
}
});
if (inColorMenu) {
$(".header").addClass("dark-menu");
} else {
$(".header").removeClass("dark-menu");
}
});
});
.header {
width: 100%;
background: rgba(0, 0, 0, 0);
margin: 0;
padding: 10px;
position: fixed;
text-align: center;
}
.header a {
color: white;
font-size: 2rem;
text-transform: uppercase;
}
.header.dark-menu a {
color: black;
}
.black {
background-color: black;
height: 200px;
}
.white,
.white-bold,
.light,
.light-bold,
.bright {
background-color: white;
height: 200px;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div class="header">
<a>This is the header</a>
</div>
<div class="black"></div>
<div class="white"></div>
<div class="black"></div>
<div class="white-bold"></div>
<div class="black"></div>
<div class="light"></div>
<div class="black"></div>
<div class="light-bold"></div>
<div class="black"></div>
<div class="bright"></div>
How this works:
Declare a variable to record whether we are in a "color-menu" class or not, and initialise this to false, e.g.:
var inColorMenu = false;
When looping through $('.color-menu').each, if we are between the top and bottom of one of divs (which your code is already detecting), then set our variable to true to record this.
We can also return false to break the each loop and stop processing the rest of the elements (it will still work without this, we are just reducing the amount of processing required):
if ((top_of_screen > top_of_element) && (top_of_screen < bottom_of_element)) {
inColorMenu = true;
return false; /* N.B. need to return "false" to break from the "each" loop */
}
Finally, after we finish our $('.color-menu').each loop, if inColorMenu is true, we know we are in a color-menu div so we add the dark-menu class to the header, otherwise we remove it:
if (inColorMenu) {
$(".header").addClass("dark-menu");
} else {
$(".header").removeClass("dark-menu");
}
Note: You need to use $(this) when getting the offset().top and outerHeight() so that you are getting the values for the current element in the loop. $(".color-menu") gets the values for an unspecified element with this class so will not work.

image script not displaying

I have this code and the problem is the "main" and "left/right" image are not being displayed. I have gone through the entire logic and can't figure out what is wrong.
The code works if I replace else with else if(flag===1 && child[I].id=="left" || child[I].id=="right")
Expected output:
movement of mouse should change the image, this change is determined by the height of the <body> element.
Output getting:
only one image is displayed and does not changes no mater where I move my mouse.
[ also changing event from "mouseover" to "mousemove" does not help ]
so why isn't it working when I remove it, shouldn't at least "main" work??
PS: I'm unable to provide an image, please find another one.
'use strict';
(function() {
var wlen = screen.availWidth;
var whet = screen.availHeight;
var last = {};
var chk = 3;
var eye = document.getElementsByClassName("eyes");
var build = function(ele) {
if (ele.previousElementSibling !== null) ele.previousElementSibling.style = "none";
last = ele.style;
last.display = "block";
}
var anite = function() {
var x = event.screenX;
var y = event.screenY;
last.display = "none";
var child;
var flag;
y < whet / 3 ? flag = 2 : (y > 2 * whet / 3) ? flag = 0 : flag = 1;
x < wlen / 2 ? child = eye[1].childNodes : child = eye[0].childNodes;
for (let i = 0; i < child.length; i++) {
if (child[i].id) {
if (child[i].id == "main" && flag === 0) {
build(child[i]);
} else if (child[i].id.search(/a/i) === 0 && flag === 2) {
build(child[i]);
} else {
build(child[i]);
}
}
}
}
document.addEventListener("mouseover", anite, false);
})()
html,body {
height: 100%;
}
body {
display: flex;
align-items: center;
}
main {
width: 100%;
overflow: hidden;
}
.eyes {
width:50%;
float: left;
height: 300px;
}
#main {
background: url('eyes.png') no-repeat 0 0;
width: 1000px;
height: 254px;
display:none;
}
#left {
background: url('eyes.png') no-repeat 0 -254px;
width: 1000px;
height: 254px;
display:none;
}
#aLeft {
background: url('eyes.png') no-repeat 0 -508px;
width: 1000px;
height: 254px;
display:none;
}
#right {
background: url('eyes.png') no-repeat 0 -762px;
width: 1000px;
height: 254px;
display:none;
}
#aRight {
background: url('eyes.png') no-repeat 0 -1016px;
width: 1000px;
height: 280px;
display:none;
}
<html>
<head>
<title>Student Details</title>
</head>
<body>
<main>
<div class="eyes">
<!-- <img src="eyes.png" alt="eyes"> -->
<p id="main"></p>
<p id="right"></p>
<p id="aRight"></p>
</div>
<div class="eyes">
<p id="main"></p>
<p id="left"></p>
<p id="aLeft"></p>
</div>
</main>
</body>
</html>

How to cycle through DIVs

I want my page to show 3 divs at a time, and when I click next I would like it to show the next 3 divs. Then when I click previous, I would like to display the previous 3.
$("#container .result").slice(0, 3).show();
$("#right").click(function () {
var items = $('#container .result:visible').hide().last();
var nextItems = items.nextAll().slice(0, 3);
if (nextItems.length === 0) {
nextItems = $("#container .result").slice(0, 3);
}
nextItems.show();
});
$("#left").click(function () {
var items = $('#container .result:visible').hide().last();
var nextItems = items.prevAll().slice(0, 3);
if (nextItems.length === 0) {
nextItems = $("#container .result").slice(0, 3);
}
nextItems.show();
});
The problem is that when I click previous, and it comes to last 3 divs and when I click again it shows 2 than 1. How can i fix that? I want it to stop when it comes to first 3.
You were very much on the right track, I was impressed by the ingenuity of your code.
Your main problem is solved with a very simple fix; in the #left click-handler, replace .last() with .first():
var items = $('#container .result:visible').hide().first();
And to loop around to the last 3 when you click previous on the first 3, change this line to the next:
nextItems = $("#container .result").slice(0, 3);
nextItems = $("#container .result").slice($("#container .result").length-3, $("#container .result").length);
But I thought the situation might occur, now or in the future, that the number of .results aren't a multitude of 3, let's say 7 or 11 for example.
I created a script that will handle that, and also loop around in both directions:
$("#container .result").first().show(); //initialize divs at pageload
$(".nav").click(function() {
var start=0, step=3;
var currentItems = $("#container .result:visible").hide();
var currentLast = (this.id==="prev" ? currentItems.first() : currentItems.last());
var nextItems = (this.id==="prev" ? currentLast.prevAll() : currentLast.nextAll());
if (nextItems.length === 0) { //if the last set of divs has been reached, loop around
var itemsLength = $("#container .result").length;
if (this.id==="prev") {start=itemsLength-step; step=itemsLength;} //determine wich way to loop around
nextItems = $("#container .result").slice(start,step); //loop around
} else if (nextItems.length < step) { //if the next divs aren't a full set, keep some divs from the current set visible
if (this.id==="prev") {step-=nextItems.length;} else {start=nextItems.length;} //determine which current items should remain visible
currentItems.slice(start,step).each(function(){nextItems.push(this);}); //add selected current items to nextItems-array
} else {nextItems=nextItems.slice(start,step);} //if the next divs are a full set, simply select the next set
nextItems.show(); //show the next set
}).click(); //initialize divs at pageload
In HTML, I gave the two buttons both a class "nav" (see code snippet below), so that I could combine their click-handlers into one.
I changed your first line to this: $("#container .result").first().show();. That line - in combination with the .click() chained to the click-handler - replaces your line: $("#container .result").slice(0, 3).show(); (at the top of your script).
This gives you much more flexibility to change the amount of divs you want to show on the page at once. At the start of the click-handler I declare var step=3;, which is the only place that number is hard-coded, so if you ever want to change the amount you only have to change that number (and maybe adjust some styling).
The rest of the explanation is in the comments in the code.
See the code snippet below for a demo:
$("#container .result").first().show(); //initialize divs at pageload
$(".nav").click(function() {
var start=0, step=3;
var currentItems = $("#container .result:visible").hide();
var currentLast = (this.id==="prev" ? currentItems.first() : currentItems.last());
var nextItems = (this.id==="prev" ? currentLast.prevAll() : currentLast.nextAll());
if (nextItems.length === 0) { //if the last set of divs has been reached, loop around
var itemsLength = $("#container .result").length;
if (this.id==="prev") {start=itemsLength-step; step=itemsLength;} //determine wich way to loop around
nextItems = $("#container .result").slice(start,step); //loop around
} else if (nextItems.length < step) { //if the next divs aren't a full set, keep some divs from the current set visible
if (this.id==="prev") {step-=nextItems.length;} else {start=nextItems.length;} //determine which current items should remain visible
currentItems.slice(start,step).each(function(){nextItems.push(this);}); //add selected current items to nextItems-array
} else {nextItems=nextItems.slice(start,step);} //if the next divs are a full set, simply select the next set
nextItems.show(); //show the next set
}).click(); //initialize divs at pageload
html,body {width:98%; height:90%;}
#container {width:100%; height:90%; background:lightgrey;}
#container .result {display:none; float:left; width:30%; height:100%; margin:0 1.66%; background:lightgreen;}
#container .result > div {display:table; width:100%; height:100%;}
#container .result > div > div {display:table-cell; width:100%; height:100%; text-align:center; vertical-align:middle; font:bolder 2em sans-serif;}
.nav {margin-top:2%; cursor:pointer;}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div id="container">
<div class="result"><div><div>1</div></div></div>
<div class="result"><div><div>2</div></div></div>
<div class="result"><div><div>3</div></div></div>
<div class="result"><div><div>4</div></div></div>
<div class="result"><div><div>5</div></div></div>
<div class="result"><div><div>6</div></div></div>
<div class="result"><div><div>7</div></div></div>
</div>
<button type="button" class="nav" id="prev">PREVIOUS</button>
<button type="button" class="nav" id="next">NEXT</button>
codepen: https://codepen.io/anon/pen/YQoJzd?editors=1010
jsfiddle: https://jsfiddle.net/k8ysj6gq/1/
You can ignore the CSS and HTML (except for the class="nav" on the buttons), that's all just so we can see it. All the relevant code is in the JS.
Basically you can do something like below.
On Next or Previous click set margin-left of container to position or loop through all div.
$(document).ready(function() {
$('.next-button').on('click', function() {
if (parseInt($('.carousel-item').css("margin-left").slice(0, -2)) < -2000) {
$('.carousel-item').animate({
"margin-left": "0px"
}, 200)
} else {
$('.carousel-item').animate({
"margin-left": "-=600px"
}, 200);
}
});
$('.prev-button').on('click', function() {
if (parseInt($('.carousel-item').css("margin-left").slice(0, -2)) > 0) {
$('.carousel-item').animate({
"margin-left": "-2000px"
}, 200)
} else {
$('.carousel-item').animate({
"margin-left": "+=600px"
}, 200);
}
});
});
.carousel-container {
height: 500px;
display: flex;
margin: 40px 20px;
position: relative;
overflow: hidden;
width: 720px;
padding: 0;
border: 1px solid red;
align-items: center;
}
.carousel-item {
height: 100%;
margin: 5px;
margin-left: 60px;
padding: 0;
-moz-box-orient: horizontal;
-ms-box-orient: horizontal;
-webkit-box-orient: horizontal;
-o-box-orient: horizontal;
box-orient: horizontal;
display: -moz-box;
display: -ms-box;
display: -webkit-box;
display: -o-box;
display: box;
list-style-type: none;
}
.item {
border: solid 1px #333;
margin-right: 10px;
width: 200px;
display: flex;
align-items: center;
}
.item>a {
width: 100%;
display: flex;
justify-content: center;
align-items: flex-end;
}
.prev-button,
.next-button {
border: 1px solid green;
background-color: gray;
}
.navigation {
width: 60px;
margin: 0;
position: absolute;
top: 0;
bottom: 0;
display: flex;
justify-content: center;
align-items: center;
}
.next-button:hover,
.prev-button:hover {
background-color: red;
}
.navigation:active {
color: white;
}
.next-button {
right: 0;
}
.prev-button {
left: 0;
}
/* .carousel-item li:nth-child(1) {
background-image: url('http://urbanphenomena.net/imgs/cover/bq2.jpg');
background-size: cover;
} */
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="carousel-container">
<a class="prev-button navigation" href="#">
<</a>
<div class="carousel-item">
<li class="item"> 1 </li>
<li class="item"> 2 </li>
<li class="item"> 3 </li>
<li class="item"> 4 </li>
<li class="item"> 5 </li>
<li class="item"> 6 </li>
<li class="item"> 7 </li>
<li class="item"> 8 </li>
<li class="item"> 9 </li>
<li class="item">
</li>
</div>
<a class="next-button navigation" href="#">></a>
</div>
Run co
Ok so your first mistake was that when trying to code back 3 you were getting the previous 3 items from the first of the 3 not the last. So i changed .last() to .first(). Then to loop back when previous = 0 all you did was slice from the current 3, instead of slicing at the end of the entire array of elements.
Here's a link to a codepen that has the working code(you'll obviously have to change the variables to fit your project): https://codepen.io/anon/pen/qjzxee?editors=1010
changed var items = $('#container .result:visible').hide().last(); to var items = $('#container .result:visible').hide().first();
and
if (nextItems.length === 0) {
nextItems = $("#container .result").slice(0, 3);
}
to
if (nextItems.length === 0) {
var allItems = $("#container .result");
nextItems = $("li").slice(allItems.length - 3,allItems.length);
}
this also only works if the number elements is a multiple of the number you are skipping each time, but i can fix that if you'd like

Categories