Responsive javascript - javascript

Can anyone please help with a dodgy if statement, try as I might I can't see anything wrong with it, the code works when outside of the if statement:
var sizeBefore;
var sizeAfterResize;
var sizeBreakPoint;
var resizeTimer;
$(function() {
sizeBefore = $(window).width();
sizeBreakPoint = 500;
doneResizing();
});
function doneResizing(){
sizeAfterResize = $(window).width();
if ((sizeBefore < sizeBreakPoint) && (sizeAfterResize >= sizeBreakPoint)) {
alert('Before:' + sizeBefore);
alert('After:' + sizeAfterResize);
sizeBefore = sizeAfterResize;
// THIS RUNS WHEN OUTSIDE IF STATEMENT
}
}
$(window).resize(function() {
//doneResizing();
clearTimeout(resizeTimer);
resizeTimer = setTimeout(doneResizing, 100);
});
EDIT: This statement should only be true on both document ready or completion of resize when the window has been resized from smaller than sizeBreakPoint to larger than sizeBreakPoint - hope this clarifies
EDIT: SOLUTION
var sizeBefore;
var sizeAfterResize;
var sizeBreakPoint;
var resizeTimer;
$(function() {
sizeBefore = $(window).width();
sizeBreakPoint = 500;
doneResizing();
});
function doneResizing(){
sizeAfterResize = $(window).width();
if ((sizeBefore < sizeBreakPoint) && (sizeAfterResize >= sizeBreakPoint)) {
alert('Before:' + sizeBefore);
alert('After:' + sizeAfterResize);
}
sizeBefore = sizeAfterResize;
}
$(window).resize(function() {
clearTimeout(resizeTimer);
resizeTimer = setTimeout(doneResizing, 100);
});

ok from looking and testing your if i can say:
if ((sizeBefore < sizeBreakPoint) && (sizeAfterResize >= sizeBreakPoint))
this is only true if your window starts with smaller then 500 and after you resize if it goes over 500. This because you never change you sizeBefore other then on page load.
Can you tell me what you really want to verify? Or if this what you really want.
** edit: suggested solution **
try to do something like this:
$(function() {
sizeBreakPointMin = 480;
sizeBreakPointMax = 520;
doneResizing();
});
function doneResizing(){
sizeAfterResize = $(window).width();
//this way you have a window where this is false and it's as you want to allow the window as in a fine size
//you can garantie that the window is always bigger then 480 and smaller then 520
if ((sizeAfterResize < sizeBreakPointMin) || (sizeAfterResize >= sizeBreakPointMax)) {
alert('Before:' + sizeBefore);
alert('After:' + sizeAfterResize);
// THIS RUNS WHEN OUTSIDE IF STATEMENT
}
}
from your code:
if ((sizeBefore < sizeBreakPoint) && (sizeAfterResize >= sizeBreakPoint)) {
...
sizeBefore = sizeAfterResize;
}
this two lines don't go well together because the first time this is true you just garantied that sizeAfterResize >= sizeBreakPoint making the next time you go check the if sizeBefore is will always be bigger then sizeBreakPoint making the if statement impossible to enter 2 times as it is (and if you don't change sizeBefore outside the if.
Hope this helps.

I think your problem lies within the if condition.
sizeBefore is whatever your screen width is at the document ready event, which if you have a fullscreen browser, will be bigger than 500 (which is your breakpoint value). But you're never updating the sizeBefore, so it will never be lower than the sizeBreakPoint, and so, this part of the if statement will never be true: (sizeBefore < sizeBreakPoint)

This is no direct answer to the question, just my own twist on a responsive JavaScript
// calculate viewport width so that we can load js conditionally
function responsive(){
var scaffolding = 'desktop';
var w = parseInt($(window).innerWidth(), 10);
if (w > 0 && w < 768) { scaffolding = 'phone'; }
if (w >= 768 && w <= 980) { scaffolding = 'tablet'; }
if (w > 980) { scaffolding = 'desktop'; }
return scaffolding;
}
if ( responsive() == phone ) {
// do stuff only on phones
}
if ( responsive() != phone ) {
// do stuff everywhere else but phones
}
You get to define what each breakpoint represents and what it is called, in a way that it still makes sense when you start using the condition later in the code.

Related

How to disable a jquery function from executing for a certain amount of time

I have a jQuery function that calculates the distance between two slideshows and detects to see if they have been scrolled past yet and tells it to display the first slide with important information on it.
However, it displays it once, but then the if statement loops and keeps displaying it, which would be expected.
I am wondering if there is a way to force the function to wait 25-ish seconds before it executes again? Any help would be much appreciated.
Here is the jQuery code:
$(window).scroll(function() {
$('.infoIdentifier').each(function() {
var scroll = $(window).scrollTop();
var objectpos = $(this).offset().top - 600;
var nextobject = $(this).parent().nextAll('.slideshow').children(".infoIdentifier")
if (nextobject.length === 0) {
var nextobjectpos = 10000;
} else {
var nextobjectpos = nextobject.offset().top - 600;
}
if (scroll > objectpos && scroll < nextobjectpos) {
var $this = $(this).parent('.slideshow');
var $currentSlide = $this.find('.active');
var $nextSlide = $this.children('.jumbotron').first();
$nextSlide.fadeIn(500).addClass('active');
$currentSlide.fadeOut(500).removeClass('active');
}
});
});
As for HTML, the slideshows are held in a main container, and each slide show with important information is tagged as class = 'infoIdentifier'. This part of the function does its job. The calculations are fine and the application of classes is fine, however, how do I disable the if (scroll > objectpos && scroll < nextobjectpos){ statement for x amount of seconds. Any help would be much appreciated. Thank you!
Here's one way to achieve this. I added a boolean outside of your scroll function called wait, which is set to false initially.
Then I added !wait as a condition to your if logic, which means it will only validate if wait is currently false.
Then inside that block, I set wait to true, and started a setTimeout for 25 seconds, after which wait is set back to false.
During those 25 seconds, that slideshow code will not run.
var wait = false;
$(window).scroll(function() {
$('.infoIdentifier').each(function() {
var scroll = $(window).scrollTop();
var objectpos = $(this).offset().top - 600;
var nextobject = $(this).parent().nextAll('.slideshow').children(".infoIdentifier")
if (nextobject.length === 0) {
var nextobjectpos = 10000;
} else {
var nextobjectpos = nextobject.offset().top - 600;
}
if (!wait && scroll > objectpos && scroll < nextobjectpos) {
var $this = $(this).parent('.slideshow');
var $currentSlide = $this.find('.active');
var $nextSlide = $this.children('.jumbotron').first();
$nextSlide.fadeIn(500).addClass('active');
$currentSlide.fadeOut(500).removeClass('active');
wait = true;
setTimeout(function() {
wait = false;
}, 25000);
}
});
});

jQuery function that will change image link

I've got the following code for my images using srcset. I'd prefer to get away from srcset altogether. I want this to process all images with a particular class.
<img src="images/Connect-Groups-600.jpg"
srcset="
images/Connect-Groups-600.jpg 600w,
images/Connect-Groups-1000.jpg 1000w,
images/Connect-Groups-1920.jpg 1920w,
images/Connect-Groups-2880.jpg 2880w
" alt=""/>
Does anyone know of a solution using jquery that will take the tag and change the location based on screen size. I need this to work on mobile devices too.
ex:
If screen is bigger than 1920w, it uses
images/2880/Connect-Groups.jpg
If screen is bigger than 1000w and
1920w or less, it will pull images/1920/Connect-Groups.jpg
If screen is between 601 and 1000 it will pull
images/1000/Connect-Groups.jpg
if screen is 600w or less, it pulls images/600/Connect-Groups.jpg
If the size detection fails, I want it to always pull the image in the tag.
I need this to work no matter what the image is...I have no clue what to even search for to find a solution to do this.
EDIT
At the end of this, I want to be able to put in on the page... the code will then pull the URL from the img tag, and append the correct size folder.
It will end up looking like on the end user side.
Please note, this method is not sustainable, I would not recommend using it for anything else, but it will help you solve this specific issue:
Given that your folder structure remains something like:
images/<size>/<filename.ext>
We can re-create a source based on this information:
function resize() {
// First, we'll grab all the images on the page that can be changed:
var img = document.querySelectorAll('img.resizable');
for(var i = 0; i < img.length; i++) {
// Grab the image extension
var src = img[i].src.split('/')
if (window.innerWidth > 1920) {
img[i].src = "/images/2880/" + src[src.length - 1]; // Add the file name and extension
}
else if (window.innerWidth > 1000 && window.innerWidth <= 1920) {
img[i].src = "/images/1920/" + src[src.length - 1]; // Add the file name and extension
}
else if (window.innerWidth > 601 && window.innerWidth <= 1000) {
img[i].src = "/images/1000/" + src[src.length - 1]; // Add the file name and extension
}
else if (window.innerWidth <= 600) {
img[i].src = "/images/600/" + src[src.length - 1]; // Add the file name and extension
}
}
}
resize(); // execute when document is loaded to insert manual images for the first time without resizing
And ofcourse, load the basic 600 width file as default.
Example in jQuery:
function resize() {
var img = $('img.resizable');
var width = $(window).innerWidth();
img.each(function(index, element) {
var name = element.src.split('/') // Split is a native javascript function, which 'splits' the string into an array with the components
if(width <= 600) {
$(element).attr('src', 'images/600/' + name[name.length - 1]) // This name[name.length -1] trick is being used to select the 'last value in the string' based on the length of the string.
}
else if(width <= 1000) {
$(element).attr('src', 'images/1000/' + name[name.length - 1])
}
else if(width <= 1920) {
$(element).attr('src', 'images/1920/' + name[name.length - 1])
}
else {
$(element).attr('src', 'images/2880/' + name[name.length - 1])
}
})
}
resize();
Pretty much identical to Muhammad's answer but in jQuery. If you wanted to do by class just remove the '#' and add a '.'
window.onresize = resize;
function resize() {
console.log($(window).innerWidth);
if ($(window).innerWidth > 1920) {
$("#imageid").src = "images/2880/Connect-Groups.jpg";
} else if ($(window).innerWidth > 1000 && $(window).innerWidth <= 1920) {
$("#imageid").src = "images/1920/Connect-Groups.jpg";
} else if ($(window).innerWidth > 601 && $(window).innerWidth <= 1000) {
$("#imageid").src = "images/1000/Connect-Groups.jpg";
} else if ($(window).innerWidth <= 600) {
$("#imageid").src = "images/600/Connect-Groups.jpg";
}
}
<img id="imageid">
[Modified]
let this is your image tag
<img class="imageid" src="images/Connect-Groups-600.jpg">
then this is the js you are looking for hopefully
var images = document.getElementsByClassName("imageid");
var sizes = ["images/2880/Connect-Groups.jpg","images/1920/Connect-Groups.jpg","images/1000/Connect-Groups.jpg","images/600/Connect-Groups.jpg"];
window.onresize = resize;
function resize() {
console.log(window.innerWidth);
if (window.innerWidth > 1920) {
images[0].src = sizes[0];
} else if (window.innerWidth > 1000 && window.innerWidth <= 1920) {
images[0].src = sizes[1];
} else if (window.innerWidth > 601 && window.innerWidth <= 1000) {
images[0].src = sizes[2];
} else if (window.innerWidth <= 600) {
images[0].src = sizes[3];
}
}
<img id="imageid" src="images/Connect-Groups-600.jpg">

Understanding Jquery function - $(document).ready(callback);

Hi am trying to run a function on window resize and document ready. As resize is triggered by mobile scroll it is necessary to check the height hasn't changed. This code works for resize but not on load. Is anyone able to explain whey the function isn't executed on document ready? Thanks in advance.
//CLOSE EXPANDED ELEMENTS FOR MOBILE
var $window = $(window);
var width = $(window).width();
var callback = function () {
if($(window).width() != width){
if ($window.width() < 756) {
$(".content_lower.collapse").removeClass('in');
}
else {
$(".content_lower.collapse").addClass('in');
}
}
};
$(document).ready(callback);
$(window).resize(callback);
console.log(callback.toString());
Actually on document ready the document is just loaded and the $(window).width() is equal to width variable.
So the function callback will be called while width = $(window).width() so it will not enter the if condition and nothing will happen inside the function.
If you try to log somtheing to the console or alert a message in the beginning of your function you will see that it's executed:
var callback = function() {
console.log("Callback entered !!!");
if ($(window).width() != width) {
if ($window.width() < 756) {
$(".content_lower.collapse").removeClass('in');
} else {
$(".content_lower.collapse").addClass('in');
}
}
};
EDIT:
If you still want to execute it in document load you can add a boolean flag initialized to false and set it to true if the window is once resized then test with it:
var $window = $(window);
var width = $(window).width();
var called = false;
var callback = function() {
console.log("callback entered !!!");
if ($(window).width() != width || !called) {
if ($window.width() < 756) {
$(".content_lower.collapse").removeClass('in');
} else {
$(".content_lower.collapse").addClass('in');
}
}
called = true;
};
$(document).ready(callback);
$(window).resize(callback);
console.log(callback.toString());
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="content_lower.collapse">the div</div>
EDIT 2:
A better approach is to use the boolean flag as a parameter of the callback function, and call it with false on document load and true on window resize:
var $window = $(window);
var width = $(window).width();
var callback = function(resized) {
if ($(window).width() != width || !resized) {
if ($window.width() < 756) {
$(".content_lower.collapse").removeClass('in');
} else {
$(".content_lower.collapse").addClass('in');
}
}
};
$(document).ready(callback(false));
$(window).resize(callback(true));
This gave the desired effect. Tanks for the help guys.
var $window = $(window);
var width = $(window).width();
var callback = function () {
if ($window.width() < 756) {
$(".content_lower.collapse").removeClass('in');
}
else {
$(".content_lower.collapse").addClass('in');
}
};
$(document).ready(callback);
$( window ).resize(function() {
if($(window).width() != width){
callback();
}
});
When the document is loaded the width variable will be set to your window-width (let's say 500px). Then it checks if the current window-width (so 500px) is equal to the width var (500 !== 500). This returns false, so you code won't be executed. You can do this instead:
var callback = function() {
if ($(window).width() < 756) {
$('body').text($(window).width() + " - if");
} else {
$('body').text($(window).width() + " - else");
}
};
$(document).ready(callback);
$(window).resize(callback);
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>

Floating JQuery menu issues on slower connection

I'm trying to create a floating menu (#quickmenu in left hand sidebar of bottom link) that stops at #weather whilst also re-calculating the bottom = $(\'#weather\').offset().top; every 0.5 seconds...
Page to test: Bristol International Jazz & Blues Festival 2014 | Festival Archive
The recalculation is key as I use expandable content in the main body and because without recaculating on slower connections it doestn't work. I need only #weather.offset.top to be recalculated every 5 seconds, not the whole script otherwise it refreshes and flickers...
I've tried to do code it myself and it's not working, it's 99% not coded correctly but can't figure out what's going wrong? The logic seems to be correct though... if (y >= top && z <= bottom) { ....
<script type="text/javascript">
$(document).ready(function () {
top = $('#quickmenu').offset().top;
var didScroll = false;
$(window).scroll(function() {
didScroll = true;
});
setInterval(function() {
if ( didScroll ) {
didScroll = false;
bottom = $('#weather').offset().top;
y = $(this).scrollTop();
z = y + $('#quickmenu').height();
if (y >= top && z <= bottom) {
// if so, add the fixed class
$('#quickmenu').addClass('fixed');
} else if(z > bottom) {
// otherwise remove it
$('#quickmenu').removeClass('fixed').addClass('absolute');
} else {
// otherwise remove it
$('#quickmenu').removeClass('fixed');
}
}
}, 500);
});
</script>
Thanks for the input, and apologies for lack of clarity within the question. I have fixed my issue by taking another approach. I hope that this is less resource heavy?
<script type="text/javascript">
(function () {
var s = document.querySelector(\'#event-info\').style;
s.overflow = \'inherit\';
s.height = \'auto\';
})();
window.updateQuickMenuPos = function () {
var menu = document.querySelector(\'#quickmenuwrapper\');
var scroll_pos = document.body.scrollTop;
var menu_pos = menu.offsetTop + 10;
var weather = document.querySelector(\'#weather\');
var pos = (scroll_pos - menu_pos);
// min height
if (pos < 0) {
pos = 0;
}
// max height
if (menu_pos + menu.offsetHeight + pos > weather.offsetTop) {
pos = weather.offsetTop - menu.offsetHeight - menu_pos;
}
var s = menu.style;
s[\'webkitTransform\'] = s[\'mozTransform\'] = s[\'transform\'] = \'translateY(\' + pos + \'px)\';
};
jQuery(document).scroll(window.updateQuickMenuPos);
</script>

Reload page when a certain width is passed

I want the page to reload only if the browser window goes above or below 768px.
This was my attempt which failed.
if ($(window.width() > "769") {
$(window).resize(function () {
if ($(window).width() < "769") {
location.reload();
}
});
}
elseif($(window.width() < "769") {
$(window).resize(function () {
if ($(window).width() > "769") {
location.reload();
}
});
}
Im sures theres a really simple way of doing this.
demo jsFiddle
The proof that the page is reloaded is (the wait icon in the tab :D ) the Math random that generates a random number (in the demo.)
var ww = $(window).width();
var limit = 769;
function refresh() {
ww = $(window).width();
var w = ww<limit ? (location.reload(true)) : ( ww>limit ? (location.reload(true)) : ww=limit );
}
var tOut;
$(window).resize(function() {
var resW = $(window).width();
clearTimeout(tOut);
if ( (ww>limit && resW<limit) || (ww<limit && resW>limit) ) {
tOut = setTimeout(refresh, 100);
}
});
The timeout function will help on window resize to wait 100ms before calling the refresh function.
You can increase the timeout value to improve usability.
There are probably other and much better ways of doing what you really need, but:
if ($(window.width() > "769"){
Should be:
if ($(window).width() > 769){
Full code:
var width = $(window).width();
$(window).resize(function() {
if (width > 769 && $(window).width() < 769) {
location.reload();
}
else if (width < 769 && $(window).width() > 769) {
location.reload();
}
});​
Live DEMO
It could be made with one if statement, but I preferred splitting it into two so it'll be easier to follow.

Categories