简体   繁体   English

当我尝试获取所选文本的html时,如何避免浏览器自动打开或关闭标签

[英]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种情况必须以不同的方式处理。

  1. When the selection starts and stops in the same text node. 当选择在同一文本节点中开始和停止时。
  2. When the selection starts and stops in a different text node. 选择开始和停止时,将在另一个文本节点中进行。

I handled those cases by comparing the anchorNode and focusNode of the selection. 我通过比较选择的anchorNodefocusNode处理了这些情况。

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.

相关问题 如何从HTML文档中仅获取文本(无标记)? - How can I get the text only (no tags) from a HTML document? 如何使用 Javascript 在选定文本中获取所有 HTML 选择标签? - How do I get all the HTML selection tags in selected text using Javascript? 如何仅获取html标签? - How can I get only tags of html? 如何扫描一段文本并将“文本后面”的所有超链接替换为HTML属性标签? - How can I get a piece of text scanned and have all hyperlinks “behind the text” replaced with HTML attribute tags? 在第一个孩子之前和之后插入带有javascript的html标签时,避免浏览器自动关闭标签 - avoid browser auto close tag when inserting html tag with javascript before first-child and after 当我靠近文本字段时,如何在 html 中显示一个小消息框 - how to show a small message box in html when I get close to a field of text 如何在Javascript文本节点内获取HTML标签? - How do I get HTML tags inside of a Javascript Text Node? 在将选项文本分配给隐藏输入时,如何从选择选项中删除HTML nbsp标记 - How can i remove HTML nbsp tags from select options when assigning the text of option to hidden input 如何将 Html 标签插入传入的动态文本 - How can I insert Html tags into incoming dynamic text 如何使用jQuery将HTML标签显示为Text? - How can I display HTML tags as Text using jQuery?
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM