Class added dynamically vanishing upon window resize

Hello,

Please compare the original code with mine before I explain the issue:

jquery waypoint demo:


$(document).ready(function() {
	$('.top').addClass('hidden');
	$.waypoints.settings.scrollThrottle = 30;
	$('#wrapper').waypoint(function(event, direction) {
		$('.top').toggleClass('hidden', direction === "up");
	}, {
		offset: '-100%'
	}).find('#main-nav-holder').waypoint(function(event, direction) {
		$(this).parent().toggleClass('sticky', direction === "down");
		event.stopPropagation();
	});
});

My use (as you can see, I didn’t need everything):



	$.waypoints.settings.scrollThrottle = 30;
	$('#nav').waypoint(function(event, direction) {
		$(this).parent().toggleClass('sticky', direction === "down");
		event.stopPropagation();
	});


The issue: the sticky class is added. Fine. But when I resize the window, it disappears, which does not happen with waypoint original demo.

I thought that maybe the problem could be that #nav parent element is <body>. But the same issue exists if I add a #wrapper div.

So, I can’t see what’s wrong… Can you help with that?

:slight_smile:

Thanks in advance.

Hello John,

I finally found the time to follow your advice.

All scripts / libraries have been commented out. The sticky element still disappears upon resizing the window. One weird thing occured to me, though: I’m using selectvzr, if I don’t include it, the sticky element doesn’t even begin to stick. I’m using FF, latest version. I had the idea to test the sticky element in Opera, and it sticks even when I resize the window.

Also, I’ve logged event (thank you so much for the tip): here’s what I get:


Object { type="waypoint", timeStamp=1314873563900, jQuery15108516184096240728=true, more...}

When I click “more”, I reach the DOM tab, and I… well… don’t know what to look at. :confused:

Does all that help you help me?

:slight_smile:

Do you maybe have a sample page online somewhere that I can look at? I’d like to see if I can reproduce your problem locally :slight_smile:

Yeah!

rep++ (too bad I can’t give rep on this forum).

Thank you so much. You’ve been patient, and efficient. You’ve made my day.

:tup:

Hello John,

Sorry for the delay. I’ve been swamped at work.

Here’s a page that shows exactly what I’m talking about. :slight_smile:

I hope it will help you understanding the problem.

And once again, thank you so much! (unfortunately, I couldn’t include jquery, even minified, the post would be too long.)


<!doctype html>
<html lang="en">

<head>

<meta charset="utf-8" />
	
<title>trouble</title>

<style type="text/css" media="screen">
	#pre {height:200px}
	#stick{
    width: 100%;
    background: #ccc;
	}
	.sticky #stick{
    position: fixed;
    top:0;
    background: #f00;
	}
	#post {height:1000px}
</style>


</head>

<body>

	<div id="pre">
	</div>
	
	<div id="stick">
	<p>stick</p>
	</div>
	
	<div id="post">
	</div>

<script type="text/javascript">

//jquery

/*
jQuery Waypoints - v1.1
Copyright (c) 2011 Caleb Troughton
Dual licensed under the MIT license and GPL license.
https://github.com/imakewebthings/jquery-waypoints/blob/master/MIT-license.txt
https://github.com/imakewebthings/jquery-waypoints/blob/master/GPL-license.txt
*/
(function($,k,m,i,d){var e=$(i),g="waypoint.reached",b=function(o,n){o.element.trigger(g,n);if(o.options.triggerOnce){o.element[k]("destroy")}},h=function(p,o){var n=o.waypoints.length-1;while(n>=0&&o.waypoints[n].element[0]!==p[0]){n-=1}return n},f=[],l=function(n){$.extend(this,{element:$(n),oldScroll:-99999,waypoints:[],didScroll:false,didResize:false,doScroll:$.proxy(function(){var q=this.element.scrollTop(),p=q>this.oldScroll,s=this,r=$.grep(this.waypoints,function(u,t){return p?(u.offset>s.oldScroll&&u.offset<=q):(u.offset<=s.oldScroll&&u.offset>q)}),o=r.length;if(!this.oldScroll||!q){$[m]("refresh")}this.oldScroll=q;if(!o){return}if(!p){r.reverse()}$.each(r,function(u,t){if(t.options.continuous||u===o-1){b(t,[p?"down":"up"])}})},this)});$(n).scroll($.proxy(function(){if(!this.didScroll){this.didScroll=true;i.setTimeout($.proxy(function(){this.doScroll();this.didScroll=false},this),$[m].settings.scrollThrottle)}},this)).resize($.proxy(function(){if(!this.didResize){this.didResize=true;i.setTimeout($.proxy(function(){$[m]("refresh");this.didResize=false},this),$[m].settings.resizeThrottle)}},this));e.load($.proxy(function(){this.doScroll()},this))},j=function(n){var o=null;$.each(f,function(p,q){if(q.element[0]===n){o=q;return false}});return o},c={init:function(o,n){this.each(function(){var u=$.fn[k].defaults.context,q,t=$(this);if(n&&n.context){u=n.context}if(!$.isWindow(u)){u=t.closest(u)[0]}q=j(u);if(!q){q=new l(u);f.push(q)}var p=h(t,q),s=p<0?$.fn[k].defaults:q.waypoints[p].options,r=$.extend({},s,n);r.offset=r.offset==="bottom-in-view"?function(){var v=$.isWindow(u)?$[m]("viewportHeight"):$(u).height();return v-$(this).outerHeight()}:r.offset;if(p<0){q.waypoints.push({element:t,offset:t.offset().top,options:r})}else{q.waypoints[p].options=r}if(o){t.bind(g,o)}});$[m]("refresh");return this},remove:function(){return this.each(function(o,p){var n=$(p);$.each(f,function(r,s){var q=h(n,s);if(q>=0){s.waypoints.splice(q,1)}})})},destroy:function(){return this.unbind(g)[k]("remove")}},a={refresh:function(){$.each(f,function(r,s){var q=$.isWindow(s.element[0]),n=q?0:s.element.offset().top,p=q?$[m]("viewportHeight"):s.element.height(),o=q?0:s.element.scrollTop();$.each(s.waypoints,function(u,x){var t=x.options.offset,w=x.offset;if(typeof x.options.offset==="function"){t=x.options.offset.apply(x.element)}else{if(typeof x.options.offset==="string"){var v=parseFloat(x.options.offset);t=x.options.offset.indexOf("%")?Math.ceil(p*(v/100)):v}}x.offset=x.element.offset().top-n+o-t;if(s.oldScroll>w&&s.oldScroll<=x.offset){b(x,["up"])}else{if(s.oldScroll<w&&s.oldScroll>=x.offset){b(x,["down"])}}});s.waypoints.sort(function(u,t){return u.offset-t.offset})})},viewportHeight:function(){return(i.innerHeight?i.innerHeight:e.height())},aggregate:function(){var n=$();$.each(f,function(o,p){$.each(p.waypoints,function(q,r){n=n.add(r.element)})});return n}};$.fn[k]=function(n){if(c[n]){return c[n].apply(this,Array.prototype.slice.call(arguments,1))}else{if(typeof n==="function"||!n){return c.init.apply(this,arguments)}else{if(typeof n==="object"){return c.init.apply(this,[null,n])}else{$.error("Method "+n+" does not exist on jQuery "+k)}}}};$.fn[k].defaults={continuous:true,offset:0,triggerOnce:false,context:i};$[m]=function(n){if(a[n]){return a[n].apply(this)}else{return a.aggregate()}};$[m].settings={resizeThrottle:200,scrollThrottle:100};e.load(function(){$[m]("refresh")})})(jQuery,"waypoint","waypoints",this);
</script>

<script type="text/javascript">

	$('#stick').waypoint(function(event, direction) {
		$(this).parent().toggleClass('sticky', direction === "down");
		event.stopPropagation();
	});
</script>

</body>
</html>

No probs, work gets like that sometimes :wink:

I had a quick look at your code and compared it to the waypoints sticky example and noticed that their method put the “position:fixed” not on the element that waypoint() is being applied to, but rather its child.

I’ve made a small amend to the CSS from your code:

<!doctype html>
<html lang="en">

<head>

<meta charset="utf-8" />
	
<title>no longer trouble</title>

<style type="text/css" media="screen">
	#pre { height:200px }

	#stick{
		width: 100%;
		width:640px;
		margin:0 auto;
	}
	#stick p {
		padding:20px;
		background: #ccc;
		margin:0;
		width:600px;
	}
	.sticky #stick p{  
	    position: fixed;
	    top:0;
		background: #f00;
	}
	#post {height:1000px}
	
</style>

</head>

<body>
<div id="wrapper">
	<div id="pre">
	</div>

	<div id="stick">
		<p>stick</p>
	</div>
	
	<div id="post">
	</div>
</div>

<script type="text/javascript" src="//ajax.googleapis.com/ajax/libs/jquery/1/jquery.min.js"></script>
<script type="text/javascript" src="waypoints.min.js"></script>

<script type="text/javascript">
	$('#stick').waypoint(function(event, direction) {
		$(this).parent().toggleClass('sticky', direction === "down");
		event.stopPropagation();
	});
</script>

</body>
</html>

Just took a quick look at the Waypoints source and it seems there is a resize event binding. Whether this is causing your class to disappear I don’t know, but take a look around line 146 - 164 of the waypoint plugin:

// Setup scroll and resize handlers.  Throttled at the settings-defined rate limits.
$(context).scroll($.proxy(function() {
	if (!this.didScroll) {
		this.didScroll = true;
		window.setTimeout($.proxy(function() {
			this.doScroll();
			this.didScroll = false;
		}, this), $[wps].settings.scrollThrottle);
	}
}, this)).resize($.proxy(function() {   /** Line 156:  << Resize handler **/
	if (!this.didResize) {
		this.didResize = true;
		window.setTimeout($.proxy(function() {
			$[wps]('refresh');
			this.didResize = false;
		}, this), $[wps].settings.resizeThrottle);
	}
}, this));

if the resize is moving the position of where the scroll offset is, and you’re no longer at your -100% offset it seems to make sense for waypoint to execute the method. Put a console.log() in the resize handler of waypoint and see what happens :slight_smile:

Hello,

Thank you very much for your reply :slight_smile:

I hope you’re patient with newbies because:

a) I wouldn’t know how to put a console.log() anywhere, and check what happened…

b) I don’t use offset in my code so I’m a bit lost (as in: “is it implied”?)…

c) I’m wondering if I should include Ben Alman » jQuery throttle / debounce: Sometimes, less is more! , which may be the problem…

d) I don’t know if a high value for $.waypoints.settings.resizeThrottle would help, or if that would be the opposite…

:slight_smile:

No probs, glad to help.

b[/b]
Ok, so first thing we’ll want to do is show you the magic of console.log() :slight_smile:

If you’re using Chrome or Firefox you have access to an excellent set up of debugging tools. In Chrome there is Web Inspector which comes with the browser and Firefox has [URL=“http://getfirebug.com/”]Firebug which is a plugin you can install.

To show dev tools in chrome hit CTRL+SHIFT+I (CMD-OPT-I on Mac) for Firebug hit F12 (CMD+F12) (or the toolbar/addon bar button).

On the console tab of the tools you’ll be able to see console.log() output, which show the contents of variables.

For example, try console.log(jQuery) after you include the jQuery library.

B[/B]
Sorry, you’re right it was a bit late here and I think I must have been looking at the wrong code when I suggested the offset thing. Though, the same thing applies, we’d still want to find out of if the resize handler is called and is affecting the class on the body.

b[/b]
It’s always a good idea to isolate problems, to make things a bit easier, it might be a good thing to comment out additinal JS so we can be sure that waypoint is causing the problem.

b[/b]
This is only reduce the number of event handler executions by throttling them to happen to a max # of times per interval, so this likely won’t help you.

So, put something like a console.log(“resize handler called”) in the jQuery.waypoint script (inside the event handler function of course).

You can also add a console.log(event) to the waypoints call in your code, to see what’s happening there (might be easier).
e.g.


	$.waypoints.settings.scrollThrottle = 30;
	$('#nav').waypoint(function(event, direction) {
		$(this).parent().toggleClass('sticky', direction === "down");
		console.log(event); // <<< This will let us know what event has been called 
		event.stopPropagation();
	});

Let me know if any of this doesn’t make sense or if you need some more help :slight_smile:

Wow, thank you so much.

I read your post carefully, will try it all asap, and I’ll post the result :slight_smile: