How to auto move active class before after in JavaScript - javascript

I have created simple scroll animation page, if I scroll right side want to delete previous items
then if I scroll left side want to delete next items. see this bellow image, how to solve this issues. could you please solve this issue.
// Sticky Catergory Menu
if ($(window).scrollTop() > 400) {
$("#stickyMenu").addClass('sticky');
} else {
$("#stickyMenu").removeClass('sticky');
}
//get current sroll position
var scrollPosition = $(window).scrollTop();
//get the position of the containers
for (i = 0; i < span_list.length; i++) {
if (scrollPosition >= ($("#" + span_list[i]).offset().top) - 50) {
$("#nav" + (i + 1)).siblings().removeClass("active");
$("#nav" + (i + 1)).addClass("active");
}
}
// if (("div.item:visible")) {
// if ($("div.item").is(":visible")) {
// var content = $(this).html()
// console.log("content == " + content)
// var row_id = $(this).parent().closest("div[id]").attr("id");
// console.log("row_id == " + row_id)
// }
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div class="topnav sticky" id="stickyMenu">
<span data-id="appetizers" id="nav1" class="cat-nav">Appetizers</span>
<span data-id="desserts" id="nav2" class="cat-nav">Desserts</span>
<span data-id="pizza--classic-11-inches-" id="nav3" class="cat-nav active">Pizza (Classic 11 inches)</span>
<span data-id="salad" id="nav4" class="cat-nav">Salad</span><span data-id="soups" id="nav5" class="cat-nav">Soups</span>
<span data-id="thai-noodles" id="nav6" class="cat-nav">Thai Noodles</span>
</div>

Related

Javascript run 2 functions on button click with multiple buttons and same class

I have a portfolio grid that has a screenshot of past work in each grid item.
Currently on button click, it calls a function to scroll the screenshot and stop once it reaches the bottom of the image.
I need to reverse the scroll once the button is clicked again. The scroll is created by a setInterval. I have a class of "down" on the button which is removed on click.
I have an if statement that does not work to check if the class of "down" is present and run a scrollUp function.
This is a PHP loop so there are multiple buttons with same class.
I cannot use jQuery.
Thanks for any help!
HTML:
<ul>
<li>
<div class="image-container overflow-hidden height-500">
<img class="item absolute pin-t w-full h-auto pin-l"
src="/image.jpg"/>
</div>
<button class="portScroll down">Scroll Down</button>
</li>
<li class="web-design-portfolio">
<div class="image-container overflow-hidden height-500">
<img class="item absolute pin-t w-full h-auto pin-l"
src="/image.jpg"/>
</div>
<button class="portScroll down">Scroll Down</button>
</li>
</ul>
JS:
function scrollDown() {
var portImg = this.parentNode.parentNode.querySelector('img.item');
var height = portImg.clientHeight;
var pos = 0;
var id = setInterval(frame, 5);
function frame() {
if (pos == height - 500) {
clearInterval(id);
} else {
pos++;
portImg.style.top = - + pos + 'px';
}
}
for (const button of document.querySelectorAll('button.portScroll')) {
button.classList.remove('down');
}
}
for (const button of document.querySelectorAll('button.portScroll')) {
if (button.classList.contains("down")) {
button.addEventListener("click", scrollDown);
} else {
button.addEventListener("click", scrollUp);
}
}
Here is the working Codepen for scroll down:
https://codepen.io/completewebco/pen/bZeVoz
I created a single function that does what is needed. I hope that is OK.
function scrollUpOrDown(_this, state) {
var portImg = _this.parentNode.parentNode.querySelector('img.item');
var height = portImg.clientHeight;
if(state.id > -1) {
clearInterval(state.id);
state.dir *= -1;
}
if(state.pos < 0) {
state.pos = 1;
}
state.id = setInterval(frame, 5);
function frame() {
if ((state.pos == height - 500 && state.dir > 0) || (state.pos == 0 && state.dir < 0)) {
clearInterval(state.id);
} else {
state.pos += state.dir;
portImg.style.top = -+state.pos + "px";
}
}
}
for (const button of document.querySelectorAll("button.portScroll")) {
let scollingState = {
pos: -1,
id: -1,
dir: 1
};
if (button.classList.contains("down")) {
button.addEventListener("click", function(){
scrollUpOrDown(this,scollingState);
});
}
}
https://codepen.io/prtjohanson/pen/QoEyQK
If you are wondering why/how it works, look at the output of this code
var array = [0,1,2,3,4,5];
for(const i in array) {
setTimeout(function(){console.log(i)}, Math.random()*1000)
}
and read https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/let#Scoping_rules_2

see more button comment show and hide past list

i need to show number of list and loop the remain number when i click on see more appear 6 of list and slice the rest and back to slice when i click prev button ..
https://codepen.io/hesham-farag/pen/Ngadvj
<div class="comment-box-container">
<div class="comment-box">
<div class="user-comment-box">0</div>
<div class="user-comment-box">1</div>
<div class="user-comment-box">2</div>
<div class="user-comment-box">3</div>
<div class="user-comment-box">4</div>
<div class="user-comment-box">5</div>
<div class="user-comment-box">6</div>
<div class="user-comment-box">7</div>
<div class="user-comment-box">8</div>
<div class="user-comment-box">9</div>
<div class="user-comment-box">10</div>
<div class="user-comment-box">11</div>
<div class="user-comment-box">12</div>
<div class="user-comment-box">13</div>
<div class="user-comment-box">14</div>
<div class="user-comment-box">15</div>
<div class="user-comment-box">16</div>
<div class="user-comment-box">17</div>
<div class="user-comment-box">18</div>
<div class="user-comment-box">19</div>x">
<button class="see-more">See More...</button>
</div><!--comment-box end-->
</div><!-- comment-box-container end-->
.user-comment-box { display:none;
}
$(function(){
// select the first 5 hidden divs
$( ".comment-box" ).each(function( index ) {
$(this).children(".user-comment-box").slice(-5).show();
});
$(".see-more").click(function(e){ // click event for load more
e.preventDefault();
var done = $('<div class="see-more=done">done</div>');
$(this).siblings(".user-comment-box:hidden").slice(-5).show(); // select next 5 hidden divs and show them
if($(this).siblings(".user-comment-box:hidden").length == 0){ // check if any hidden divs
$(this).replaceWith(done); // if there are none left
}
});
});
Thanks!
Here's the working code:
$(function(){
// select the first 5 hidden divs
var count = 5;
var currentCount = 0;
$( ".comment-box" ).each(function( index ) {
$(this).children(".user-comment-box").slice(0,count).show();
currentCount = count;
});
$(".see-more").click(function(e){ // click event for load more
e.preventDefault();
$( ".comment-box" )children(".user-comment-box").slice(0,count).hide();
var done = $('<div class="see-more=done">done</div>');
$(this).siblings(".user-comment-box").hide();
$(this).siblings(".user-comment-box:hidden").slice(currentCount,currentCount + count).show(); // select next 5 hidden divs and show them
currentCount +=count;
if($(this).siblings(".user-comment-box").length == currentCount){ // check if any hidden divs
$(this).replaceWith(done); // if there are none left
}
});
});
i found the answer and put in this link for anyone search for
link
$(document).ready(function() {
var $pagination = $(".pagination");
var $lis = $pagination.find("li:not(#prev, #next)");
$lis.filter(":gt(3)").hide();
$lis.filter(":lt(5)").addClass("active");
var $next = $("#next").click(function() {
var idx = $lis.index($lis.filter(".active:last")) || 0;
var $toHighlight = $lis.slice(idx + 1, idx + 6);
$(".prev").show();
if ($toHighlight.length == 0) {
$prev.show();
return;
}
$next.show();
$lis.filter(".active").removeClass("active").hide();
$toHighlight.show().addClass("active");
});
var $prev = $("#prev").click(function() {
var idx = $lis.index($lis.filter(".active:first")) || 0;
var start = idx < 4 ? 0 : idx - 3;
var $toHighlight = $lis.slice(start, start + 5);
if ($toHighlight.length == 0) {
$prev.hide();
return;
}
$next.show();
$lis.filter(".active").removeClass("active").hide();
$toHighlight.show().addClass("active");
});
}); // close jquery

Adding option elements resets scroll position in select element

I am building a select list with a large number of options with lazy loading. The data starts by loading a preset number of items, and then as the user scrolls down the list, more items are loaded. This is all working great.
However, when new options are added, the browser scrolls to the most recently selected item, or to the top if no item is selected (tested in Firefox and IE11). This is very jarring and annoying. I would like the viewport to remain in the same spot when adding options. This is not an issue with other HTML elements like divs or lis.
Here is the CSS:
#main {
height: 200px;
width: 200px;
}
Here is the HTML with knockout bindings:
<div>
<span data-bind="text: 'Loaded ' + items().length + ' out of ' + data.length + ' items'"></span>
</div>
<select id="main" size="10" data-bind="foreach: items, event: { scroll: scrolled }">
<option data-bind="text: name"></option>
</select>
Here is the JavaScript:
var data = [];
for (var i = 0; i < 100; i++) {
data.push({
id: i,
name: "Item" + i
});
}
function getItems(count) {
var target = viewModel.maxId + count;
while (viewModel.maxId < target && viewModel.maxId < data.length) {
viewModel.items.push(data[viewModel.maxId++]);
}
}
var viewModel = {
data: data, // total data
items: ko.observableArray([]), // visible items out of data
scrolled: function(data, event) {
var elem = event.target;
if (elem.scrollTop > (elem.scrollHeight - elem.offsetHeight - 10)) {
getItems(20);
}
},
maxId: 0
};
ko.applyBindings(viewModel);
getItems(20);
And here is the fiddle: http://jsfiddle.net/4wjra438/2/
After getting new items, you can reset the scrollTop to what it was before getItems. That will make the jump-to-top less noticeable, but I don't know how to prevent it altogether.
scrolled: function(data, event) {
var elem = event.target;
var scrollPos = elem.scrollTop;
if (scrollPos > (elem.scrollHeight - elem.offsetHeight - 10)) {
getItems(20);
elem.scrollTop = scrollPos;
}
},

How to disable more than one scroll function?

I am making a page, where on scroll down, the left side of the page will slide up, and the right side of the page will slide down.
and on scroll up, the left side of the page will slide down, and the right side of the page will slide up.
I have this working if the user ONLY scrolls once (using a mouse wheel), when you scroll multiple times (before the function has completed, the left and right side will continue to scroll and mess up. Is there a way to disable more than one scroll?
I have added my code and the fiddle below.
<div class="left">
<div id="left1" class="onLeft Side">
</div>
<div id="left2" class="onLeft Side">
</div>
<div id="left3" class="onLeft Side">
</div>
</div>
<div class="right">
<div id="right3" class="onRight Side">
</div>
<div id="right2" class="onRight Side">
</div>
<div id="right1" class="onRight Side">
</div>
</div>
$(document).ready(function(){
var wholeHeight = jQuery('.right').height();
var rightLength = jQuery('.onRight').length;
jQuery('.right').css({top:-((wholeHeight*rightLength)-wholeHeight)});
var leftHeight = jQuery('.left').height();
var leftLength = jQuery('.onLeft').length;
var tot = (leftHeight * leftLength) - leftHeight;
console.log('tot', tot)
$('body').bind('mousewheel', function(e){
var height = jQuery('.left').height();
var leftTop = jQuery('.left').position().top;
var rightTop = jQuery('.right').position().top;
if(e.originalEvent.wheelDelta /120 > 0) {
if (leftTop != 0) {
console.log('scrolling up !');
jQuery('.left').animate({top:leftTop + height});
jQuery('.right').animate({top:rightTop - height});
} else {
console.log('The up end');
}
} else {
if (leftTop != -tot) {
console.log('scrolling down !');
jQuery('.left').animate({top:leftTop - height});
jQuery('.right').animate({top:rightTop + height});
} else {
console.log('the down end')
}
}
});
});
https://jsfiddle.net/11pftj26/
Thanks
try this:
$(document).ready(function(){
var wholeHeight = jQuery('.right').height();
var rightLength = jQuery('.onRight').length;
jQuery('.right').css({top:-((wholeHeight*rightLength)-wholeHeight)});scrolling=false;
var leftHeight = jQuery('.left').height();
var leftLength = jQuery('.onLeft').length;
var tot = (leftHeight * leftLength) - leftHeight;
console.log('tot', tot)
$('body').bind('mousewheel', function(e){
if(scrolling)
return;
scrolling=true;
var height = jQuery('.left').height();
var leftTop = jQuery('.left').position().top;
var rightTop = jQuery('.right').position().top;
if(e.originalEvent.wheelDelta /120 > 0) {
if (leftTop != 0) {
console.log('scrolling up !');
jQuery('.left').animate({top:leftTop + height},{done:function(){scrolling=false}});
jQuery('.right').animate({top:rightTop - height},{done:function(){scrolling=false}});
} else {
console.log('The up end');
scrolling=false;
}
} else {
if (leftTop != -tot) {
console.log('scrolling down !');
jQuery('.left').animate({top:leftTop - height},{done:function(){scrolling=false}});
jQuery('.right').animate({top:rightTop + height},{done:function(){scrolling=false}});
} else {
console.log('the down end');
scrolling=false;
}
}
});
});
Fiddle in Action
You can use .one() function of Jquery, read the official guide.
http://api.jquery.com/one/
When you scroll twice quickly your calculations for leftTop and leftRight will be off. What you can do is seperate the top calculation from the DOM state:
https://jsfiddle.net/11pftj26/2/
$(document).ready(function(){
var wholeHeight = jQuery('.right').height();
var rightLength = jQuery('.onRight').length;
jQuery('.right').css({top:-((wholeHeight*rightLength)-wholeHeight)});
var leftHeight = jQuery('.left').height();
var leftLength = jQuery('.onLeft').length;
var tot = (leftHeight * leftLength) - leftHeight;
var index = 0;
function animate(index) {
jQuery('.left').stop().animate({top: -1 * index * leftHeight});
jQuery('.right').stop().animate({top: -1 * (rightLength - index - 1) * wholeHeight });
}
$('body').bind('mousewheel', function(e) {
if (e.originalEvent.wheelDelta > 0) {
index = Math.max(0, index - 1);
} else {
index = Math.min(index + 1, rightLength - 1);
}
animate(index);
});
});

Cannot read top of Undefined jquery scroll

I've tried to find a solution to this error but with no luck so I'll post my specific problem. I have a jquery scroll that scrolls to the hashtags in the menu and when reached the specific target hashtags it should change the menu item color from grey to white. Everything works fine with one small error.
When you click on the menu item it scrolls down but then you have to scroll 1-5px more in order for the script to change the menu item to active (white color), the console also gives me a "cannot read property 'top' of undefined. Im clueless because the script gathers the menu items in an array and if I console.log the array the items are there. If I console.log the height and position of the div it returns values but still gives me the error messages.
<div class="header">
<div id="nav-anchor"></div>
<div class="container-fluid menu-content">
<div class="row">
<div class="col-md-6">
<img src="images/logotype.png" alt="Logotype" title="" class="brand">
</div><!-- end col md 6 brand -->
<div class="col-md-6 menu">
<nav>
<ul>
<li>About</li>
<li>Work</li>
<li>Cases</li>
<li>Meet us</li>
<li>Follow us</li>
</ul>
</nav>
</div><!-- end col md 6 menu -->
</div><!-- end row -->
</div><!-- end container -->
</div><!-- end header -->
$(document).ready(function(){
/**
* This part does the "fixed navigation after scroll" functionality
* We use the jQuery function scroll() to recalculate our variables as the
* page is scrolled/
*/
$(window).scroll(function(){
var window_top = $(window).scrollTop(); // the "12" should equal the margin-top value for nav.stick
var div_top = $('.header').offset().top;
});
/**
* This part causes smooth scrolling using scrollto.js
* We target all a tags inside the nav, and apply the scrollto.js to it.
*/
$(".menu li a").click(function(evn){
evn.preventDefault();
$('html,body').scrollTo(this.hash, this.hash);
if (window_top > div_top) {
$('nav').addClass('stick');
} else {
$('nav').removeClass('stick');
}
});
/**
* This part handles the highlighting functionality.
* We use the scroll functionality again, some array creation and
* manipulation, class adding and class removing, and conditional testing
*/
var aChildren = $("nav li").children(); // find the a children of the list items
var aArray = []; // create the empty aArray
for (var i=0; i < aChildren.length; i++) {
var aChild = aChildren[i];
var ahref = $(aChild).attr('href');
aArray.push(ahref);
} // this for loop fills the aArray with attribute href values
$(window).scroll(function(){
var windowPos = $(window).scrollTop(); // get the offset of the window from the top of page
var windowHeight = $(window).height(); // get the height of the window
var docHeight = $(document).height();
for (var i=0; i < aArray.length; i++) {
var theID = aArray[i];
var divPos = $(theID).offset().top; // get the offset of the div from the top of page
var divHeight = $(theID).height(); // get the height of the div in question
if (windowPos >= divPos && windowPos < (divPos + divHeight)) {
$("a[href='" + theID + "']").addClass("active");
} else {
$("a[href='" + theID + "']").removeClass("active");
}
}
if(windowPos + windowHeight == docHeight) {
if (!$("nav li:last-child a").hasClass("active")) {
var navActiveCurrent = $(".active").attr("href");
$("a[href='" + navActiveCurrent + "']").removeClass("active");
$("nav li:last-child a").addClass("active");
}
}
});
});
window_top needs to be a global variable, also you can add the specified amount of pixels you need to the actual variable so var div_top = $('.header').offset().top + 5;

Categories