Problem after migration to latest jQuery version

Hi everybody.

I am trying to migrate to the latest jQuery version (3.4.1) for my smooth scroll effect, and got seems that something adds a display-none style to the body tag leaving my page useless.

The script is:

(function($){
  
    var jump=function(e)
    {
       if (e){
           e.preventDefault();
           var target = $(this).attr("href");
       }else{
           var target = location.hash;
       }

       $('html,body').animate(
       {
           scrollTop: $(target).offset().top
       },1000,function()
       {
           location.hash = target;
       });

    }

    $('html, body').hide()

    $(document).ready(function()
    {
        $('a[href^=#]').bind("click", jump);

        if (location.hash){
            setTimeout(function(){
                $('html, body').scrollTop(0).show()
                jump()
            }, 0);
        }else{
          $('html, body').show()
        }
    });
  
})(jQuery)

It works with 1.7.1 and other more recent versions, but after 1.11.2 I get a blank page.

I am not a jQuery expert and would like to know if there might be any solution or I should try other script.

Regards.

Calling .hide() on the body and html elements will add display:none to their styles. So that gives us a clue. The body is being hidden… and yet your code says it should be shown later. Hm! This makes me think there’s an error thrown which is stopping code from executing.

So, I tried your script on a simple web page which has some links and divs. If I use a recent version of jQuery, then - aha! - I see this error in the JavaScript console:

Uncaught Error: Syntax error, unrecognized expression: a[href^=#]
    at Function.se.error (jquery-3.4.1.min.js:2)
    at se.tokenize (jquery-3.4.1.min.js:2)
    at se.select (jquery-3.4.1.min.js:2)
    at Function.se [as find] (jquery-3.4.1.min.js:2)
    at k.fn.init.find (jquery-3.4.1.min.js:2)
    at new k.fn.init (jquery-3.4.1.min.js:2)
    at k (jquery-3.4.1.min.js:2)
    at HTMLDocument.<anonymous> (jnk.html:88)
    at e (jquery-3.4.1.min.js:2)
    at t (jquery-3.4.1.min.js:2)

Check your JavaScript console - does it show the same error?

If I use an old version of jQuery, 1.7.2, there is no error. This sounds like your problem indeed.

This is the key takeaway: “unrecognized expression: a[href^=#]”. I did a little hunting around, and it seems like “#” needs to be escaped, like this:

$('a[href^=\\#]').bind("click", jump);

Maybe try that small change and see if your required functionality returns.

3 Likes

It’s also worth noting that as of jQuery 3.0, .bind() has been deprecated. You should be using the .on() method for attaching event handlers.

You were right fullstackdev; I escaped the hash and the script works perfectly with 3.4.1.

        $('a[href^=\\#]').bind("click", jump);

I also tried the James’ suggestion about replacing .bind() with .on() but then the style is applied again.

1 Like

Could you supply a little HTML to go with your JavaScript so I can test it out.

Based on his binding, any link beginning with an anchor in the href will trigger the function.

<html>
<body>
<a href='#test1'>Link1</a>
<a href='#test2'>Link2</a>
<div style='height: 1000px;'>&nbsp;</div>
<a name='test1'>
<p>Test1</p>
<div style='height: 1000px;'>&nbsp;</div>
<a name='test2'>
<p>Test2</p>
<div style='height: 1000px;'>&nbsp;</div>
</body>
</html>

His formatting suggests he’s embedding this inside a Wordpress page, as it relies on the WP workaround for the redefinition of $ away from the jquery default.

That gives me the following error: TypeError: $(...).offset(...) is undefined

Codez:

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8">
    <title>Document</title>
  </head>
  <body>
    <a href='#test1'>Link1</a>
    <a href='#test2'>Link2</a>
    <div style='height: 1000px;'>&nbsp;</div>
    <a name='test1'>
    <p>Test1</p>
    <div style='height: 1000px;'>&nbsp;</div>
    <a name='test2'>
    <p>Test2</p>
    <div style='height: 1000px;'>&nbsp;</div>

    <script src="https://code.jquery.com/jquery-3.4.1.min.js"></script>
    <script>
      (function($){
        var jump=function(e)
        {
          if (e){
            e.preventDefault();
            var target = $(this).attr("href");
          } else {
            var target = location.hash;
          }

          $('html,body').animate(
          {
            scrollTop: $(target).offset().top
          },1000,function()
          {
            location.hash = target;
          });
        }

        $('html, body').hide()

        $(document).ready(function()
        {
          $('a[href^=\\#]').bind("click", jump);

          if (location.hash){
            setTimeout(function(){
              $('html, body').scrollTop(0).show()
              jump()
            }, 0);
          }else{
            $('html, body').show()
          }
        });
      })(jQuery)
    </script>
  </body>
</html>

oh sorry. The target means that the anchors need an ID attribute as well, to be valid targets when called as $(target).

<a name='test1' id='test1'>

1 Like

Ta.

@andresb: this works fine (using .on()), or am I missing something?

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8">
    <title>Document</title>
  </head>
  <body>
    <a href='#test1'>Link1</a>
    <a href='#test2'>Link2</a>
    <div style='height: 1000px;'>&nbsp;</div>
    <a name='test1' id='test1'>
    <p>Test1</p>
    <div style='height: 1000px;'>&nbsp;</div>
    <a name='test2' id='test2'>
    <p>Test2</p>
    <div style='height: 1000px;'>&nbsp;</div>

    <script src="https://code.jquery.com/jquery-3.4.1.min.js"></script>
    <script>
      (function($){
        var jump=function(e)
        {
          if (e){
            e.preventDefault();
            var target = $(this).attr("href");
          } else {
            var target = location.hash;
          }

          $('html,body').animate(
          {
            scrollTop: $(target).offset().top
          },1000,function()
          {
            location.hash = target;
          });
        }

        $('html, body').hide()

        $(document).ready(function()
        {
          $('a[href^=\\#]').on("click", jump);

          if (location.hash){
            setTimeout(function(){
              $('html, body').scrollTop(0).show()
              jump()
            }, 0);
          }else{
            $('html, body').show()
          }
        });
      })(jQuery)
    </script>
  </body>
</html>

Yes, it works fine using .on(), but now I have found a problem in some browsers in mobile devices. The pages including the script seems to load twice. Maybe the display:none property is added and then removed, Cannot be sure. I described the problem on this other post:

https://www.sitepoint.com/community/t/strange-reloading-after-loading-page-that-includes-jquery/346080

Hi,

Happy New Year :slight_smile:

Please don’t cross post. You seem to have got your answer here (which is pretty much what I would have said):

1 Like