Fire script once with JQuery window resize and media queries - javascript

I'm using Masterslider to power an image carousel.
For desktop, I'd like the script to run layout: 'autofill'. For mobile, I would like the script to run layout: 'boxed'.
To achieve this, I am using window .resize() with Modenizr mq:
( function( $ ) {
$( window ).resize(function() {
if (Modernizr.mq('(max-width: 767px)')) {
var slider = new MasterSlider();
slider.setup('masterslider' , {
width: 1440, // slider standard width
height: 400, // slider standard height
space: 5,
layout: 'boxed',
});
// adds Arrows navigation control to the slider.
slider.control('arrows');
} else {
var slider = new MasterSlider();
slider.setup('masterslider' , {
width: 1440, // slider standard width
height: 400, // slider standard height
space: 5,
layout: 'autofill',
});
// adds Arrows navigation control to the slider.
slider.control('arrows');
}
}).resize();
} )( jQuery ); // End JQuery
This method seems to fire the script multiple times with the following multiple errors in console:
Uncaught TypeError: Cannot read property 'position' of undefined
How should I run the script only once, calling the layout operator on resize?

Speaking with another developer, we came up with the following solution:
( function( $ ) {
var slider = new MasterSlider();
var changeSetup = function(){
if (Modernizr.mq('(max-width: 767px)')) {
slider.setup('masterslider' , {
width: 1440, // slider standard width
height: 400, // slider standard height
space: 5,
layout: 'boxed',
});
// adds Arrows navigation control to the slider.
slider.control('arrows');
}
else {
slider.setup('masterslider' , {
width: 1440, // slider standard width
height: 400, // slider standard height
space: 5,
layout: 'autofill',
});
// adds Arrows navigation control to the slider.
slider.control('arrows');
}
};
changeSetup();
$( window ).resize(function(){
changeSetup();
});
} )( jQuery ); // End JQuery

Related

GSAP ScrollTrigger Reveal Fixed Header Not Working with Locomotive Scroll

I am currently on a project which use Locomotive Scroll for smooth-scrolling. All I wanted to do is to make my main navigation header menu fixed on load, then it hides when scroll down and reveal when scroll up. First I tried to create this Without Locomotive Scroll and it is working perfectly. But when I add locomotive scroll, the code is not working at all. It just view as another normal element. Not fixed nor reveal. If anyone can help me, it is highly appreciated. Thank you..!
Element Styles
#my-header {
position: fixed !important;
width: 100% !important;
z-index: 99999 !important;
}
Working code without Locomotive Scroll
;( function() {
// wait until all required libraries are available
let chck_if_gsap_loaded = setInterval( function() {
if(window.gsap && window.ScrollTrigger ) {
// register scrolTrigger
gsap.registerPlugin( ScrollTrigger );
// ... do your thing
my_stuff();
// clear interval
clearInterval( chck_if_gsap_loaded );
}
}, 500 );
function my_stuff() {
const site_header = document.querySelector('#my-header');
const my_stuff = gsap.from(site_header,{
yPercent: -100,
duration: 0.25,
ease: 'sine.out'
}).progress(1);
ScrollTrigger.create({
start: 'top top-=' + 100,
onUpdate: (self)=>{
if(self.direction === -1) my_stuff.play();
else my_stuff.reverse();
}
});
}
} )();
Not Working Code with Locomotive Scroll
;( function() {
let loco_scroll = {};
// wait until all required libraries are available
let chck_if_gsap_loaded = setInterval( function() {
if( window.sfe_loco_scroll && Object.keys( window.sfe_loco_scroll ).length !== 0 && window.gsap && window.ScrollTrigger ) {
// store to the local variable
loco_scroll = window.sfe_loco_scroll;
// register scrolTrigger
gsap.registerPlugin( ScrollTrigger );
// ... do your thing
my_stuff();
// clear interval
clearInterval( chck_if_gsap_loaded );
}
}, 500 );
function my_stuff() {
/* DON'T CHANGE THIS */
// each time Locomotive Scroll updates, tell ScrollTrigger to update too (sync positioning)
loco_scroll.on('scroll', ScrollTrigger.update);
// tell ScrollTrigger to use these proxy methods for the '.sfe-locomotive-scroll-wrapper' element since Locomotive Scroll is hijacking things
ScrollTrigger.scrollerProxy('.sfe-locomotive-scroll-wrapper', {
scrollTop(value) {
return arguments.length ? loco_scroll.scrollTo(value, 0, 0) : loco_scroll.scroll.instance.scroll.y;
}, // we don't have to define a scrollLeft because we're only scrolling vertically.
getBoundingClientRect() {
return {
top: 0,
left: 0,
width: window.innerWidth,
height: window.innerHeight
};
},
// LocomotiveScroll handles things completely differently on mobile devices - it doesn't even transform the container at all! So to get the correct behavior and avoid jitters, we should pin things with position: fixed on mobile. We sense it by checking to see if there's a transform applied to the container (the LocomotiveScroll-controlled element).
pinType: document.querySelector('.sfe-locomotive-scroll-wrapper').style.transform ? 'transform' : 'fixed'
});
/* DON'T CHANGE THIS END */
var site_header = document.querySelector('#my-header');
var my_stuff = gsap.from(site_header,{
yPercent: -100,
duration: 0.25,
ease: 'sine.out'
}).progress(1);
ScrollTrigger.create({
start: 'top top-=' + 100,
onUpdate: (self)=>{
if(self.direction === -1) my_stuff.play();
else my_stuff.reverse();
}
});
/* DON'T CHANGE THIS */
// each time the window updates, we should refresh ScrollTrigger and then update LocomotiveScroll.
ScrollTrigger.addEventListener( 'refresh', () => loco_scroll.update());
// after everything is set up, refresh() ScrollTrigger and update LocomotiveScroll because padding may have been added for pinning, etc.
ScrollTrigger.refresh();
/* DON'T CHANGE THIS END */
}
} )();
Actually I don't know exactly where should I insert Scroller Proxy and Trigger in this code. Also, there are NO ANY data-scroll* attributes for this element. (And I think it's don't required here).

Disable Zoom effect on Hover for Mobile devices in elevateZoom

when you check the elevateZoom on Mobile, the page scroll option does not work when we click on the image although we off the zoom option. which is a trouble.
We want to disable zoom option for Mobile devices or responsive sizes.
Is there any value or variable we can use to ONLY disable Zoom effect completely for mobile devices?
Can anyone suggest how to do this or if someone did it for their theme in past?
ElevateZoom API you can get:
var ezApi = $('#primaryImage').data('elevateZoom');
In order to enable/disable zoom you should use "changeState" method
ezApi.changeState('enable'); // or disable
To detect change media query breakpoint you can use matchMedia
var mq = window.matchMedia('(min-width: 768px)');
mq.addListener((b) => {
if (b.matches) {
// do something for screens > 768px, for example turn on zoom
ezApi.changeState('enable');
} else {
// do something for screens < 768px, for example turn off zoom
ezApi.changeState('disable');
}
});
Try Disable/Comment Touch events in jquery.elevatezoom.js or jquery.elevateZoom version min (my version: 3.0.8):
//touch events
/* self.$elem.bind('touchmove', function(e){
e.preventDefault();
var touch = e.originalEvent.touches[0] || e.originalEvent.changedTouches[0];
self.setPosition(touch);
});
self.zoomContainer.bind('touchmove', function(e){
if(self.options.zoomType == "inner") {
self.showHideWindow("show");
}
e.preventDefault();
var touch = e.originalEvent.touches[0] || e.originalEvent.changedTouches[0];
self.setPosition(touch);
});
self.zoomContainer.bind('touchend', function(e){
self.showHideWindow("hide");
if(self.options.showLens) {self.showHideLens("hide");}
if(self.options.tint && self.options.zoomType != "inner") {self.showHideTint("hide");}
});
self.$elem.bind('touchend', function(e){
self.showHideWindow("hide");
if(self.options.showLens) {self.showHideLens("hide");}
if(self.options.tint && self.options.zoomType != "inner") {self.showHideTint("hide");}
});
if(self.options.showLens) {
self.zoomLens.bind('touchmove', function(e){
e.preventDefault();
var touch = e.originalEvent.touches[0] || e.originalEvent.changedTouches[0];
self.setPosition(touch);
}); */
try to
var image = $('#primaryImage');
var zoomConfig = {};
var zoomActive = false;
image.on('click', function(){
zoomActive = !zoomActive;
if(zoomActive)
{
image.elevateZoom(zoomConfig);//initialise zoom
}
else
{
$.removeData(image, 'elevateZoom');//remove zoom instance from image
$('.zoomContainer').remove();// remove zoom container from DOM
}
});
Other option
$('#primaryImage').click(function(){
if($(window).width()>768){
$(this).elevateZoom({
zoomWindowPosition:1,
zoomWindowOffetx: 5,
zoomWindowWidth:$(this).width(),
zoomWindowHeight:$(this).height(),
});
}
else{
$.removeData($(this), 'elevateZoom');//remove zoom instance from image
$('.zoomContainer').remove(); // remove zoom container from DOM
return false;
}
});
https://github.com/elevateweb/elevatezoom/issues/8
Best Answer I've found and easiest from here: https://github.com/elevateweb/elevatezoom/issues/102#issuecomment-255942134
#media(max-width: $tablet-max) { /* The image that has zoom on it */ .product__img { pointer-events: none; } }
In js plugin add this option
touchEnabled: false,
With this option in desktop PC image will be zoom and in mobile device, zoom will be disabled.
Or you could just hide .zoomContainer using media queries?
For example:
#media screen and (max-width: 425px) {
.zoomContainer {
display: none;
}
}
I was having the same issue so I edit my js file and put a if, else condition on it. This condition will act similar as CSS media query.
//JQUERY CODE
if (window.matchMedia('(min-width: 500px)').matches) {
jQuery.fn.elevateZoom.options = {
zoomEnabled: true
}
}else{
jQuery.fn.elevateZoom.options = {
zoomEnabled: false
}
}
If you tried everything and nothing works for you, try a CSS cover (it works perfect for me)
In your HTML:
<figure class="product-main-image">
<div class="product-zoom-cover"> </div>
<img id="product-zoom" src="............">
</figure>
In your CSS:
.product-zoom-cover{
display: none;
}
#media screen and (max-width: 768px) {
.product-main-image{
position: relative;
}
.product-zoom-cover{
display: block;
position: absolute;
top: 0;
left: 0;
right: 0;
bottom: 0;
z-index: 48;
}
}
Success to all and good code!
For those who still come from search engines to this topic, The best way to manage every option (like enable / disable on mobile) in different sizes is using plugin`s documentation!
Here we go:
First you have to manage global options for elevatezoom:
jQuery('.mainproimg').ezPlus({
easing: true,
lensFadeIn: 200,
lensFadeOut: 200,
zoomWindowFadeIn: 200,
zoomWindowFadeOut: 200,
zoomWindowPosition: 11,
zoomWindowWidth: 400,
zoomWindowHeight: 400,
borderSize:1,
responsive: true
});
Then add the following code:
respond: [
{
range: '320-991',
enabled: false,
showLens: false
}
]
So, the whole code would be:
jQuery('.mainproimg').ezPlus({
easing: true,
lensFadeIn: 200,
lensFadeOut: 200,
zoomWindowFadeIn: 200,
zoomWindowFadeOut: 200,
zoomWindowPosition: 11,
zoomWindowWidth: 400,
zoomWindowHeight: 402,
zoomWindowOffsetY: -8,
borderSize:1,
responsive: true,
enabled: true,
showLens: true,
respond: [
{
range: '320-991',
enabled: false,
showLens: false
}
]
});
In this case, elevatezoom will be disabled on devices that has 320px to 991px width.
Of course you can add more ranges and manage plugin options for each breakpoint.
unbind touchmove from element
$('#img-product-zoom').unbind('touchmove');
and then hide the container of zoom area
$('.ZoomContainer').hide();
use this code to detect mobile phone
if (/Android|webOS|iPhone|iPad|iPod|BlackBerry|IEMobile|Opera Mini/i.test(navigator.userAgent)){
///here put your code
}

Content inside fancy box need to be responsive

I would like to create a gallery that is inside a fancy box , so firstly I downloaded all the content of the gallery and appended to the html container.
<div id="popup" style="display:none;"><div class="galleria"></div></div>
The jquery part
$("#hidden_content").instagram({
clientId: blockInstaSettings.clientId
, hash: hash
, userId: blockInstaSettings.userId
, next_url: insta_next_url
, show: 10
, image_size: image_size
, onComplete: function (photos, data) {
var album_html = "";
$.each(photos, function( index, val ) {
album_html += "<img src='" + val.images.standard_resolution.url + "' data-title='' data-description='" + val.caption.text.replace("'","’") + "' longdesc='" + val.link + "'>";
});
$(".galleria").html(album_html);
$('#block_instagram').on('click', function () {
openPop();
return false;
});
}
});
Notice that I set up the listener in the button that show the fancybox
function openPop(){
$.fancybox({
'autoScale': true,
'transitionIn': 'elastic',
'transitionOut': 'elastic',
'speedIn': 500,
'speedOut': 300,
'autoDimensions': true,
'centerOnScroll': true,
'href' : '#popup'
});
Galleria.run('.galleria', {
transition: 'fade',
popupLinks: true,
show: no,
extend: function(options) {
Galleria.get(0).$('info-link').click();
}
});
}
Attempted to call galleria.run when fancybox's afterShow event; but it is still the same.
Also for CSS, it need to be :
.galleria{
width:700px;
height:500px;
}
Otherwise ,it can not generate the gallery
How to fix that?
Reference
My site:
http://internal001.zizsoft.com/be_pure/
(When you scroll to bottom, there is a slider showing instagram photos, click on the photo and you will see the gallery)
The plugin used:
http://galleria.io/
http://fancyapps.com/fancybox/
As others mentioned in the commants all those plugins you are using are responsive already. When i visit your site if i resize the window after opening the fancybox its not resized as defined as "responsive". I thought this is what you are worrying about. You can invoke this by resize galleria on window resize event. Please refer this resize script for galleria to achieve. Thanks
Update: (Essential code blocks from the referred link)
to re-initialize the galleria while window resize.
First, set up the resize function:
function ResizeGallery() {
gWidth = $(window).width();
gHeight = $(window).height();
gWidth = gWidth - ((gWidth > 200) ? 100 : 0);
gHeight = gHeight - ((gHeight > 100) ? 50 : 0);
$("#gallerycontainer").width(gWidth);
$("#gallery").width(gWidth);
$("#gallery").height(gHeight);
// Reload theme
Galleria.loadTheme('js/galleria/themes/classic/galleria.classic.js', { show: curIdx });
}
Then bind it to the window resize event:
var TO = false;
$(window).resize(function () {
if (TO !== false)
clearTimeout(TO);
TO = setTimeout(ResizeGallery, 200); //200 is time in miliseconds
});
This will essentially re-initialize by reloading the default theme. In this example, I am using the second parameter to specify which image to show- otherwise it will display the first image. Be aware that this may cause another instance of Galleria. I believe this to be a bug, and posted on their forums. You can remove the older instances as follows:
var gcount = Galleria.get().length;
if (gcount > 1) {
Galleria.get().splice(0, gcount - 1);
}
Run it after the loadTheme method. Use settimeout to delay it, because loadTheme takes some time to complete. I use 200ms. Ugly, but I need some of the features in Galleria. Hope this helps.
every thing is responsive and works good. Elaborate your problem .
if you want your popup thumbnails appear in middle of your popup use the following code
.galleria-thumbnails {
text-align: center;
width: 100% !important;
}
.galleria-image {
display: inline-block;
float: none !important;
}
I found that using the javascript to handle that worked best for me you could have your script calculate height and then do something like this where you initialized fancybox
fitToView : true,
autoSize : true,
width : 100%,
height : 'auto',
you can play with fitToView and autoSize till you get the desired effect much like pinterest
you can do this with a simple css trick .
in the responsive media screen you have to set the css as
.tp-simpleresponsive .slotholder *, .tp-simpleresponsive img {
background-size: 100% auto !important;
}

Smooth jScrollPane scrollbar length adjustment with dynamic content

Some of my webpages contain several text elements that expand and collapse with a jQuery "accordion" effect:
function show_panel(num) {
jQuery('div.panel').hide();
jQuery('#a' + num).slideToggle("slow");
}
function hide_panel(num) {
jQuery('div.panel').show();
jQuery('#a' + num).slideToggle("slow");
}
This causes the window size to change so jScrollPane has to be reinitialized, which will also change the length of the scrollbar. To achieve a smooth length adjustment of the scrollbar, I set the "autoReinitialise" option to "true" and the "autoReinitialiseDelay" to "40" ms:
$(document).ready(function () {
var win = $(window);
// Full body scroll
var isResizing = false;
win.bind(
'resize',
function () {
if (!isResizing) {
isResizing = true;
var container = $('#content');
// Temporarily make the container tiny so it doesn't influence the
// calculation of the size of the document
container.css({
'width': 1,
'height': 1
});
// Now make it the size of the window...
container.css({
'width': win.width(),
'height': win.height()
});
isResizing = false;
container.jScrollPane({
showArrows: false,
autoReinitialise: true,
autoReinitialiseDelay: 40
});
}
}).trigger('resize');
// Workaround for known Opera issue which breaks demo (see
// http://jscrollpane.kelvinluck.com/known_issues.html#opera-scrollbar )
$('body').css('overflow', 'hidden');
// IE calculates the width incorrectly first time round (it
// doesn't count the space used by the native scrollbar) so
// we re-trigger if necessary.
if ($('#content').width() != win.width()) {
win.trigger('resize');
}
});
The effect is ok, but on the cost of a very high CPU usage which makes my fan go wild.
This is a jsfiddle which shows the settings and the effect: http://jsfiddle.net/VVxVz/
Here's an example page (in fact it's an iframe within the webpage shown): http://www.sicily-cottage.net/zagaraenausfluege.htm
Is there a possibility to achieve the same "smooth" transition of the scrollbar length without using the "autoReinitialise" option, maybe with an additional script, some modification of the jscrollpane.js, or simply a css animation of the scrollbar and then calling the reinitialise manually?
I'm absolutely useless at javascript so any help would be greatly appreciated.
There is no need to initialise jScrollPane on your content everytime window is resized. You should do it only once - on $(document).ready(). Also, there is no need in using autoReinitialize if your content is staic. You should reinitialise jScrollPane to update scrollbar size only when you slideUp/slideDown one of your container or on window.resize. So, code become less and more beautiful :)
function togglePanel(num) {
var jsp = $('#content').data('jsp');
jQuery('#a' + num).slideToggle({
"duration": "slow",
"step": function(){
jsp.reinitialise();
}
});
return false;
}
$(document).ready(function () {
var container = $('#content').jScrollPane({
showArrows: false,
autoReinitialise: false
});
var jsp = container.data('jsp');
$(window).on('resize', function(){
jsp.reinitialise();
});
// Workaround for known Opera issue which breaks demo (see
// http://jscrollpane.kelvinluck.com/known_issues.html#opera-scrollbar )
$('body').css('overflow', 'hidden');
// IE calculates the width incorrectly first time round (it
// doesn't count the space used by the native scrollbar) so
// we re-trigger if necessary.
if (container.width() != $(window).width()) {
jsp.reinitialise();
}
});

Jquery - get the real dimension of the image or a way to be compliant if no js

Hello
The context is a gallery and a page of thumbnails
The goal of the script is to minimize the thumbnails and on hover to display them with their original size.
The script do it well :
-get the minimum size of thumbnails
-define this minimal size for all thumbnails
-on hover increase z-index and define the size as the original size of this thumbnail
but if the javascript is disabled it's a mess because each thumbnails has is own size
If I define the same size for all thumbnails by CSS or in html -in order to be compliant if there is no js-, the script will take this as the original size of the thumbnails, whereas it's not the real size of the picture.
the code is :
<script type="text/javascript">
jQuery(window).load(function(){
var min_dim_width = 10000;
var min_dim_height = 10000;
$("ul.thumbnails img").each(function() {
$.data(this, 'size', { width: $(this).width(), height: $(this).height() });
if ($.data(this,'size').height < min_dim_height)
min_dim_height = $.data(this,'size').height;
if ($.data(this,'size').width < min_dim_width)
min_dim_width = $.data(this,'size').width;
});
$(".thumbnails img").each(function () {
$(this)
.css('width', min_dim_width+'px')
.css('height', min_dim_height+'px')
$(this).parents('li')
.css('width', min_dim_width+5+'px')
.css('height', min_dim_height+5+'px');
}).hover(function() {
if ($.data(this,'size').height == min_dim_height)
{
new_dim_height = min_dim_height*1.2;
}
else
{
new_dim_height = $.data(this,'size').height;
}
if ($.data(this,'size').width == min_dim_width)
{
new_dim_width = min_dim_width*1.2;
}
else
{
new_dim_width = $.data(this,'size').width;
}
$(this).parents('li').css({'z-index' : '10'}); /*Add a higher z-index value so this image stays on top*/
$(this).addClass("hover").stop() /* Add class of "hover", then stop animation queue buildup*/
.animate({
marginTop: '-'+new_dim_height/2+'px',
marginLeft: '-'+new_dim_width/2+'px',
top: '50%',
left: '50%',
width: new_dim_width, /* Set new width */
height: new_dim_height, /* Set new height */
padding: '10px'
}, 200); /* this value of "200" is the speed of how fast/slow this hover animates */
}, function() {
$(this).parents('li').css({'z-index' : '0'}); /* Set z-index back to 0 */
$(this).removeClass("hover").stop() /* Remove the "hover" class , then stop animation queue buildup*/
.animate({
marginTop: '0', /* Set alignment back to default */
marginLeft: '0',
top: '0',
left: '0',
width: min_dim_width, /* Set width back to default */
height: min_dim_height, /* Set height back to default */
padding: '5px'
}, 400);
});
});
</script>
thx for reading this and all my consideration if you succeed !
we can see it in action right there : http://www.planete-flop.fr/gallerie/index.php?/category/12
PS : reformulation of my "problem"
Well... I don't know if it's what you are looking for but... generally it's a good idea to set the image's dimensions in the html markup itself... as in:
<img src="cheese.jpg" alt="an image" title="whee!" height="100" width="200" />
You can override w/ JS if it is supported. Otherwise, at the least you get some predictability for your layout (even if the thumbs appear skewed).
Hope it helps!
Just find the correct size on the server
http://php.net/manual/en/function.getimagesize.php

Categories

Resources