目标是在用户输入键入时将其转换为大写。我使用以下扩展程序:
ko.extenders.uppercase = function (target, option) {
target.subscribe(function (newValue) {
target(newValue.toUpperCase());
});
return target;
};
可以将此扩展程序添加到绑定到HTML文本框的observable:
self.userField = ko.observable(product.userField || "").extend({ uppercase: true });
这很有效。将绑定到observable的文本转换为大写。当用户将文本键入空字段或将其添加到现有文本的末尾时,文本将转换为大写。
到目前为止,非常好!
现在,当用户想要插入文本时,光标将被放置到插入点,或者使用光标键或鼠标,并且输入新文本,字符将作为大写插入,但光标位置现在跳转到结束文本,因为底层的observable已更新。
如何在将用户输入转换为大写的同时保留光标位置?
更新1:
我创建了一个自定义绑定,因此我可以访问该元素并获取并设置光标位置。我试图利用现有的value
绑定优点。我正在使用内置的ko.selectExtensions.writeValue
函数。这可能对我的应用程序来说足够好,但可能无法在所有浏览器中使用。
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();
}
}
}
};
答案 0 :(得分:3)
在测试了自定义绑定和Thanasis Grammatopoulos发布的基于jQuery的解决方案之后,我决定采用CSS路线并首先创建了一个新类:
.upper-case {
text-transform: uppercase;
}
然后我将它应用于我想要显示为大写的输入元素:
<input type="text" maxlength="16" class="upper-case" data-bind="value: fhaNum, valueUpdate: 'afterkeydown', disable: isReadOnly" />
由于这不会将文本保存为observable中的大写,因此我在将值发送到服务器之前将其设置为高位:
var data = {
"fhaNum": self.fhaNum().toUpperCase()
};
答案 1 :(得分:1)
嗯,我认为最好的解决方案是使用Vanilla Javascript。如果没有,检查值是否为UpperCase,获取位置,更改值,设置位置。容易。
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();
}
}
}
&#13;
<input type="text" id="myinput"/>
&#13;
您可以附加更多键盘事件,使其看起来更流畅。