Ajax请求成功但无论如何都继续到目标URL

时间:2014-05-01 16:00:53

标签: javascript jquery ajax jquery-masonry masonry

我正在处理一个页面,其中包含div中的各种Youtube视频缩略图,其中每个<img>都附有链接,并且容器上有Masonry来控制类切换以调整所选视频的大小。

我们的想法是点击div,这会触发砌体更改CSS,并触发{django .ajax()请求,该请求会返回所选视频的模板。 (当您再次选择它以返回缩略图模板并使用Masonry重置为正常时,将执行相反的操作)。

目前我有两个javascript函数,一个触发div上的砌体,然后另一个触发视频链接上的ajax请求;

<script>
(function($) {
    $(document).ready(function() {
        var container = $('.masonry'), masonry;
        //masonry = new Masonry(container[0]);
        container.masonry('stamp', container.find('.stamp'));

        container.unbind('click').on('click', '.item', function() {
            var $this = $(this),
                this_link = $this.find('a'),
                $this_link = $(this_link),
                this_href = $this_link.attr('href'),
                video_id = $this.attr('data-video-id'),
                gigante = $this.hasClass('gigante'),
                selector = 'div#panel-area.video_grid div.masonry div.item.' + video_id;

            $.ajax({
                type: "GET",
                async: false,
                url: this_href,
                timeout: 5000,
                data: {'g': gigante},
                dataType: 'html',
                success : function(data) {
                    $(selector).html(data);
                    container.find('.item').removeClass('gigante');
                    $(this).toggleClass('gigante', !gigante);
                    container.masonry();
                    console.log('Selector: ' + selector + '\nSuccess');
                }
            })
            .done(function(msg){
                console.log('Done: ' + msg);
            })
            .fail(function(jqXHR, textStatus){
                console.log('Failed: ' + textStatus);
            });

        });
    });
})(jQuery);    </script>

HTML;

<div class="masonry js-masonry" data-masonry-options='{ "stamp": ".stamp", "isOriginLeft": false }'>
    <div class="mpus stamp">            
    </div>
    <div class="item video {{ object.id }}" data-video-id="{{ object.id }}">
        <a class="GetYoutubeVideo" href="{% url 'show_video' video_id=object.id %}">
            <i class="icon-play-circled play"></i>

            <span class="title">
                {{ object.get_title|slice:":20" }}...<br/>
                {{ object.date_created|date:"d/m/Y" }}
            </span>
            {{ object.get_img_tag }}
        </a>
    </div>
</div>

我本质上是一个javascript新手,所以我确信这是一个非常基本的问题。当我通过禁用async的chrome dev工具运行此操作时,我看到ajax请求返回预期的内容,但最终会在目标页面上结束,而不是按预期将内容加载到$(selector)。 当我启用async时,它立即失败。我已经阅读了很长时间的文档但是我觉得我无处可去。任何帮助将不胜感激。

3 个答案:

答案 0 :(得分:3)

要避免默认点击操作,请按以下步骤修改点击处理程序:

.on('click', '.item', function(e) {
    var ...

    e.preventDefault();

    $.ajax({

        ...
    )}

    ...
})

e添加到点击处理函数意味着事件详细信息在函数中可用 - 在e对象上运行preventDefault()方法,以防止发生默认操作 - 对于例如,超链接将不再导航到其目标。

事件通常以下列方式发生,但这不是一个深入的总结:

点击事件发生在a元素上。

click事件开始搜索事件处理程序。如果在导致该元素的元素上找不到,那么该事件将会“冒泡”。在DOM树上,一次一个级别,直到它到达根DOM元素并且不能再进一步,或者找到点击处理程序。

在任何时候,如果找到单击处理程序,则执行单击处理程序中的代码。如果点击处理程序在事件对象上设置preventDefault(),或者返回false,则不会采取进一步操作。

如果点击处理程序既不返回false也不设置preventDefault(),那么除了您自己的事件处理程序之外,还将执行原始浏览器默认操作。

您的代码完整修改:

<script>
(function($) {
    $(document).ready(function() {
        var container = $('.masonry'), masonry;
        //masonry = new Masonry(container[0]);
        container.masonry('stamp', container.find('.stamp'));

        container.unbind('click').on('click', '.item', function(e) {
            var $this = $(this),
                this_link = $this.find('a'),
                $this_link = $(this_link),
                this_href = $this_link.attr('href'),
                video_id = $this.attr('data-video-id'),
                gigante = $this.hasClass('gigante'),
                selector = 'div#panel-area.video_grid div.masonry div.item.' + video_id;

            e.preventDefault();

            $.ajax({
                type: "GET",
                async: false,
                url: this_href,
                timeout: 5000,
                data: {'g': gigante},
                dataType: 'html',
                success : function(data) {
                    $(selector).html(data);
                    container.find('.item').removeClass('gigante');
                    $(this).toggleClass('gigante', !gigante);
                    container.masonry();
                    console.log('Selector: ' + selector + '\nSuccess');
                }
            })
            .done(function(msg){
                console.log('Done: ' + msg);
            })
            .fail(function(jqXHR, textStatus){
                console.log('Failed: ' + textStatus);
            });

        });
    });
})(jQuery);
</script>

答案 1 :(得分:1)

如果您不希望它直接转到该网址,那么在您的href元素上设置正常的<a>属性是否有意义?

不要试图变得聪明,只是询问是否有特定原因。

因为问题在于您的<a>元素仍然在执行其正常的&#39;职责,即改变页面。我可以看到你在稍后阶段通过jQuery检索该URL,但这不重要。

将您使用的属性更改为非href:

<a class="GetYoutubeVideo" href="#" data-custom-url="{% url 'show_video' video_id=object.id %}">

当您需要检索该值时,只需使用该新属性名称:

this_href = $this_link.attr('data-custom-url')

请注意,如果您需要砌筑的href属性,我不能100%确定。从我在代码示例中看到的内容来看,只要您能够从属性(非具体的href)中检索值,就无所谓了。

如果不使用href属性,您需要确保<a>元素在点击时没有实际的URL引用。

这是一个可接受的解决方案/解决方法吗?

答案 2 :(得分:1)

您只需在点击事件回调中返回false:

container.unbind('click').on('click', '.item', function() {
    ...
    #ajax
    ...
    return false;
});

我认为这是一种更实用的方法,可以停止默认操作并阻止事件冒泡。