如何使用JavaScript实现textarea中单行文本上下移动
实现textarea内文本行的上下移动功能
我正在开发一个通过MySQL预填充表单textarea的项目,需要实现点击某行文本后,通过按钮(或上下箭头键)调整文本行顺序。目前已有能实现select组件选项上下移动的代码,但不知道怎么修改适配textarea,附上可用的select代码和尝试的textarea代码,求帮忙。
可用的Select代码
<select id="towns" size="5"> <option>Sofia</option> <option>Varna</option> <option>Plovdiv</option> <option>Ruse</option> </select> <button id="btnUp" onclick="move(-1)">↑</button> <button id="btnDown" onclick="move(+1)">↓</button> <script> function move(direction) { let OptionToMove = $('#towns option:selected'); if (direction == -1) { OptionToMove.insertBefore(OptionToMove.prev()); } if (direction == +1) { OptionToMove.insertAfter(OptionToMove.next()); } } </script>
尝试的textarea代码
<textarea name='city' id='city' cols='30' rows='10'> Sofia Varna Plovdiv Ruse </textarea> <input type="button" value="↑" id="btnUp" onclick="move(-1)"></input> <input type="button" value="↓" id="btnDown" onclick="move(+1)"></input> <script> function move(direction) { let OptionToMove = $('#city toggle:selected'); if (direction == -1) { OptionToMove.insertBefore(OptionToMove.prev()); } if (direction == +1) { OptionToMove.insertAfter(OptionToMove.next()); } } </script>
解决方案
textarea和select的DOM结构完全不同:select有独立的<option>元素可以直接操作,但textarea仅存储纯文本内容,因此需要通过拆分文本为行数组的方式实现行移动,具体步骤如下:
- 拆分textarea内容为行数组
- 定位光标所在的行号
- 交换数组中目标行的位置
- 重新拼接数组并更新textarea,同时恢复光标位置
修改后的完整代码如下:
<textarea name='city' id='city' cols='30' rows='10'> Sofia Varna Plovdiv Ruse </textarea> <button id="btnUp" onclick="move(-1)">↑</button> <button id="btnDown" onclick="move(+1)">↓</button> <script> function move(direction) { const textarea = document.getElementById('city'); // 拆分文本为行数组,可选过滤空行 const lines = textarea.value.split('\n').filter(line => line.trim() !== ''); const cursorPos = textarea.selectionStart; const currentLine = getCurrentLine(textarea, cursorPos); // 边界判断:第一行不能上移,最后一行不能下移 if (direction === -1 && currentLine === 0) return; if (direction === 1 && currentLine === lines.length - 1) return; // 交换行位置 const targetLine = currentLine + direction; [lines[currentLine], lines[targetLine]] = [lines[targetLine], lines[currentLine]]; // 更新textarea内容 textarea.value = lines.join('\n'); // 恢复光标到移动后的行(这里默认移到行尾,可根据需求调整列位置) let newCursorPos = 0; for (let i = 0; i < targetLine; i++) { newCursorPos += lines[i].length + 1; // +1 对应换行符长度 } newCursorPos += lines[targetLine].length; textarea.setSelectionRange(newCursorPos, newCursorPos); textarea.focus(); } // 辅助函数:获取光标所在的行号 function getCurrentLine(textarea, cursorPos) { const textBeforeCursor = textarea.value.substring(0, cursorPos); return textBeforeCursor.split('\n').length - 1; } </script>
额外优化:支持键盘快捷键
如果需要通过Ctrl+上下箭头触发行移动,可添加以下事件监听:
document.getElementById('city').addEventListener('keydown', function(e) { // Ctrl+上箭头:上移当前行 if (e.key === 'ArrowUp' && e.ctrlKey) { e.preventDefault(); move(-1); } // Ctrl+下箭头:下移当前行 else if (e.key === 'ArrowDown' && e.ctrlKey) { e.preventDefault(); move(1); } });
内容的提问来源于stack exchange,提问作者Joe Sugerdale
相关产品推荐
相关产品推荐

