一个实验项目需要用到文本高亮的功能,使用javascript实现文本高亮的方法,暂时能想到的方法就是在给文本加上标签,然后添加样式。而如何给文本包裹一个标签,暂时也只想到两个方法:1、使用dom操作 2、用正则修改html代码
下午试验了一下使用dom操作的方法
/**
* 使用原生javascript操作dom,实现文本高亮
*/
var HIGH_LIGHT_CLS = 'high-light';
var WRAP_TAG_NAME = 'a';
var TEXT_TYPE = 3;
var ELEMENT_TYPE = 1;
var COLOR = '#FFFF96';
Highlighter = function() {
this.lastKey = null;
};
Highlighter.prototype = {
/**
* 取消高亮
* @param {ElementNode} node #require
* @param {Node} parent #imply
*/
lowLightNode : function(node, parent) {
//如果不是元素节点则退出
if (!node || node.nodeType != ELEMENT_TYPE) {
return;
}
//如果parent参数没传则默认使用node节点的父亲节点
parent = parent ? parent : node.parentNode;
//取得节点对应的文本值
var text = node.firstChild.nodeValue + '';
//使用文本节点替换元素节点
parent.replaceChild(document.createTextNode(text), node);
},
/**
* 高亮
* @param {String} key 关键字 #require
* @param {TextNode} node #require
* @param {Node} parent #imply
*/
highlightNode : function(key, node, parent) {
//如果不是文本节点则退出
if (!node || node.nodeType != TEXT_TYPE) {
return;
}
//如果没有传parent参数则parent默认为node节点的父亲节点
parent = parent ? parent : node.parentNode;
//大小小不敏感
key = key.toLowerCase();
//取得文本节点的值
var text = node.nodeValue;
//每次截取关键字后剩余的文本
var remain = text + '';
//每次截取时关键字对于文本值的的索引
var index;
//创建片段
var fragment = document.createDocumentFragment();
var count = 0;
//对文本内容循环截取关键字,截取的每部分都包裹上一个classname为'high-light'
//背景色为黄色, 的 a标签,
while ((index = remain.toLowerCase().indexOf(key)) != -1) {
//关键字前面部分的文本
var beforeMatch = remain.substring(0, index);
if (beforeMatch.length > 0) {
fragment.appendChild(document.createTextNode(beforeMatch));
count++;
}
//对文本包裹了a标签后的元素
var wrapEl = document.createElement(WRAP_TAG_NAME);
//设置包裹元素的html代码
wrapEl.innerHTML = remain.substring(index, index + key.length);
//设置classname
wrapEl.setAttribute("class", HIGH_LIGHT_CLS);
wrapEl.setAttribute("className", HIGH_LIGHT_CLS); // for IE
//设置背景色
wrapEl.style.backgroundColor = COLOR;
//往片段添加包裹后的文本相关节点
fragment.appendChild(wrapEl);
count++;
remain = remain.substring(index + key.length);
}
//截取完关键字后,添加剩余的文本
if (remain.length > 0) {
fragment.appendChild(document.createTextNode(remain));
count++;
}
//将截取到的对应的文本节点替换成a标签元素节点
parent.replaceChild(fragment, node);
//返回截取到的关键字数量
return count;
},
//判断一个节点(节点是否为对应关键字的包裹节点)
isWrapEl : function(node, key) {
if (key) {
//比较节点类型
if (node.nodeType == ELEMENT_TYPE) {
//比较标签名
if (node.tagName.toLowerCase() == WRAP_TAG_NAME.toLowerCase()) {
//比较classname
var cls = (node.getAttribute("class") || node.getAttribute("className") || "").toLowerCase();
if (cls.indexOf(HIGH_LIGHT_CLS.toLowerCase()) != -1) {
var firstNode = node.firstChild;
//比较文本值
if (firstNode
&& firstNode.nodeValue
&& firstNode.nodeValue.toLowerCase().indexOf(
key.toLowerCase()) != -1) {
return true;
}
}
}
}
}
return false;
},
/**
*
* @param {HtmlElement} el #required 对el元素的所有子节点进行关键字高亮
* @param {String} key #required 关键字
* @param {bool} earseLast #imply 是否擦出上一次高亮(可能两次高亮的关键字不一样)
* @param {bool} forece #imply 强制高亮
*/
highlight : function(el, key, earseLast, force) {
if(!el) return;
if (this.lastKey == key && force !== true) return;
doHighlight(el, key, earseLast, this);
this.lastKey = key;
},
/**
* @param {} el #required 对el元素的所有子节点取消所有文本高亮
*/
removeAllHighlight : function(el){
if(!el) return;
doRemoveAllHighlight(el, this);
this.lastKey = null;
}
};
//只是不想上边代码太长,就写下来了
function doRemoveAllHighlight(el, me){
//获取el下的所有子节点
var nodes = el.childNodes;
for ( var i = 0; i < nodes.length; i++) {
var node = nodes[i];
var nodeType = node.nodeType;
//如果是元素节点
if (nodeType == ELEMENT_TYPE) {
//如果确定是高亮包裹的元素
if (me.isWrapEl(node, me.lastKey)) {
//进行取消高亮操作
me.lowLightNode(node);
}else{
//递归子节点进行取消高亮
doRemoveAllHighlight(node, me);
}
}
}
}
function doHighlight (el, key, earseLast, me) {
//大小写不敏感
key = key.toLowerCase();
//获得el下的子节点
var nodes = el.childNodes;
for ( var i = 0; i < nodes.length; i++) {
var node = nodes[i];
var nodeType = node.nodeType;
// 如果是文本节点
if (nodeType == TEXT_TYPE) {
var text = node.nodeValue;
// 如果该文本节点的文本值包含关键字
if (text.toLowerCase().indexOf(key) != -1) {
//进行高亮 (因为nodes.length会实时对应dom的状态做更新,所以要改变迭代的i)
i = i + me.highlightNode(key, node, el) - 1;
}
}
// 如果是元素节点
else if (nodeType == ELEMENT_TYPE) {
//判断是否为上次高亮包裹的元素,并且是否需要擦出
if (me.isWrapEl(node, me.lastKey) && earseLast === true) {
//擦出上次高亮
me.lowLightNode(node);
// 当前索引对应的节点再走一次
i--;
} else {
//递归进行高亮
doHighlight(node, key, earseLast, me);
}
}
}
}
分享到:
相关推荐
jsdiff 一个javascript的文本差异比较实现
本文实例讲述了JavaScript简单实现关键字文本搜索高亮显示功能。分享给大家供大家参考,具体如下: <!DOCTYPE ...
jquery实现的关键字高亮插件,简单易用,连textarea中的关键字都可以高亮哦
HR.js 微小JavaScript插件用于高亮显示和替换DOM中的文本
JavaScript应用实例-文本搜索高亮.js
本资料介绍了两种能让文本中的关键字实现高亮显示的javascript的代码
jquery.mark是一款功能强大的jQuery关键字文本高亮插件。它支持变音符号,同义词,自定义元素,自定义class名称,单词边界和iframe。它可以通过搜索的方式来高亮所有的指定关键字。
LuminJS:一个JavaScript库用于逐步高亮显示页面上的任何文本
jsTextOperation 网页文本选中高亮,关键字搜索高亮 文本编辑元素中的文本选择(Input, TextArea) document.activeElement() 方法 跨标签文本选择 Selection 对象,window.getSelection() 方法
最近需要给HTML5的WebAPP在页面上实现一个...在微信浏览器内是很容易实现长按文本激发系统菜单,高亮全选文本内容的。但是在其他浏览器的表现就不是很一致了。包括模拟focus input,JavaScript Selection, 使用a标签尝
墨滴高亮文本用于的插件,可实现Markdown文本突出显示扩展。...安装ipm install highlight-text用法这是一个示例,其中显示了与块引号结合使用的文本高亮显示: > ==To be, or not to be==, that is the question
React Native组件用于高亮单词在一个大的文本中
WPF4上使用的语法高亮文本编辑器。从SharpDevelopment里面提取出来的。本人修改过源代码,使控件支持MySql语法。控件原生支持的语法有:ASP.NET,Boo, Coco/R grammars, C++, C#, HTML, Java, JavaScript, Patch ...
用于微信小程序的HTML和Markdown格式的富文本渲染组件,支持代码高亮
超过 120 种语言的语法高亮显示(可以导入TextMate/Sublime/ .tmlanguage文件) 超过 20 个主题(可以导入TextMate/Sublime/ .tmtheme文件) 自动缩进和升级 一个可选的命令行 处理巨大的文档(最后检查,4,000,000 ...
Notepad++ 是一款非常有特色的编辑器,是开源软件,可以免费使用。 <br>功能有: ①、内置支持多达 27 种语法高亮度显示... 支持的语言: C, C++ , Java , C#, XML, HTML, PHP, Javascript , ! <br>
1 自定义语法高亮,支持HTML, XML, CSS, JavaScript, VBScript, ASP, PHP, CSS, Perl/CGI,C/C++, C#, Java, VB, Pascal, 汇编, SQL, Python, NSIS,INI, REG, INF, BAT,DIFF等众多脚本文件。 2 支持ANSI,Unicode,...
jQuery Highlighter 是一个用来高亮显示文本关键字的 jQuery 插件。 支持同时高亮多个关键字 多个关键字之间可以重叠 能够取消高亮关键字