jQuery的.show()和.hide()在Safari中无法正常工作 - 在<a href>中添加旋转图标

11

我有一些非常基本的代码,用作网页加载时的动画:

加载和内容容器位于我的基础模板中。


//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;
}

我的代码在Firefox和Chrome中运行得非常好,但在Safari或iOS上却不行。

顺便说一句,我已经检查过我的函数是否正常工作,控制台显示了"fire",这是我在onclick()后直接打印出的。

编辑

这是控制台中唯一的错误:

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

更新1

我已经给我的<a href="url" class="..."添加了一个类,并更新了我的JavaScript代码如下:

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

当我点击链接时,我可以让 Safari 显示 se-pre-con div ,但这将完全禁用 href 链接。是否可能在 jquery 中执行 .show() 命令后继续追踪链接单击?也许我误解了 preventDefault(); - 但我认为它可能能够作为一种解决方法。 问题仍然只存在于 Safari 中

更新2

如 @maximast 建议的那样,我已决定使用 addClass 和 removeClass。通常在 Chrome 和 Firefox 中有效,但在 Safari 中不起作用。代码相同,我只是添加了一个必要的 hide 类。

如果我使用 Safari 检查器手动删除 hide 类,则旋转符号会显示出来。 当我单击页面上的链接以触发 jQuery 函数时,我可以看到从 div 中正确删除了 hide 类。但是,即使删除了 hide 类,旋转符号也不会出现。也许我遗漏了一些显而易见的东西。

这里是我正在使用的库:

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

更新3

这里有一个测试页面的链接。有一个链接可以使应用程序休眠3秒钟,为旋转器触发提供足够的时间。旋转器位于标志中。测试页面将显示旋转器在Chrome和Firefox中工作,但不适用于safari。此按钮的实现与我应用程序中其他位置使用的按钮完全相同。

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

我已将标志中的链接更改为:<a href='#',这是第一次在所有三个浏览器中渲染旋转器(进展!)。但是,当您单击“单击以触发旋转器。”链接时,会发生以下情况:

  1. Chrome-旋转器第一次工作。
  2. Firefox-旋转器第一次工作,但有几次我必须再次单击它。
  3. Safari-无效。

这是管理spinner-test页面的Flask代码:

@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'))

1
由于您似乎在某个地方有一个元素ID称为“loading”,请尝试将函数名称更改为其他名称。 - user1106925
1
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: - archienorman
2
你能添加一些HTML代码使其成为一个[mcve]吗?到目前为止,发布的代码不足以让我复制问题。 - blurfus
我曾经认为触发器不是问题,因为我能够记录到我的控制台。 - archienorman
1
是的,目前我怀疑这不是你提供的代码片段的问题(因为所有示例在我的Safari上都正常工作)。更可能是你的Safari有问题(尝试更新它),或者像@ochi提到的那样,可能缺少某些依赖项。我建议检查是否有任何事件绑定到.spin_click - Mendy
显示剩余14条评论
6个回答

4
看起来你的函数名为spinner,但你正在尝试在a标签(onclick="javascript:loading();)中触发loading()。将函数名更改为loading应该可以解决问题。
这是一个可行的示例: https://jsfiddle.net/nvzge1e8/5/ 更新后的问题编辑: 你需要阻止事件,如果在你的函数顶部添加event.preventDefault(),它应该播放动画。请注意,这样做将防止您的链接实际将用户发送到页面,因此您可能需要添加定时重定向到您要发送到的任何页面。
示例代码:
 $(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);

 });
});

抱歉,那是我的错误,我只是根据之前的评论使用了函数名称。在我的代码中,函数名称是相同的。唯一的差异在于SO上。 - archienorman
啊,没关系。你确定在这个函数之前添加了jQuery吗?我的jsfiddle链接对你有效吗? - Mendy
我在头部加载了jQuery:<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.0/jquery.min.js"></script>,但它只在Firefox中有效,所以jQuery的位置肯定不会有影响。不幸的是,这个jsfiddle对我来说无法工作。 - archienorman
1
你能在函数顶部添加 console.log(typeof jQuery) 并告诉我控制台记录了什么吗? - Mendy
日志显示:函数 - archienorman
显示剩余3条评论

3

根据提供的代码,我无法重现问题。但是,我会添加一个答案,其中包含您想要完成的简单版本。

我猜测未提供的代码比您描述的更复杂(或缺少某些依赖项)。

由于您已经在使用jQuery,我也将使用该库来提供答案。

更新:添加了其他由OP使用的库,以测试其存在是否引入所描述的问题)

请参见以下示例代码:

$(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://istack.dev59.com/akN6H.webp?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>


1
谢谢您提供这么详细的答案。我已经按照您的建议进行了更改,但不幸的是仍然出现相同的问题。它可以在Firefox中运行,但在Safari中无法正常工作。 - archienorman
@user3939059 控制台有任何错误吗?- 我马上会尝试Safari。 - blurfus
没有错误。作为一个提示,你的代码在Chrome中也可以运行。但是在Safari或iOS上仍然没有成功。 - archienorman
我尝试了Safari版本10.0.1(12602.2.14.0.7)- 你用的是哪个版本? - blurfus
@user3939059 我已添加依赖项并在Safari中进行了测试,仍无法重现此问题。恐怕您的代码中还有其他原因导致了这个问题。您能否分享更多的代码? - blurfus
显示剩余3条评论

1

我没有在Safari中测试过,但你可以尝试一下

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

但请确保删除


display: none

从你的CSS中。

这会使“loading” div 整个时间都出现。 - archienorman
问题似乎是Safari特有的(OP说它在FF和Chrome上运行正常),所以除非您能复制该问题(因为您没有在Safari中测试它,所以您没有测试它),否则这不是一个好答案。我建议在Safari中进行测试或将其删除。 - blurfus

1
抱歉,我没有尝试复制您的错误,但除非必须使用elem.hide()elem.show(),否则请不要使用它们。

或者,您可以使用addClass和removeClass函数。

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

使用.hide { display: none; }可以完美地在Safari上运行。

谢谢你的回答。我已经尝试使用 addClassremoveClass,并且可以看到 JS 正常工作,分别添加和删除了 hide 类。然而,在 Safari 中旋转器仍然没有出现。这让我觉得可能是 CSS 的问题。 - archienorman
为什么你会认为在如此流行的库jQuery中,hide()show()函数(相当基础的功能)存在bug呢?难道你不觉得这个问题早就被修复了吗?你有没有查看他们的问题跟踪器,看看是否存在这样的问题(也许只有某些版本的Safari)?相反,你假设存在一个bug(责备别人),并提供了一个替代方案,基本上与这些函数执行的完全相同的操作:(如果你查看他们的代码,它确实做了你建议的事情)。 - blurfus
不是在责怪任何人,只是想帮助那个人解决问题。 - maximast
修改后,我不再做任何假设,希望这对您有用。祝好! - maximast

1

尝试使用以下替代方法,而不是$('elem').show()$('elem').hide()

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

在CSS中添加...
属性选择器被使用两次以增加特异性;)
[data-display][data-display='none'] {
  display:none!important;
}
[data-display][data-display='block'] {
  display:block!important;
}

代码将会是这样的...

$('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>

这将隐藏它(即使有一些 CSS 使用 !important 强制可见性),如果不行,请尝试增加选择器的特异性。检查元素会有帮助 ;)

1
从哪个版本开始,jQuery支持设置内联important?据我记得,它以前不支持。 - Qwertiy
嗨@Qwertiy,是的,谢谢你指出并更新了我的答案 :) - shramee

0

我遇到了与OP相同的问题,我只是试图在IOS上显示/隐藏元素,但show/hide不起作用,任何添加类/删除类的组合也不起作用。

在我的情况下,我正在开发渐进式Web应用程序,这个问题占去了我一半的时间。

甚至在同一个函数方法中,我有一个警报尝试触发show和/或remove class。这个警报按预期触发,但元素从未出现。如果我只是删除hide类并重新加载页面,它就会出现,如果我在CSS中将元素默认显示,它就可以工作,但到目前为止,我尝试过的所有方法都不能通过JS使元素出现。我已经尝试在CSS电子表格和内联样式中使用它。我尝试使用visibility、display none/block以及通过JS简单地隐藏/取消隐藏。在IOS上什么都不起作用。在Chrome、Internet Explorer、Edge、Firefox和其他各种浏览器中都可以正常工作。但在Safari上的IOS上无法工作,坦率地说,我对此感到困惑。

如果我最终解决了这个问题,我会发布一个答案,但我必须说,这是我在20年的开发生涯中遇到的最难以理解的情况之一。

!!更新!!

终于解决了!经过长时间的压力,同事建议可能是Safari中的弹出窗口拦截器...他建议将其与单击绑定以证明概念。

就在那一刻,一个错误模态框自己弹了出来,这让我想到...等等 - 这是怎么回事。它不会在页面加载时发生!有延迟!

而且神奇的是 - 将展示功能包装在非常小的setTimeout函数(10ms)中解决了问题。

在我的情况下,我正在添加功能以复制Android PWA“添加到主屏幕”功能,以便在检测到设备为IOS并且PWA尚未在主屏幕上时,轻松提示用户添加它。


我在想这可能是原因。 OP:你/你之前用过Bootstrap吗? - ViniH

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接