You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何实现textarea与div块选中文本双向同步高亮显示

实现方案

实现逻辑

  1. 先保证textarea和preview区域的文本排版完全一致,避免选中位置出现偏移
  2. 分别监听两个区域的选中事件,获取选中文本的起止位置
  3. 加同步锁避免双向触发导致的死循环
  4. 将选中位置同步到另一个区域,实现双向高亮效果

完整修改代码

CSS代码

::-moz-selection { /* Code for Firefox */
  color: red;
  background: yellow;
}

::selection {
  color: red;
  background: yellow;
}

#preview { 
  width:410px; 
  border: solid 1px #999; 
  padding:5px;
  /* 新增:保证和textarea的空格、换行排版完全一致 */
  white-space: pre-wrap;
  word-break: break-all;
  min-height: 100px;
}
textarea {
  white-space: pre-wrap;
  word-break: break-all;
}

JS代码

// 同步锁,避免双向触发循环
let isSyncing = false;

function showPreview()
{
  let value = $('textarea').val().trim();
  // 修改为全局替换特殊字符
  value = value.replace(/</g, "&lt;").replace(/>/g, "&gt;");
  // 改用text方法赋值,保证只有单个文本节点,方便计算选中位置
  $('#preview').text(value);
}

// 同步textarea的选中状态到preview
function syncTextareaToPreview() {
  if (isSyncing) return;
  isSyncing = true;
  const textarea = $('textarea')[0];
  const start = textarea.selectionStart;
  const end = textarea.selectionEnd;
  
  const preview = $('#preview')[0];
  const textNode = preview.firstChild;
  const selection = window.getSelection();
  if (!textNode || start === end) {
    selection.removeAllRanges();
    isSyncing = false;
    return;
  }
  // 创建选中范围
  const range = document.createRange();
  range.setStart(textNode, start);
  range.setEnd(textNode, end);
  selection.removeAllRanges();
  selection.addRange(range);
  isSyncing = false;
}

// 同步preview的选中状态到textarea
function syncPreviewToTextarea() {
  if (isSyncing) return;
  isSyncing = true;
  const selection = window.getSelection();
  const textarea = $('textarea')[0];
  
  if (selection.rangeCount === 0) {
    textarea.selectionStart = textarea.selectionEnd = 0;
    isSyncing = false;
    return;
  }
  const range = selection.getRangeAt(0);
  const preview = $('#preview')[0];
  // 校验选中区域是否在preview内部
  if (!preview.contains(range.commonAncestorContainer)) {
    isSyncing = false;
    return;
  }
  // 赋值选中位置到textarea
  textarea.selectionStart = range.startOffset;
  textarea.selectionEnd = range.endOffset;
  isSyncing = false;
}

// 页面加载完成后绑定事件
$(function() {
  // 初始化预览内容
  showPreview();
  // 监听textarea选中相关事件
  $('textarea').on('select keyup mouseup', syncTextareaToPreview);
  // 监听preview选中相关事件
  $('#preview').on('mouseup keyup', syncPreviewToTextarea);
})

HTML代码

保持原有结构不变即可。


注意事项

  • 文本排版一致性是选中位置准确的前提,必须保留white-space: pre-wrap属性
  • 支持鼠标选中、键盘shift+方向键选中两种场景
  • 同步锁避免了两个区域的选中事件互相触发导致的死循环问题

内容的提问来源于stack exchange,提问作者Ivan Dern

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.09.30 11:06:05