Knockout具有焦点绑定,数字输入无法在Firefox上运行

时间:2016-06-13 13:51:36

标签: javascript firefox knockout.js

我有一个包含货币值的输入字段。我想在输入字段没有焦点时显示格式化的货币金额。输入字段类型设置为数字。虽然这适用于Chrome,IE和Edge;在Firefox上,输入文本框在获取后立即失去焦点。这是简化的jsfiddle

https://jsfiddle.net/nkkfmLmc/2/

这与http://knockoutjs.com/documentation/hasfocus-binding.html的示例2类似,但数字字段除外。如果我将输入类型从数字更改为文本(但也失去了所有的好处),问题就解决了。 任何指针或解决方法都将不胜感激。

HTML:

<p>
    Name: 
    <b data-bind="visible: !editing(), text: '$'+amount(), click: edit">&nbsp;</b>
    <input type="number" min="0" max="100" step="1" data-bind="visible: editing, value: amount, hasFocus: editing" />
</p>
<p><em>Click the amount to edit it; click elsewhere to apply changes.</em></p>

JS:

function PersonViewModel(amount) {
    // Data
    this.amount = ko.observable(amount);
    this.editing = ko.observable(false);

    // Behaviors
    this.edit = function() { this.editing(true) }
}

ko.applyBindings(new PersonViewModel(51.22));

2 个答案:

答案 0 :(得分:2)

hasFocus绑定与Document.activeElement一起使用以确定哪个元素是焦点:

来源:https://github.com/knockout/knockout/blob/master/src/binding/defaultBindings/hasfocus.js#L17

var ownerDoc = element.ownerDocument;
if ("activeElement" in ownerDoc) {
  var active;
  try {
    active = ownerDoc.activeElement;
  } catch (e) {
    // IE9 throws if you access activeElement during page load (see issue #703)
    active = ownerDoc.body;
  }
  isFocused = (active === element);
}

当您在小提琴中单步执行此绑定时,我注意到它会将body元素作为文档的activeElement返回,使isFocused成为false

在关于activeElement的{​​{3}}页面上,我读到了:

  

注意:在Mac上,不是文本输入元素的元素往往不会将焦点分配给它们。

对我而言,这表明在number输入中根本不支持此绑定。

我建议:

  • 坚持使用文本输入并添加自定义向上和向下按钮以及键侦听器
  • 创建一个基于事件侦听器的自定义绑定,而不是document.activeElement

淘汰赛开发者可能有充分的理由坚持使用activeElement方法。他们在评论中说:

// Where possible, ignore which event was raised and determine focus state using activeElement,
// as this avoids phantom focus/blur events raised when changing tabs in modern browsers.
// However, not all KO-targeted browsers (Firefox 2) support activeElement. For those browsers,
// prevent a loss of focus when changing tabs/windows by setting a flag that prevents hasfocus
// from calling 'blur()' on the element when it loses focus.
// Discussion at https://github.com/SteveSanderson/knockout/pull/352

因此,选择第一个选项可能是明智的......

答案 1 :(得分:0)

通过使用额外的observable控制可见性并为控制焦点的observable添加一个限制来实现它。 看起来在元素变得可见之前发生了hasFocus绑定检查。

https://jsfiddle.net/nkkfmLmc/8/

JS:

<p>
    Name: 
    <b data-bind="visible: !editingWrapper(), text: '$'+amount(), click: edit">&nbsp;</b>
    <input type="number" min="0" max="100" step="1" data-bind="visible: editingWrapper, value: amount, hasFocus: editing" />
</p>
<p><em>Click the amount to edit it; click elsewhere to apply changes.</em></p>

HTML:

function PersonViewModel(amount) {
    // Data
    var self = this;
    this.amount = ko.observable(amount);
    this.editing = ko.observable(false).extend({throttle:200});
    this.editingWrapper = ko.observable(false);

    // Behaviors
    this.edit = function() { self.editingWrapper(true);self.editing(true); }

    this.editing.subscribe(function(newVal){
        self.editingWrapper(newVal);
    })
}

ko.applyBindings(new PersonViewModel(51.22));
相关问题