0

I've made a webpage. I want to implimenet the feature which scrolls the webpage to the location of href target of menu anchors. My code is as following

 var myscroll = {};
 myscroll.list = document.getElementsByClassName("navbar-right")[0].getElementsByTagName("li");

 myscroll.bodypos = function getScrollY() {
   scrOfY = 0;
   if (typeof(window.pageYOffset) == 'number') {
     //Netscape compliant
     scrOfY = window.pageYOffset;

   } else if (document.body && (document.body.scrollLeft || document.body.scrollTop)) {
     //DOM compliant
     scrOfY = document.body.scrollTop;

   } else if (document.documentElement && (document.documentElement.scrollLeft || document.documentElement.scrollTop)) {
     //IE6 standards compliant mode
     scrOfY = document.documentElement.scrollTop;

   }
   return scrOfY;
 }

 function getScrollpos(idname) {
   return document.getElementById(idname).offsetTop;
 }
 myscroll.point = [];
 myscroll.point[0] = getScrollpos("home");
 myscroll.point[1] = getScrollpos("artists");
 myscroll.point[2] = getScrollpos("songs");
 myscroll.point[3] = getScrollpos("beats");
 myscroll.point[4] = getScrollpos("contact");

 function removeclass() {
   for (var i = 0; i < 5; i++) {
     myscroll.list[i].className = "";
   }
 }

 window.addEventListener('scroll', function(e) {

   if (myscroll.bodypos() >= myscroll.point[0]) {
     removeclass();
     myscroll.list[0].className = "active";
   }


   if (myscroll.bodypos() >= myscroll.point[1]) {
     removeclass();

     myscroll.list[1].className = "active";
   }

   if (myscroll.bodypos() >= myscroll.point[2]) {
     removeclass();
     myscroll.list[2].className = "active";

   }

   if (myscroll.bodypos() >= myscroll.point[3]) {
     removeclass();
     myscroll.list[3].className = "active";

   }

   if (myscroll.bodypos() >= myscroll.point[4]) {
     removeclass();
     myscroll.list[4].className = "active";

   }
 });

 for (var j = 0; j < 5; j++) {

   (function(j) {

     myscroll.list[j].anchor = document.getElementsByClassName("navbar-right")[0].getElementsByTagName("li")[j].getElementsByTagName("a")[0];
     myscroll.list[j].anchor.addEventListener("click", function() {



       if ((document.body.scrollTop != undefined) && (document.body.scrollTop < myscroll.point[j])) {

         var clr1 = setInterval(function() {
           if (document.body.scrollTop < myscroll.point[j] - 10) {
             document.body.scrollTop += 3;
           } else {
             document.body.scrollTop = myscroll.point[j];
             clearInterval(clr1);
           }
         }, 1);
       }



       if ((document.documentElement.scrollTop != undefined) && (document.documentElement.scrollTop < myscroll.point[j])) {

         var clr2 = setInterval(function() {
           if (document.documentElement.scrollTop < myscroll.point[j] - 10) {
             document.documentElement.scrollTop += 3;
           } else {
             document.documentElement.scrollTop = myscroll.point[j];
             clearInterval(clr2);
           }
         }, 1);
       }


       if ((document.body.scrollTop != undefined) && (document.body.scrollTop > myscroll.point[j])) {
         var clr3 = setInterval(function() {
           if (document.body.scrollTop >= myscroll.point[j] + 4) {
             document.body.scrollTop -= 3;
           } else {
             document.body.scrollTop = myscroll.point[j];
             clearInterval(clr3);
           }

         }, 1);
       }

       if ((document.documentElement.scrollTop != undefined) && (document.documentElement.scrollTop > myscroll.point[j])) {
         var clr4 = setInterval(function() {
           if (document.documentElement.scrollTop >= myscroll.point[j] + 4) {
             document.documentElement.scrollTop -= 3;
           } else {
             document.documentElement.scrollTop = myscroll.point[j];
             clearInterval(clr4);
           }

         }, 1);
       }
       alert(j);

     }, true);

   }(j));

 }
#navbar,
#navbar a:link,
#navbar a:visited,
#navbar a:hover {
  position: fixed;
  color: red !important;
}
#home {
  width: 500px;
  height: 500px;
  background-color: black;
  display: block;
}
#artists {
  width: 500px;
  height: 500px;
  background-color: gray;
  display: block;
}
#songs {
  width: 500px;
  height: 500px;
  background-color: yellow;
  display: block;
}
#beats {
  width: 500px;
  height: 500px;
  background-color: blue;
  display: block;
}
#contact {
  width: 500px;
  height: 500px;
  background-color: green;
  display: block;
}
<div id="navbar" class="navbar-collapse collapse">
  <ul class="nav navbar-nav navbar-right">
    <li class="active"><a href="#">Home</a>
    </li>
    <li><a href="#artists">Artists</a>
    </li>
    <li><a href="#songs">Songs</a>
    </li>
    <li><a href="#beats">Beats</a>
    </li>
    <li><a href="#contact">Contact</a>
    </li>
  </ul>
</div>

<div id="home"></div>
<div id="artists"></div>
<div id="songs"></div>
<div id="beats"></div>
<div id="contact"></div>

As such the code doesn't do what it is supposed to. If we remove href attributes of menu's anchor tags then the code works as expected but with one bug. The problem with the href tags is that before the onclick function could do anything the webpages scrolls quickly to the href target. Other posts say returntning false with onclick would disable the href target. The problem is that I am not using onclick; I am using addEventListener("click"). I tried returning both false and true but nothing worked. So,

  • Why is it said returning false stops href function of anchor elements? Now I know that preventDefault will do what I want. But I want to know how to acheive the same by returning false.

Now comes the bug. When I click on contact link it scrolls down to the bottom of page and remains fixed there. If I scroll upwards then the page is automatically scrolled to bottom.

 var myscroll = {};
 myscroll.list = document.getElementsByClassName("navbar-right")[0].getElementsByTagName("li");

 myscroll.bodypos = function getScrollY() {
   scrOfY = 0;
   if (typeof(window.pageYOffset) == 'number') {
     //Netscape compliant
     scrOfY = window.pageYOffset;

   } else if (document.body && (document.body.scrollLeft || document.body.scrollTop)) {
     //DOM compliant
     scrOfY = document.body.scrollTop;

   } else if (document.documentElement && (document.documentElement.scrollLeft || document.documentElement.scrollTop)) {
     //IE6 standards compliant mode
     scrOfY = document.documentElement.scrollTop;

   }
   return scrOfY;
 }

 function getScrollpos(idname) {
   return document.getElementById(idname).offsetTop;
 }
 myscroll.point = [];
 myscroll.point[0] = getScrollpos("home");
 myscroll.point[1] = getScrollpos("artists");
 myscroll.point[2] = getScrollpos("songs");
 myscroll.point[3] = getScrollpos("beats");
 myscroll.point[4] = getScrollpos("contact");

 function removeclass() {
   for (var i = 0; i < 5; i++) {
     myscroll.list[i].className = "";
   }
 }

 window.addEventListener('scroll', function(e) {

   if (myscroll.bodypos() >= myscroll.point[0]) {
     removeclass();
     myscroll.list[0].className = "active";
   }


   if (myscroll.bodypos() >= myscroll.point[1]) {
     removeclass();

     myscroll.list[1].className = "active";
   }

   if (myscroll.bodypos() >= myscroll.point[2]) {
     removeclass();
     myscroll.list[2].className = "active";

   }

   if (myscroll.bodypos() >= myscroll.point[3]) {
     removeclass();
     myscroll.list[3].className = "active";

   }

   if (myscroll.bodypos() >= myscroll.point[4]) {
     removeclass();
     myscroll.list[4].className = "active";

   }
 });

 for (var j = 0; j < 5; j++) {

   (function(j) {

     myscroll.list[j].anchor = document.getElementsByClassName("navbar-right")[0].getElementsByTagName("li")[j].getElementsByTagName("a")[0];
     myscroll.list[j].anchor.addEventListener("click", function(event) {


          event.preventDefault();
       if ((document.body.scrollTop != undefined) && (document.body.scrollTop < myscroll.point[j])) {

         var clr1 = setInterval(function() {
           if (document.body.scrollTop < myscroll.point[j] - 10) {
             document.body.scrollTop += 3;
           } else {
             document.body.scrollTop = myscroll.point[j];
             clearInterval(clr1);
           }
         }, 1);
       }



       if ((document.documentElement.scrollTop != undefined) && (document.documentElement.scrollTop < myscroll.point[j])) {

         var clr2 = setInterval(function() {
           if (document.documentElement.scrollTop < myscroll.point[j] - 10) {
             document.documentElement.scrollTop += 3;
           } else {
             document.documentElement.scrollTop = myscroll.point[j];
             clearInterval(clr2);
           }
         }, 1);
       }


       if ((document.body.scrollTop != undefined) && (document.body.scrollTop > myscroll.point[j])) {
         var clr3 = setInterval(function() {
           if (document.body.scrollTop >= myscroll.point[j] + 4) {
             document.body.scrollTop -= 3;
           } else {
             document.body.scrollTop = myscroll.point[j];
             clearInterval(clr3);
           }

         }, 1);
       }

       if ((document.documentElement.scrollTop != undefined) && (document.documentElement.scrollTop > myscroll.point[j])) {
         var clr4 = setInterval(function() {
           if (document.documentElement.scrollTop >= myscroll.point[j] + 4) {
             document.documentElement.scrollTop -= 3;
           } else {
             document.documentElement.scrollTop = myscroll.point[j];
             clearInterval(clr4);
           }

         }, 1);
       }
       alert(j);

     }, true);

   }(j));

 }
#navbar,
#navbar a:link,
#navbar a:visited,
#navbar a:hover {
  position: fixed;
  color: red !important;
}
#home {
  width: 500px;
  height: 500px;
  background-color: black;
  display: block;
}
#artists {
  width: 500px;
  height: 500px;
  background-color: gray;
  display: block;
}
#songs {
  width: 500px;
  height: 500px;
  background-color: yellow;
  display: block;
}
#beats {
  width: 500px;
  height: 500px;
  background-color: blue;
  display: block;
}
#contact {
  width: 500px;
  height: 500px;
  background-color: green;
  display: block;
}
<div id="navbar" class="navbar-collapse collapse">
  <ul class="nav navbar-nav navbar-right">
    <li class="active"><a href="#">Home</a>
    </li>
    <li><a href="#artists">Artists</a>
    </li>
    <li><a href="#songs">Songs</a>
    </li>
    <li><a href="#beats">Beats</a>
    </li>
    <li><a href="#contact">Contact</a>
    </li>
  </ul>
</div>

<div id="home"></div>
<div id="artists"></div>
<div id="songs"></div>
<div id="beats"></div>
<div id="contact"></div>
  • How do I remove this bug?
Community
  • 1
  • 1
user31782
  • 7,087
  • 14
  • 68
  • 143

1 Answers1

0

Use preventDefault() on the event, to stop the default for the click event to be executed.

window.addEventListener('scroll', function(e) {
    e.preventDefault();
    ...

Then do your thing in your handler, and at the end, manually update the window.location with the value of the event target's href attribute.

EDIT

RE the comment: your event still bubbles, only the default action is prevented. To stop it from bubbling up, there is event.stopPropagation().

The default action for you event is simply to set the window.location to the value of your event target's href attribute

window.location = e.target.getAttribute('href');
C14L
  • 12,153
  • 4
  • 39
  • 52
  • Isn't there anything like `allowDefault()` which I could execute after my javascript function is finished? OR isn't there any way I could _reorder_ the execution of default behaviour and my javascript function. Something like bubbling? – user31782 May 20 '16 at 06:13
  • I added it to my answer – C14L May 20 '16 at 08:01
  • There is a problem `window.location = e.target.getAttribute('href');` adds the `href` target before jquery function is executed. It causes a blinking effect. – user31782 May 20 '16 at 08:30
  • You have to add it at the end of what you are doing. So, probably in the callback function of whatever jQuery thing you do. So it actually only updates `windows.location` once everything else is done. – C14L May 20 '16 at 08:36
  • Since I couldn't remove the bug of my custom javascript which I mentioned in the question. I replaced the code on live site with the following jquery code: `$(myscroll.list[j].anchor).click(function(event) { event.preventDefault(); $('html, body').animate({ scrollTop: myscroll.point[j] }, 2000); window.location = event.target.getAttribute('href'); });` But now the problem is that window.location is updated before scrolling animation of jquery finishes. – user31782 May 20 '16 at 08:41