1

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

这个想法是div点击,这会触发砌体来更改 CSS 并触发.ajax()对 django 的请求,该请求会返回所选视频的模板。(当您再次选择它以返回缩略图模板并使用 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 开发工具运行它时,我看到 ajax 请求返回预期的内容,但最终最终出现在目标页面上,而不是$(selector)按预期加载内容。当我启用async它时,它会立即失败。我已经阅读文档很长时间了,但我觉得我没有取得任何进展。任何帮助,将不胜感激。

4

3 回答 3

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>
于 2014-05-06T10:15:21.677 回答
1

您可以简单地在单击事件回调中返回 false:

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

我相信这是停止默认操作并防止事件冒泡的更实用的方法。

于 2014-05-09T04:08:39.893 回答
1

如果您不希望它实际直接转到该 URL,是否有必要在您的元素上设置功能href属性?<a>

不是想聪明,只是问是否有特定的原因。

因为问题在于您的<a>元素仍在执行其“正常”职责,即更改页面。我可以看到您在稍后阶段通过 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')

请注意,我不是 100% 确定您是否需要砖石的 href 属性。从我从您的代码示例中可以看出,只要您能够从属性(而不是特别是 href)中检索值,这并不重要。

通过不使用 href 属性,您可以确保您的<a>元素在被点击时没有可引用的实际 URL。

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

于 2014-05-06T10:43:37.657 回答