以下情景。
我用material2写了一个angular2应用程序。
在我的SideNav中是一个搜索输入字段。当用户输入时,他被重定向(通过路由)到搜索组件,而搜索到的单词作为路由参数被移交。
搜索组件显示应用程序的所有页面,其中包含搜索的单词(后台索引)。一旦用户点击该条目,他就被重定向到该页面,并且搜索到的单词被附加为查询参数。我现在正试图突出显示页面上搜索词的所有外观,用户被重定向到。目前我正在这样做:
subscription: ISubscription;
searchTerm: string;
constructor(private router: Router, private elementRef: ElementRef) {}
ngOnInit(): void {
this.subscription = this.router.routerState.queryParams.subscribe(queryParams => {
let searchTerm = queryParams['searchTerm'];
if (searchTerm) {
this.searchTerm = searchTerm;
} else {
this.searchTerm = null;
}
});
}
ngAfterContentInit(): void {
if (this.searchTerm && isStaticDoc) {
let regExp = new RegExp(`(${this.searchTerm})`, 'i');
this.highlightWords(this.elementRef.nativeElement, regExp);
}
}
ngOnDestroy(): void {
this.subscription.unsubscribe();
}
highlightWords(node, regExp: RegExp) {
if (!node || ! regExp) {
return;
}
if (node.nodeType === 3) {
let regs = regExp.exec(node.nodeValue);
if (regs) {
let match = document.createElement('span');
match.appendChild(document.createTextNode(regs[0]));
match.classList.add('search-hl');
let after = node.splitText(regs.index);
after.nodeValue = after.nodeValue.substring(regs[0].length);
node.parentNode.insertBefore(match, after);
}
} else if (node.hasChildNodes()) {
for (let i = 0; i < node.childNodes.length; i++) {
this.highlightWords(node.childNodes[i], regExp);
}
}
}
现在的问题是,我得到一个错误RangeError: Maximum call stack size exceeded
,这可能是一个提示,递归级别是深入的。
我已经尝试过使用第三方库,其中非机器人实际上是从angular2和顶部使用的,编写代码并不困难......但它不起作用。
任何想法如何按照相同或类似的方法在最大调用堆栈大小之下暂存?
tl; dr 尝试在页面上突出显示searchTerm(作为queryParam传递)的所有外观 - &gt;我的方法(见代码)不是 由于最大调用堆栈大小而工作。
修改:使用rc4 atm,很快升级,但这不应该是一个问题(我猜)
答案 0 :(得分:2)
感谢user3791775我提出了解决方案。
highlightWords(html: string, searchTerm: string): string {
let regExp = new RegExp(`(${searchTerm})`, 'i');
let results = regExp.exec(html);
if (results) {
let before = html.substr(0, results.index);
let after = html.substr(results.index + searchTerm.length);
let indexOpenTag = before.lastIndexOf('<');
let indexCloseTag = before.lastIndexOf('>');
let indexOpenTagAfter = after.indexOf('<');
let indexCloseTagAfter = after.indexOf('>');
if (indexOpenTag <= indexCloseTag && indexOpenTagAfter <= indexCloseTagAfter) {
return `${before}<span class="search-hl">${results[0]}</span>${this.highlightWords(after, searchTerm)}`;
} else {
return `${before}${results[0]}${this.highlightWords(after, searchTerm)}`;
}
} else {
return html;
}
}
这可以通过以下方式使用
let ref = document.getElementById('my-highlicht-content');
ref.innerHtml = this.highlightWords(ref.innerHtml, this.searchTerm)
感谢您的帮助!
修改强> 有另一个边缘,这使得有必要检查关键字后面的部分。更新了我的例子。