Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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

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'))
like image 771
archienorman Avatar asked Nov 01 '16 17:11

archienorman


3 Answers

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);

 });
});
like image 81
Mendy Avatar answered Sep 22 '22 22:09

Mendy


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>
like image 22
blurfus Avatar answered Sep 24 '22 22:09

blurfus


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

like image 44
BaleineBleue Avatar answered Sep 22 '22 22:09

BaleineBleue