如何在不将光标位置移至末尾的情况下更改输入值?

huangapple go评论61阅读模式
英文:

How to change the value of input without the position of cursor going to the end?

问题

The newest question: can you give another more robust or succinct solution that can exactly accomplish the same goal as I described?

这是我的代码,存在一些问题。我想要将每五个字母分开,用空格隔开。

如果在输入的末尾输入或删除,它会表现得很好,但是如果在输入的末尾之外输入或删除,光标会自动移到末尾。

例如,文本框现在有ABCDE FGHJK。如果我删除A,光标会在删除A后移到末尾。

如何修复这个代码以防止这种情况发生?(它应该只包括原始的JavaScript代码,但不包括CSS、HTML代码或Jquery。)

我尝试过重新定位cursorPosition,但它不起作用...

如果可能的话,我希望代码尽可能简洁

请记住,目标是尽可能地使输入更方便

一些示例(|代表光标):

原始输入 操作 操作前的结果 操作后的结果 光标位置相同
`ABCD E FGHJ` 输入 X `ABCDX E FGHJ`
`ABCD E FGHJK` 输入 X `ABCDX E FGHJK`
`ABCDE FGHJK` 输入 X `ABCDEX FGHJK`
`ABCDE FGHJK` 输入 X `ABCDE X FGHJK`
`ABCD E FGHJK L` 退格 `ABC E FGHJK L`
`ABCD E FGHJK` 退格 `ABC E FGHJK`
`ABCDE F GHJK` 退格 `ABCDE GHJK`
`ABCDE FGHJK` 退格 `ABCDE FGHJK`
`ABCDE FGHJK` 退格 `ABCD FGHJK`
`ABC DE FGHJK` 输入空格 `ABC DE FGHJK`

更新:

这是我的修复:

let Input = document.createElement("input");
Input.setAttribute("type", "text");
Input.style.width = "100%";
Input.style.height = "30px";
Input.style.fontSize = "20px";
Input.addEventListener("input", () => {
  const cursorPosition = Input.selectionStart;
  const imValue = Input.value;
  Input.value = Input.value.replace(/\s*/g,"").replace(/(.{5})/g, '$1 ').trim();
  const lenDiff = Input.value.length - imValue.length;
  if(cursorPosition == imValue.length) {
      Input.setSelectionRange(Input.value.length, Input.value.length);
      return ;
  }
  if(imValue[cursorPosition] === " " && Input.value[cursorPosition - 1] === " ") {
      Input.setSelectionRange(cursorPosition + 1, cursorPosition + 1);
      return ;
  }
  if(imValue[cursorPosition - 1] === " ") {
      Input.setSelectionRange(cursorPosition - 1, cursorPosition - 1);
      return ;
  }
  Input.setSelectionRange(cursorPosition, cursorPosition);
});
document.body.appendChild(Input);

但是这个修复也有一个问题:它无法处理多字母字符串的复制和粘贴(只能处理单字母输入)。

更新:

问题通过在beforeinput事件监听器中拆分字符串而得以解决。

let Input = document.createElement("input");
Input.setAttribute("type", "text");
Input.style.width = "100%";
Input.style.height = "30px";
Input.style.fontSize = "20px";
Input.addEventListener("beforeinput", e => {
  if(e.data) {
    e.preventDefault();
    const data = e.data.replace(/\s*/g,"");
    for(let i = 0; i < data.length; i++) {
      let cursorPosition = Input.selectionStart;
      Input.value = Input.value.slice(0, cursorPosition) + data[i] + Input.value.slice(cursorPosition);
      Input.setSelectionRange(cursorPosition + 1, cursorPosition + 1);
      Input.dispatchEvent(new Event("input"));
    }
  }
});
Input.addEventListener("input", () => {
  const cursorPosition = Input.selectionStart;
  const imValue = Input.value;
  Input.value = Input.value.replace(/\s*/g,"").replace(/(.{5})/g, '$1 ').trim();
  const lenDiff = Input.value.length - imValue.length;
  if(cursorPosition == imValue.length) {
      Input.setSelectionRange(Input.value.length, Input.value.length);
      return ;
  }
  if(imValue[cursorPosition] === " " && Input.value[cursorPosition - 1] === " ") {
      Input.setSelectionRange(cursorPosition + 1, cursorPosition + 1);
      return ;
  }
  if(imValue[cursorPosition - 1] === " ") {
      Input.setSelectionRange(cursorPosition - 1, cursorPosition - 1);
      return ;
  }
  Input.setSelectionRange(cursorPosition, cursorPosition);
});
document.body.appendChild(Input);
英文:

The newest question: can you give another more robust or succinct solution that can exactly accomplish the same goal as I described?


This is the code of mine that has some problems.
I want to split every five letters with a space.

It does well if you enter or delete at the end of the input BUT when you enter or delete NOT at the end of the input, the cursor would automatically go to the end.

For instance, the textbox now have ABCDE FGHJK. If I delete the A, the cursor would go the end after deleting the A.

<!-- begin snippet: js hide: false console: true babel: false -->

<!-- language: lang-js -->

let Input = document.createElement(&quot;input&quot;); 
Input.setAttribute(&quot;type&quot;, &quot;text&quot;);
Input.style.width = &quot;100%&quot;;
Input.style.height = &quot;30px&quot;;
Input.style.fontSize = &quot;20px&quot;;
// The code AFTER this need modification and improvement
Input.addEventListener(&quot;input&quot;, () =&gt; {
Input.value = Input.value.replace(/\s*/g,&quot;&quot;);
Input.value = Input.value.replace(/(.{5})/g, &#39;$1 &#39;);
Input.value = Input.value.trim();
});
// The code BEFORE this need modification and improvement
document.body.appendChild(Input);

<!-- end snippet -->

How to fix the code to prevent it? (It should ONLY include original Javascript code but NOT CSS, HTML code or Jquery.)

I've tried to relocate the cursorPosition but it doesn't work...

I would appreciate that if the code is as succinct as possible.

Remember the goal is to make the input as convenient as possible.

Some examples here (| is the cursor):

Original Input Operation Result Before Operation Result After Operation cursorPosSame
`ABCD E FGHJ` Enter X `ABCDX E FGHJ`
`ABCD E FGHJK` Enter X `ABCDX E FGHJK`
`ABCDE FGHJK` Enter X `ABCDEX FGHJK`
`ABCDE FGHJK` Enter X `ABCDE X FGHJK`
`ABCD E FGHJK L` Backspace `ABC E FGHJK L`
`ABCD E FGHJK` Backspace `ABC E FGHJK`
`ABCDE F GHJK` Backspace `ABCDE GHJK`
`ABCDE FGHJK` Backspace `ABCDE FGHJK`
`ABCDE FGHJK` Backspace `ABCD FGHJK`
`ABC DE FGHJK` Enter Space `ABC DE FGHJK`

Update:

Here is my fix:

<!-- begin snippet: js hide: false console: true babel: false -->

<!-- language: lang-js -->

let Input = document.createElement(&quot;input&quot;);
Input.setAttribute(&quot;type&quot;, &quot;text&quot;);
Input.style.width = &quot;100%&quot;;
Input.style.height = &quot;30px&quot;;
Input.style.fontSize = &quot;20px&quot;;
Input.addEventListener(&quot;input&quot;, () =&gt; {
const cursorPosition = Input.selectionStart;
const imValue = Input.value;
Input.value = Input.value.replace(/\s*/g,&quot;&quot;).replace(/(.{5})/g, &#39;$1 &#39;).trim();
const lenDiff = Input.value.length - imValue.length;
if(cursorPosition == imValue.length) {
Input.setSelectionRange(Input.value.length, Input.value.length);
return ;
}
if(imValue[cursorPosition] === &quot; &quot; &amp;&amp; Input.value[cursorPosition - 1] === &quot; &quot;) {
Input.setSelectionRange(cursorPosition + 1, cursorPosition + 1);
return ;
}
if(imValue[cursorPosition - 1] === &quot; &quot;) {
Input.setSelectionRange(cursorPosition - 1, cursorPosition - 1);
return ;
}
Input.setSelectionRange(cursorPosition, cursorPosition);
});
document.body.appendChild(Input);

<!-- end snippet -->

But this fix also has a problem: it cannot deal with copy and paste of multi-letter string (can only deal with single-letter input).


Update:
The problem is solved by splitting the string in the eventlistener beforeinput.

<!-- begin snippet: js hide: false console: true babel: false -->

<!-- language: lang-js -->

let Input = document.createElement(&quot;input&quot;);
Input.setAttribute(&quot;type&quot;, &quot;text&quot;);
Input.style.width = &quot;100%&quot;;
Input.style.height = &quot;30px&quot;;
Input.style.fontSize = &quot;20px&quot;;
Input.addEventListener(&quot;beforeinput&quot;, e =&gt; {
if(e.data) {
e.preventDefault();
const data = e.data.replace(/\s*/g,&quot;&quot;);
for(let i = 0; i &lt; data.length; i++) {
let cursorPosition = Input.selectionStart;
Input.value = Input.value.slice(0, cursorPosition) + data[i] + Input.value.slice(cursorPosition);
Input.setSelectionRange(cursorPosition + 1, cursorPosition + 1);
Input.dispatchEvent(new Event(&quot;input&quot;));
}
}
});
Input.addEventListener(&quot;input&quot;, () =&gt; {
const cursorPosition = Input.selectionStart;
const imValue = Input.value;
Input.value = Input.value.replace(/\s*/g,&quot;&quot;).replace(/(.{5})/g, &#39;$1 &#39;).trim();
const lenDiff = Input.value.length - imValue.length;
if(cursorPosition == imValue.length) {
Input.setSelectionRange(Input.value.length, Input.value.length);
return ;
}
if(imValue[cursorPosition] === &quot; &quot; &amp;&amp; Input.value[cursorPosition - 1] === &quot; &quot;) {
Input.setSelectionRange(cursorPosition + 1, cursorPosition + 1);
return ;
}
if(imValue[cursorPosition - 1] === &quot; &quot;) {
Input.setSelectionRange(cursorPosition - 1, cursorPosition - 1);
return ;
}
Input.setSelectionRange(cursorPosition, cursorPosition);
});
document.body.appendChild(Input);

<!-- end snippet -->

答案1

得分: 1

以下是您的代码部分的翻译:

let Input = document.createElement("input");
Input.setAttribute("type", "text");
Input.style.width = "100%";
Input.style.height = "30px";
Input.style.fontSize = "20px";

function formatValue(value) {
  return value.replace(/\s*/g, "").replace(/(.{5})/g, "$1 ").trim();
}

Input.addEventListener("input", function(e) {
  const cursorPosition = Input.selectionStart;
  const oldValue = Input.value
  Input.value = formatValue(Input.value);

  const newPosition = oldValue.length < Input.value.length ? cursorPosition + 1 : cursorPosition
  Input.setSelectionRange(newPosition, newPosition);
});

Input.addEventListener("keydown", function(e) {
  let cursorPosition = Input.selectionStart;
  let value = Input.value;

  if (e.key === 'Backspace') {
    e.preventDefault();
    if (cursorPosition === 0) return

    const offset = Input.value[cursorPosition - 1] === ' ' ? 2 : 1;

    value = value.slice(0, cursorPosition - offset) + value.slice(cursorPosition);

    Input.value = formatValue(value);
    Input.setSelectionRange(cursorPosition - 1, cursorPosition - 1);

  } else if (e.key === 'Delete') {
    e.preventDefault();
    if (cursorPosition >= value.length) return

    const offset = Input.value[cursorPosition] === ' ' ? 2 : 1
    value = value.slice(0, cursorPosition) + value.slice(cursorPosition + offset);

    Input.value = formatValue(value);
    Input.setSelectionRange(cursorPosition, cursorPosition);

  }
});

document.body.appendChild(Input);

这是您提供的代码的中文翻译部分。

英文:

Modified your code a bit to restore cursor position:

<!-- begin snippet: js hide: false console: true babel: false -->

<!-- language: lang-js -->

let Input = document.createElement(&quot;input&quot;);
Input.setAttribute(&quot;type&quot;, &quot;text&quot;);
Input.style.width = &quot;100%&quot;;
Input.style.height = &quot;30px&quot;;
Input.style.fontSize = &quot;20px&quot;;
function formatValue(value) {
return value.replace(/\s*/g, &quot;&quot;).replace(/(.{5})/g, &quot;$1 &quot;).trim();
}
Input.addEventListener(&quot;input&quot;, function(e) {
const cursorPosition = Input.selectionStart;
const oldValue = Input.value
Input.value = formatValue(Input.value);
const newPosition = oldValue.length &lt; Input.value.length ? cursorPosition + 1 : cursorPosition
Input.setSelectionRange(newPosition, newPosition);
});
Input.addEventListener(&quot;keydown&quot;, function(e) {
let cursorPosition = Input.selectionStart;
let value = Input.value;
if (e.key === &#39;Backspace&#39;) {
e.preventDefault();
if (cursorPosition === 0) return
const offset = Input.value[cursorPosition - 1] === &#39; &#39; ? 2 : 1;
value = value.slice(0, cursorPosition - offset) + value.slice(cursorPosition);
Input.value = formatValue(value);
Input.setSelectionRange(cursorPosition - 1, cursorPosition - 1);
} else if (e.key === &#39;Delete&#39;) {
e.preventDefault();
if (cursorPosition &gt;= value.length) return
const offset = Input.value[cursorPosition] === &#39; &#39; ? 2 : 1
value = value.slice(0, cursorPosition) + value.slice(cursorPosition + offset);
Input.value = formatValue(value);
Input.setSelectionRange(cursorPosition, cursorPosition);
}
});
document.body.appendChild(Input);

<!-- end snippet -->

答案2

得分: 1

以下是您要翻译的代码部分:

<!-- begin snippet: js hide: false console: true babel: false -->

<!-- language: lang-js -->
document.addEventListener("DOMContentLoaded", function() {
  const input = document.createElement("input");
  input.setAttribute("type", "text");
  input.style.width = "100%";
  input.style.height = "30px";
  input.style.fontSize = "20px";

  let previousValue = "";
  let previousCursorPosition = 0;

  input.addEventListener("input", function(e) {
    const cursorPosition = input.selectionStart;
    const value = input.value.replace(/\s*/g, "").replace(/(.{5})/g, "$1 ").trim();
    input.value = value;
    input.setSelectionRange(cursorPosition, cursorPosition);
    previousValue = value;
    previousCursorPosition = cursorPosition;
  });

  input.addEventListener("keydown", function(e) {
    const cursorPosition = input.selectionStart;

    // Handle the scenario when Backspace key is pressed
    if (e.key === "Backspace" && cursorPosition > 0 && input.value[cursorPosition - 1] === " " &&
        input.value[cursorPosition] !== " ") {
      e.preventDefault();
      const valueBeforeCursor = input.value.slice(0, cursorPosition - 2);
      const valueAfterCursor = input.value.slice(cursorPosition - 1);
      input.value = valueBeforeCursor + valueAfterCursor;
      input.setSelectionRange(cursorPosition - 1, cursorPosition - 1);
      previousValue = input.value.replace(/\s*/g, "").replace(/(.{5})/g, "$1 ").trim();
      previousCursorPosition = cursorPosition - 1;
    }
  });

  input.addEventListener("keydown", function(e) {
    if (e.keyCode === 32 && input.selectionStart !== input.selectionEnd) {
      // Space bar pressed with text selected, remove spaces from the selection
      const start = input.selectionStart;
      const end = input.selectionEnd;
      const value = input.value.substring(start, end).replace(/\s/g, "");
      input.value = input.value.substring(0, start) + value + input.value.substring(end);
      input.setSelectionRange(start, start + value.length);
      e.preventDefault();
    } else if (e.keyCode === 32 && input.selectionStart === input.selectionEnd) {
      // Space bar pressed with no text selected, don't add space
      e.preventDefault();
    }
  });

  document.body.appendChild(input);
});

<!-- end snippet -->

请注意,这段代码主要是关于在文本输入框中进行文本处理和格式化的JavaScript代码。

英文:

You may try this:

<!-- begin snippet: js hide: false console: true babel: false -->

<!-- language: lang-js -->

     document.addEventListener(&quot;DOMContentLoaded&quot;, function() {
const input = document.createElement(&quot;input&quot;);
input.setAttribute(&quot;type&quot;, &quot;text&quot;);
input.style.width = &quot;100%&quot;;
input.style.height = &quot;30px&quot;;
input.style.fontSize = &quot;20px&quot;;
let previousValue = &quot;&quot;;
let previousCursorPosition = 0;
input.addEventListener(&quot;input&quot;, function(e) {
const cursorPosition = input.selectionStart;
const value = input.value.replace(/\s*/g, &quot;&quot;).replace(/(.{5})/g, &quot;$1 &quot;).trim();
input.value = value;
input.setSelectionRange(cursorPosition, cursorPosition);
previousValue = value;
previousCursorPosition = cursorPosition;
});
input.addEventListener(&quot;keydown&quot;, function(e) {
const cursorPosition = input.selectionStart;
// Handle the scenario when Backspace key is pressed
if (e.key === &quot;Backspace&quot; &amp;&amp; cursorPosition &gt; 0 &amp;&amp; input.value[cursorPosition - 1] === &quot; &quot; &amp;&amp;                             input.value[cursorPosition] !== &quot; &quot;) {
e.preventDefault();
const valueBeforeCursor = input.value.slice(0, cursorPosition - 2);
const valueAfterCursor = input.value.slice(cursorPosition - 1);
input.value = valueBeforeCursor + valueAfterCursor;
input.setSelectionRange(cursorPosition - 1, cursorPosition - 1);
previousValue = input.value.replace(/\s*/g, &quot;&quot;).replace(/(.{5})/g, &quot;$1 &quot;).trim();
previousCursorPosition = cursorPosition - 1;
}
});
input.addEventListener(&quot;keydown&quot;, function(e) {
if (e.keyCode === 32 &amp;&amp; input.selectionStart !== input.selectionEnd) {
// Space bar pressed with text selected, remove spaces from the selection
const start = input.selectionStart;
const end = input.selectionEnd;
const value = input.value.substring(start, end).replace(/\s/g, &quot;&quot;);
input.value = input.value.substring(0, start) + value + input.value.substring(end);
input.setSelectionRange(start, start + value.length);
e.preventDefault();
} else if (e.keyCode === 32 &amp;&amp; input.selectionStart === input.selectionEnd) {
// Space bar pressed with no text selected, don&#39;t add space
e.preventDefault();
}
});
document.body.appendChild(input);
});

<!-- end snippet -->

huangapple
  • 本文由 发表于 2023年5月17日 14:30:26
  • 转载请务必保留本文链接:https://go.coder-hub.com/76269117.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定