我有一个创建表的Composite视图,其中childView集合显示每一行。在每行的末尾是一个基于Bootstrap的按钮下拉列表。 单击该行将打开一个模态(工作),但单击按钮下拉列表时仍会触发该事件,因此模式显示AND下方的下拉列表。
如何防止按钮上的点击向下传播到行点击事件,而不会阻止Bootstrap挂钩被切断?
处理这些类型的特殊点击事件的标准方法(在我的研究和书籍阅读中),对返回的jquery事件使用e.stopPropagation()
,以防止事件进一步发展,但是这会阻止Bootstrap触发下拉开启事件。
如果在单击buttongroup时仍然调用stopPropagation(),则使用事件对象的currentTarget对象并手动切换类,我可以让下拉列表打开而不会发生冲突,但是因为关闭按钮触发了4层下来,我会有蛮力&拨打.parent()4次以切换课程,这听起来不太可持续或不便携。
如何进行行单击操作并使用Bootstrap的内置切换功能打开和关闭下拉列表?
ItemView控件
Show.Result = Marionette.ItemView.extend({
tagName:"tr",
template: "#row-template",
events:{
"click .js-delete-result": "editRow",
"click .js-edit-result": "deleteRow",
"click div.btn-group button": "openSettings"
"click": "rowClicked",
},
editRow: function(e){e.stopPropagation();alert("you trying to delete bro?!")},
deleteRow: function(e){e.stopPropagation();alert("you trying to edit bro?!")},
openSettings: function(e){
//e.stopPropagation()
//$(e.currentTarget).parent().toggleClass('open')
//e.currentTarget.button('toggle');
},
rowClicked:function(e){
e.preventDefault()
this.trigger("show:result",this)
},
}
模板
<script id="row-template">
<td class="vert-align"><%= value %></td>
<td class="vert-align"><%= notes %></td>
<td class="vert-align">
<div class="btn-group">
<button class="btn btn-xs btn-default dropdown-toggle" aria-haspopup="true" data-toggle="dropdown" aria-expanded="false">
<span class="glyphicon glyphicon-edit"/>
</button>
<ul class="dropdown-menu" role="menu">
<li><a href="#" class="js-edit-result">Edit</a></li>
<li><a href="#" class="js-delete-result"> Delete <i class= "glyphicon glyphicon-trash"/></a></li>
</ul>
</div>
</td>
</script>
随意的想法:也许我以错误的方式思考问题,而应该找到一个更好的CSS / jQuery选择器来覆盖除按钮组之外的所有选项;有没有&#39;没有&#39;选择器与CSS?
修改
我尝试更改"click": "rowClicked",
通用点击处理程序,以使用&#39; not&#39; css选择器; "click :not(div.btn-group *)": "rowClicked"
,但没有任何效果;单击按钮时,它仍会打开模型。经过更多的研究,我意识到我的非选择器没有被正确地格式化/使用,但这可能是很大的,因为我试图以一种它没有用的方式使用它。
编辑2:
我终于能够阻止传播(排序),但在此过程中发现正在生成两个单独的点击。 我不知道为什么。这是因为事件传播永远不会停止,并且会向下传播到根HTML元素,在本例中为TR。
更改通用点击功能以检查点击的目标是什么,以及每次点击时它的祖先是否包含.btn-group
类,但仅限于按钮本身;如果你只点击该行,那么它只会触发一次。
如何在正确的项目上阻止此传播/设置事件侦听器?
rowClicked:function(e){
e.preventDefault()
console.log("I get called twice?!")
if($(e.target).parents('.btn-group').length > 0){
//do nothing
}
else{
e.stopPropagation()
this.trigger("show:result",this)
}
},
答案 0 :(得分:0)
只是一个想法,没有经过测试。你在按钮的父母身上停止传播的内容是什么?例如 def decoded_symbol
@input.map! do |symbols|
if @symbols.include?(symbols)
symbols = " "
else
symbols = symbols
end
end
@input.join # Here
end
?它不应该干扰默认的引导行为,但它会阻止它冒泡到行本身。
答案 1 :(得分:0)
试试这个;
rowClicked:function(e){
if($(e.currentTarget).is('td')){ //or e.target will also do
this.trigger("show:result",this);
}
},
答案 2 :(得分:0)
经过大量谷歌搜索和测试我的代码后,我认为这可能是目前最好的方法。它并没有真正解决我的问题的核心,但由于一般的点击事件处理程序在引导程序到达之前插入自身,将点击的焦点更改为更具体的内容似乎已经成功了。
感谢@Pawan
和@squall3d
这方面的一些指示,但我仍然在寻找如何更好地传播/设置/控制事件侦听器以避免与其他库发生冲突的答案将来
但是,为了让它现在正常运行,我将通用点击更改为"click td": "rowClicked"
。 td
几乎是基础层,但具体到足以使其不会干扰按钮事件。我不再需要按钮单击处理程序,(我们希望引导程序执行此操作),因此删除了: "click div.btn-group button": "openSettings"
Show.Result = Marionette.ItemView.extend({
tagName:"tr",
template: "#row-template",
events:{
"click .js-delete-result": "editRow",
"click .js-edit-result": "deleteRow",
"click td": "rowClicked",
},
editRow: function(e){e.stopPropagation();alert("you trying to delete bro?!")},
deleteRow: function(e){e.stopPropagation();alert("you trying to edit bro?!")},
rowClicked:function(e){
e.preventDefault()
this.trigger("show:result",this)
},
}
值得注意的是,我 在rowClicked函数中添加了其他代码,以防止在显示按钮下拉列表时打开模式,并且在下拉列表外单击时意外地单击了一行关闭它。我发现这是一个更好的用户体验。
rowClicked:function(e){
if($("#edit-btn").hasClass("open")){
//also do nothing - the dropdown is open
}
else{
e.stopPropagation()
e.preventDefault()
this.trigger("show:result",this)
}
}
并在btn-group中为jquery选择添加了一个id
<div class="btn-group" id="edit-btn">
这是有效的,因为Bootstrap添加了一个.open
css类来触发显示下拉列表html。