我正在处理一个页面,其中包含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
时,它立即失败。我已经阅读了很长时间的文档但是我觉得我无处可去。任何帮助将不胜感激。
答案 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;
});
我认为这是一种更实用的方法,可以停止默认操作并阻止事件冒泡。