Jump to content

Why "sometimes" changing display property of div cause my "hide" script to fall into infitinite repetition state ?


eaglehopes
Go to solution Solved by kicken,

Recommended Posts

I tried to hide some "div" elements inside another sticky "div" element by changing their display property to "none" when scroll the page down.  But, sometimes the result is like that:

1. when scroll the page down, elements inside the sticky container removed successfully

2. when elements removed, its container's top position in the page changed( I do not understand why)

3. then according to my condition(which depends on the main sticky container's top position) it again start to show elements

4. then when elements I hide shown, again the container's top position changes and that repeats infinitely ! Stucked at that point.

How can I overcome this ? Example is in online at my web page.

1. enter into http://enginery.freecluster.eu

2. change the browser windows width to lesser so that that top-down scroll appears at the right,

3. press "blog" menu button.

4. at some width positions, page instantly starts shaking( i.e. try to use my hide and show elements javascipts at the same time) when scroll down, sometimes it does not

The code I used is that to hide elements in sticky sub-menu container is :

<html >
  <head> ...</head>
  <body onscroll="showHideSubMenus()"> 
    ...
  <div id="MenuContainer" style="position:sticky; top : 0px"> 
  	<div id="secondLevelMenu" > 
      ....
    </div>
    <div id="thirdLevelMenu" > 
      ....
    </div>
	...    
  </div>
    ...
<script>
var secondLvlMenu, thirdLvlMenu;
var topPos ;
var container ; 

window.onload = function() { 
  secondLvlMenu = document.getElementById("secondLevelMenu");
  thirdLvlMenu = document.getElementById("thirdLevelMenu");
  container = document.getElementById("MenuContainer"); // container div
};

function showHideSubMenus() {
  secondLvlMenu = document.getElementById("secondLevelMenu");
  thirdLvlMenu = document.getElementById("thirdLevelMenu");

  if(container) {
    topPos=container.getBoundingClientRect().top;
    if( topPos < 50 ) {
      hideSecondNThirdLevelMenus();
      return;
    } else {
      showSecondNThirdLevelMenus();
      return;
    }
  }
}

function hideSecondNThirdLevelMenus() {
  console.log("hide menus");
  hearderElement.style.maxHeight = "69";
  if(secondLvlMenu ) {
    //DEBUG I used that but gave same result  : secondLvlMenu.style.display="none"; 
    secondLvlMenu.style.visibility= "hidden";
    secondLvlMenu.style.maxHeight= "0";
  }
  if(thirdLvlMenu) {
    //DEBUG I used that but gave same result  : thirdLvlMenu.style.display="none";
    thirdLvlMenu.style.visibility= "hidden";
    thirdLvlMenu.style.maxHeight = "0";
  }
}

function showSecondNThirdLevelMenus() {
  console.log("show menus");
  if(secondLvlMenu ) {
    // secondLvlMenu.style.display="block";
    secondLvlMenu.style.visibility= "visible";
    secondLvlMenu.style.maxHeight= "initial";
  }
  if(thirdLvlMenu) {
    //thirdLvlMenu.style.display="block";
    thirdLvlMenu.style.visibility= "visible";
    thirdLvlMenu.style.maxHeight = "initial";
  }
}
</script>
    ...
    </body>
  ...
</html>

Does anybody have any idea about what is the permanent/bug free solution ? Thanks.

Link to comment
Share on other sites

Thanks requinix.

I think yes, I understood the problem. I wanted to do that : when user pressed blog page and show second level or/and third level menus  and when they are showing on the sticky "MenuContainer" div, simply hide them. Reason is that the menu height is so big so that it hides the page content mostly. 

Condition of hide : 

I used checking condition as sticky container's top position; when it goes up(i.e. user scroll down), less than 69 pixels from the top, hide both sub-menus. I tried condition as "less than 1 pixel" but it was the worst !

 

Link to comment
Share on other sites

You know, I'm not actually sure how to "professionally" solve this.
The issue being, to be clear, that with a certain viewport height there is a certain range where scrolling into it causes the bar to hide, thus decreasing the height of the document, and if the viewport is also close enough to the bottom, the decreased height causes the document to scroll "up" and triggering the bar to display, and that can cause a scroll event again where it's re-calculated that the bar should be hidden... And narrowing the viewport width enough causes wrapping which increases the element's height and thus also the size of the problematic range, making it easier to trigger.

Barring more specific advice, my suggestion would be to toss out what you've come up with and see if Google can suggest a different implementation to use.
eg. https://www.google.com/search?q=css+disappearing+nav+scroll+down

I'm betting that a successful solution will involve the scrollTop property.

Link to comment
Share on other sites

  • Solution

There is a concept in design/engineering called Hysteresis.  In a nut shell, you don't define hard cut-off points and instead define a range, or introduce a delay of some sort.

So instead of having your code hide the menus when the container is <50 px from the top and show them when 50px or more from the top, you instead set it up such as:

  1. If container is <50 px from the top, hide the menus
  2. If container is >150px from the top, show the menus.
  3. If the container is between 50px and 150px from the top, just maintain whatever the current state is.

The range can be fixed like the example, or dynamic by calculating the menu heights.  You just need the range to be large enough that toggling the visibility of the menus doesn't cross both boundaries.

 

 

  • Great Answer 1
Link to comment
Share on other sites

I understood the hysteresis, but adjusting the range is not easy; since each device show may page with their own width-height, so I think could not manage it. I solved it by using change in the body element's top position during scrolling of my page. So, my final code like that 

var mainBody ;
...
mainBody = document.getElementById("mainbody");
...

topPos=mainBody.getBoundingClientRect().top;

if( topPos >= -10 ) {
	showSecondNThirdLevelMenus();
} else if(topPos < -10) { 
	hideSecondNThirdLevelMenus();
}

Even a 10 pixel scroll down cause menus to collapse. Other than that, showing menus.

Difference from the first code? Main difference is that: fistly I referenced the sticky element itself which is also moving when scrolling down-up. However , second solution I select the fixed (i.e. anchored to the scrolling page) element. Then hide/show does not effect the fixed element's position.

So I will chose fixed elements as a reference for style changes next time ! Thanks for guiding. :D

Link to comment
Share on other sites

  • 2 weeks later...

I hope admins do not angry with me :D  but I solved my problem with an better alternative as requinix suggeted at the end. Because

1. although my above code works for desktop sized screens, when I checked my webpage's mobile or tablet visualizations, since top menu squeezed, its height increase so that menu closed too early and user could not see the whole menu !

2. code for hiding/showing an independent side bar is easy and ready but, implementing it into my php required harder work

so that, I just added a few lines of code to add to a "show/hide menu" button on sticky menu and user can close/open it anytime s/he wants. I think it is more "reliable" code. 

Link to comment
Share on other sites

1 hour ago, eaglehopes said:

I hope admins do not angry with me :D  but I solved my problem with an better alternative as requinix suggeted at the end. Because

1. although my above code works for desktop sized screens, when I checked my webpage's mobile or tablet visualizations, since top menu squeezed, its height increase so that menu closed too early and user could not see the whole menu !

2. code for hiding/showing an independent side bar is easy and ready but, implementing it into my php required harder work

so that, I just added a few lines of code to add to a "show/hide menu" button on sticky menu and user can close/open it anytime s/he wants. I think it is more "reliable" code. 

The purpose of phpfreaks is to help people learn about and develop web applications.  Ultimately, all we want is people who are genuinely making their best effort.  There's no reason for anyone to be angry with you or this thread.  I do appreciate you providing an update on your progress, and the reasoning behind your conclusions.

Link to comment
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Guest
Reply to this topic...

×   Pasted as rich text.   Restore formatting

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

×
×
  • Create New...

Important Information

We have placed cookies on your device to help make this website better. You can adjust your cookie settings, otherwise we'll assume you're okay to continue.