I have a plugin that hides a menubar. But i only want this to happen below 480px document size (aka, on phones, not on desktop computers).
var wi;
$(window).ready(function() {
wi = $(window).width();
});
$(window).resize(function() {
wi = $(window).width();
});
$(function() {
if(wi<480){
$('nav').scrollUpMenu({
waitTime: 200,
transitionTime: 150,
menuCss: { 'position': 'fixed', 'top': '0'}
});
}
});
The scrollUpMenu() code is from https://github.com/dvdsmpsn/Scroll-Up-Menu
Now when I open the website it works. When I resize the window from desktop to phone size (<480px), it will not hide the menu when scrolling. But if I refresh the page at that size, it will. And vice versa. I thought my $(window).resize function would take care of it, but I guess not. Anyone any ideas?
You'll need to execute the width check in the resize event:
var wi;
$(window).ready(function() {
wi = $(window).width();
checkWidth();
});
$(window).resize(function() {
wi = $(window).width();
checkWidth();
});
function checkWidth() {
if(wi < 480){
$('nav').scrollUpMenu({
waitTime: 200,
transitionTime: 150,
menuCss: { 'position': 'fixed', 'top': '0'}
});
}
}
A cleaner solution would be something like this:
$(window).on('load resize',
function () {
if($(window).width() < 480){
$('nav').scrollUpMenu({
waitTime: 200,
transitionTime: 150,
menuCss: { 'position': 'fixed', 'top': '0'}
});
}
}
);
This way you're binding the event listeners to window in 1 call.
You need to run your handler on the resize event.
But it is best to keep a flag of the state so that you only run your code once per layout change
$(function(){
var breakpoint = 480,
state = 'big';
function handleLayout(){
var width = $(window).width();
if (width < breakpoint && state === 'big') {
state = 'small';
$('nav').scrollUpMenu({
waitTime: 200,
transitionTime: 150,
menuCss: { 'position': 'fixed', 'top': '0'}
});
} else if (width >= breakpoint && state === 'small') {
state = 'big';
// do what you want to revert to normal here..
}
}
$(window).resize(handleLayout).trigger('resize');
});
In the end I went with A. Wolff's matchMedia, and for initial/resize check Cerbrus' function:
$(window).on('load resize',
function () {
var mq = matchMedia('(max-width: 480px)');
if (mq.matches) {
document.title = 'mobile';
}else{
document.title = 'desktop';
}
}
);
Because it has the best device support and performance
http://jsperf.com/matchmedia-vs-resize/3
Related
I've created a function that has to run only if the window is wider than 769px. It works when the page loads, but not on resize...
It looks like this:
$(window).on('load resize', function () {
if ($(window).width() >= 769) {
...funcion...
}
});
EDITED:
Full code below
$(window).on('load resize', function () {
if ($(window).width() >= 769) {
var $element = $('#cont_quote');
var $follow = $element.find('.img_quote');
var followHeight = $element.find('.img_quote').outerHeight();
var height = $element.outerHeight() - 300;
var window_height = $(window).height();
$(window).scroll(function () {
var pos = $(window).scrollTop();
var top = $element.offset().top;
// Check if element is above or totally below viewport
if (top + height - followHeight < pos || top > pos + window_height) {
return;
}
var offset = parseInt($(window).scrollTop() - top);
if (offset > 0) {
$follow.css('transform', 'translateY('+ offset +'px)');
}
})
}
});
HTML:
<section id="cont_quote">
<article class="cont_q">
Lorem ipsum
<img class="img_quote" src="img">
</article>
</section>
Try something like this:
$(document).ready(function(){
$(window).resize(function(){
if ($(window).width() >= 769) {
...funcion...
}
}
}
You can change on ready or on load, depending on what you need, but the the function should trigger on window resize.
I think you can try this solution this is just javaScript
var onWindowResize = function(e) {
width = e.target.outerWidth;
//uncomment if need height = e.target.outerHeight;
if(width >= 769) {
//remove alert just added for debug
alert("if");
}
else{
//remove alert
alert("else");
}
}
window.addEventListener("resize", onWindowResize);
JSFiddle Demo
For the above JSFiddle demo, I need to position the last image so that it is centered, compared to the first three images.
How do I do this?
position()
window.onresize = function(event) {
position();
};
function position(){
var id = document.getElementById( "imageDisplay" );
console.log( window.innerWidth );
if( window.innerWidth > 400 ) {
console.log( "left" );
id.style.left = "200px";
id.style.bottom = 0;
id.style.top = "20px";
} else if( window.innerWidth <= 250 ) {
console.log( "left" );
id.style.left = "200px";
id.style.top = "20px";
id.style.right = 0;
}
}
Like this? Inside the position function you can write the conditions, refer the if else if condition, which checks the window size and determines the position of the element! When the document loads the position() function is ran once, to determine the initial position.
JSFiddle Demo
Javascript:
position()
window.onresize = function(event) {
position();
};
function position(){
var id = document.getElementById("img");
console.log(window.innerWidth);
if(window.innerWidth >800){
console.log("left");
id.style.left=0;
id.style.bottom=0;
id.style.top="";
}else if(window.innerWidth >600){
console.log("left");
id.style.left=0;
id.style.top=0;
id.style.right="";
}else if(window.innerWidth < 600){
console.log("right");
id.style.right=0;
id.style.top=0;
id.style.left="";
}
}
Using jquery I think you would be able to do it.
$(window).load( function() {
//find height only after all elements have loaded
var widthOfImage = $('#image').width();
//condition for image
if(widthOfImage < 200) {
$('#image').css({
'position': 'absolute',
'top': 0,
'left': 0
});
} else {
$('#image').css({
'position': 'relative',
'top': 100,
'left': 100
});
}
});
I'm using Google pubads on http://development-client-server.com/ds/ which is working great, until you get to the actual story page (see http://development-client-server.com/ds/speech-more-common-autism/), when the right top sidebar ad will load and then disappear quickly.
I've narrowed it down to the stickySidebars function I'm using to stick both the social media bar on the left and the jobs listing div on the right (beneath where the Google ad is). However, the sticky function shouldn't affect the Google ad at all?
Here's the JS function I'm using, which I've already rewritten several times (and have tried to talk the clients out of using already).
<script>
// Sticky Sidebars
function stickySidebars() {
var length = $('.post-content').height() - $('article .sharing-links').height() + $('.post-content').offset().top;
var lengthSidebar = $('.sticky-container').height() - $('aside .job-listings').height() + $('.sticky-container').offset().top -30;
$(window).scroll(function () {
// Sharing Links
var scroll = $(this).scrollTop() + 90;
var height = $('article .sharing-links').height() + 'px';
if (scroll < $('.post-content').offset().top) {
$('article .sharing-links').css({
'position': 'absolute',
'top': 'auto',
'bottom': 'auto'
});
} else if (scroll > length) {
$('article .sharing-links').css({
'position': 'absolute',
'bottom': '0',
'top': 'auto'
});
} else {
$('article .sharing-links').css({
'position': 'fixed',
'top': '90px',
'height': height
});
}
// Sidebar
var heightSidebar = $('aside .job-listings').height() + 'px';
if (scroll < $('aside .job-listings').offset().top) {
$('aside .job-listings').css({
'position': 'absolute',
'top': '300px',
'bottom': 'auto'
});
} else if (scroll > lengthSidebar) {
$('aside .job-listings').css({
'position': 'absolute',
'bottom': '30px',
'top': 'auto'
});
} else {
if (scroll < $('.sticky-container').offset().top + 300) {
$('aside .job-listings').css({
'position': 'absolute',
'top': '300px',
'bottom': 'auto'
});
} else {
$('aside .job-listings').css({
'position': 'fixed',
'top': '90px',
'height': heightSidebar
});
}
}
});
}
$(window).on('load',function(){
if($(window).width() > 1100){
stickySidebars();
}
});
$(window).resize(function() {
if($(window).width() > 1100){
stickySidebars();
}
});
</script>
The issue is not caused by the sticky sidebar. It is caused by this bit of code:
$(window).on('load',function(){
// Other unrelated functions here...
/*****************************/
// Move Sidebar in Mobile
/*****************************/
if($(window).width() <= 980){
$("aside").appendTo(".mobile-sidebar");
} else {
$("aside").insertAfter(".single-article article");
}
});
Essentially the ad loads and then you move the container (the aside), which causes the ad to disappear.
There are a few different options, but essentially you either need the Google ad script to run after that piece of code or you need to refresh the ads. To refresh the ads you should be able to run this line of code straight after your if else statement:
googletag.pubads().refresh()
This refreshes all of the ads. Depending on how you have it setup you can pass in a variable to refresh() so that a specific ad is refreshed e.g.
var slot1 = googletag.pubads().display('/1234567/sports', [728, 90], 'div-1');
googletag.pubads().refresh([slot1]);
Google Reference Docs for refresh()
Sorry for the terrible title, but I'm not sure how else to describe what I'm trying to build. I'm using some code I found on this site, basically what I'm trying to do is build a left handed navigation menu, that highlights the appropriate section as the user scrolls to it.
$(document).ready(function() {
var topRange = 200, // measure from the top of the viewport to X pixels down
edgeMargin = 20, // margin above the top or margin from the end of the page
animationTime = 600, // time in milliseconds
contentTop = []; //array of sidebar links
$('nav ul').append('<div id="slider"></div>');
var sliderTop = $("nav ul li a").eq(0).parent().position().top;
var sliderLeft = $("nav ul li a").eq(0).parent().position().left;
var sliderHeight = $("nav ul li a").eq(0).parent().outerHeight();
$('#slider').css({
'height': sliderHeight,
'left': sliderLeft,
'top': sliderTop,
'width': '100%'
});
// Stop animated scroll if the user does something
$('html,body').bind('scroll mousedown DOMMouseScroll mousewheel keyup', function(e) {
if (e.which > 0 || e.type == 'mousedown' || e.type == 'mousewheel') {
$('html,body').stop();
}
})
// Set up content an array of locations
$('#sidebar').find('a').each(function() {
contentTop.push($($(this).attr('href')).offset().top);
})
// Animate menu scroll to content
$('#sidebar').find('a').click(function() {
var sel = this,
newTop = Math.min(contentTop[$('#sidebar a').index($(this))], $(document).height() - $(window).height()); // get content top or top position if at the document bottom
$('html,body').stop().animate({
'scrollTop': newTop
}, animationTime, function() {
window.location.hash = $(sel).attr('href');
});
return false;
})
//scroll function
function scroller() {
var winTop = $(window).scrollTop(),
bodyHt = $(document).height(),
vpHt = $(window).height() + edgeMargin; // viewport height + margin
$.each(contentTop, function(i, loc) {
if ((loc > winTop - edgeMargin && (loc < winTop + topRange || (winTop + vpHt) >= bodyHt))) {
//animate slider
x = $("#sidebar li").eq(i).position();
$("#slider").animate({
top: (x.top)
}, 100);
}
})
}
//scroll event handler
$(window).scroll(scroller)
})
I have most of it working, however when you actually click a link on the menu the animation is very slow to catch up with the actual scrolling. I understand why this is happening, because it updates the position one at a time after each section is reached, but I'm wondering if there's a way to make this animation faster, and more fluid. I've attached a fiddle with my code, thank you in advance for your help!
http://jsfiddle.net/jamesmyers/6mbmq1pe/
You will get a better slider animation effect by temporarily detaching the scroll handler and scrolling the slider directly, with the same animationTime as for the main animation.
To do this, you also need to :
namespace the scroll event .nav, to allow safe use of .off()
stop() the slider animation in the "if the user does something" block
I've also included a few efficiency savings in the way contentTop and #slider are set up but these are not actually necessary.
$(document).ready(function() {
var topRange = 200, // measure from the top of the viewport to X pixels down
edgeMargin = 20, // margin above the top or margin from the end of the page
animationTime = 600, // time in milliseconds
contentTop, //array of sidebar links
navLinkWrapper = $("nav ul li a").eq(0).parent();
var $slider = $("<div id=\"slider\" />").css({
'height': navLinkWrapper.outerHeight(),
'left': navLinkWrapper.position().left,
'top': navLinkWrapper.position().top,
'width': '100%'
}).appendTo($('nav ul'));
// Stop animated scroll if the user does something
$('html,body').on('scroll mousedown DOMMouseScroll mousewheel keyup', function(e) {
if (e.which > 0 || e.type == 'mousedown' || e.type == 'mousewheel') {
$('html,body').stop();
$slider.stop(); //<<<<<<<
}
});
// Set up content an array of locations
contentTop = $('#sidebar a').map(function() {
return $($(this).attr('href')).offset().top;
});
// Animate menu scroll to content
$('#sidebar a').on('click', function(e) {
e.preventDefault();
$(window).off('scroll.nav', scroller); //<<<<<<<
$slider.stop().animate({ //<<<<<<<
top: ($(this).closest("li").position().top) //<<<<<<<
}, animationTime); //<<<<<<<
var sel = this,
newTop = Math.min(contentTop[$('#sidebar a').index($(this))], $(document).height() - $(window).height()); // get content top or top position if at the document bottom
$('html,body').stop().animate({
'scrollTop': newTop
}, animationTime, function() {
window.location.hash = $(sel).attr('href');
$(window).on('scroll.nav', scroller); //<<<<<<<
});
});
//scroll function
function scroller() {
var winTop = $(window).scrollTop(),
bodyHt = $(document).height(),
vpHt = $(window).height() + edgeMargin; // viewport height + margin
$.each(contentTop, function(i, loc) {
if ((loc > winTop - edgeMargin && (loc < winTop + topRange || (winTop + vpHt) >= bodyHt))) {
//animate slider
$slider.animate({
top: ($("#sidebar li").eq(i).position().top)
}, 100);
}
});
}
//scroll event handler
$(window).on('scroll.nav', scroller); //<<<<<<<
});
Updated fiddle
I have a div that follows the browser as it scrolls and is contained within another div.
The following function keeps my div in place and moving when the user scrolls:
$(function() {
var offset = $("#sidebar").offset();
var topPadding = 15;
$(window).scroll(function() {
if ($(window).scrollTop() > offset.top) {
$("#sidebar").stop().animate({
marginTop: $(window).scrollTop() - offset.top + topPadding
});
} else {
$("#sidebar").stop().animate({
marginTop: 0
});
};
});
});
This works pretty well, except when the browser height is less than 400px, then it gets buggy.
So I thought I'd include a simple line to get it to only run when the browser is >=400 as such:
if (window.innerHeight >= 400) {
$(function() {
var offset = $("#sidebar").offset();
var topPadding = 15;
$(window).scroll(function() {
if ($(window).scrollTop() > offset.top) {
$("#sidebar").stop().animate({
marginTop: $(window).scrollTop() - offset.top + topPadding
});
} else {
$("#sidebar").stop().animate({
marginTop: 0
});
};
});
});
}
This seems to work fine so long as the initial browser height is greater than 400px. If the browser window is resized from it's initial height, the code will still execute, which is counter to what I want.
Essentially, is there a way to dynamically track the browser size and only run this code when the height is larger than 400px and not run when less than 400px?
Thanks for any help!
Just move the check into your event handler:
$(function() {
var offset = $("#sidebar").offset();
var topPadding = 15;
$(window).scroll(function() {
if (window.innerHeight >= 400) { // <=== Moved it here
if ($(window).scrollTop() > offset.top) {
$("#sidebar").stop().animate({
marginTop: $(window).scrollTop() - offset.top + topPadding
});
} else {
$("#sidebar").stop().animate({
marginTop: 0
});
}
}
});
});
Now the check is done when you're processing the scroll event, rather than just once at the outset preventing the scroll from being hooked at all.
Separately, because you're doing this on the scroll event, which happens pretty often, I'd try to minimize the number of times you wrap or look up elements. Instead of doing it on every event, since window isn't going to change and I suspect your sidebar isn't going to change either, wrap/look them up once:
$(function() {
var offset = $("#sidebar").offset();
var topPadding = 15;
var sideBar = $("#sidebar");
var $window = $(window);
$window.scroll(function() {
if ($window.height() >= 400) { // <=== Moved it here
if ($window.scrollTop() > offset.top) {
sidebar.stop().animate({
marginTop: $window.scrollTop() - offset.top + topPadding
});
} else {
sidebar.stop().animate({
marginTop: 0
});
}
}
});
});
That also makes it reasonable to use jQuery's height function on window for cross-browser compatibility.
To track the browser width & height as it is being resized:
$(window).resize(function()
{
var viewportWidth = $(window).width();
var viewportHeight = $(window).height();
// More code here...
};
However, I think there is a better way to keep your div in place, one that does not involve Javascript. Have you tried using position:fixed?