Wagtail富文本编辑器Pre标签按钮:实现选中文本包裹/解包裹功能求助
解决Wagtail富文本编辑器
标签切换按钮的问题
我刚帮你排查了代码里的问题,核心是你对getSelection()返回的原生Selection对象处理不对,还有切换逻辑的判断方式有问题。咱们一步步改,让按钮像粗体/斜体那样支持添加/移除
标签:问题分析
lastSelection = widget.options.editable.getSelection()拿到的是原生Selection对象,不是DOM元素,所以直接用$(lastSelection)会失效,这也是你看到lastSelection相关报错的原因。- 判断选中文本是否包含
的逻辑不对,应该检查选区的内容是否已经被标签包裹,而不是直接查找选区里的。- 直接拼接
<pre>和Selection对象的方式错误,应该用Range API来操作选区内容。修改后的完整代码
(function() { (function($) { return $.widget("IKS.prebutton", { options: { uuid: '', editable: null }, populateToolbar: function(toolbar) { var button, widget; widget = this; button = $('<span></span>'); button.hallobutton({ uuid: this.options.uuid, editable: this.options.editable, label: 'Pre Tag', icon: 'fa fa-backward', command: null }); toolbar.append(button); return button.on("click", function(event) { event.preventDefault(); var selection = widget.options.editable.getSelection(); // 确保有选中内容 if (selection.rangeCount === 0) return; var range = selection.getRangeAt(0); var selectedContent = range.extractContents(); var preElement = null; // 检查选区是否在<pre>标签内 var currentNode = range.commonAncestorContainer; // 从文本节点往上找元素节点 while (currentNode && currentNode.nodeType !== 1) { currentNode = currentNode.parentNode; } preElement = $(currentNode).closest('pre')[0]; if (preElement) { // 如果已经在<pre>里,移除标签,放回内容 var parent = preElement.parentNode; parent.insertBefore(selectedContent, preElement); parent.removeChild(preElement); } else { // 如果没有<pre>,创建新标签包裹内容 var pre = document.createElement('pre'); pre.appendChild(selectedContent); range.insertNode(pre); } // 触发编辑器变化事件,让Wagtail保存修改 widget.options.editable.element.trigger('change'); // 重新选中处理后的内容(可选,提升用户体验) var newRange = document.createRange(); newRange.selectNodeContents(preElement ? parent : pre); selection.removeAllRanges(); selection.addRange(newRange); }); } }); })(jQuery); }).call(this);关键修改点说明
- 正确处理Selection和Range:用
selection.getRangeAt(0)获取选区的Range对象,通过Range API来提取、插入内容,这是操作富文本选区的标准方式。 - 检查
存在性:从选区的共同祖先节点往上查找,判断是否已经在
标签内,避免误判。
- 切换逻辑实现:
- 如果已经有
:把
标签移除,将里面的内容放回原来的位置。
- 如果没有
:创建新的
标签,把选中的内容包裹后插入选区。
- 如果已经有
- 触发change事件:确保Wagtail能感知到编辑器内容的变化,正常保存修改。
- 可选的选区恢复:处理完后重新选中内容,让用户直观看到操作效果。
记得把这段代码替换你原来的按钮点击事件部分,同时确保你的页面已经正确引入了jQuery和jQuery UI(你提供的外部脚本没问题)。
内容的提问来源于stack exchange,提问作者JaredOzzy
相关产品推荐
相关产品推荐

