Jquery image scroller slow and jerky - javascript

So I built this image scroller with little thumbnail images at the bottom, I wanted the thumbnails to scroll left and right when you hover over an indicated area and stop when the last one comes into view ( and the same with the first one for the other direction) The code that I came up with works for a little while on the page but after a while it starts to get slow and jerky so I was wondering if there was a cleaner way to accomplish the same thing.
The code is:
var licount = $('.hs_cos_flex-slides-thumb li').length; //counts rows in list
var thumbwidth = licount * 210; //gets width of all rows
var viewwidth = $(".hs-cos-flex-slider-control-panel").width(); //gets width of sarounding div
var scrollwidth = thumbwidth - viewwidth; //gets width where last row is visible
var intervalId = window.setInterval;
$( ".thumb-for" ).hover(
function() {
var scrollposition = $(".hs_cos_flex-slides-thumb").position().left; //calculates how far left it has moved
var absposition = Math.abs(scrollposition); //gets absolute value of left movement
var shover = true;
if ( scrollwidth > (absposition + 209) ){
$('.hs_cos_flex-slides-thumb').animate({
right: '+=210px'
}, 1500, 'linear');
absposition+=210;
}
intervalId = window.setInterval(moveticker, 1500)
function moveticker() {
if ( scrollwidth > (absposition + 209) ){
$('.hs_cos_flex-slides-thumb').animate({
right: '+=210px'
}, 1500, 'linear');
absposition+=210;
}
};
}, function() {
window.clearInterval(intervalId);
}
);
$( ".thumb-back" ).hover(
function() {
var scrollposition = $(".hs_cos_flex-slides-thumb").position().left; //calculates how far left it has moved
var absposition = Math.abs(scrollposition); //gets absolute value of left movement
var shover = true;
if ( scrollposition < 0 ){
$('.hs_cos_flex-slides-thumb').animate({
right: '-=210px'
}, 1500, 'linear');
scrollposition+=210;
}
intervalId = window.setInterval(moveticker, 1500)
function moveticker() {
if ( scrollposition < 0 ){
$('.hs_cos_flex-slides-thumb').animate({
right: '-=210px'
}, 1500, 'linear');
scrollposition+=210;
}
};
}, function() {
window.clearInterval(intervalId);
}
);

Related

Get elements coordinates

I need some help here.
First off, here is a small demo code from my game: https://jsfiddle.net/MiloSx7/a0dn9a4f/2/
Animation idea: Make the coin scale to 2x after it's collected, then slowly move it and gradually reduce scale to the exact spot where the image displaying the coin inventory stat is , invLocation is the ID of the element where the animation should end. It starts from the current coinId X and Y
Is it possible to somehow get the X and Y of the invLocation, so that I know where should I tell the animation to move?
You can do this with JQuery position() and offset() methods.
const spawnTime = 10000;
var coin = 0;
var intervalId = '';
var coinDiv = $('#coinDiv');
var coinImg = $('#coinImg');
var invDiv = $('#invDiv');
var invId = $('#inventoryId');
var invImg = $('#invLocation');
coinImg.on('click', collect);
intervalId = setInterval(setLocation, spawnTime);
function setLocation() {
var x = parseInt( Math.random()*(80-20+1) ) + 20;
var y = parseInt( Math.random()*(80-20+1) ) + 20;
coinImg.animate({
opacity: 1
}, 3000,
function() {
coinImg.css('top', x+'%');
coinImg.css('left', y+'%');
coinImg.css('display', 'initial');
setTimeout( () => coinImg.animate({ opacity: 0 }, 3000), 6000);
});
}
function collect() {
clearInterval(intervalId);
coinImg.stop();
coinImg.css('opacity', 1);
/* Increment coin counter */
coin++;
invId.text(coin);
/* In order to disable multiple clicks */
coinImg.css('pointer-events', 'none');
/* Double the size */
coinImg.css('width', '128px');
coinImg.css('height', '128px');
/* Animate and return to normal */
coinImg.animate({
width: '32px',
height: '32px',
left: invImg.offset().left + 'px',
top: invImg.offset().top + 'px'
}, 1500,
function() {
coinImg.css('pointer-events', 'auto');
coinImg.css('display', 'none');
coinImg.css('width', '64px');
coinImg.css('height', '64px');
intervalId = setInterval(setLocation, spawnTime);
}
);
}
Working example: https://jsfiddle.net/wz4q9w69/

Animation continues after once trigged by scroll

I made a bar chart only with CSS and a animation from low to up that works well, however I want to run only when trigged by scroll.
Somehow the animation after trigged by the scroll does not stop, it keeps running.
look in the inspect element the latest bar.
jquery
// Bar Chart Animation
function barChart(){
$("#demographicsBars li .bar").each( function( key, bar ) {
var percentage = $(this).data('percentage');
$(this).animate({
'height' : percentage + '%'
}, 1000, function() {
$('.viewerDemographics #demographicsBars li .bar').css('overflow','inherit');
});
});
};
// Scroll Call Animation
$(window).scroll(function () {
$('.viewerDemographics').each(function () {
var imagePos = $(this).offset().top;
var imageHeight = $(this).height();
var topOfWindow = $(window).scrollTop();
if (imagePos < topOfWindow + imageHeight && imagePos + imageHeight > topOfWindow) {
barChart();
} else {
}
});
});
jsfiddle
It's because you're asking it to.
http://jsfiddle.net/g6r1vngh/1/
Tell JS it hasn't been drawn
// Bar Chart Animation
var barChartDrawn = false;
Set it to true when it runs
function barChart(){
barChartDrawn = true;
Don't do any of those calculations, or run the function, if it's true
$(window).scroll(function () {
if (barChartDrawn) return;

How to always show submenu in vertical menu with this js file?

My question is if anybody knows what to change in the following js file to always show submenu on the vertical menu , meaning to show the submenu on page load and stay shown whether i hover on it or not, in clear make it part of the vertical menu and not an hidden sub menu that you have to hover on the parent category to access.
What do i need to change in the following code to acomplish that, :
Thanks in advance guys !
* DC Vertical Mega Menu - jQuery vertical mega menu
* Copyright (c) 2011 Design Chemical
*
* Dual licensed under the MIT and GPL licenses:
* http://www.opensource.org/licenses/mit-license.php
* http://www.gnu.org/licenses/gpl.html
*
*/
(function($){
//define the new for the plugin ans how to call it
$.fn.dcVerticalMegaMenu = function(options){
//set default options
var defaults = {
classParent: 'dc-mega',
arrow: true,
classArrow: 'dc-mega-icon',
classContainer: 'sub-container',
classSubMenu: 'sub',
classMega: 'mega',
classSubParent: 'mega-hdr',
classSubLink: 'mega-hdr',
classRow: 'row',
rowItems: 3,
speed: 'fast',
effect: 'show',
direction: 'right',
menubg: '0',
menufixwidth: '0',
menufixheight: '0'
};
//call in the default otions
var options = $.extend(defaults, options);
var $dcVerticalMegaMenuObj = this;
//act upon the element that is passed into the design
return $dcVerticalMegaMenuObj.each(function(options){
$mega = $(this);
if(defaults.direction == 'left'){
$mega.addClass('left');
} else {
$mega.addClass('right');
}
// Get Menu Width
var megaWidth = $mega.width();
// Set up menu
$('> li',$mega).each(function(){
var $parent = $(this);
var $megaSub = $('> ul',$parent);
if($megaSub.length > 0){
$('> a',$parent).addClass(defaults.classParent).append('<span class="'+defaults.classArrow+'"></span>');
$megaSub.addClass(defaults.classSubMenu).wrap('<div class="'+defaults.classContainer+'" />');
var $container = $('.'+defaults.classContainer,$parent);
if($('ul',$megaSub).length > 0){
$parent.addClass(defaults.classParent+'-li');
$container.addClass(defaults.classMega);
// Set sub headers
$('> li',$megaSub).each(function(){
$(this).addClass('mega-unit');
if($('> ul',this).length){
$(this).addClass(defaults.classSubParent);
$('> a',this).addClass(defaults.classSubParent+'-a');
} else {
$(this).addClass(defaults.classSubLink);
$('> a',this).addClass(defaults.classSubLink+'-a');
}
});
$('> li li',$megaSub).each(function(){
if($('> ul',this).length){
$(this).addClass('mega-sub3'); //rajib
$('.mega-sub3 ul').addClass("show3div");
}
});
} else {
$container.addClass('non-'+defaults.classMega);
if(defaults.menubg==1){
var catimages =$('.non-'+defaults.classMega).closest("li").attr('id');
catimages = catimages.replace(/\s+/g, '-').toLowerCase();
$('.non-'+defaults.classMega).css('background','#333 url(modules/leftmegamenu/bgimages/'+catimages+'.gif) no-repeat right bottom');
}
}
}
var $container = $('.'+defaults.classContainer,$parent);
var subWidth = $megaSub.outerWidth(true);
var subHeight = $container.height();
if(defaults.menufixwidth>0){
var subWidth = defaults.menufixwidth;
}
if(defaults.menufixheight>0){
var subHeight = defaults.menufixheight;
}
var itemHeight = $parent.outerHeight(true);
// Set position to top of parent
$container.css({
height: subHeight+'px',
width: subWidth+'px',
zIndex: '1000'
}).hide();
});
// HoverIntent Configuration
var config = {
sensitivity: 2, // number = sensitivity threshold (must be 1 or higher)
interval: 10, // number = milliseconds for onMouseOver polling interval
over: megaOver, // function = onMouseOver callback (REQUIRED)
timeout: 0, // number = milliseconds delay before onMouseOut
out: megaOut // function = onMouseOut callback (REQUIRED)
};
$('li',$dcVerticalMegaMenuObj).hoverIntent(config);
function megaOver(){
$(this).addClass('mega-hover');
var $link = $('> a',this);
var $subNav = $('.sub',this);
var $container = $('.sub-container',this);
var width = defaults.menufixwidth;
var outerHeight = $container.outerHeight();
var height = defaults.menufixheight;
var itemHeight = $(this).outerHeight(true);
var offset = $link.offset();
var scrollTop = $(window).scrollTop();
var offset = offset.top - scrollTop
var bodyHeight = $(window).height();
var maxHeight = bodyHeight - offset;
var xsHeight = maxHeight - outerHeight;
if(defaults.menubg==1){
var catimages =$(this).closest("li").attr('id');
catimages = catimages.replace(/\s+/g, '-').toLowerCase();
$container.css({
background: '#333 url(modules/leftmegamenu/bgimages/'+catimages+'.gif) no-repeat right bottom'
});
}
if(xsHeight < 0){
var containerMargin = xsHeight - itemHeight;
$container.css({marginTop: containerMargin+'px'});
}
var containerPosition = {right: megaWidth};
if(defaults.direction == 'right'){
containerPosition = {left: megaWidth};
}
if(defaults.effect == 'fade'){
$container.css(containerPosition).fadeIn(defaults.speed);
}
if(defaults.effect == 'show'){
$container.css(containerPosition).show();
}
if(defaults.effect == 'slide'){
$container.css({
width: 0,
height: 0,
opacity: 0});
if(defaults.direction == 'right'){
$container.show().css({
left: megaWidth
});
} else {
$container.show().css({
right: megaWidth
});
}
$container.animate({
width: width,
height: height,
opacity: 1
}, defaults.speed);
}
}
function megaOut(){
$(this).removeClass('mega-hover');
var $container = $('.sub-container',this);
$container.hide();
}
});
};
})(jQuery);
$(document).ready(function($){
// menu slide hoverIntend
$('#rajbrowsecat').hoverIntent({
over: startHover,
out: endHover,
timeout: 1000
});
function startHover(e){
$('#rajdropdownmenu').slideDown(200)
}
function endHover(){
$('#rajdropdownmenu').slideUp(600)
}
// menu slide hoverIntend
$('#rajmegamenu').dcVerticalMegaMenu({
rowItems: '5',
speed: 'fast',
effect: 'slide',
direction: 'right',
menubg: '1',
menufixwidth: '236',
menufixheight: '155'
});
});
UPDATE:
So i managed to do it by diabling all the code (with /*) related to hover effect from the line "// HoverIntent Configuration" to "// menu slide hoverIntend" and by twicking the css a bit for presentation , seemed to do the trick to always showing submenus but for those who are interested i also found a way by adding to the css the line "height:auto", that also seemed to work fairly nicely.
Anyway thanks guys for yor answers anyway , it's always nice to to know that we have a place you can turn to when we are stuck !

scroll to next div already in browser

I have a series of divs that are 100% height with a scroll to function that takes you to the next div out of the viewport on background click. However, if the next div is already slightly in the viewport the whole thing is counted as being visible and the scroll to bypasses it. Can anyone offer direction on how to get the script to scroll to the div even if it's partially in the viewport already?
Codepen here.
If you begin scrolling slightly in the codepen and then click on the background you'll see that it doesnt scroll you to the div that's already in the viewport but the div after that.
$(document).ready(function() {
// get initial nav height
var $window = $(window);
var wst = $window.scrollTop();
var th = $('div.top').height();
var currentSlide = $('#wrapper').data( 'current-slide', $('div.slide').eq(0) );
$('div.scroll_images').css({ height: 'auto', overflow: 'visible', top: 0 });
$('div.scroll_images div.inner').css({ position: 'absolute', top: 0 });
$('div.slide').each(function() {
$(this).css('padding',function() {
return (($(window).height()-$(this).height())/2)+'px 0'
});
});
// scrollto for click on slide
jQuery.fn.scrollTo = function(hash) {
$this = $(this);
st = $this.offset().top - th; // subtract nav height
$('html, body').animate({ scrollTop: st }, 550
);
}
$('#wrapper').click(function(e){
//get the current slide index from the body tag.
$this = currentSlide.data( 'current-slide' );
$next = $(".slide:below-the-fold");
if($next.length) {
$next.scrollTo($next.attr('id'));
//Save the next slide as the current.
$('#wrapper').data( 'current-slide', $next );
} else {
//Throw us back to the top.
$('div.slide:first').scrollTo($('div.slide:first').attr('id'));
//Save the first slide as the first slide, which
//Cycles us back to the top.
$('#wrapper').data( 'current-slide', $('div.slide:first'));
}
})
//Images fade in
$('img').hide();
$('img').each(function(i) {
if (this.complete) {
$(this).fadeIn();
} else {
$(this).load(function() {
$(this).fadeIn();
});
}
});
//Stop links affecting scroll function
$("a").click(function(e) {
e.stopPropagation();
});
});
(function($) {
$.belowthefold = function(element, settings) {
var fold = $(window).height() + $(window).scrollTop();
return fold <= $(element).offset().top - settings.threshold;
};
$.extend($.expr[':'], {
"below-the-fold": function(a, i, m) {
return $.belowthefold(a, {threshold : 0});
}
});
})(jQuery);
Here's what I might try to do: go through each div in the series. Find the div who's offset() is closest to $(window).scrollTop(). Now, find the next() div after the "current" one and scroll to it.
For comparing the offset() of each div, try something like this:
var closest = $('[selector]:first');
$('[selector]').each(function() {
var oldDistance = Math.abs(closest.offset() - $(window).scrollTop());
var newDistance = Math.abs($(this).offset() - $(window).scrollTop());
if(newDistance < oldDistance) {
closest = $(this);
}
}

JQuery continuous image carousel only moving one image at a time?

Currently working on an image carousel and I believe it is 99% done, except for one thing... I can only move one picture at a time, and then I have to rehover in order to keep the slider going. So is there some sort of jump statement or goto statement that I can use to continually run the loops?
Here is what I have so far :
Fiddle
JQuery
$(document).ready(function(){
$('.carousel').each(function(){
if($(this).width() < $(this).children('ul').width()){
$(this).children('carrow').each(function(){
$(this).hide();
});
}
});
$('.carousel').hover(function(){
$(this).children('.carrow').each(function(){
$(this).addClass('carrow-hover');
});
}, function(){
$(this).children('.carrow').each(function(){
$(this).removeClass('carrow-hover');
});
});
$('.carrow').hover(function(){
var SD = 210;
var $carousel = $(this).parent();
var $ul = $carousel.children('ul');
var distance = SD;
var time = 2500;
var rate = distance/time;
//When animation is completed, Jump back to here
distance = Math.abs($ul.position().left);
if($(this).hasClass('left-arrow')){
if(distance == 0) {
$ul.css({left: -210});
$ul.prepend($ul.children('li:last-child'));
} else {
time = distance/rate;
}
$ul.stop().animate({
left: 0
}, time, 'linear');
}
else if($(this).hasClass('right-arrow')){
if(distance != 0){
distance = SD - distance;
time = distance/rate;
}
$ul.stop().animate({
left: -210
}, time, 'linear', function(){
$ul.append($ul.children('li:first-child'));
$ul.css({left: 0});
});
}
}, function(){
$(this).parent().children('ul').stop();
});
});
You can separate animation routine in it's own function, e.g.
function myAnimate(that){
// animation goes here
}
And call itself as a callback function at the animation end
$ul.stop().animate({
left: 0
}, time, 'linear', function(){myAnimate(that)});
This way as soon as one animation ends - the other begins
Demo: http://jsfiddle.net/bjyuA/1/
All I did was loop the part I had wanted and created a few extra dependencies which Yuriy had fixed, but I figured I would share my approach as well.
$('.carrow').hover(function(){
var SD = 210;
var $this = $(this);
var $carousel = $(this).parent();
var $ul = $carousel.children('ul');
var distance = SD;
var time = 2500;
var rate = distance/time;
distance = Math.abs($ul.position().left);
continue_scroll = function(dist) {
time = 2500;
if(arguments.length != 0){
distance = dist;
}
if($this.hasClass('left-arrow')){
if(distance == 0) {
time = 2500;
} else {
time = distance/rate;
}
$ul.stop().animate({
left: 0
}, time, 'linear', function(){
$ul.prepend($ul.children('li:last-child'));
$ul.css({left: -210});
continue_scroll(210);
});
}
else if($this.hasClass('right-arrow')){
if(distance != 0 && arguments.length == 0){
distance = SD - distance;
time = distance/rate;
}
$ul.stop().animate({
left: -210
}, time, 'linear', function(){
$ul.append($ul.children('li:first-child'));
$ul.css({left: 0});
continue_scroll(0);
});
}
}
continue_scroll();
}, function(){
$(this).parent().children('ul').stop();
});

Categories