I have a function(s) that expand a drop down list when the browser is size n.
Size n is determined by css media queries and works as expected.
However when I physically drag the width of the browser window out, the .click function remains bound to the element even though a media query indicates that a css hover effect takes place when the browser is size n + 1.
A refresh at any point produces the desired behavior but of course I don't want to require a refresh.
var section_4 = "#main-menu > li:nth-child(4) > a";
var sub_section_4 = "#main-menu > li:nth-child(4) > ul";
$( section_4 ).click(function() {
$( sub_section_4 ).slideToggle(300);
return false;
});
how can I apply this function only on a given size and not have the .click follow to the inline list ? thanks
You could use jquery .width() and .resize() like this:
var section_4 = "#main-menu > li:nth-child(4) > a";
var sub_section_4 = "#main-menu > li:nth-child(4) > ul";
var docWidth = (window).width();
$(document).resize(function(){
docWidth = (window).width(); // Refresh value on resize
});
$( section_4 ).click(function() {
if( docWidth < [integer] ){ // set integrer the same as your #media.
$( sub_section_4 ).slideToggle(300);
return false;
}
});
Related
I'm trying to change the Z index of an image according to the scroll position,currently in chrome (but it should be working on all broswers).
anyway, it's not working on chrome, unless I get into inspection mode and I don't understand why it's only working in inspection mode?
this is the script:
$( window ).scroll(function() {
var scrollTop = $(window).scrollTop();
if ($(this).scrollTop()>700) {
document.getElementById("back-ground-image").style.zIndex = "-9";
console.log("-9");
} else {
document.getElementById("back-ground-image").style.zIndex = "-19";
console.log("-19");
}
});
Problem
What you need is $(document) not $(window).
By default, you scroll the $(document), not the $(window).
However, when you open your Chrome DevTools, the $(window) is not being scrolled which is why your code works.
To fix the issue, change $(window).scroll() to $(document).scroll() and $(window).scrollTop() to $(document).scrollTop()
Improvements
1. Use jQuery functions
Also, if you're already using jQuery, why not use jQuery selectors and .css():
$("#back-ground-image").css('zIndex', '-9')
instead of
document.getElementById("back-ground-image").style.zIndex = "-9";
2. Use DRY code
(Don't Repeat Yourself)
If you follow recommendation #1, why not set $("#back-ground-image") to a variable instead of repeating it twice.
$(document).scroll(function() {
var scrollTop = $(document).scrollTop(),
$bkImg = $("#back-ground-image");
if ($(this).scrollTop() > 700) {
$bkImg.css('zIndex', '-9');
console.log("-9");
} else {
$bkImg.css('zIndex', '-19');
console.log("-19");
}
});
Otherwise, you could use:
$(document).scroll(function() {
var scrollTop = $(document).scrollTop(),
background = document.getElementById("back-ground-image");
if ($(this).scrollTop()>700) {
background.style.zIndex = "-9";
console.log("-9");
} else {
background.style.zIndex = "-19";
console.log("-19");
}
});
I have a div called #menu which I want to display when I scroll past the element #section3, if I scroll up past that element again, I want #menu to disappear
How would I code this?
Maybe something like this?
scrolled = "no"
$(window).scroll(function(){
scr = $("body").scrollTop();
if (scr > 100 && scrolled == "no"){
$("#menu").css({"display:block"})
displayed = "yes"
}
if (displayed == "yes" && scrolled = "yes"){
$("#menu").css({"display:none"})
}
});
The above assumes that #section3 is 100 pixels down the page. If you do not know where its going to be on the page then you could use the method outlined here:
Trigger event when user scroll to specific element - with jQuery
With jQuery you can get the scroll position with $("body").scrollTop();.
Expanding on what #Ned Hulton said, I recommend comparing the scroll position to the top of a "container element" (or 'row') in your page like this:
if ($('body').scrollTop() > $('#someRow').offset().top){
//do something
}
That way you can account for your container appearing at a variable distance down the page (which will come in handy for mobile browsing or cases where your text wraps to additional lines)
I just whipped this up in jsfiddle
https://jsfiddle.net/rb56j0yu/
it uses jQuery, and checks the scroll position against the target div. Css sets the menu as position: fixed, and defaults to hidden.
$(window).scroll(function(){
var yPos = $("body").scrollTop();
var yCheck = $("#c3").position().top;
if (yPos > yCheck && !$("#menu").is(":visible"))
{
$("#menu").show();
}
if (yPos <= yCheck && $("#menu").is(":visible"))
{
$("#menu").hide();
}
});
First, get your #section3 top offset and height. Which will be used as the threshold whether #section3 is actually on the window screen.
var top = $('#section3').offset().top;
var bot = topOffset + $('#section3').height();
Then, detect it on your scroll event.
$(window).on('scroll', function () {
var scrollTop = $(window).scrollTop();
if (scrollTop >= top && scrollTop <= bot) {
// #section3 is within the screen.
$('#menu').show();
}
else {
// #section3 is out of screen.
$('#menu').hide();
}
});
This is a common use case, I wrote following code:
// what does "Auto Header" mean, goto https://www.yahoo.com/
// scroll down and you will see the purple part auto fixed to top,
// while when scroll up, it restores and does not be fixed.
// 1. multiple auto header elements handled
// 2. dynamically create/remove elements issue handled
// 3. no unnecessary dom operation, high performance
// usage: just add 'class="auto-header"' to any element you want to auto header
// suggest set each auto-header element specific width and height
// do not guarantee it works when resize or scroll left/right
$(document).ready(function() {
var rawTops = [],
rawLefts = [],
rawStyles = [],
$locations = [], // record next sibling so that element easily find where to restore
fixed = []; // mark whether this element is fixed
$(".auto-header").each(function() {
var $this = $(this),
offset = $this.offset();
rawTops.push(offset.top);
rawLefts.push(offset.left);
rawStyles.push($this.attr("style"));
$locations.push($this.siblings().eq($this.index()));
fixed.push(false);
});
$(window).on("scroll", function() {
$(".auto-header").each(function(i, e) {
if(!fixed[i] && $(window).scrollTop() > rawTops[i]) {
var $te = $(this).clone(true);
$(this).remove();
$locations[i].before($te);
$te.css({
"position": "fixed",
"top": 0,
"left": rawLefts[i],
"z-index": 100
});
fixed[i] = true;
} else if(fixed[i] && $(window).scrollTop() < rawTops[i]) {
$(this).removeAttr("style").attr("style", rawStyles[i]);
fixed[i] = false;
}
});
});
});
I have this function that moves a HTML element around the DOM based on whether the window size is less than 640px or more. I'm moving the image with prepend and append, but because the function fires every time the window is resized I think I'm asking for performance issues.
The code:
function moveDealsImage() {
var mobile_width = 640;
var wi = $(window).width();
if (wi < mobile_width) {
$( ".deals-header" ).prepend( $("div.htp") );
} else {
$( ".deals-header" ).append( $("div.htp") );
}
}
window.addEventListener("resize", moveDealsImage);
moveDealsImage();
I need to keep the listener in there.
Is there a way to do that, but then only prepending/appending the element once each time that the if or else statements become true? (instead of it happening on every pixel change)
There are a few things that you can do to optimize this.
A first option is to only execute your moveDealsImage function when the state changes from mobile to desktop or reverse. All the other resizes can just be ignored.
This can be accomplished by using something like following code:
var mobile_width = 640;
var is_mobile = (window.innerWidth <= mobile_width);
function moveDealsImage(e) {
// Only execute the function when then state changes from mobile to desktop or reverse
if(
! is_mobile && window.innerWidth > mobile_width ||
is_mobile && window.innerWidth <= mobile_width
)
return;
// Update state
is_mobile = (window.innerWidth <= mobile_width);
console.log('your code here');
}
window.addEventListener("resize", moveDealsImage);
moveDealsImage();
Another and better solution would be to use CSS media queries. This can be done with the following CSS and HTML.
.desktop-deals-header {
display: block;
}
.mobile-deals-header {
display: none;
}
#media only screen
and (max-width : 640px) {
.desktop-deals-header {
display: none;
}
.mobile-deals-header {
display: block
}
}
and in your HTML you add two headers, one for desktop and one for mobile.
<div class="mobile-deals-header">Mobile header</div>
<div class="desktop-deals-header">Desktop header</div>
I have this page:
I want to capture on which div I am while I'm scrolling.
I know If I use:
if( $(document).scrollTop() > $('#div1').position().top) {
console.log('Div1')
}
...it will capture the div1 but instead of using this code for every div I want to set 1 snippet for all divs
Something like:
var a = // The div i am at
if( $(document).scrollTop() > $(a).position().top) {
console.log($(a).attr('id'))
}
I am looking something like the viewport: http://www.appelsiini.net/projects/viewport/3x2.html
Can I achieve that without a plugin, simply 2-3 lines?
Here's a nice way to do it. You may want to optimize the '<=' with a pixel offset to improve user experience and move the div selector ($divs) outside the callback to increase performance. Have a look at my fiddle: http://jsfiddle.net/brentmn/CmpEt/
$(window).scroll(function() {
var winTop = $(this).scrollTop();
var $divs = $('div');
var top = $.grep($divs, function(item) {
return $(item).position().top <= winTop;
});
});
Just throw it into a loop.
var list = [];
$("div").each(function(index) {
if( $(document).scrollTop() > $(this).position().top)
list.push($(this));
});
alert(list);
The list will than have every div that is within your viewport.
I'd suggest using the jQuery Inview plugin:
https://github.com/protonet/jquery.inview
Well maintained Plugin that detects whatever content is in the viewer currently, enabling you to bind functions to an inview event. So as soon as your div is in view you could fire off all the relevant functions you wanted and then again when it has left the users view. Would be great for your needs.
$(window).scroll(function () {
$("#privacyContent div").each(function () {
var bottomOffset = ($(this).offset().top + $(this).height());
console.log("Botom=",bottomOffset ,"Win= ", $(window).scrollTop());
if (bottomOffset > $(window).scrollTop()) {
$("#menu a").removeClass("active");
// console.log("Div is= ",$(this).attr('id'));
$("#menu a[href='#" + $(this).attr('id') + "']").addClass("active");
$(".b").removeClass("fsActive");
var div = $(this);
div.find(".b").addClass("fsActive");
return false;
}
});
});
I do it like this it works fine it detect all div id
I am new at JQuery and I have a specific question about the IF-THEN-ELSE fork.
The big problem for me is the syntax of this (I suck at Javascript). It would help me if anyone can "translate" the pseudo code into a JQuery (or Javascript) valide code.
The pseudo code:
IF "#Contentshowroom" css "left" is NOT > 1960px
THEN
On Click "#Forwardbutton" DO
animate "#Contentshowroom" css "left" =+980px
ELSE You can not click on the "#Forwardbutton"
Place the if() statement in the click handler for #Forwardbutton to test the left position of #Contentshowroom.
If you're using jQuery:
$('#Forwardbutton').click(function() {
var $Content = $('#Contentshowroom');
if( $Content.offset().left <= 1960 ) {
$Content.animate({ left: '+= 980' });
}
});
So now when you click the Forwardbutton, it will check the left .offset() position of the Contentshowroom to see if it is less than or equal to 1960px. And if so, it will animate the left position an additional 980px.
jQuery's .offset() method gives you the top/left positions relative to the body. If you want it relative to its parent container, then use jQuery's .position() method.
click doc
animate doc
offset doc
$("#Forwardbutton").click( function( e ){
// lookup is safe, no noticable performance cost.
// though a reference makes it more losely coupled.
// I'll leave it at your discretion.
var target = $("#Contentshowroom")
// NOTE: the offset parent should have position relative or absolute.
, leftPos = target.offset().left;
if ( leftPos < 1960 ) {
target.animate({
left : leftPos + 980
}); // see docs to tweak animation
} // else do nothing.
} );
Could also use e.preventDefault(); , but don't if it's not needed, it will safe you headaches if you add more listeners to your buttons and find out they're not working.
// first store contentShowroom and it's left property to save getting > 1
var contentShowroom = $('#Contentshowroom');
var showroomLeft = contentShowroom.css('left');
var forwardButton = $('#Forwardbutton');
if (showroomLeft <= 1960){
forwardButton.click(function(){
contentShowroom.animate({left: showroomLeft + 980);
}
}
else {
forwardButton.unbind('click');
}
if this is to be run once at the beginning then
if ( $('#Contentshowroom').offset().left > 1960 )
{
$('#Forwardbutton').click( function(){
$('#Contentshowroom').animate({left:'+=980'});
} );
}
else
{
// if the #Contentshowroom is a link then
$('#Contentshowroom').removeAttr('href');
// if the #Contentshowroom is a button then
// $('#Contentshowroom').attr('disabled',true);
}