【问题标题】:Can I conditionally change the character entered into an input on keypress?我可以有条件地更改按键输入的字符吗?
【发布时间】:2010-10-13 11:24:58
【问题描述】:

是否可以不手动更改按键输入的字符?

例如,如果我想根据某些条件强制使用大写字母,最好执行以下操作:

function onKeypressHandler(e)
{
    if ( condition )
    {
        e.which -= 32;
    }
}

但这当然行不通。

注意:不是全面大写,而是特定字符。

也许我想说if ( e.which >= 97 && e.which <= 102 )if ( Wind.Direction == 'South' ) 或其他 - 条件本身并不重要,但大写必须只适用于当前字符而不是整个输入。


我可以通过手动附加更改的字符来做到这一点,但这是一种丑陋而混乱的做法,而且可能比它可能的要慢。

function onKeypressHandler(e)
{
    if ( condition )
    {
        $j(this).val( $j(this).val() + String.fromCharCode( e.which - 32 ) );
        return false;
    }
}

此方法的一个特定缺陷 - 如果选择所有输入文本并输入一个键,如果它掉入其中,那么它不会删除现有内容,而只是附加到用户想要删除的内容。 (需要调查检测任何选定的文本来解决这个问题,这使得这个更难看。)

谁能提供更好的解决方案?

【问题讨论】:

  • 您将如何处理粘贴、撤消/重做、拖放或其他同时输入多个字符的情况,或者这不重要吗?
  • 安迪,这在这里不是很重要,但仍然很有用 - 我想它必须涉及在 onchange 事件中手动遍历字符串?
  • oninputonpropertychange 事件。不久前我在我的博客上概述了这些 - whattheheadsaid.com/2010/09/… 并且我有一个几乎完整的 jQuery 插件正在开发中。

标签: javascript jquery keypress


【解决方案1】:

以下将完成这项工作。它基于an answer I wrote to another question。自定义transformTypedChar功能以满足您的需求;我的示例仅将字母 a-g 大写。

如果您需要在 textarea 而不是 <input type="text"> 上使用它,请注意 IE Is there an Internet Explorer approved substitute for selectionStart and selectionEnd?

function transformTypedChar(charStr) {
    return /[a-g]/.test(charStr) ? charStr.toUpperCase() : charStr;
}

document.getElementById("your_input_id").onkeypress = function(evt) {
    var val = this.value;
    evt = evt || window.event;

    // Ensure we only handle printable keys, excluding enter and space
    var charCode = typeof evt.which == "number" ? evt.which : evt.keyCode;
    if (charCode && charCode > 32) {
        var keyChar = String.fromCharCode(charCode);

        // Transform typed character
        var mappedChar = transformTypedChar(keyChar);

        var start, end;
        if (typeof this.selectionStart == "number" && typeof this.selectionEnd == "number") {
            // Non-IE browsers and IE 9
            start = this.selectionStart;
            end = this.selectionEnd;
            this.value = val.slice(0, start) + mappedChar + val.slice(end);

            // Move the caret
            this.selectionStart = this.selectionEnd = start + 1;
        } else if (document.selection && document.selection.createRange) {
            // For IE up to version 8
            var selectionRange = document.selection.createRange();
            var textInputRange = this.createTextRange();
            var precedingRange = this.createTextRange();
            var bookmark = selectionRange.getBookmark();
            textInputRange.moveToBookmark(bookmark);
            precedingRange.setEndPoint("EndToStart", textInputRange);
            start = precedingRange.text.length;
            end = start + selectionRange.text.length;

            this.value = val.slice(0, start) + mappedChar + val.slice(end);
            start++;

            // Move the caret
            textInputRange = this.createTextRange();
            textInputRange.collapse(true);
            textInputRange.move("character", start - (this.value.slice(0, start).split("\r\n").length - 1));
            textInputRange.select();
        }

        return false;
    }
};

【讨论】:

  • 谢谢蒂姆,看起来它也在处理我刚刚发现的新文本选择问题。会尝试一下,看看效果如何。
  • 好的。我刚刚添加了一个关于在 textareas 中使用它的注释。
【解决方案2】:

阻止默认操作然后触发按键怎么样?类似的,

function onKeypressHandler(e)
{
    if ( condition )
    {
        e.preventDefault();
        // create new event object (you may clone current e)
        var ne = new jQuery.Event("keypress");
        ne.which = e.which - 32;
        $(e.target).trigger(ne);   // you may have to invoke with setTimeout
    }
}

【讨论】:

  • 行不通。您无法在浏览器中模拟按键的效果。
  • 噢!在我看到蒂姆的评论之前,这似乎很有希望。无论如何都是好主意。 :(
  • @Tim,感谢您的信息。顺便说一句,来自 jquery docs 的示例使用 .keypress() 来触发事件。那么在这种情况下会发生什么 - 只有事件处理程序在没有控制接收字符的情况下被调用?
  • @VinayC:你能发布 jQuery 文档链接吗?很可能模拟一个按键事件,以便它在特定元素上触发(我没有尝试这样做),但它不会执行通常的浏览器操作(例如使字符出现在输入中)。
  • @Tim - 这是链接:api.jquery.com/keypress。它使用 keypress() 来触发事件处理程序。该示例未在输入中输入任何字符,但未指定任何事件对象。
【解决方案3】:

你必须看到这个.. 让它工作后我对自己很满意..

您显然希望包含足够的标准以避免在此处陷入循环。

当条件评估为真时,下面的代码返回假,但它使用不同的 charCode 触发相同的事件,不会返回假。

document.getElementById("input1").onkeypress = Handler;
function Handler(e)
{
    e = e || window.event;
    if ( e.charCode == 97 )
    {
        var evt = document.createEvent("KeyboardEvent");
        evt.initKeyEvent("keypress",true, true, window, false, false,false, false, 0, e.charCode -32);
        this.dispatchEvent(evt);
        return false;
    }
    return true;
}

你可以在 IE 中使用 fireEvent... 我用了 http://help.dottoro.com/ljrinokx.phphttps://developer.mozilla.org/en/DOM/event.initKeyEvent供参考

【讨论】:

  • 有趣。但是,这只适用于 Mozilla。幸运的是,它的范围似乎有限:尝试触发诸如 Ctrl-B(用于书签)、Ctrl-A(全选)之类的键盘快捷键不起作用。不过我不知道你能做到这么多。
  • 不完全是.. IE 也支持触发事件.. 代替 dispatchEvent,您使用 fireEvent 并创建事件,您使用 object.createEventObject。见help.dottoro.com/ljhlvomw.php。我在 Linux 上,所以无法帮助您进行代码/测试。但这似乎可行
  • 该链接中似乎已经提供了跨浏览器鼠标事件处理的代码。
  • 我已经测试了 IE 版本,虽然它正确触发了一个新事件,但它并没有执行相关的浏览器行为,例如在输入中插入一个字符。
  • 我还在Chrome、Safari和Opera的最新版本中测试了原始代码,结果相同。这意味着在主流浏览器中,您的方法仅适用于 Firefox。
【解决方案4】:

不太确定你想要什么,但这会奏效吗?

$('#my_element').keyup(function(){ $(this).val().toUpperCase(); });

或使用子字符串来按下最后一个字符并在上面执行toUpperCase()

(psst...您也可以使用 keydown 或 keypress)。

【讨论】:

  • 再说一次,这不是有条件的,toUpperCase 并不是对 String.fromCharCode() 方法的真正改进。
  • 条件是什么意思?
  • 我已经更新了问题以澄清 - 我只想(也许)大写当前字符,而不是整个字符串 - 如果我大写它取决于 if 条件(精确检查并不重要问题)。
【解决方案5】:

你会用css吗?

<input type="text" style="text-transform: uppercase;" />

【讨论】:

  • 这不会改变实际输入值,更重要的是不会有条件地应用。
  • 在处理提交的值时能否将a转为大写?有条件是什么意思?
  • 我已经更新了问题以澄清 - 我只想(也许)大写当前字符,而不是整个字符串 - 如果我大写它取决于 if 条件(精确检查并不重要问题)。
【解决方案6】:

彼得,

您可能会在这里找到一些灵感:

http://www.maconstateit.net/tutorials/JSDHTML/JSDHTML15/jsdhtml15-05.htm

基本上围绕着各种方式来查看该“区域”周围的按键事件和功能。

【讨论】:

    猜你喜欢
    • 2011-01-05
    • 1970-01-01
    • 1970-01-01
    • 2017-08-21
    • 1970-01-01
    • 2019-07-26
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多