Jquery + HTML Thumbnail scroll - javascript

I want to create a list of thumbnails with a button previous and another next, showing 10 thumbnails at a time and hiding the rest, and when you reach the 10th tumbnail and click the next button, the 1st disappear and appear the 11th.
I've tried with:
Javascript
jQuery(document).ready(function() {
var count = 0;
var images = 11;
var page = 1;
var current = 1;
jQuery('.ice-navigator li').each(function(index) {
count++;
jQuery(this).attr('id', 'menu-item-' + count);
jQuery(this).attr('class', 'menu-page-' + page);
if(count >= (page * images)) {
page++;
}
jQuery(this).hide();
})
jQuery('.ice-navigator li.menu-page-1').show();
jQuery('.ice-next').click(function() {
if(current >= count) {
current = 1;
} else {
current++;
}
item = jQuery('.ice-navigator li#menu-item-' + current);
if(jQuery(item).hasClass('active')) {
jQuery(item).removeClass('active');
page = jQuery('.ice-navigator li#menu-item-' + current).attr('class');
jQuery(item).addClass('active');
} else {
page = jQuery('.ice-navigator li#menu-item-' + current).attr('class');
}
jQuery('.ice-navigator li').hide();
jQuery('.ice-navigator li.' + page).show();
})
jQuery('.ice-previous').click(function() {
current--;
if(current <= 0) {
current = count;
}
item = jQuery('.ice-navigator li#menu-item-' + current);
if(jQuery(item).hasClass('active')) {
jQuery(item).removeClass('active');
page = jQuery('.ice-navigator li#menu-item-' + current).attr('class');
jQuery(item).addClass('active');
} else {
page = jQuery('.ice-navigator li#menu-item-' + current).attr('class');
}
})
jQuery('.ice-navigator li').click(function() {
current = jQuery(this).attr('id').replace('menu-item-', '');
})
})
HTML
<div class="ice-previous">Previous</div>
<div class="ice-navigator-wrapper clearfix">
<div class="ice-navigator-outer">
<ul class="ice-navigator">
<li>THUMBNAIL 1</li>
<li>THUMBNAIL 2</li>
[...]
<li>THUMBNAIL 11</li>
<li>THUMBNAIL 12</li>
</ul>
</div>
</div>
<div class="ice-next">Next</div>
Thanks!

Edit: I now understand it is like a circular ref. I have made some changes accordingly.
See my updated DEMO here
Below is for regular nav which stops when you reach the end.
Check my old DEMO here.
I used 2 pointers to manage the start and end position. Implemented adjustNav function to show/hide div based on start and end position.

This looks like a job for jCarousel:
http://sorgalla.com/jcarousel/
There are other plugins that provide this functionality. I just used jCarousel on another project and it was the first thing I thought of.
EDIT
I didn't realize you don't want to use a plugin. You could do this with hand-coded jQuery, but you're going to be writing a lot of code.

Related

Javascript List Item Animations

I am working on a very basic animation where classes are removed from list items once they have been loaded and appended to the document. The issue I am having is with the animation itself. I want the animation to execute in a stepped manner like the image below...
What actually though is that the loop runs completely, console.log messages get output in a stepped manner, but the classes are all removed at the same time once the loop has completed. How can I change this behavior? Why would the console.log messages be stepped but the classList.remove functionality is not executed at the same time?
Here is my code...
function sleep(milliseconds) {
var start = new Date().getTime();
for (var i = 0; i < 1e7; i++) {
if ((new Date().getTime() - start) > milliseconds){
break;
}
}
}
/**/
function showListItems() {
var listItems = document.querySelector('.idList');
var n = 20;
var c = 0;
var itemArray = new Array();
for (var i = 0; i < listItems.children.length; i++) {
var item = listItems.children[i];
if (item.classList && item.classList.contains('idList__item--hide')) {
console.log('Item: ', item);
itemArray[c] = item;
c++;
}
}
console.log('Item Array: ', itemArray);
itemArray.forEach(function(el, index) {
sleep(n);
el.classList.remove('idList__item--hide');
console.log("EL[" + index + "]: ", el);
});
}
I realize this code may look over complex and perhaps it is, but I have tried about everything I can think of. I have tried using promises, for loops, now the forEach method.
Thank you.
The browser doesn't update until javascript finishes running. Your script doesn't relinquished control back to the browser while sleeping so the browser can't update. This is exactly what setTimeout is for.
Change
itemArray.forEach(function(el, index) {
sleep(n);
el.classList.remove('idList__item--hide');
console.log("EL[" + index + "]: ", el);
});
to
itemArray.forEach(function(el, index) {
const ms = n * (index + 1);
setTimeout(function() {
el.classList.remove('idList__item--hide');
console.log("EL[" + index + "]: ", el);
}, ms);
});
We're scheduling all the remove calls in advance which is why we're multiplying n by index + 1.
And in case you're interested, here is the code I used to test sleep vs setTimeout.
https://codepen.io/rockysims/pen/jeJggZ
This may be a bad way but it should solve your problem.
You can use setTimeout() in forEach, and use index to change time parameter, like it:
itemArray.forEach(function(el, index) {
setTimeout(function(){
el.classList.remove('idList__item--hide')
},500*(index+1))
});
I used Jquery each and setTimeout functions for chaining the animations.
$( "li" ).each(function( index ) {
var listItem = $( this );
setTimeout(function() {
listItem.animate({
opacity: 1
}, 500);
}, (index + 1) * 500);
});
ul {
padding : 20px;
}
ul li {
list-style : none;
height : 50px;
background-color : lightgreen;
margin : 20px;
opacity : 0;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<ul>
<li>Hello world 1</li>
<li>Hello world 2</li>
<li>Hello world 3</li>
<li>Hello world 4</li>
</ul>

How to add li class when clicking another div

I have two divs: #slider-next and #slider-prev. Also i have 4 li elements. On each click #slider-next i need to add .active class to each li.
First look:
<ul class="items-list">
<li class="active" id="l1">One</li>
<li id="l2">Two</li>
<li id="l3">Three</li>
<li id="l4">Four</li>
</ul>
After click #slider-next it should looks like:
<ul class="items-list">
<li id="l1">One</li>
<li class="active" id="l2">Two</li>
<li id="l3">Three</li>
<li id="l4">Four</li>
</ul>
It should repeating by clicking like it was at start
Here is my code but it adds class only for a second li:
function arrowNext() {
if( $('#l1, #l2, #l3, #l4').hasClass('active') ) {
$('.items-list li').removeClass('active');
$('li:nth-child(1)').next().addClass('active');
}
}
If You need circular Next and Previous, you can try this:
var nextCircularIndex = function(currentIndex, totalIndex) {
currentIndex = currentIndex + 1;
return currentIndex % totalIndex;
}
var previousCircularIndex: function (currentIndex, totalIndex) {
currentIndex = currentIndex - 1;
return currentIndex < 0 ? totalIndex - 1 : currentIndex;
}
Then change arrowNext like
var currentSlider = 0;
var totalSlider = 4;
function arrowNext() {
currentSlider = nextCircularIndex(currentSlider, totalSlider);
$("ul.items-list li.active").removeClass('active');
$("ul.items-list li:nth-child(" + currentSlider + ")").next().addClass('active');
}
function arrowPrevious() {
currentSlider = previousCircularIndex(currentSlider, totalSlider);
$("ul.items-list li.active").removeClass('active');
$("ul.items-list li:nth-child(" + currentSlider + ")").next().addClass('active');
}
I would approach it like this
function arrowNav(prev) {
// get the current index of the active item
var index = $('.items-list li.active').index();
// remove the active class from all items
$('.items-list li').removeClass('active');
// add or subtract one if next or previous
var newIndex = prev ? index - 1 : index + 1;
// rolling over the top or bottom
if (newIndex < 0)
newIndex = $('.items-list li').length - 1;
else if (newIndex >= $('.items-list li').length)
newIndex = 0;
// setting the class of the new active item
$('.items-list li').eq(newIndex).addClass('active');
}
$('#slider-prev').on('click', function() {
arrowNav(true)
});
$('#slider-next').on('click', function() {
arrowNav(false)
});
.active {
background-color: blue;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<ul class="items-list">
<li class="active" id="l1">One</li>
<li id="l2">Two</li>
<li id="l3">Three</li>
<li id="l4">Four</li>
</ul>
<button id="slider-prev">
Prev
</button>
<button id="slider-next">
Next
</button>
Maybe something like this:
var list_items = $(".items-list li");
var li_active = 1;
var li_total = list_items.length;
$("#prev").click(function() {
list_items.removeClass('active');
if (li_active == 1) {
li_active = li_total;
} else {
li_active--;
}
$('.items-list li:nth-child(' + li_active + ')').addClass('active');
});
$("#next").click(function() {
list_items.removeClass('active');
if (li_active == li_total) {
li_active = 1;
} else {
li_active++;
}
$('.items-list li:nth-child(' + li_active + ')').addClass('active');
});
.active {
color: red;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<ul class="items-list">
<li class="active" id="l1">One</li>
<li id="l2">Two</li>
<li id="l3">Three</li>
<li id="l4">Four</li>
</ul>
<button id="prev">Prev</button>
<button id="next">Next</button>
I think it's a good way you to follow
$(".next").on("click", function(){
if($(".active").next("div").html() === undefined) {
$(".active").removeClass("active");
$("div").first().addClass("active");
} else {
$(".active").removeClass("active").next("div").addClass("active");
}
})
$(".prev").on("click", function(){
if($(".active").prev("div").html() === undefined) {
$(".active").removeClass("active");
$("div").last().addClass("active");
} else {
$(".active").removeClass("active").prev("div").addClass("active");
}
})
here's a fiddle: https://jsfiddle.net/v58jzp9L/
here is a update with a loop :) https://jsfiddle.net/v58jzp9L/2/
You could use something like
var item = $("ul").closest("li");
var item2 = item.closest(".active");
item2.toggleClass("active");
if (item2.next("li") != null) {
item2.next("li").toggleClass("active");
} else {
item.toggleClass("active");
}
You should have some conception of state that tracks which of the lis are "active". This could be as simple as an array that looks like this:
const state = {
list_items: [false, true, false, false]
};
Or, more succinctly, a single number, representing the index of the li that is "active"
const state = {
active_list_item: 1
};
Then when you press next, you can increment state.active_list_item appropriately. Find a way to manage overflow. Does it wrap? If not, maybe use a createClamp(..) function. Otherwise, use a createWrap(..) function.
When the state is changed, you will want the appropriate DOM side effects to flow from the state change.
let list_items = document.getElementsByClassName('items-list')[0].children;
list_items = [].slice.apply(list_items);
list_items.forEach((list_item, i) => {
if (i === state.active_list_item) {
list_item.classList.add('active');
}
else {
list_item.classList.remove('active');
}
});
You should be able to figure out how to create the "previous" functionality now.
Two comments:
In general I would prefer to use $(document).ready() or something similar to ensure there is always one class="active" (since you're doing a slider seems sensible) as opposed to seeing if that condition exists.
$('li:nth-child(1)') selects the first <li> always, not the one that was previously active. What you probably want instead is
$('li.active') // Selects the li with class active
.removeClass('active') // returns the same li acted on
.next() // selects the next li
.addClass('active'); // adds the class active
This method of "chaining" is part of what makes jQuery so convenient :)
If you want it to "wrap around" you could do something like
var $next = $('li.active') // Selects the li with class active
.removeClass('active') // returns the same li acted on
.next(); // selects the next li
if ($next.length === 0) {
$next = $('li:first');
}
$next.addClass('active'); // adds the class active

Javascript - Mouse Wheel Go to Class

Every time I use the mouse wheel (you know normal scrolling) I want the JS (jquery or whatever) to scroll to a specific class (or id doesn't matter).
I have multiple divs so code like $('body').scrollTo($nextdiv) is not an option.
I just want to make every wheel cycle to move to a next div with a specific class/id. The same for the reverse scroll. To move one div (with a specific class) up.
I found mouse wheel event and how to move to a specific div but can't manage to make it work together.
Animated scroll would be cool.
Simple question. Can I have class AND id in the same div? ex <div class="a" id="b"> ?
Quick example, this code can be improved. Better to test on jsfiddle. Point mouse over list and scroll.
Note: I didn't use class but if you understand what I did it's easy to use classes.
Note 2: I just change color but logic can be replace with anything you want.
demo
demo 2 (with classes)
var i = 0;
var list = document.getElementById("list"), length = list.children.length;
list.addEventListener("wheel", ColorLi);
function ColorLi(e) {
//reset colors
for(var j = 0; j < length; j++)
list.children[j].style.color = "black";
//calculate index
if(e.wheelDelta > 0)
i++;
else
i--;
//fix index out of range
i = i < 0 ? 0 : i;
i = i > length-1 ? length-1 : i;
//set color
list.children[i].style.color = "red";
}
<ul id="list">
<li style="color: red">A</li>
<li>B</li>
<li>C</li>
<li>D</li>
</ul>
You could use the following plugins: jquery.mousewheel and jquery.scrollTo plugin, like:
/*!
* jQuery Mousewheel 3.1.13
*
* Copyright 2015 jQuery Foundation and other contributors
* Released under the MIT license.
* http://jquery.org/license
*/
!function(a){"function"==typeof define&&define.amd?define(["jquery"],a):"object"==typeof exports?module.exports=a:a(jQuery)}(function(a){function b(b){var g=b||window.event,h=i.call(arguments,1),j=0,l=0,m=0,n=0,o=0,p=0;if(b=a.event.fix(g),b.type="mousewheel","detail"in g&&(m=-1*g.detail),"wheelDelta"in g&&(m=g.wheelDelta),"wheelDeltaY"in g&&(m=g.wheelDeltaY),"wheelDeltaX"in g&&(l=-1*g.wheelDeltaX),"axis"in g&&g.axis===g.HORIZONTAL_AXIS&&(l=-1*m,m=0),j=0===m?l:m,"deltaY"in g&&(m=-1*g.deltaY,j=m),"deltaX"in g&&(l=g.deltaX,0===m&&(j=-1*l)),0!==m||0!==l){if(1===g.deltaMode){var q=a.data(this,"mousewheel-line-height");j*=q,m*=q,l*=q}else if(2===g.deltaMode){var r=a.data(this,"mousewheel-page-height");j*=r,m*=r,l*=r}if(n=Math.max(Math.abs(m),Math.abs(l)),(!f||f>n)&&(f=n,d(g,n)&&(f/=40)),d(g,n)&&(j/=40,l/=40,m/=40),j=Math[j>=1?"floor":"ceil"](j/f),l=Math[l>=1?"floor":"ceil"](l/f),m=Math[m>=1?"floor":"ceil"](m/f),k.settings.normalizeOffset&&this.getBoundingClientRect){var s=this.getBoundingClientRect();o=b.clientX-s.left,p=b.clientY-s.top}return b.deltaX=l,b.deltaY=m,b.deltaFactor=f,b.offsetX=o,b.offsetY=p,b.deltaMode=0,h.unshift(b,j,l,m),e&&clearTimeout(e),e=setTimeout(c,200),(a.event.dispatch||a.event.handle).apply(this,h)}}function c(){f=null}function d(a,b){return k.settings.adjustOldDeltas&&"mousewheel"===a.type&&b%120===0}var e,f,g=["wheel","mousewheel","DOMMouseScroll","MozMousePixelScroll"],h="onwheel"in document||document.documentMode>=9?["wheel"]:["mousewheel","DomMouseScroll","MozMousePixelScroll"],i=Array.prototype.slice;if(a.event.fixHooks)for(var j=g.length;j;)a.event.fixHooks[g[--j]]=a.event.mouseHooks;var k=a.event.special.mousewheel={version:"3.1.12",setup:function(){if(this.addEventListener)for(var c=h.length;c;)this.addEventListener(h[--c],b,!1);else this.onmousewheel=b;a.data(this,"mousewheel-line-height",k.getLineHeight(this)),a.data(this,"mousewheel-page-height",k.getPageHeight(this))},teardown:function(){if(this.removeEventListener)for(var c=h.length;c;)this.removeEventListener(h[--c],b,!1);else this.onmousewheel=null;a.removeData(this,"mousewheel-line-height"),a.removeData(this,"mousewheel-page-height")},getLineHeight:function(b){var c=a(b),d=c["offsetParent"in a.fn?"offsetParent":"parent"]();return d.length||(d=a("body")),parseInt(d.css("fontSize"),10)||parseInt(c.css("fontSize"),10)||16},getPageHeight:function(b){return a(b).height()},settings:{adjustOldDeltas:!0,normalizeOffset:!0}};a.fn.extend({mousewheel:function(a){return a?this.bind("mousewheel",a):this.trigger("mousewheel")},unmousewheel:function(a){return this.unbind("mousewheel",a)}})});
// The actual code:
$(document).ready(function () {
var targets = $('.scroll'); // List of elements to scroll to
var index = 0;
var duration = 500;
var canScroll = true;
var cache;
function limit(x, min, max) {
return Math.min(max, Math.max(min, x));
}
$(window).mousewheel(function (ev) {
if (canScroll) {
cache = index;
if (ev.deltaY < 0) {
index = index + 1; // Scrolling down, so increase index
} else {
index = index - 1; // Scrolling up, so decrease index
}
// Make sure the index is between 0 and (targets.length - 1)
index = limit(index, 0, targets.length - 1);
console.log(index);
// Make sure to scroll if and only if the value has changed
if (index !== cache) {
// Scroll to the target element:
$(window).scrollTo(targets.get(index), {
duration: duration,
easing: 'swing'
});
canScroll = false;
setTimeout(function () {
canScroll = true;
}, duration);
}
}
ev.preventDefault();
return false;
});
});
div {
content: ' ';
height: 500px;
background-color: #f2f2f2;
}
div:nth-child(even) {
background-color: #d0d0d0;
}
<script src="//code.jquery.com/jquery-1.11.3.min.js"></script>
<script src="//cdn.jsdelivr.net/jquery.scrollto/2.1.0/jquery.scrollTo.min.js"></script>
<div class="scroll">div1</div>
<div class="scroll">div2</div>
<div class="scroll">div3</div>
<div class="scroll">div4</div>
<div class="scroll">div5</div>
<div class="scroll">div6</div>

Creating / Removing a Row in a series of float: left divs

I have a list of div elements, all with float:left one after another like so
<div id="container">
<div id=0" style="float:left;> Stuff </div>
<div id=1" style="float:left;> Stuff </div>
<div id=2" style="float:left;> Stuff </div>
...
<div id=n" style="float:left;> Stuff </div>
</div>
What I am trying to achieve is the following:
If I click on one of the divs, it will push the surrounding divs away (the ones on its left up and the ones on its right down) and populate its own row. Then when clicked again it returns to the original configuration.
My Attempts:
Add a brute force separator: just use jQuery to stack before and after the div
Toggle the CSS property: clear: both for the desired div
It may be because it is rather late, but neither of these approaches seem reliable. What would be a more reasonable means of attaining this functionality?
Thanks for your time!
I think you want to achieve this, please check this Fiddle
var parentWidth = $("#container").css("width");
var originalWidth = $($("#container div")[0]).css("width");
$("#container div").click(function(){
if($(this).css("width") != parentWidth) {
$(this).css("width",parentWidth);
}
else {
$(this).css("width",originalWidth);
}
});
var divWidth = 250;
var n= 5; //this will be no of inner divs
$(function(){
$('#container div').each(function(index, element) {
$(this).click(function(e) {
if($(this).width() == divWidth)
{
var dt = divWidth;
if(index != 0)
{
$(this).prev().hide();
dt += divWidth;
}
else if(index < n)
{
$(this).next().hide();
dt += divWidth;
}
$(this).width(dt);
}
else
{
$(this).width(divWidth);
if(index != 0)
{
$(this).prev().show();
}
else if(index < n)
{
$(this).next().show();
}
}
});
});
});

how to use Javascript for slide left

i have use the javascript for sliding the element up and down as fallow
<script type="text/javascript">
$(function () {
var $divSlide = $("div.slide");
$divSlide.hide().eq(0).show();
var panelCnt = $divSlide.length;
setInterval(panelSlider, 3000);
function panelSlider() {
$divSlide.eq(($divSlide.length++) % panelCnt)
.slideUp("slow", function () {
$divSlide.eq(($divSlide.length) % panelCnt)
.slideDown("slow");
});
}
});
</script>
which slide the panel up and down having slide tag panals are added as fallow
//protion
DataTable promo = SQl.ExecuteSelectCommand("select Promo_Code,Promo_Discription,Promo_Min_Ammount,Persent_Off,Start_Date,End_Date,Supp_Name from Prommosion_Details_View ");
if (promo.Rows.Count > 0)
{
for (int i = 0; i <= promo.Rows.Count - 1; i++)
{
Panel p = new Panel();
p.CssClass = "slide";
PromoUC PUC = (PromoUC)Page.LoadControl("PromoUC.ascx");
PUC.setText(promo.Rows[i][3].ToString(), promo.Rows[i][1].ToString(), promo.Rows[i][4].ToString(), promo.Rows[i][5].ToString(), promo.Rows[i][0].ToString(), " From " + promo.Rows[i]["Supp_Name"].ToString());
p.Controls.Add(PUC);
searchBoxPromoPlaceHolder.Controls.Add(p);
}
}
above code is working fine but the problem is tat i have to scroll it left and right with elastic effect
You should check the jQuery.animate() which helps you to do any animation effect.
you can animate any css property,in your case the width could fit your needs.check the examples online.

Categories

Resources