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

JQuery选中文本重复插入问题:多次选中文本后插入重复内容

多次选中文本后点击插入,重复插入所有选中内容的问题解决

我正在实现一个功能:用户从评论区选中文本后,点击插入按钮,就能把选中的内容以特定格式插入到textarea里。目前功能基本可用,但遇到一个奇怪的问题:多次选中文本(每次选中后点击别处取消选择),再点击插入按钮时,会把所有选中过的内容一并插入,而不是只插入最后一次选中的。比如重复选中"here"四次,点击插入就会出现四次带格式的内容。

我当前的代码:

获取选中文本的函数:

// selected text
function getSelected() {
 var return_text = '';
 if (window.getSelection) {
 return_text = window.getSelection();
 } else if (document.getSelection) {
 return_text = document.getSelection();
 }
 return return_text;
}

处理选中文本和插入按钮的代码:

var quote_box = $('#selective-quote');
$(document).on('mouseup', ".comment-body div", function(e) {
 if ($('#comment').length) // only do this if comment box exists (logged in)
 {
 var selection = getSelected();
 var selectedText = selection.toString();
 if (typeof selection !== undefined && selectedText.length > 0 && selection.anchorNode.nodeName == '#text') {
 var container = $(this);
 var r=selection.getRangeAt(0).getBoundingClientRect();
 var relative=document.body.parentNode.getBoundingClientRect();
 // show the quote button box
 quote_box.css('position','absolute');
 quote_box.css('top',r.bottom -relative.top - 45);
 quote_box.css('left',r.left);
 quote_box.css('height', 'auto');
 quote_box.show();
 var text_to_insert = '';
 $(document).on('click', "#insert-selective-quote", function(e) {
 var username = container.parent().parent().children('.comment-meta').find('.username').text();
 text_to_insert = '[quote='+username+']' + $.trim(selectedText) + '[/quote]';
 console.log(text_to_insert);
 var current_text = $('#comment').val();
 $('#comment').val(current_text + text_to_insert);
 quote_box.hide();
 });
 } else {
 quote_box.hide();
 }
}
});

问题原因分析

核心问题出在事件绑定的时机:你每次触发mouseup事件(也就是每次选中文本后松开鼠标),都会给#insert-selective-quote按钮绑定一个新的click事件处理函数。

举个例子:

  • 第一次选中文本:按钮绑定了1个click事件,点击会插入1次内容
  • 第二次选中文本:按钮又绑定了1个新的click事件,现在总共有2个
  • 重复四次后,按钮就有4个click事件处理函数,点击一次就会执行四次插入操作,所以你看到四次内容被插入。

解决方案

我给你两种解决思路,推荐第二种更优雅的方案:

方案1:绑定新事件前先解绑旧事件

在每次绑定click事件之前,先移除按钮上已有的同类型事件,避免重复绑定:

// 替换原来的点击事件绑定代码
$(document).off('click', "#insert-selective-quote").on('click', "#insert-selective-quote", function(e) {
 var username = container.parent().parent().children('.comment-meta').find('.username').text();
 text_to_insert = '[quote='+username+']' + $.trim(selectedText) + '[/quote]';
 console.log(text_to_insert);
 var current_text = $('#comment').val();
 $('#comment').val(current_text + text_to_insert);
 quote_box.hide();
});

这里用.off('click', "#insert-selective-quote")先清除之前绑定的click事件,再绑定新的,确保按钮永远只有一个有效的click处理函数。

方案2:将点击事件绑定移到mouseup事件外部(更优)

把插入按钮的click事件绑定逻辑抽离出来,只在页面初始化时绑定一次,然后通过变量存储当前要插入的内容。这样就从根源上避免了重复绑定:

var quote_box = $('#selective-quote');
// 定义变量存储当前要插入的文本
var currentInsertContent = '';

// 只绑定一次插入按钮的点击事件
$(document).on('click', "#insert-selective-quote", function(e) {
 if (currentInsertContent) {
 var current_text = $('#comment').val();
 $('#comment').val(current_text + currentInsertContent);
 quote_box.hide();
 currentInsertContent = ''; // 插入后清空,避免重复插入
 }
});

// 处理选中文本的mouseup事件
$(document).on('mouseup', ".comment-body div", function(e) {
 if ($('#comment').length) {
 var selection = getSelected();
 var selectedText = selection.toString();
 if (selection && selectedText.length > 0 && selection.anchorNode.nodeName == '#text') {
 var container = $(this);
 var r=selection.getRangeAt(0).getBoundingClientRect();
 var relative=document.body.parentNode.getBoundingClientRect();
 // 显示按钮
 quote_box.css({
 'position':'absolute',
 'top': r.bottom - relative.top - 45,
 'left': r.left,
 'height': 'auto'
 }).show();
 // 更新当前要插入的内容
 var username = container.parent().parent().children('.comment-meta').find('.username').text();
 currentInsertContent = '[quote='+username+']' + $.trim(selectedText) + '[/quote]';
 } else {
 quote_box.hide();
 currentInsertContent = ''; // 未选中有效文本时清空
 }
 }
});

这种方案的优势是事件只绑定一次,性能更好,逻辑也更清晰——mouseup事件只负责更新要插入的内容和显示按钮,click事件只负责执行插入操作。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.08 14:32:35