如何从contenteditable元素中仅选中数值部分而非单位字符?
解决方案:contenteditable双击仅选中数值部分
要实现双击contenteditable元素时只选中数值部分(排除末尾的计量单位),可以利用原生的Selection和Range API精确控制选中范围,以下提供两种适配不同场景的方案:
方案1:固定减去末尾单位长度(适合单位长度固定,如"mm")
如果你的计量单位长度固定(比如"mm"占2个字符),直接计算文本长度减去单位长度,选中前面的数值部分:
$('body').on('dblclick', '.value', function(){ $(this).attr('contenteditable', true); const $el = $(this); const text = $el.text(); const unitLength = 2; // 对应"mm"的字符长度 const valueLength = text.length - unitLength; // 创建范围和选中对象 const range = document.createRange(); const selection = window.getSelection(); // 选中从开头到数值结束的位置 range.setStart($el[0].firstChild, 0); range.setEnd($el[0].firstChild, valueLength); // 替换原有选中范围 selection.removeAllRanges(); selection.addRange(range); });
方案2:正则匹配数值部分(适合单位不固定的场景)
如果存在多种计量单位(如"mm"、"cm"、"m"),用正则匹配出数值部分的长度再选中,适配性更强:
$('body').on('dblclick', '.value', function(){ $(this).attr('contenteditable', true); const $el = $(this); const text = $el.text(); // 匹配开头的数值(支持带逗号的千分位格式) const match = text.match(/^[\d,]+/); if(match){ const valueLength = match[0].length; const range = document.createRange(); const selection = window.getSelection(); range.setStart($el[0].firstChild, 0); range.setEnd($el[0].firstChild, valueLength); selection.removeAllRanges(); selection.addRange(range); } });
完整代码示例
HTML
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.7.1/jquery.min.js"></script> <div class="list"> <div class="item"> <span class="id">1</span> <span class="value">100mm</span> </div> <div class="item"> <span class="id">2</span> <span class="value">2,500mm</span> </div> <div class="item"> <span class="id">3</span> <span class="value">340mm</span> </div> </div>
CSS
.list{ display: flex; flex-direction: column; gap: 10px; .item{ display: flex; .id{ width: 20px; font-weight: 600; } &:has(.value[contenteditable="true"]){ .id{ color: red; } } } }
JavaScript(以方案2为例)
$('body').on('dblclick', '.value', function(){ $(this).attr('contenteditable', true); const $el = $(this); const text = $el.text(); // 匹配开头的数值(支持带逗号的千分位) const match = text.match(/^[\d,]+/); if(match){ const valueLength = match[0].length; const range = document.createRange(); const selection = window.getSelection(); range.setStart($el[0].firstChild, 0); range.setEnd($el[0].firstChild, valueLength); selection.removeAllRanges(); selection.addRange(range); } }); $(document).mouseup(function(e){ var element = $('body').find('.value[contenteditable="true"]'); if (!element.is(e.target) && element.has(e.target).length === 0){ $('.value').attr('contenteditable', false); } }); $(document).keypress(function(e) { if($('.value[contenteditable="true"]').length){ if(e.which == 13){ // 回车键关闭编辑 $('.value').attr('contenteditable', false); } } });
注:原代码中
if($('.value[contenteditable="true"]'))存在逻辑漏洞,jQuery对象即使为空也会返回true,已改为if($('.value[contenteditable="true"]').length)判断是否存在可编辑元素。
内容的提问来源于stack exchange,提问作者c01gat3
相关产品推荐
相关产品推荐

