[英]How can i avoid browser auto open or close tags when i try to get the html of the text selected
I´m creating a application for students where user is gonna be able to highlight the text for the document and make comment, now for the highlight of the text i´m just taking the selected text and wrapping the content in a mark
tag using window.selection.getRangeAt(0).surroundContents()
, now what i need to do is to get the html of the selection and avoid that browser auto open or close the html tags, for example, i have this text: 我正在为学生创建一个应用程序,使用户可以突出显示文档的文本并进行注释,现在要突出显示文本,我只是将选定的文本并使用
window.selection.getRangeAt(0).surroundContents()
将内容包装在mark
标签中window.selection.getRangeAt(0).surroundContents()
,现在我需要做的是获取所选内容的html,并避免浏览器自动打开或关闭html标签,例如,我有以下文本:
Super wonder ultra mega promotion. 超级奇迹超级促销。
where the HTML of the text will this <p>Super wonder <strong>ultra mega</strong> promtion</p>
, if the user select Super wonder ultra
the HTML i will get back should be <p>Super wonder <strong>ultra
and in the case the user select mega promotion
the HTML i should get is mega </strong> promtion</p>
but because the browser auto open and close tags if i select Super wonder ultra
the HTML i get back is <p>Super wonder<strong>ultra</strong></p>
. 文本的HTML将在
<p>Super wonder <strong>ultra mega</strong> promtion</p>
,如果用户选择Super wonder ultra
则我将返回的HTML应该是<p>Super wonder <strong>ultra
并且在用户选择mega promotion
的情况下,我应该获得的HTML是mega </strong> promtion</p>
mega promotion
mega </strong> promtion</p>
但是因为如果我选择Super wonder ultra
,浏览器会自动打开和关闭标签,所以我返回的HTML Super wonder ultra
了<p>Super wonder<strong>ultra</strong></p>
。 is there any way to avoid this behavior or to achieve this. 有什么办法可以避免这种行为或实现这一目标。
this the function i´m using to get the html of the selection: 这是我用来获取所选内容的html的函数:
public getHtmlSelection(selection: any): string {
let html: string;
const container = document.createElement('div');
for (let i = 0, len = selection.rangeCount; i < len; ++i) {
container.appendChild(selection.getRangeAt(i).cloneContents());
}
html = container.innerHTML;
return html;
}
and here i highlight the text selected: 在这里,我突出显示所选的文本:
public markContent(): void {
const selection: any = window.getSelection();
const range: any = selection.getRangeAt(0);
if (range.startOffset !== range.endOffset) {
if (this.markerEvent === 'p' || this.markerEvent === 'mark' || this.markerEvent === 'strong') {
const textSeleted: string = selection.toString();
const highlight: any = range.commonAncestorContainer;
if (this.markerEvent !== 'mark') {
const marker: any = document.createElement('mark');
marker.setAttribute('class', this.colorMarker);
range.surroundContents(marker);
this.hideBubble();
return;
}
const mark: any = range.commonAncestorContainer;
mark.remove();
range.deleteContents();
range.insertNode(document.createTextNode(highlight.textContent));
this.hideBubble();
}
}
}
thanks so much for any help or comment. 非常感谢您的帮助或评论。 if i´m not to clear please ask i little but more in the comments.
如果我不清楚,请在评论中少问我。
The only way I could do this was to manipulate the innerHTML
of the commonAncestorContainer
element. 我能做到这一点的唯一方法是操纵
commonAncestorContainer
元素的innerHTML
。 There are 2 cases that have to be handled differently. 有2种情况必须以不同的方式处理。
I handled those cases by comparing the anchorNode
and focusNode
of the selection. 我通过比较选择的
anchorNode
和focusNode
处理了这些情况。
This code is not a complete solution 此代码不是完整的解决方案
If you insert another paragraph below the first and try highlighting across the 2 paragraphs it will not work. 如果您在第一段下面插入另一段,然后尝试突出显示两段,则该段将无效。 You can not split a
mark
element across 2 block level elements. 您不能将
mark
元素拆分为2个块级元素。 In order to perform that operation more logic would have to be added to the markText
function to identify and properly manipulate all the block level elements involved. 为了执行该操作,必须将更多逻辑添加到
markText
函数中,以识别和正确处理所有涉及的块级元素。 I did not write that code for you. 我没有为您编写该代码。
document.getElementById('mark').addEventListener('click', markText); function markText() { var selection = window.getSelection(); if(selection.isCollapsed) return; var range = selection.getRangeAt(0), sameNode = selection.anchorNode === selection.focusNode, startText = '', endText = '', parentHtml = ''; if(sameNode) { parentHtml = range.commonAncestorContainer.parentNode.innerHTML; startText = range.commonAncestorContainer.textContent.substring(range.startOffset, range.endOffset); parentHtml = parentHtml.replace(startText, '<mark>' + startText + '</mark>'); range.commonAncestorContainer.parentNode.innerHTML = parentHtml; } else { parentHtml = range.commonAncestorContainer.innerHTML; startText = range.startContainer.textContent.substring(range.startOffset); endText = range.endContainer.textContent.substring(0, range.endOffset); parentHtml = parentHtml.replace(startText, '<mark>' + startText); parentHtml = parentHtml.replace(endText, endText + '</mark>'); range.commonAncestorContainer.innerHTML = parentHtml; } }
<p>Super wonder <strong>ultra mega</strong> promotion</p> <button id="mark">Mark Text</button>
Well thanks to @gforce301 i was able to find a solution for the situation, just to put some context to the problem, everything start because i was not able to wrap the text select cros-tags like @gforce301 mention on the solution he post, i was trying to get html in this way: bold text</strong> and more text</p>
because my idea was check text and open and close the mark
tag before of the closing of the </strong>
tag and open another mark tag at the end and close it at the end of the selection, something like this <mark>bold text</mark></strong><mark>and more text</mark>
but because the browser close if it find a open tag with out been closed and open tag if it find just the closed one i was getting back this HTML <p><strong>bold text</strong> and more text</p>
. 好了,感谢@ gforce301,我能够找到这种情况的解决方案,只是为了解决问题,一切都开始了,因为我无法在他发布的解决方案上包装诸如@ gforce301之类的选择cros-tag的文本,我试图以这种方式获取html:
bold text</strong> and more text</p>
因为我的想法是检查文本并在</strong>
标签关闭之前打开并关闭mark
标签,然后再打开另一个标签在标记的末尾标记标记,并在选择的结尾将其关闭,类似这样的<mark>bold text</mark></strong><mark>and more text</mark>
但是由于浏览器在找到一个带有未关闭标签的open标记,如果找到刚关闭的标签,则打开标签,我正在找回HTML <p><strong>bold text</strong> and more text</p>
。
after testing the solution of @gforce301 i get to this solution: 在测试@ gforce301的解决方案后,我得到以下解决方案:
public markContent(): void {
const selection: any = window.getSelection();
const range: any = selection.getRangeAt(0);
if (range.startOffset !== range.endOffset) {
const htmlSelection = this.getHtmlSelection(selection);
const textSeleted: string = selection.toString();
const highlight: any = range.commonAncestorContainer;
if (this.markerEvent !== 'mark') {
const marker: any = document.createElement('mark');
marker.setAttribute('class', this.colorMarker);
marker.innerHTML = htmlSelection;
range.deleteContents();
range.insertNode(marker);
this.hideBubble();
return;
}
const p = document.createElement('p');
p.style.display = 'inline';
p.style.margin = '0';
p.innerHTML = highlight.innerHTML;
highlight.remove();
range.deleteContents();
range.insertNode(p);
this.hideBubble();
}
}
basically what i´m doing is get HTML of the selection using this function, 基本上我正在做的就是使用此功能获取所选内容的HTML,
public getHtmlSelection(selection: any): string {
let html: string;
const container = document.createElement('div');
for (let i = 0, len = selection.rangeCount; i < len; ++i) {
container.appendChild(selection.getRangeAt(i).cloneContents());
}
html = container.innerHTML;
return html;
}
i storage the HTML on a constant, create the mark element and insert the HTML of the selection on the new mark
element i create, remove the selection content and then insert the mark
node in the selection. 我将HTML存储在一个常量上,创建mark元素,然后将所选内容的HTML插入到我创建的新
mark
元素中,删除所选内容,然后在所选内容中插入mark
节点。 in case the user select again the text already highlighted is gonna remove the mark tag from the hold highlighted text. 如果用户再次选择已经突出显示的文本将从保留突出显示的文本中删除标记标签。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.