在扩展器中更新可观察的淘汰赛 js 时如何保留光标位置 [英] How To Retain Cursor Position When Updating A Knockout js Observable In An Extender

查看:16
本文介绍了在扩展器中更新可观察的淘汰赛 js 时如何保留光标位置的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

目标是在用户输入时将其转换为大写.我正在使用以下扩展程序:

The goal is to have user input converted to upper case as they type. I am using the following extender:

ko.extenders.uppercase = function (target, option) {
    target.subscribe(function (newValue) {
        target(newValue.toUpperCase());
    });
    return target;
};

这个扩展器可以添加到绑定到 HTML 文本框的 observable 中:

This extender can be added to the observable that are bound to HTML text boxes:

self.userField = ko.observable(product.userField || "").extend({ uppercase: true });

这很好用.将绑定到 observable 的文本转换为大写.当用户在空白字段中键入文本或将其添加到现有文本的末尾时,文本将转换为大写.

This works great. Converts text bound to the observable to upper case. As the user types text into an empty field or adds it to the end of existing text, the text is converted to upper case.

到目前为止,一切都很好!

So far, so good!

现在当用户想要插入文本时,使用光标键或鼠标将光标放置到插入点,然后输入新文本,字符以大写形式插入,但光标位置现在跳转到文本,因为底层 observable 已更新.

Now when the user wants to insert text, the cursor is placed to the insertion point either with the cursor keys or mouse and the new text is entered the character is inserted as upper case but the cursor position now jumps to the end of the text because the underlying observable is updated.

如何在将用户输入转换为大写的同时保留光标位置?

How can the cursor position be retained while still converting the user input to upper case?

更新 1:

我创建了一个自定义绑定,这样我就可以访问元素并获取和设置光标位置.我试图利用现有的 value 绑定优势.我正在使用内置的 ko.selectExtensions.writeValue 函数.这对我的应用程序来说可能已经足够了,但可能不适用于所有浏览器.

I created a custom binding so I could access the element and get and set the cursor position. I tried to tap into the existing value binding goodness. I am using the built in ko.selectExtensions.writeValue function. This may be good enough for my application but may not work in all browsers.

ko.bindingHandlers.upperCase = {
    init: function (element, valueAccessor, allBindings, viewModel, bindingContext) {
        ko.bindingHandlers["value"].init(element, valueAccessor, allBindings);
    },
    update: function (element, valueAccessor, allBindings, viewModel, bindingContext) {
        var caretPosition = getCaretPosition(element);
        var newValue = ko.utils.unwrapObservable(valueAccessor());
        ko.selectExtensions.writeValue(element, newValue.toUpperCase());

    setCaretPosition(element, caretPosition);

        // Code from: http://stackoverflow.com/questions/2897155/get-cursor-position-in-characters-within-a-text-input-field
        function getCaretPosition (ctrl) {
            var CaretPos = 0;

            // IE Support
            if (document.selection) {
                ctrl.focus ();
                var Sel = document.selection.createRange ();
                Sel.moveStart ('character', -ctrl.value.length);
                CaretPos = Sel.text.length;
            }
            // Firefox support
            else if (ctrl.selectionStart || ctrl.selectionStart == '0') {
                CaretPos = ctrl.selectionStart;
            }

            return (CaretPos);
        }

        function setCaretPosition(ctrl, pos) {
            if(ctrl.setSelectionRange) {
                ctrl.focus();
                ctrl.setSelectionRange(pos,pos);
            }
            else if (ctrl.createTextRange) {
                var range = ctrl.createTextRange();
                range.collapse(true);
                range.moveEnd('character', pos);
                range.moveStart('character', pos);
                range.select();
            }
        }
    }
};

推荐答案

好吧,我认为最好的解决方案是使用 Vanilla Javascript.检查值是否为大写,如果不是,获取位置,更改值,设置位置.很简单.

Well, i think the best solution is with Vanilla Javascript. Check the value is UpperCase if not, get position, change value, set position. Easy.

var stayUpperCase = function () {
  if(this.value != this.value.toUpperCase()){
    var caretPos = getCaretPosition(this);
    this.value = this.value.toUpperCase();
    setCaretPosition(this, caretPos);
  }
};
document.getElementById('myinput').addEventListener('keyup', stayUpperCase);
document.getElementById('myinput').addEventListener('change', stayUpperCase);

// Code from http://stackoverflow.com/questions/2897155/get-cursor-position-in-characters-within-a-text-input-field
function getCaretPosition (elem) {
  // Initialize
  var caretPos = 0;

  // IE Support
  if (document.selection) {
    // Set focus on the element
    elem.focus ();
    // To get cursor position, get empty selection range
    var sel = document.selection.createRange ();
    // Move selection start to 0 position
    sel.moveStart ('character', -elem.value.length);
    // The caret position is selection length
    caretPos = sel.text.length;
  }

  // Firefox support
  else if (elem.selectionStart || elem.selectionStart == '0'){
    caretPos = elem.selectionStart;
  }

  // Return results
  return (caretPos);
}

// Code from http://stackoverflow.com/questions/512528/set-cursor-position-in-html-textbox
function setCaretPosition(elem, caretPos) {
  if(elem != null) {
    if(elem.createTextRange) {
      var range = elem.createTextRange();
      range.move('character', caretPos);
      range.select();
    }
    else {
      if(elem.selectionStart) {
        elem.focus();
        elem.setSelectionRange(caretPos, caretPos);
      }
      else
        elem.focus();
    }
  }
}

<input type="text" id="myinput"/>

您可以附加更多键盘事件以使其看起来更流畅.

You can attach more keyboard events to make it looks smoother.

这篇关于在扩展器中更新可观察的淘汰赛 js 时如何保留光标位置的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆