Modifying Layout via Javascript Causes Repeat of Element

I’m using a viewportWidth script to add/modify elements/content for viewport widths less than 769 pixels.

What happens is that on devices less than 769 pixels width, the text ‘Filter Options’ that appears repeats below itself. I know that my onclick function isn’t the cause of it, but I’m wondering if it’s the ‘if (viewportWidth)’ is causing the problem. Screenshot:

   function mobileViewUpdate() {
    var viewportWidth = jQuery(window).width();
		if (viewportWidth < 769) {
			jQuery(".leftcol").before("<p class='filterop'>Filter Options <i class='glyphicon glyphicon-chevron-down'></i></p>");
			jQuery(".leftcol").before("<p class='filterop two'>Close <i class='glyphicon glyphicon-chevron-up'></i></p>");
			jQuery(".leftcol, .filterop.two").hide(); 
			jQuery(function() {     
				jQuery(".filterop").on("click", function(){
						jQuery(".leftcol").toggle("slow");
						jQuery(".filterop, .filterop.two").toggle("slow");
				});
			});
			jQuery(".leftcol #nav_menu-2, .woof_container_pa_style li").addClass("col-xs-6");
			jQuery(".woof_container_pa_style, .woof_list").addClass("clearfix");
			jQuery("#menu-shop-menu").before("<h4 style='margin-top: 0'>Collection</h4>");		
		}
	}

Can we get the HTML that corresponds with that section? I’m wondering if you have multiple .leftcol’s?

The text ‘elements/content’ above is a link to it.

That script is definitely causing some bizarre behavior.

I suspect the reason is because the function is getting called too often

   function mobileViewUpdate() {
    var viewportWidth = jQuery(window).width();
		if (viewportWidth < 769) {

What does the code that calls mobileViewUpdate look like?

A couple of things to note:

  • You’re inserting those .filterop elements before .leftcol on every update, but never removing them – resulting in those repeating elements.
  • Inside the update function, you have an $(document).ready() handler, which doesn’t really make sense here; in fact, it appears that the handler gets executed on every update, adding more and more click handlers to the .filterop elements, and thus causing the broken behaviour @Mittineague described.
  • I assume you’re executing the update function on resize. Note that in practice, a device width rarely changes during a user session. If you want to account for orientation changes, you might be much better off using CSS media queries for this, so you don’t have to touch the DOM at all; resize handlers are very expensive.
3 Likes

As m3g4p0p said I’m not sure why you aren’t using media queries for this as that was what they were designed for. The layout you want seems easily achievable with a few media query tweaks.

If you do need to use js to change something at viewport width then you can use the more efficient matchMedia instead which works for modern browsers.

However, I think you can do everything you want in the normal way.

Try this CSS:

@media screen and (min-width:762px){
    .filterop{display:none!important}
}   
@media screen and (max-width:761px){
    .filterop{display:block} 
    .leftcol{width:auto;display:table;float:none;margin:0 auto 33px;background:pink;display:none}
    .menu-shop-menu-container{float:left;width:48%}
    .woof_container_2 {clear:both}
    .woof_list_radio  li{display:inline-block;width:45%}
}

Remove your mobile resize script and just use this instead .

<script>  
jQuery(function() {     
	jQuery(".filterop").on("click", function(){
		jQuery(".leftcol").toggle("slow");
		jQuery(".filterop, .filterop.two").toggle("slow");
	});
});    
</script>

Then add the filter into the html by default (its hidden on desktops via css).

<p class='filterop'>Filter Options <i class='glyphicon glyphicon-chevron-down'></i></p>
<p class='filterop two' style=display:none>Close <i class='glyphicon glyphicon-chevron-up'></i></p>
<!-- added just above leftcol -->

<div class="leftcol col-sm-3">

You may need to tweak a few things but the basics are there to do what you want.

2 Likes

Using your references, gents, I’ve made only some minor mods that worked great!

jQuery(".leftcol").before("<p class='filterop'>Filter Options <i class='glyphicon glyphicon-chevron-down'></i></p>");
	jQuery(".leftcol").before("<p class='filterop two'>Close <i class='glyphicon glyphicon-chevron-up'></i></p>");
	jQuery(function() {
		jQuery(".filterop.two").hide();     
		jQuery(".filterop").on("click", function() {
			jQuery(".leftcol, .filterop").toggle("slow");
			jQuery(".filterop.two").show();
			});
	});

Next time I’ll use CSS more to control the display of elements more often while using minimal scripting.

1 Like

This topic was automatically closed 91 days after the last reply. New replies are no longer allowed.