Flexslider2 not resizing on window resize - javascript

I have a responsive slider which is supposed to show 1 item per slide at less than 600px width and 3 per slide above that. (as per http://flexslider.woothemes.com/dynamic-carousel-min-max.html) It works if window is loaded at those sizes, but does not work if window is resized (the items per slide don't change). I get an error "Cannot read property 'vars' of undefined" I've tried replacing "$" with jQuery in front of the var but the entire thing breaks at that point.
jQuery(window).load(function() {
// store the slider in a local variable
  var $window = $(window),
flexslider;
// tiny helper function to add breakpoints
function getGridSize() {
return (window.innerWidth < 600) ? 1 :
(window.innerWidth < 900) ? 3 : 3;
}
$(function() {
SyntaxHighlighter.all();
});
jQuery('.flexslider').flexslider({
animation: "slide",
animationLoop: false,
itemWidth: 290,
itemMargin: 0,
 minItems: getGridSize(), // use function to pull in initial value
      maxItems: getGridSize() // use function to pull in initial value
    });
// check grid size on resize event
jQuery(window).resize(function() {
var gridSize = getGridSize();
flexslider.vars.minItems = gridSize;
flexslider.vars.maxItems = gridSize;
});
  });
}(document));

Related

JavaScript: Set scroll position variable according to media queries

I am working on a fade-in/out-effect-on-scroll on a web project.
On my js I have to set a certain value for the scroll position i. e. the offset to make the effect kick in.
The problem:
The offset value cannot be applied to all kinds of devices due to
different heights.
Questions (hierarchic):
How to make the static values dynamic and variable to the device
height/media queries?
How can you generally slim down the code?
How can I trigger an additional slide-slightly-from-right/left to the
effect?
Here is the code:
// ---### FOUNDATION FRAMEWORK ###---
$(document).foundation()
// ---### FADE FX ###---
// ## SECTION-01: fade out on scroll ##
$(window).scroll(function(){
// fade out content a
$(".j-fadeOut").css("opacity", 1 - $(window).scrollTop() / 470);// 470 should be variable
// ## SECTION-02: fade in/out on scroll bottom ##
var offset = $('.j-fadeOut-2').offset().top;
console.log('offset: '+offset);
console.log('window: '+$(window).scrollTop())
if($(window).scrollTop() > offset)
{
// fade out top part of content b
$(".j-fadeOut-2").css("opacity", 1-($(window).scrollTop() - offset)/520);// 520 should be variable
// fade in bottom part of content c
$(".j-fadeIn").css("opacity", 0 + ($(window).scrollTop() - offset)/ 1100);// 1100 should be variable
}
});
See here for JavaScript Media Queries
You can use window.matchMedia to perform media queries in JavaScript. Example:
var mediaQuery = window.matchMedia( "(min-width: 800px)" );
The result will be stored as a boolean in mediaQuery.matches, i.e.
if (mediaQuery.matches) {
// window width is at least 800px
} else {
// window width is less than 800px
}
You can use multiple of these to suit your different device widths. Using the standard Bootstrap buckets:
var sizes = ['1200px', '992px', '768px', '480px']; // standard Bootstrap breakpoints
var fadeOutAs = [470, 500, 530, 560]; // this corresponds to your content a fadeout variable. Modify as required per screen size
var fadeOutBs = [520, 530, 540, 550]; // content B fadeout
var fadeOutCs = [1100, 1200, 1300, 1400]; // content C fadeout
var fadeOutA = 0;
var fadeOutB = 0;
var fadeOutC = 0;
for (i = 0; i < sizes.length; i++) {
var mediaQuery = window.matchMedia( "(min-width: " + sizes[i] + ")" );
if (mediaQuery.matches) {
fadeOutA = fadeOutAs[i];
fadeOutB = fadeOutBs[i];
fadeOutC = fadeOutCs[i];
}
}
Hope this helps

Auto-scroll embedded window only once when entering viewport. Can't scroll back up

I have an image embedded in a container with a background image to give the effect of scrolling within the page. Initially, I had the scrolling effect take place on page load, with this simple bit of script which worked perfectly.
$(window).on("load", function () {
$(".embedded_scroller_image").animate({ scrollTop: $('.embedded_scroller_image')[0].scrollHeight}, 2500, "easeInOutCubic");
}); // end on load
However, the element is too far down the page now and I want that animation to fire when the element enters 80% of the viewport. That part is also working fine with this code here (I'm using a scroll limiter to improve browser performance)
// limit scroll call for performance
var scrollHandling = {
allow: true,
reallow: function() {
scrollHandling.allow = true;
},
delay: 500 //(milliseconds) adjust to the highest acceptable value
};
$(window).on('scroll', function() {
var flag = true;
if(scrollHandling.allow) { // call scroll limit
var inViewport = $(window).height()*0.8; // get 80% of viewport
$('.embedded_scroller_image').each(function() { // check each embedded scroller
var distance = $(this).offset().top - inViewport; // check when it reaches offset
if ($(window).scrollTop() >= distance && flag === true ) {
$(this).animate({ scrollTop: $(this)[0].scrollHeight}, 2500, "easeInOutCubic"); //animate embedded scroller
flag = false;
}
});
} // end scroll limit
}); // end window scroll function
The problem is this: I want the autoscroll to happen once and then stop. Right now, it works on entering viewport, but if I then try to manually scroll the image, it keeps pushing back down or stutters. You can't get the element to scroll normally. I attempted to use the flag in the code to stop the animation, but couldn't get that to successfully work.
How can I have this animation fire when the element is 80% in the viewport, but then completely stop after one time?
Here is a codepen I mocked up as well http://codepen.io/jphogan/pen/PPQwZL?editors=001 If you scroll down, you will see the image element autoscroll when it enters the viewport, but if you try to then scroll that image up in its container, it won't work.
Thanks!
I have tweaked your script a bit:
// limit scroll call for performance
var scrollHandling = {
allow: true,
reallow: function() { scrollHandling.allow = true; },
delay: 500 //(milliseconds) adjust to the highest acceptable value
};
$(window).on('scroll', function() {
if(scrollHandling.allow) { // call scroll limit
var inViewport = $(window).height()*0.8; // get 80% of viewport
$('.embedded_scroller_image').each(function() { // check each embedded scroller
var distance = $(this).offset().top - inViewport; // check when it reaches offset
if ($(window).scrollTop() >= distance ) {
$(this).animate({ scrollTop: $(this)[0].scrollHeight}, 2500, "easeInOutCubic"); //animate embedded scroller
scrollHandling.allow = false;
}
});
} // end scroll limit
}); // end window scroll function
I have kicked out your flag and simply made use of scrollHandling.allow declared already.
Try if it works for you :)
Cheers!

JQuery reload three settings variables based on window size

I am trying to load three setting variables for bxSlider, based on the size of the window. I want the new settings to load dynamically when the browser is resized, not just on load. I have the below code that is setting the variables, I'm just struggling with making it play nicely with the bottom variable of mySlider, which is what is laoding the script upon resize.
Can anybody offer tips?
$(document).ready(function () {
/* Set variables for the maxSlides option */
var slidenumber,
width = $(window).width();
if (width < 768) {
slidenumber = 1;
} else if (width < 1024) {
slidenumber = 2;
} else {
slidenumber = 3;
}
$('.bxslider').bxSlider({
slideWidth: 5000,
minSlides: slidenumber,
maxSlides: slidenumber,
slideMargin: 50
});
var mySlider;
function tourLandingScript() {
mySlider.reloadSlider(slidenumber());
}
mySlider = $('.bxslider').bxSlider(slidenumber());
$(window).resize(tourLandingScript);
});
Best way to achieve this would be using CSS and media queries, so that you can hide or shrink slides without changing their number. However, if you need more complex behaviour that can't be achieved just with plain CSS, you'll need to write some javascript to it.
You need to listen to window's resize event and when it fires, recalculate required number of slides and if it changes, update slider using it's reloadSlider() method. The code could look somehow like this:
$(document).ready(function () {
var slideCount;
var mySlider;
// separate function to calculate required slide count
function calculateSlides() {
var width = $(window).width();
var slidenumber;
if (width < 768) {
slidenumber = 1;
} else if (width < 1024) {
slidenumber = 2;
} else {
slidenumber = 3;
}
return slidenumber;
}
// when page loads, we initialize the slider
slideCount = calculateSlides();
mySlider = $('.bxslider').bxSlider({
slideWidth: 5000,
minSlides: slideCount,
maxSlides: slideCount,
slideMargin: 50
});
// when we resize the window, just recalculate number of slides
// and if it has changed, reload the slider
$(window).resize(function() {
var newSlideCount = calculateSlides();
if (newSlideCount != slideCount) {
slideCount = newSlideCount;
mySlider.reloadSlider({
minSlides: newSlideCount,
maxSlides: newSlideCount
});
}
});
});
I also added some small optimization, so that browser won't rebuild whole slider component on every window resize (which triggers several times per second when resizing window by dragging its edge), but only in the moment when actual number of slides changes.
Hope this helps.
Thank you to Ondra Koupil for his help, however I was not able to get his solution to work exactly as required, I have ended up opting for an entirely new approach, which I'm sure could be pulled apart in order to optimise and is unlikely to be the most efficient option, but it works for me and hopefully can be of use to others.
The below solution is intended to be two entirely separate pieces of JS, which will not work if combined on one page. The intention is to load the relevant option (settings one/two) on the relevant page.
/* Settings one */
$(document).ready(function () {
var settings = function() {
var settings1 = { /* Desktop */
minSlides: 3,
maxSlides: 3,
moveSlides: 1,
slideWidth: 5000, /* Intentionally set to high value, bxslider will auto calculate */
slideMargin: 50
};
var settings2 = { /* Mobile */
minSlides: 1,
maxSlides: 1,
moveSlides: 1,
slideWidth: 2000 /* Intentionally set to high value, bxslider will auto calculate */
};
return ($(window).width()<1200) ? settings2 : settings1;
}
var mySlider;
function reloadonresize() {
mySlider.reloadSlider(settings());
}
mySlider = $('.bxslider').bxSlider(settings());
$(window).resize(reloadonresize);
});
/* End settings */
/* Settings two */
$(document).ready(function () {
var settings = function() {
var settings1 = { /* Desktop */
minSlides: 4,
maxSlides: 5,
moveSlides: 3,
slideWidth: 5000, /* Intentionally set to high value, bxslider will auto calculate */
slideMargin: 50
};
var settings2 = { /* Mobile */
minSlides: 2,
maxSlides: 2,
moveSlides: 1,
slideWidth: 2000 /* Intentionally set to high value, bxslider will auto calculate */
};
return ($(window).width()>=768) ? settings1 : settings2;
}
var mySlider;
function reloadonresize() {
mySlider.reloadSlider(settings());
}
mySlider = $('.bxslider').bxSlider(settings());
$(window).resize(reloadonresize);
});
/* End settings */

Stop/Restart an animation loop on window resize

I have an animation where three images rotate up and down. JSfiddle: http://jsfiddle.net/rLgkyzgc/1/
$(window).load(function() {
// Load images in BG that have been hidden by CSS
$('.banners').show();
// Create an empty array
var banners = [];
// Fill array with banner ids
$('.banners').each(function () {
var banner = $(this).attr('id');
banners.push(banner);
});
function switchBanners(){
var $firstBanner = $('#' + banners[0]);
var $secondBanner = $('#' + banners[1]);
var firstBannerHeight = $firstBanner.height();
var secondBannerHeight = $secondBanner.height();
$firstBanner.animate({ bottom: -firstBannerHeight }, 1200);
$secondBanner.animate({ bottom: 0 }, 1200, function(){
b = banners.shift(); banners.push(b);
setTimeout(function(){
switchBanners();
}, 4000);
});
};
// Delay initial banner switch
setTimeout(function(){
switchBanners();
}, 4000);
});
This is great for the desktop view, but on mobile, I want to stop the animation and just show one static image.
So my questions. How can I :
Only start the animation on page load if the window width is > 940px
Stop (reset) the animation if the page is resized to be < 940px wide
THEN restart the animation if the page resized to be > 940px wide
You should use window.matchMedia (see the documentation) to detect the viewport size on document.ready and when the window is resized, so something like this:
function resetAnimation() {
$firstBanner.stop(true, true);
$secondBanner.stop(true, true);
if(window.matchMedia("(min-width: 940px)").matches) {
//Start the animations here
}
}
$(document).ready(function() {
resetAnimation();
}
$(window).resize(function() {
resetAnimation();
}
Note that you don't really need to stopthe animations on document.ready, but this way you have a single function to reset the animations and then restart them only if necessary, which is something you typically want to do every time you resize the browser window, regardless of the viewport size.
I'll reference these in order:
1. Only start the animation on page load if the window width is > 940px
In your window load function, grab your browser width with $(window).width(). Then check that against your 940 (leave off the "px"), and perform necessary actions.
So:
if ($(window).width() > 940){ *actions* }
2. Stop (reset) the animation if the page is resized to be < 940px wide
To do this, you'll need to use the window resize function ($(window).resize()) and check your 940 against the browser width.
So:
$(window).resize(function(){
if ($(window).width() <= 940){
*stop (reset) animation*
}
});
3. THEN restart the animation if the page resized to be > 940px wide
This logic is essentially the same as #2, just reversed:
$(window).resize(function(){
if ($(window).width() > 940){
*restart animation*
}
});

Global JS var not being seen

My company bought a timeline plugin and it throws an error in every browser. It still works in Chrome and FireFox but is totally busted in IE (v11)
The JS error has to do with a global variable (defined in audio.min.js) that is not being seen in a following JS file (jquery.timeline.js).
The JS files in the HTML page are listed with the JS file with the global variable, first, followed by the other JS file, where the error is being generated so that all looks right.
Not sure what could cause this...
<script type="text/javascript" src="/Timeline/js/jquery/jquery-1.7.1.min.js"></script>
<script type="text/javascript" src="/Timeline/js/audiojs/audio.min.js"></script>
<script type="text/javascript" src="/Timeline/js/jquery.timeline.js"></script>
Here is the line that causes the error:
audio.prettyPaused = 0;
The errors:
SCRIPT1028: Expected identifier, string or number
Unable to set property 'prettyPaused' of undefined or null reference
Uncaught TypeError: Cannot set property 'prettyPaused' of undefined
The var "audio" is defined in a separate JS file (audio.min.js), right at the top of the file:
//SHARED VARIABLE TO INTERACT WITH VIDEO & PRETTYPHOTO
var audio;
Here is the line in context:
//HTML5 AUDIO PLAYER
audiojs.events.ready(function() {
var as = audiojs.createAll({
autoplay: true,
loop: true
});
audio.prettyPaused = 0;
});
Even More Context
//jquery.timeline.js
jQuery(document).ready(function() {
jQuery.myTimeline();
});
(function($) {
// GLOBAL VARS
var preload, container, tl, vidRoll, imgRoll, readBt, viewport, images, milestones, content, bar, track, dragger, marksAmount, fadeInDelay;
// CLASS CONSTRUCTOR / INIT FUNCTION
$.myTimeline = function() {
//SETUP VARS
preload = $('.preload');
container = $('#timeline_container');
tl = $('#timeline');
vidRoll = $('.video_rollover');
imgRoll = $('.image_rollover');
readBt = $('.readmore');
viewport = $('#timeline .viewport');
images = $('#timeline .viewport .images');
milestones = $('#timeline .milestones');
content = $('#timeline .milestones .content');
bar = $('#timeline .scrollbar');
track = $('#timeline .scrollbar .track');
dragger = $('#timeline .scrollbar .track .dragger');
marksAmount = $('.marks > div').length;
fadeInDelay = parseInt(tl.attr("data-fadeInDelay"));
//CONFIG ALL ELEMENTS SIZES AND POSITIONS BASED ON HTML ATTRIBS
container.css("width", tl.attr("data-width"));
container.css("height", tl.attr("data-height"));
images.css("width", tl.attr("data-imagesWidth"));
viewport.css("height", tl.attr("data-imagesHeight"));
content.css("width", tl.attr("data-contentWidth"));
milestones.css("height", tl.attr("data-contentHeight"));
bar.css("top", tl.attr("data-imagesHeight") - tl.attr("data-draggerHeight"));
track.css("height", tl.attr("data-draggerHeight"));
dragger.css("height", tl.attr("data-draggerHeight"));
//PRELOAD & GLOBAL FADE IN
preload.delay(fadeInDelay - 500).animate({ opacity:0 }, 500, 'easeOutQuad');
container.delay(fadeInDelay).animate({ opacity:1 }, 1000, 'easeOutQuad');
//HTML5 AUDIO PLAYER
audiojs.events.ready(function() {
var as = audiojs.createAll({
autoplay: true,
loop: true
});
audio.prettyPaused = 0;
});
//PRETTYPHOTO LIGHTBOX GALLERY
$('a[data-rel]').each(function() {
$(this).attr('rel', $(this).data('rel'));
});
$("a[rel^='prettyPhoto']").prettyPhoto({social_tools:false});
//TIPSY - TOOLTIP
readBt.tipsy({ gravity: 'w', fade: true, offset: 5 });
//IMAGE ROLLOVER ICON
imgRoll.append("<span></span>");
imgRoll.hover(function(){
$(this).children("span").stop(true, true).fadeIn(600);
},function(){
$(this).children("span").stop(true, true).fadeOut(200);
});
//VIDEO ROLLOVER ICON
vidRoll.append("<span></span>");
vidRoll.hover(function(){
$(this).children("span").stop(true, true).fadeIn(600);
},function(){
$(this).children("span").stop(true, true).fadeOut(200);
});
//VIDEO THUMB STOPS MUSIC ON CLICK (IF PLAYING)
vidRoll.click(function() {
if (audio.playing) {
audio.prettyPaused = 1;
audio.pause();
} else {
audio.prettyPaused = 0;
}
});
//START DRAG IMAGES FUNCTION
startDrag(images);
//SCROLLBAR MILESTONES MARKS
for ( var i = 0; i < marksAmount; i++ ) {
current = $('#m'+i);
current.stop(true, true)
.delay(fadeInDelay + 500)
.animate({ left:current.attr("data-xpos"), opacity:1 }, 700 + 100*i, 'easeOutQuad')
.show()
.tipsy({ gravity: 's', fade: true, offset: 3, fallback: current.attr("data-label") });
};
//INIT SCROLLBAR
tl.tinyscrollbar({
wheel: 20,
mouseWheel: tl.attr("data-mouseWheel"),
size: tl.attr("data-width"),
draggerWidth: tl.attr("data-draggerWidth")
});
} // END OF CLASS CONSTRUCTOR
var audio; defines it, but doesn't initialize it. That's the problem. Nothing you've shown suggests that audio is actually initialized. My guess would be that audio and audiojs are probably intended to be the same thing, but that's a guess based on just what you provided.
Unable to set property 'prettyPaused' of undefined or null reference means that var audio has not been initialized, so it could be a global problem or just not initialized.
You say it gets created in that script - very well, add code below to make sure:
<script type="text/javascript" src="/Timeline/js/audiojs/audio.min.js">
console.log(audio);
</script>
I would suspect that's going to return "undefined" or "null". Means you have to create the object or request it somehow via that script.

Categories