当前位置: 首页 > news >正文

基于ueditor编辑器的功能开发之重写ueditor的查找和替换功能,支持滚动定位

百度编辑器的查找和替换无法随着页面滚动定位,找到searchreplace.js,重写里面的方法

效果展示:

20250421173735

思路:

找到查找和替换的输入框,发现id名分别为findtxt和findtxt1,分别绑定change事件,并定义两套变量,分别为currentIndex 、matches和replacecurrentIndex、replacematches用于存储当前滚动到的数组位置和查找到的文本的位置的数组列表

点击下一个上一个按钮的的时候注释原来的代码,改为调用我们自己写的方法scrollToMatch,参数传递当前要定位的数组索引和类型(查找或者替换),代码如下

/*** Created with JetBrains PhpStorm.* User: xuheng* Date: 12-9-26* Time: 下午12:29* To change this template use File | Settings | File Templates.*///清空上次查选的痕迹
editor.firstForSR = 0;
editor.currentRangeForSR = null;
//给tab注册切换事件
/*** tab点击处理事件* @param tabHeads* @param tabBodys* @param obj*/
//相关搜索变量
//当前查找的变量
let currentIndex = -1; 
let matches = [];
// 当前替换的变量
let replacecurrentIndex = -1
let replacematches = []
// let highlightSpan = document.createElement('span');
// highlightSpan.style.backgroundColor = '#ff0000';
// highlightSpan.style.color = '#ffffff';
// let execFlag = false;
function clickHandler( tabHeads,tabBodys,obj ) {//head样式更改for ( var k = 0, len = tabHeads.length; k < len; k++ ) {tabHeads[k].className = "";}obj.className = "focus";//body显隐var tabSrc = obj.getAttribute( "tabSrc" );for ( var j = 0, length = tabBodys.length; j < length; j++ ) {var body = tabBodys[j],id = body.getAttribute( "id" );if ( id != tabSrc ) {body.style.zIndex = 1;} else {body.style.zIndex = 200;}}}/*** TAB切换* @param tabParentId  tab的父节点ID或者对象本身*/
function switchTab( tabParentId ) {var tabElements = $G( tabParentId ).children,tabHeads = tabElements[0].children,tabBodys = tabElements[1].children;for ( var i = 0, length = tabHeads.length; i < length; i++ ) {var head = tabHeads[i];if ( head.className === "focus" )clickHandler(tabHeads,tabBodys, head );head.onclick = function () {clickHandler(tabHeads,tabBodys,this);}}
}
$G('searchtab').onmousedown = function(){$G('search-msg').innerHTML = '';$G('replace-msg').innerHTML = ''
}
//是否区分大小写
function getMatchCase(id) {return $G(id).checked ? true : false;
}
// 给输入框绑定change时间,用于变量初始化
$G('findtxt').onchange =function(e){console.log(e,'input输入框时间是否改变')currentIndex = -1; //当前matches = [];searchText('findtxt')
}
// 给替换绑定change事件
$G('findtxt1').onchange =function(e){console.log(e,'替换是否改变')replacecurrentIndex = -1; //当前replacematches = [];searchText('findtxt1')
}
//查找
$G("nextFindBtn").onclick = function (txt, dir, mcase) {var findtxt = $G("findtxt").value, obj;if (!findtxt) {return false;}if (matches.length === 0) return;currentIndex = (currentIndex + 1) % matches.length;scrollToMatch(currentIndex,'findtxt');// 自定义实现查找过程// this.searchText()// obj = {//     searchStr:findtxt,//     dir:1,//     casesensitive:getMatchCase("matchCase")// };// if (!frCommond(obj)) {//     var bk = editor.selection.getRange().createBookmark();//     $G('search-msg').innerHTML = lang.getEnd;//     editor.selection.getRange().moveToBookmark(bk).select();// }
};
$G("nextReplaceBtn").onclick = function (txt, dir, mcase) {var findtxt = $G("findtxt1").value, obj;if (!findtxt) {return false;}// obj = {//     searchStr:findtxt,//     dir:1,//     casesensitive:getMatchCase("matchCase1")// };// frCommond(obj);if (replacecurrentIndex.length === 0) return;replacecurrentIndex = (replacecurrentIndex + 1) % replacematches.length;scrollToMatch(replacecurrentIndex,'findtxt1');
};
$G("preFindBtn").onclick = function (txt, dir, mcase) {var findtxt = $G("findtxt").value, obj;if (!findtxt) {return false;}// obj = {//     searchStr:findtxt,//     dir:-1,//     casesensitive:getMatchCase("matchCase")// };// if (!frCommond(obj)) {//     $G('search-msg').innerHTML = lang.getStart;// }if (matches.length === 0) return;currentIndex = (currentIndex - 1 + matches.length) % matches.length;scrollToMatch(currentIndex,'findtxt');
};
$G("preReplaceBtn").onclick = function (txt, dir, mcase) {var findtxt = $G("findtxt1").value, obj;if (!findtxt) {return false;}// obj = {//     searchStr:findtxt,//     dir:-1,//     casesensitive:getMatchCase("matchCase1")// };// frCommond(obj);if (replacecurrentIndex.length === 0) return;replacecurrentIndex = (replacecurrentIndex - 1 + replacematches.length) % replacematches.length;scrollToMatch(replacecurrentIndex,'findtxt1');
};
//替换
$G("repalceBtn").onclick = function () {var findtxt = $G("findtxt1").value.replace(/^\s|\s$/g, ""), obj,replacetxt = $G("replacetxt").value.replace(/^\s|\s$/g, "");if (!findtxt) {return false;}if (findtxt == replacetxt || (!getMatchCase("matchCase1") && findtxt.toLowerCase() == replacetxt.toLowerCase())) {return false;}obj = {searchStr:findtxt,dir:1,casesensitive:getMatchCase("matchCase1"),replaceStr:replacetxt};frCommond(obj);
};
//全部替换
$G("repalceAllBtn").onclick = function () {var findtxt = $G("findtxt1").value.replace(/^\s|\s$/g, ""), obj,replacetxt = $G("replacetxt").value.replace(/^\s|\s$/g, "");if (!findtxt) {return false;}if (findtxt == replacetxt || (!getMatchCase("matchCase1") && findtxt.toLowerCase() == replacetxt.toLowerCase())) {return false;}obj = {searchStr:findtxt,casesensitive:getMatchCase("matchCase1"),replaceStr:replacetxt,all:true};var num = frCommond(obj);if (num) {$G('replace-msg').innerHTML = lang.countMsg.replace("{#count}", num);}
};
//执行
var frCommond = function (obj) {return editor.execCommand("searchreplace", obj);
};
function searchText(str) {let searchValue = $G(`${str}`).valueif (!searchValue) return;//获取编辑器内容//获取编辑器iframe文档对象const iframeDoc = editor.iframe.contentDocument;const body = iframeDoc.body;const textNodes = getTextNodes(body);//查找所有匹配项if(str == 'findtxt1'){replacematches = []} else {matches = []}textNodes.forEach(node => {const nodeText = node.nodeValue;const regex = new RegExp(`(${searchValue})`, 'gi');let match;while ((match = regex.exec(nodeText)) !== null) {if(str == 'findtxt1'){replacematches.push({node,offset: match.index,length: match[0].length})} else {matches.push({node,offset: match.index,length: match[0].length})}}});console.log(matches,replacematches,'matches')
}
//获取所有文本节点
function getTextNodes(node) {const textNodes = [];if (node.nodeType === Node.TEXT_NODE) {textNodes.push(node);} else {const children = node.childNodes;for (let i = 0; i < children.length; i++) {textNodes.push(...getTextNodes(children[i]));}}return textNodes;
}
//定位到指定匹配项
function scrollToMatch(index,str) {let flagif(str =='findtxt1'){if (replacematches.length === 0 || replacecurrentIndex < 0 || replacecurrentIndex >= replacematches.length){flag = true}} else if(str =='findtxt'){if (matches.length === 0 || currentIndex < 0 || currentIndex >= matches.length){flag = true}}if(flag) returnlet iframeDoc = editor.iframe.contentDocument;let selection = iframeDoc.getSelection();selection.removeAllRanges();let match = str == 'findtxt1' ?replacematches[index]:matches[index];let range = document.createRange();range.setStart(match.node, match.offset);range.setEnd(match.node, match.offset + match.length);selection.addRange(range);// range.surroundContents(highlightSpan);// editor.fireEvent('selectionchange');let rect = range.getBoundingClientRect();// let iframeWindow = editor.iframe.contentWindow;// let body = iframeWindow.document.querySelector('body');//计算滚动位置let scrollTop = rect.top + editor.document.documentElement.scrollTop - 30;editor.document.documentElement.scrollTo({top: scrollTop,behavior: "smooth"});
}
switchTab("searchtab");

相关文章:

  • ts中的类型
  • CSS零基础入门笔记:狂神版
  • 前端实战-AJAX
  • ubuntu 22.04 安装和配置 mysql 8.0,设置开机启动
  • 力扣热题100——矩阵
  • Spring Boot 断点续传实战:大文件上传不再怕网络中断
  • 74.搜索二维矩阵
  • 学习海康VisionMaster之垂线查找
  • 电控---SWD协议
  • Python进程与线程的深度对比
  • 【仿Mudou库one thread per loop式并发服务器实现】HTTP协议模块实现
  • Java中如何创建操作线程
  • 【Tip】MathType中输入空格符号
  • Indocia启动$INDO代币预售第一阶段 - 100% 社区安全,具有真正的盈利潜力
  • 【Python】如何查找电脑上的Python解释器
  • 【回眸】error: failed to compile `xxxxxx`重装rust环境
  • Unocss 类名基操, tailwindcss 类名
  • 【错误记录】Windows 命令行程序循环暂停问题分析 ( 设置 “ 命令记录 “ 选项 | 启用 “ 丢弃旧的副本 “ 选项 | 将日志重定向到文件 )
  • SpringBoot和微服务学习记录Day3
  • Java 自动装箱与拆箱:基本数据类型与包装类的转换
  • 盗播热门影视剧、电影被追究刑事附带民事责任,最高法发声
  • 同济研究生开发AI二维码拿下大奖,新一代00开发者掀起AI创业潮
  • 30小时已过,俄罗斯复活节停火不再延长
  • 专访|松重丰:“美食家”不孤独,他在自由地吃饭
  • 以优良作风激发改革发展动力活力,中管企业扎实开展深入贯彻中央八项规定精神学习教育
  • 在没有穹顶的剧院,和春天的音乐会来一场约会