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

如何修复textarea中特定词汇触发自定义右键菜单及词汇替换功能

修复textarea右键特定词汇菜单与替换功能

需求说明

  • 使用JavaScript实现textarea内词汇的追加与替换功能;
  • 自定义右键菜单仅在右键点击textarea中属于指定数组specificwords(包含'hi'、'hello'、'yo'等词汇)的词汇时才触发显示,菜单需包含词汇替换选项;若点击的词汇不在数组中,菜单不显示。

现有问题

当前代码有两个核心问题:

  1. 逻辑错误:只要textarea里存在特定词汇,右键点击任意位置都会弹出菜单,未判断点击位置是否落在目标词汇上;
  2. 功能缺失:完全未实现词汇替换功能,无法满足需求。

修复后的完整代码

HTML

<!DOCTYPE html>
<head>
    <link href="./main.css" rel="stylesheet"/>
</head>
<body>
    <textarea>hello This is some text. Click on any word and then do right click</textarea>
    <ul class="custom-context-menu">
        <li data-action="replace">替换为 rule</li>
        <li data-action="replace">替换为 slde</li>
        <li data-action="replace">替换为 rebaz</li>
        <li data-action="append">追加到末尾</li>
    </ul>
</body>
<script src="./main.js" type="text/javascript"></script>
</html>

CSS

.custom-context-menu {
    z-index: 1100;
    display: none;
    position: absolute;
    list-style: none;
    margin: 0;
    padding: 0;
    border: 1px solid black;
    background: white;
}

.custom-context-menu li {
    padding: 5px;
    cursor: pointer;
}

.custom-context-menu li:hover {
    background-color: aqua;
}

JavaScript

const textarea = document.querySelector("textarea");
const contextMenu = document.querySelector(".custom-context-menu");
const specificWords = ['hi', 'hello', 'yo', 'hey', 'some', 'howdy'];
let clickedWord = null;

// 获取右键点击位置对应的词汇
function getClickedWord(textarea, event) {
    const start = textarea.selectionStart;
    const value = textarea.value;
    // 向左定位单词起始位置
    let left = start;
    while (left > 0 && /\S/.test(value[left - 1])) {
        left--;
    }
    // 向右定位单词结束位置
    let right = start;
    while (right < value.length && /\S/.test(value[right])) {
        right++;
    }
    // 提取单词并去除标点,转小写用于匹配数组
    const word = value.slice(left, right).replace(/[^\w]/g, '').toLowerCase();
    return { word, left, right };
}

textarea.addEventListener('contextmenu', (event) => {
    event.preventDefault();
    const { word, left, right } = getClickedWord(textarea, event);
    
    // 仅当点击的词汇在指定数组中时显示菜单
    if (specificWords.includes(word)) {
        clickedWord = { word, left, right };
        // 定位菜单到点击坐标
        contextMenu.style.left = `${event.pageX}px`;
        contextMenu.style.top = `${event.pageY}px`;
        contextMenu.style.display = 'block';
        contextMenu.classList.add('on');
    } else {
        // 点击非目标词汇时隐藏菜单
        contextMenu.style.display = 'none';
        contextMenu.classList.remove('on');
        clickedWord = null;
    }
});

// 处理菜单点击事件:替换或追加词汇
contextMenu.addEventListener('click', (event) => {
    if (!clickedWord) return;
    
    const action = event.target.dataset.action;
    const targetText = event.target.textContent.replace(/替换为 /, '');
    
    if (action === 'replace') {
        // 替换选中的目标词汇
        const newValue = textarea.value.slice(0, clickedWord.left) + targetText + textarea.value.slice(clickedWord.right);
        textarea.value = newValue;
        // 光标定位到替换后的词汇末尾
        textarea.selectionStart = textarea.selectionEnd = clickedWord.left + targetText.length;
    } else if (action === 'append') {
        // 将词汇追加到textarea末尾
        textarea.value += ` ${targetText}`;
        textarea.selectionStart = textarea.selectionEnd = textarea.value.length;
    }
    
    // 操作完成后隐藏菜单
    contextMenu.style.display = 'none';
    contextMenu.classList.remove('on');
    clickedWord = null;
});

// 点击页面其他区域时隐藏菜单
document.addEventListener('click', (event) => {
    if (contextMenu.classList.contains('on') && !contextMenu.contains(event.target)) {
        contextMenu.style.display = 'none';
        contextMenu.classList.remove('on');
        clickedWord = null;
    }
});

关键修复说明

  1. 精准定位点击词汇:新增getClickedWord函数,利用textarea的selectionStart属性定位点击位置,提取对应词汇并处理标点、大小写后,与指定数组比对,只有匹配才显示菜单;
  2. 实现替换与追加功能:给菜单项添加data-action标记操作类型,点击时根据记录的词汇位置完成替换,或追加到文本末尾,同时调整光标位置提升体验;
  3. 优化菜单状态管理:点击非目标词汇或页面其他区域时,及时隐藏菜单并重置状态,避免菜单异常残留。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.04 19:39:52