【问题标题】:using hasFocus binding on table or div element在 table 或 div 元素上使用 hasFocus 绑定
【发布时间】:2015-11-17 15:28:42
【问题描述】:

所以基本上我有这个输入文本框:

 <input id="usersInputField" data-bind="hasFocus: isSearchInputFocused"/>

只要输入字段有焦点,就会弹出一个表格:

<div data-bind="visible: isSearchInputFocused">
   <table>
       <tbody data-bind="foreach: usersFromSearch">
           <!-- some info -->
       </tbody>
   </table>
</div>

...效果很好。虽然,我希望表格保持可见,以防用户也点击 div。

代替表绑定中的isSearchInputFocused observable,我尝试使用ko.computed observable,如果文本框或用户表被聚焦并在其上添加hasFocus 绑定,则返回true,但这并没有似乎不起作用。我假设hasFocus 绑定优先于click 绑定。

如何在表格或输入具有焦点时保持 div 打开?

【问题讨论】:

    标签: javascript jquery html knockout.js


    【解决方案1】:

    默认情况下,表格是不可聚焦的,因此您的第一个想法不会奏效。但是,如果添加tabindex 属性,则可以安全地将焦点设置在表格上。因此,如果你这样做,你可以为每个元素使用一个可观察的焦点,并使用一个计算来确定它们中的任何一个是否被聚焦以保持 div 可见。

    var vm = {
      inputHasFocus: ko.observable(),
      tableHasFocus: ko.observable(),
    };
    
    // Don't take completing a model like this as a good practice:
    vm.somethingHasFocus = ko.pureComputed(function() {
      var inputHasFocus = vm.inputHasFocus(); // ensures subscription
      var tableHasFocus = vm.tableHasFocus(); // ensures subscription
      return  inputHasFocus || tableHasFocus;
    }, vm);
    
    ko.applyBindings(vm);
    
    // IE Hack
    $('table *').on('click', function() { vm.tablehasFocus(true); })
    table {
      border: solid 1px black;
      border-collapse: true;
      width: 80%;
      margin: 20px 0;
    }
    
    *:focus {
      border-color: #FF0000;
      box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 8px rgba(255, 0, 0, 0.6);
      outline: none;
    }
    
    div {
      background-color: silver;
      margin: 20px 0;
    }
    <script src="https://cdnjs.cloudflare.com/ajax/libs/knockout/3.2.0/knockout-min.js"></script>
    <script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
    
    <input tabindex="0" type="text" data-bind="hasFocus: inputHasFocus"/>
    
    
    <table tabindex="1" data-bind="hasFocus: tableHasFocus">
      <tr>
        <td>I'm a table cell</td>
        <td>I'm another</td>
      <tr>
    </table>
    
    <div data-bind='visible: inputHasFocus'>Input has focus</div>
    <div data-bind='visible: tableHasFocus'>Table has focus</div>
    <div data-bind='visible: somethingHasFocus'>Something has focus</div>

    注意:像往常一样,IE 有一个奇怪的行为:至少 IE10 允许专注于表格单元格。脚本中包含的解决方案是 hack。有更聪明的选择:

    • 创建一个自定义绑定elementOrDescendantHasFocus,应该不会太难:可以使用委托事件处理来检测table或者children中的焦点事件
    • 为每个表格单元格创建一个 hasFocus 数组,以及一个依赖于它们的计算(我宁愿实现 hack)
    • 通过向单元格添加负的tabindex 属性使单元格无法聚焦

    因此,如果您必须支持 IE(至少 IE10),请选择这些解决方案中的任何一个,包括 hack。在 Chrome 和 Firefox 中没有这样的问题

    【讨论】:

    • 非常感谢您的所有回答!我决定使用这个,因为只有在表格本身或输入字段聚焦时表格才保持可见。我刚刚在我的 div 上添加了“ data-bind='visible: inputHasFocus() || tableHasFocus()' ”,现在就像一个魅力!干杯!
    • 很高兴它对你有用。但是,在绑定中包含表达式“是基于”的;)您宁愿创建一个依赖于这两个属性的 pureComputed,并在绑定中使用它。如果您很快习惯于在视图模型中制作这些东西,那么您将来不会有做复杂绑定的诱惑。而且我可以保证,当您开始使用复杂的绑定时,事情会变得复杂。此外,您无法像使用计算的 viemodel 一样轻松地调试它们。
    • 我发现IE10有问题。我已经更新了答案
    • 是的!我还需要IE支持。我首先尝试了破解,但我得到一个“对象不支持属性或方法”tableHasFocus“。负面的 tabindex 解决方案也没有对我有用。而且我还没有进入自定义绑定。所以我实现了'hasFocus on each cell'方法。非常感谢!我欠你的债:)
    • 我的错。我在使用 IE hack 时打错字了!
    【解决方案2】:

    如果您想这样做,请注意,但您可以这样做,以便表格在输入的焦点上打开并保持打开状态,直到您关闭它。

    // Here's my data model
    var ViewModel = function() {
        var self = this;
        
        self.focusMePlease = ko.observable(false);
        self.focusMePlease.subscribe(function() {
        	if (self.focusMePlease() == true) {
            	self.isSearchInputFocused(true);
            }
        });
        self.isSearchInputFocused = ko.observable(false);
        
        self.close = function() {
        	self.isSearchInputFocused(false);
        };
        
    };
     
    ko.applyBindings(new ViewModel());
    td {
        border: 1px solid black;
        padding: 5px;
    }
    <script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/knockout/3.1.0/knockout-min.js"></script><input id="usersInputField" data-bind="hasFocus: focusMePlease"/>
    <br/><br/>
    <div data-bind="visible: isSearchInputFocused">
       <table>
           <tr><td>stuff</td><td>stuff</td></tr>
       </table>
        <button data-bind="click: close">X</button>
    </div>

    【讨论】:

      【解决方案3】:

      也许你可以使用焦点事件来解决这个问题,比如下面的例子:

      http://jsbin.com/jewozilofe/edit?html,js,output

      【讨论】:

        猜你喜欢
        • 2012-01-14
        • 2017-01-03
        • 1970-01-01
        • 2014-01-05
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2013-11-09
        相关资源
        最近更新 更多