【问题标题】:A better way of keeping track of cursor position in a text-field while auto-correcting?在自动更正时跟踪文本字段中光标位置的更好方法?
【发布时间】:2012-09-30 15:22:10
【问题描述】:

我正在开发一个 jQuery 插件,用于实时(自动更正)将拉丁字符转换为日文假名符号 (live example),如果我输入的速度不是太快,它可以正常工作。这是个问题.

例如:

wakarimasu -> わかります

但是,当我以正常速度打字时,我得到了这个:

wakarimasu -> わかりあすm(实际上是 wakariasum,光标在最后“す”和“m”之间)

如果我不输入“su”,我会得到:

wakarima -> わかりあm(实际上是 wakariam,光标在最后“あ”和“m”之间)

我知道为什么以及如何发生这种情况。基本上,“ri - り”符号仍在从拉丁文转换为日文假名,而我已经输入了“m”并且它在我设法输入“a”之前完成了一点点。因为我的函数在每次转换后定位光标,它将光标定位在“ri”和“m”之间,这就是我的“a”结束的地方。

其他词也会出现这种情况,但我以这个为例。

有没有一种方法可以更智能地跟踪光标位置,或者有没有一种方法可以只更新/转换/替换部分文本字段而不更新整个文本字段(它现在的工作方式是获取文本字段,在函数内部的变量中用假名替换拉丁文,用变量中的新字符串更新文本字段,然后定位光标)?告诉访问者不要打字太快并不是真正要走的路..

图例:wa=わ ka=か ri=り ma=ま su=す a=あ

可以在我提供的链接中查看源代码。谢谢。

编辑:要考虑的另一件事是用户可能会左右移动光标以添加或删除字符/符号。这会使定位有点复杂,但目前可以。

【问题讨论】:

  • 尝试将用户输入存储在数据属性中,这样您每次都可以正确转换它,因为您知道整个上下文
  • 复制粘贴也行不通,但解决这个问题会大很多。
  • @howderek - 是的,但我打算稍后在人们应该输入内容的地方使用它,而不是 c/p 它只是想将它作为插件共享,也许有人可能会觉得它有用。
  • 不,别误会,我认为它很棒,我只是指出它要么需要更多代码,要么只适用于某些情况。
  • @howderek 是的,我同意 :) thnx

标签: javascript performance algorithm optimization autocorrect


【解决方案1】:
function translateWord( textarea, oldText, newText ) {
  var ctpos   = getCaretPosition( textarea );

  var textStr = textarea.value;

  var oldTextLen  = oldText.split("").length;
  var newTextLen  = newText.split("").length;

  var txtDiffLen  = ( newTextLen - oldTextLen );

  var escText = oldText.replace( /([()\[\]\\\/+*?.-])/g, "\\$1" );
  var regExpr = new RegExp( "\\b"+escText+"\\b", 'gi' );
  var diffStr = textStr.match( regExpr );
      diffStr = ( diffStr ) ? diffStr.length : 1;

  var newStr  = textStr.replace( regExpr, newText );
      ctpos   = ( ctpos + ( txtDiffLen * diffStr ) );

  textarea.value = newStr;
  setCaretPosition( textarea, ctpos );
}

function getCaretPosition( textarea ) {
  if ( textarea.selectionStart ) {
    return textarea.selectionStart;
  }
  else if ( !document.selection ) {
    return 0;
  }

  var c   = "\001",
      sel = document.selection.createRange(),
      dul = sel.duplicate(),
      len = 0;

  dul.moveToElementText( textarea );
  sel.text  = c;
  len = dul.text.indexOf( c );
  sel.moveStart( 'character', -1 );
  sel.text  = "";
  return len;
}

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

translateWord( document.getElementById('text-input'), 'wakarimasu', 'わかります' );

我知道这是一个老问题,但这段代码会帮助像我这样的菜鸟:) 来自其他答案的混合功能:)

【讨论】:

    【解决方案2】:

    为了结束这个,我设法弄清楚问题实际上是第三个字符(在这种情况下为“m”)进入了与“ri”相同的 .keyup 迭代,而不是像我之前认为的那样在它之后(相同的症状,但不同的原因)..

    为了解决这个问题,我只是修改了 .keyup 代码,在偏移量上添加 +1,以便在转换后字符串中还剩下拉丁(罗马字)字符时将光标向右移动一个位置。

    【讨论】:

      猜你喜欢
      • 2011-01-27
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2017-04-16
      • 1970-01-01
      • 2010-12-20
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多