Marionette ItemView事件处理与Bootstrap下拉列表冲突

时间:2015-04-24 18:58:08

标签: javascript jquery twitter-bootstrap twitter-bootstrap-3 marionette

我有一个创建表的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)
        }
    }, 

3 个答案:

答案 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。