jquery .show() and .hide() not working in safari - adding spinner to <a href

10,623

Solution 1

It appears that you function is named spinner, yet you're attempting to fire loading() inside your a tag (onclick="javascript:loading();). Changing your function name to loading should fix it.

Here's a working example:

https://jsfiddle.net/nvzge1e8/5/

Edit for updated question:

You need to prevent the event, if you stick event.preventDefault() at the top of your function, it should play the animation. Do note, doing this will prevent your link from actually sending your user to the page, so you may need to add a timed redirect to whatever page you're sending them to.

Example code:

 $(function() {
 $(".spin_click").click(function(event) {
     event.preventDefault()
     $("#logo_spinner").attr("src", "/static/images/loaders/spinner.gif");
     $('.content').addClass('hide');
     setTimeout(function() {
         window.location.href = "/wait";
     }, 4000);

 });
});

Solution 2

I am unable to reproduce the issue with the code provided. However, I am adding an answer with a simple version of what you want to accomplish.

My guess is that the code not provided is more complex than you describe (or some dependencies are missing).

Since you already are using jQuery, I am giving you my answer using that library as well.

(updated: added other libraries, used by the OP, to test if their presence introduces the issue described)

See sample code below:

$(function() {
  // add event listener to home (class) - 
  // used instead of inline binding using 'onclick'
  $('.home').on('click', function() {
    console.log('show spinner');
    // show spinner right away
    $("#loading").show();

    console.log('waiting now...');

    // simulate delay in fetching backend response (delay is 3 secs)
    // contains the callback function to be invoked after your response is completed
    setTimeout(function() {
      // hide spinner
      console.log('hide spinner');
      $("#loading").hide();

      // show content
      console.log('show content');
      $("#content").show();
    }, 3 * 1000); // time is in ms so 1000ms = 1 sec (3*1000=3secs)

  });
});
div#loading {
  height: 50px;
  position: relative;
  display: none;
  background: white;
}
.ajax-loader {
  position: absolute;
  left: 0;
  top: 0;
  right: 0;
  bottom: 0;
  max-width: 100px;
  margin: auto;
}
#content {
  display: none;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/materialize/0.97.7/js/materialize.min.js"></script>
    <script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/moment.js/2.15.0/moment.min.js"></script>
    <script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/Chart.js/2.2.2/Chart.min.js"></script>


<header>
  Header here
</header>
<hr/>

<a href="#" class="home">Home</a>

<div id="loading">
  <img class="ajax-loader" src="https://i.stack.imgur.com/akN6H.png?s=48&amp;g=1" alt="" width="24" height="24" class="avatar-me js-avatar-me">
</div>
<hr/>
<div id="content">

  content will be loaded here

</div>

<footer>footer here
</footer>

Solution 3

I have not tested this in Safari but you could try

$("#loading").fadeIn(0);
$("#content").fadeOut(0);

But make sure to remove the

display: none

from your CSS

Solution 4

Sorry haven't tried reproducing your bug but unless you must use elem.hide() and elem.show().

Alternatively, You can work with addClass and removeClass functions

$('#loading').addClass('hide');
$('#loading').removeClass('hide');

with .hide { display: none; }

works perfectly on safari too.

Solution 5

Instead of $('elem').show() and $('elem').hide() try using...

$('elem').attr( 'data-display', 'block');
$('elem').attr( 'data-display', 'none');

In CSS add...

Attribute selector used twice to increase specificity ;)

[data-display][data-display='none'] {
  display:none!important;
}
[data-display][data-display='block'] {
  display:block!important;
}

Code will look like this...

$('h1').attr( 'data-display', 'block');
$('h2').attr( 'data-display', 'none');
[data-display][data-display='none'] {
  display:none!important;
}
[data-display][data-display='block'] {
  display:block!important;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<h1>I'm displayed</h1>
<h2>I'm hidden</h2>
<p>
  I'm unaffected ;)
</p>

This will hide it (even if there is some css forcing visibility by using !important), if not try increasing specificity of selector even more. Inspecting the element would help ;)

Share:
10,623

Related videos on Youtube

archienorman
Author by

archienorman

Updated on September 14, 2022

Comments

  • archienorman
    archienorman over 1 year

    I have some very basic code that acts as a loading gif for a webpage:

    The loading and content containers sit in my base template. The


    //header
    
    <a href="{{ url_for('welcome', id=id, profile=profile) }}" onclick="spinner();" class="home">Home</a>
    
    //more html
    
    <div id="loading">
        <img src="/static/images/Loading.gif" class="ajax-loader">
    </div>
    
    <div id="content">
    
        {% block content %}{% endblock %}
    
    </div>
    
    <script type="text/javascript">
        function spinner() {
            console.log('fire');
            $("#loading").show();
            $("#content").hide();
        }
    </script>
    

    div#loading {
        height: 350px;
        position: relative;
        display: none;
        background: white;
    }
    
    .ajax-loader {
        position: absolute;
        left: 0;
        top: 0;
        right: 0;
        bottom: 0;
        max-width: 100px;
        margin: auto;
    }
    

    My code works perfectly well in firefox and chrome, but not in safari or on ios.

    ps. I have checked that my function is working, the console shows 'fire' which i print straight after the onclick().

    Edit

    This is the only error in the console:

    [Error] Failed to load resource: the server responded with a status of 404 (NOT FOUND) (jquery-ui.min.css, line 0)

    Update 1

    I have added a class to my <a href="url" class="..." and updated my javascript to the following:

    <script type="text/javascript">
        $(function() {
            $( ".spin_click" ).click(function( event ) {
                event.preventDefault();
                console.log('hiding content');
                $(".content").hide();
                console.log('show spinner');
                $(".se-pre-con").show();
                console.log('waiting now...');
            });
        });
    </script>
    
    #html
    
    <div class="se-pre-con"></div>
        <div class="content">
    
            {% block content %}{% endblock %}
        </div>
    

    I can get safari to show the se-pre-condiv when I click on a link, however it completely disables the href link. Is it possible to pursue the link click having executed the .show() command in the jquery? Perhaps I have misunderstood preventDefault(); - but I thought it might be able to act as a workaround. The issue still only exists in safari

    Update 2

    As suggested by @maximast, I have decided to use addClass and removeClass. As usual it works in chrome and firefox, but not safari. The code is the same, I have just added a hide class which is added and removed as necessary.

    If I use the safari inspector and remove the hide class manually, the spinner does show up. When I click on a link in the page to trigger the jquery function, I can see the hide class removed correctly from the div. However, even though the hide class is removed, the spinner does not appear. Perhaps I am missing something obvious here.

    Here are the libraries i am using:

    <script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
        <script src="https://cdnjs.cloudflare.com/ajax/libs/materialize/0.97.7/js/materialize.min.js"></script>
        <script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/moment.js/2.15.0/moment.min.js"></script>
        <script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/Chart.js/2.2.2/Chart.min.js"></script>
    

    Update 3

    Here is a link to a test page. There is a link which puts the app to sleep for 3 seconds giving enough time for the spinner to trigger. The spinner sits in the logo. The test page will show the spinner working in a Chrome and Firefox, but not safari. The implementation with this button is exactly the same as used elsewhere in my app.

    http://ec2-54-88-245-245.compute-1.amazonaws.com/spinner-test

    I have changed the link in the logo to: <a href='#' which for the first time render the spinner in all three browsers. (progress!). However when you click on the 'Click to trigger spinner.' link, the following happens:

    1. Chrome - spinner works first time.
    2. Firefox - spinner works first time, however there were a couple of occasions when I had to click it a second time.
    3. Safari - no luck.

    Here is the flask code with the managing the spinner-test page:

    @app.route('/spinner-test', methods=['GET'])
    def spinner():
        return render_template('spinner-test.html')
    
    
    @app.route('/wait', methods=['GET'])
    def wait():
        time.sleep(3)
        return redirect(url_for('spinner'))
    
    • Admin
      Admin over 7 years
      Since you seem to have an element ID somewhere called loading, try changing the name of the function to some other name.
    • archienorman
      archienorman over 7 years
      jquery-ui.min.css - Failed to load resource: the server responded with a status of 404 (NOT FOUND) this is the only error. Change the function name did not help. Removed javascript:
    • blurfus
      blurfus over 7 years
      Can you add some of the HTML to make it a minimal reproducible example? So far, code posted is not enough to replicate the issue for me
    • Mendy
      Mendy over 7 years
      Yeah, at this point I doubt it's an issue with the snippet of code you provided (as all of the examples are working fine on my Safari). It's more likely an issue with your Safari (try updating it), or as @ochi mentioned, perhaps some dependencies are missing. I would perhaps check if there's any events bound to .spin_click.
  • archienorman
    archienorman over 7 years
    this makes the loading div appear the whole time
  • archienorman
    archienorman over 7 years
    sorry that was a mistake on my part, i just the function name as per a comment earlier on. The functions names are the same in my code. The discrepancy is only on SO
  • Mendy
    Mendy over 7 years
    Ah, no worries. Are you sure you've added jQuery before this function? Does my jsfiddle link work for you?
  • archienorman
    archienorman over 7 years
    i load jquery in the head: script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.0/jque‌​ry.min.js"></script> but it works in firefox, so surely the position of jquery wouldn't make a difference. unfortunately, the jsfiddle doesnt work for me
  • blurfus
    blurfus over 7 years
    the issue seems to be safari-specific (OP says it works on FF and chrome) so unless you can replicate the issue (which you didn't as you didn't test it in Safari) - this is not a good answer. I recommend testing it in safari or remove it
  • Mendy
    Mendy over 7 years
    Can you add console.log (typeof jQuery) to the top of your function, and let me know what the console logs?
  • archienorman
    archienorman over 7 years
    the log says: function
  • archienorman
    archienorman over 7 years
    thank you for this detailed answer. i have added the changes you suggest and unfortunately see the same behaviour. It works with firefox, but not safari
  • blurfus
    blurfus over 7 years
    @user3939059 any error in console? - I will try safari shortly
  • archienorman
    archienorman over 7 years
    there is no error. as an fyi, your code also works in chrome. but still no luck with safari or iOS
  • Mendy
    Mendy over 7 years
    Alright, that indicates jQuery is loading fine. What version of Safari are you working with?
  • archienorman
    archienorman over 7 years
    Version 10.0.1 (12602.2.14.0.7)
  • archienorman
    archienorman over 7 years
    it works in firefox, but again does not work in safari logs: n [div id="loading"] Could not fetch properties. Object may no longer exist.
  • archienorman
    archienorman over 7 years
    thanks for your answer. i have tried with addClass and removeClass and can see that the js works, the hide class is added and removed respectively. However the spinner still does not appear in safari. Which makes me think this could be a css issue.
  • blurfus
    blurfus over 7 years
    @user3939059 I am sorry I didn't get back to you... I did try it on safari (on Sierra) and it did work for me as expected. - is it possible that you have other JS libraries that might be interfering with this?
  • blurfus
    blurfus over 7 years
    why would you assume there is a bug in hide() and show() functions (pretty basic functionality) with such a popular library such as jQuery? Don't you think that it would have been fixed by now? did you look at their issue tracker to see if there is such a thing (maybe with certain versions of Safari only)? - no, instead, you assume there is a bug (blame someone else) and provide an alternative that, basically, does the exact same thing as the functions :( - (if you look at their code, it does what you suggest)
  • blurfus
    blurfus over 7 years
    I tried Safari Version 10.0.1 (12602.2.14.0.7) - which version are you trying it with?
  • Qwertiy
    Qwertiy over 7 years
    Since what version does jQuery support setting inline important? As I remember, it didn't.
  • blurfus
    blurfus over 7 years
    @user3939059 oh, and which version of JQuery are you using?
  • archienorman
    archienorman over 7 years
    Hi, jsut adde the scripts being loaded into the question. the version is 2.1.1
  • blurfus
    blurfus over 7 years
    @user3939059 I added the dependencies and tested it in Safari again, I still cannot reproduce the issue. I am afraid there is something else in your code causing this issue. Can you share more of your code?
  • shramee
    shramee over 7 years
    Hi @Qwertiy, Yeah, thanks for pointing out updated my answer :)
  • maximast
    maximast over 7 years
    not blaming anyone just trying to help the guy get past his problem.
  • maximast
    maximast over 7 years
    edited, now am not assuming anything hope that works for you. cheers
  • ViniH
    ViniH almost 5 years
    I am wondering if this might be the cause. OP: are you/were you using Bootstrap by any chance? stackoverflow.com/questions/51005067/…