>  기사  >  웹 프론트엔드  >  JS Range HTML 문서/텍스트 컨텐츠 선택, 라이브러리 및 애플리케이션 소개_javascript 기술

JS Range HTML 문서/텍스트 컨텐츠 선택, 라이브러리 및 애플리케이션 소개_javascript 기술

WBOY
WBOY원래의
2016-05-16 18:06:481299검색
一、前面的些话
本文的内容基本上是基于“区域范围对象(Range objects)”这个概念来说的。这个玩意,可以让你选择HTML文档的任意部分,并可以拿这些选择的信息做你想做的事情。其中,最常见的Range是用户用鼠标选择的内容(user selection)。

本文有不少篇幅就是讲如何将用户的这种选择转换为W3C Range或Microsoft Text Range对象。

二、什么是Range?
所谓"Range",是指HTML文档中任意一段内容。一个Range的起始点和结束点位置任意,甚至起始点和结束点可以是一样的(也就是空Range)。最常见的Range是用户文本选择范围(user text selection)。当用户选择了页面上的某一段文字后,你就可以把这个选择转为Range。当然,你也可以直接用程序定义Range。

例如下面这个模样的例子:

2011-04-12 
负责调查切尔诺贝利核事故对人与环境造成影响的俄科学家亚布罗科夫<span class="selected">博士指出,因福岛核电站使用的燃料较切尔诺贝利核电站多,且有反应堆使用</span>了含有高毒性的钚的燃料,因此"福岛核电站事故可能会比切尔诺贝利带来更严重的后果"。

上面选中状态的那些文字就可以转换成Range对象(下面会详细讲述)。通过Range对象你可以找到Range的起始点和结束点,如果你实在有心,还可以删除或是复制这些内容,或是用其他文字替换,甚至是简单的HTML。

上面的例子可以说是最简单的Range对象的例子,因为其只包含了文字。而实际上,Range对象也是可以包含HTML代码内容的,例如下面这个示例:

<time>2011-04-12</time> 
<p>据日本广播协会电视台12日报道,日本经济产业省原子能安全保安院决定将福岛第一核电站核泄漏事故等级提高至7级。这使日本核<span class="selected">泄漏事故等级与苏联切尔诺贝利核电站核泄漏事故等级相同。</p> 
<p>负责调查切尔诺贝</span>利核事故对人与环境造成影响的俄科学家亚布罗科夫博士指出,因福岛核电站使用的燃料较切尔诺贝利核电站多,且有反应堆使用了含有高毒性的钚的燃料,因此"福岛核电站事故可能会比切尔诺贝利带来更严重的后果"。</p>

同样的,Range对象被创建,且包含HTML,现在的问题是选择的内容正好跨过了楚河和汉界(跨标签),如果就单纯的论选择的内容的话,应该如下:

泄漏事故等级与苏联切尔诺贝利核电站核泄漏事故等级相同。</p> 
<p>负责调查切尔诺贝

显然,上面的HTML属于1级残废,基本无效。然而幸运的是,所有的浏览器都会自动调整HTML片段使其有效,就像变成下面这样:

泄漏事故等级与苏联切尔诺贝利核电站核泄漏事故等级相同。</p> <p>负责调查切尔诺贝

可以看到,浏览器自动补全了一定数目的HTML来让Range有效。如果你复制或是移动Range,你所复制或移动的HTML内容一定是有效的。

三、浏览器的兼容性

在真正操刀JavaScript之前我们需要大致知道Range对象的浏览器兼容性情况。实际上,问题是比较麻烦的,因为至少有3种类似Range对象,且你有必要全部理解。先展示详细的兼容性情况表:

支持:支持不支持:不支持部分支持:部分支持

1. W3C 범위
W3C 제품군
  Explorer 6/7 Firefox 2 Safari 1.3 Opera 9
cloneContents() 不支持 支持 部分支持 支持
cloneRange() 不支持 支持 支持 支持
collapse() tbd tbd tbd tbd
collapsed 不支持 支持 支持 支持
commonAncestorContainer 不支持 支持 支持 支持
compareBoundaryPoints() 不支持 支持 支持 支持
comparePoint() – Mozilla 扩展 不支持 支持 不支持 不支持
createContextualFragment() – Mozilla 扩展 不支持 支持 支持 支持
deleteContents() 不支持 支持 支持 支持
detach() 不支持 支持 支持 支持
endContainer 不支持 支持 支持 支持
endOffset 不支持 支持 支持 部分支持
extractContents() 不支持 支持 支持 支持
insertNode() 不支持 支持 支持 支持
isPointInRange() – Mozilla 扩展 不支持 支持 不支持 不支持
selectNode() 不支持 支持 支持 支持
selectNodeContents() 不支持 支持 支持 支持
setEnd() 不支持 支持 支持 支持
setEndAfter() 不支持 支持 支持 支持
setEndBefore() 不支持 支持 支持 支持
setStart() 不支持 支持 支持 支持
setStartAfter() 不支持 支持 支持 支持
setStartBefore() 不支持 支持 支持 支持
startContainer 不支持 支持 支持 支持
startOffset 不支持 支持 支持 部分支持
surroundContents() 不支持 支持 支持 支持

说明:
cloneContents()的用法类似docFrag = rangeObject.cloneContents()Range对象内容被克隆同时被添加到文档片段上,并返回自身。但是在Safari下有个问题,即如果选择范围是空,将会返回null而不是空的文档片段。可以通过类似docFrag = rangeObject.cloneContents() || document.createDocumentFragment()这样的代码修复。

deleteContents()处,Range内容会被永久删除,无返回值。

endContainer指用户选择内容结尾处的容器节点。通常是文本节点。

extractContents()用法docFrag = rangeObject.extractContents()。从DOM树上剪切Range对象并返回文档片段。该片段可以粘贴到页面上。

startContainer指用户选择内容起始处的容器节点。通常是文本节点。

startOffset在Opera浏览器下,在选择内容为空的时候返回0

2. 모질라 선택
모질라 선택
  Explorer 6/7 Firefox 2 Safari 1.3 Opera 9
addRange() 不支持 支持 不支持 支持
anchorNode 不支持 支持 支持 支持
anchorOffset 不支持 支持 支持 部分支持
collapse() tbd tbd tbd tbd
collapseToEnd() 不支持 支持 支持 支持
collapseToStart() 不支持 支持 支持 支持
containsNode() 不支持 支持 不支持 支持
deleteFromDocument() 不支持 支持 不支持 支持
extend() 不支持 支持 不支持 支持
focusNode 不支持 支持 支持 支持
focusOffset 不支持 支持 支持 部分支持
getRangeAt() 不支持 支持 不支持 支持
isCollapsed 不支持 支持 支持 支持
rangeCount 不支持 支持 不支持 支持
removeAllRanges() 不支持 支持 不支持 支持
removeRange() 不支持 支持 不支持 支持
selectAllChildren() 不支持 支持 不支持 支持
selectionLanguageChange() 不支持 支持 不支持 支持

说明:
anchorNode用法为userSelection.anchorNode。指用户选择内容起始处的容器节点。通常是文本节点。

anchorNode在Opera浏览器下,在选择内容为空的时候返回0

focusNode用法为userSelection.focusNode。指用户选择内容结尾处的容器节点。通常是文本节点。

focusOffset在Opera浏览器下,在选择内容为空的时候返回0

getRangeAt()用法为rangeObject = userSelection.getRangeAt(0),作用是将Mozilla Selection转换为W3C Range

3. 마이크로소프트 텍스트레인지
Microsoft TextRange
  Explorer 6/7 Firefox 2 Safari 1.3 Opera 9
boundingHeight 支持 不支持 不支持 不支持
boundingLeft 支持 不支持 不支持 不支持
boundingTop 支持 不支持 不支持 不支持
boundingWidth 支持 不支持 不支持 不支持
collapse() tbd tbd tbd tbd
compareEndPoints() 支持 不支持 不支持 不支持
duplicate() 支持 不支持 不支持 支持
expand() 支持 不支持 不支持 不支持
findText() 支持 不支持 不支持 不支持
htmlText 支持 不支持 不支持 不支持
move() 支持 不支持 不支持 支持
moveEnd() 支持 不支持 不支持 支持
moveStart() 支持 不支持 不支持 支持
moveToElementText() 支持 不支持 不支持 支持
moveToPoint() 支持 不支持 不支持 不支持
offsetLeft 支持 不支持 不支持 不支持
offsetTop 支持 不支持 不支持 不支持
parentElement() 支持 不支持 不支持 支持
pasteHTML() 支持 不支持 不支持 不支持
scrollIntoView() 支持 不支持 不支持 不支持
select() 支持 不支持 不支持 支持
text 支持 不支持 不支持 支持

说明:
htmlText用法为htmlString = userSelection.htmlText。返回字符串,为TextRange的HTML内容,相当于innerHTML。只读。

pasteHTML(),当粘贴HTML到一个文本节点时,该文本节点自动分隔。

text用法为string = userSelection.text。返回字符串,为TextRange的文本内容,相当于innerText。可读/写。

4. 总的兼容性
总的兼容性
  Explorer 6/7 Firefox 2 Safari 1.3 Opera 9
W3C Range

详述

不支持 支持 支持 支持
Mozilla Selection

详述

不支持 支持 部分支持 支持
Microsoft Text Range

详述

支持 不支持 不支持 部分支持

지침:

  • W3C Range对象가 유일한 공식 명칭입니다. 기본적으로 Range을 DOM을 포함하는 문서 조각으로 처리합니다.
  • Mozilla Selection对象은 다소 중복되며 Netscape 4와의 하위 호환성을 위해 존재합니다. W3C Range对象과 유사하며 DOM 트리를 기반으로 합니다.
  • Microsoft Text Range对象Guo Degang과 Xuan Bin의 차이점은 문자열을 기반으로 하기 때문에 위 두 가지입니다. 사실 Text Range에 포함된 문자열이 DOM 노드로 한꺼번에 점프하기는 어렵습니다.

일반적으로 Mozilla Selection对象은 사용자가 선택한 모든 콘텐츠를 완전한 Range对象으로 직접 변환할 수 있으며 일부 추가 방법이나 속성이 Netscape 4와 역호환될 수 있다는 점이 유일한 장점입니다. . 하지만 불행하게도 IE를 제외한 다른 브라우저는 이것을 지원합니다 Selection对象.

4. 사용자가 선택한 콘텐츠 얻기

시어머니 설명 필요없이 해당 코드만 보시면 됩니다:

코드 복사 코드는 다음과 같습니다:

var userSelection;
if (window.getSelection) { //최신 브라우저
userSelection = window.getSelection()
} else if (document.selection ) { //IE 브라우저는 Opera를 고려하여 맨 마지막에 배치해야 합니다
userSelection = document.selection.createRange()
}

호환성 문제로 인해 IE 브라우저는 IE와 다른 브라우저를 활용합니다. Mozilla 찐빵을 먹어보세요.

위의 userSelection은 Mozilla, Safari, Opera에서는 Selection 개체이고, IE에서는 Text Range 개체입니다. 이러한 차이점은 후속 스크립트에 영향을 미칩니다. Internet Explorer의 텍스트 범위는 Mozilla의 Selection 또는 W3C의 Range 개체와 완전히 다릅니다. IE 및 기타 브라우저에 대해 두 가지 다른 스크립트 세트를 작성해야 합니다.

스크립트 작성 순서에 주의해야 합니다. Mozilla Selection을 먼저 배치해야 합니다. 그 이유는 Opera가 두 종류의 객체를 지원하기 때문입니다. window.getSelection()을 사용하여 사용자가 선택한 내용을 읽으면 Opera는 Selection 객체를 생성하고 document.selection을 사용하면 Text Range 객체를 생성합니다.

Opera는 Mozilla Selection과 W3C Range를 매우 잘 지원하지만 Microsoft Text Range에 대한 지원은 만족스럽지 않기 때문입니다. 따라서 표준 브라우저(예: window.getSelection() 사용)에 우선순위가 부여됩니다.

5. userSelection의 내용
userSelection 변수의 현재 내용은 Mozilla Selection 또는 Microsoft Text Range 개체입니다. 따라서 개체에 정의된 모든 메서드와 속성에 대한 액세스를 허용합니다.

Mozilla Selection 객체에는 다음과 같이 사용자가 선택한 텍스트 콘텐츠가 포함되어 있습니다.

alert(userSelection)
형식이 문자열은 아니지만 다음과 유사한 팝업이 표시됩니다. 최신 브라우저에서는 다음 내용이 계속 표시됩니다. 내용:

누출 사고 수준은 소련 체르노빌 원자력 발전소에서 발생한 핵 누출 사고 수준과 같습니다. 체르노빌 조사 담당자
Microsoft Text Range 개체에서 동일한 정보를 얻으려면 userSelection.text를 사용해야 합니다. 회전된 텍스트를 읽으려면 다음과 유사한 코드를 사용하면 됩니다.
코드 복사 코드는 다음과 같습니다.

var selectedText = userSelection;
if (userSelection.text) {
selectedText = userSelection.text;
}

이제 selectedText에 텍스트가 포함됩니다. 사용자가 선택했습니다.

여기를 클릭하세요: 사용자가 선택한 텍스트 데모 가져오기

예를 들어 IE7 브라우저에서 텍스트를 선택하고 데모 페이지에서 테스트 버튼을 클릭하세요. 팝업 내용은 다음과 같습니다.
JS Range HTML 문서/텍스트 컨텐츠 선택, 라이브러리 및 애플리케이션 소개_javascript 기술
6. Selection 개체에서 Range 개체를 만듭니다.
IE 브라우저에서는 userSelection이 Text Range입니다. 브라우저에서 userSelection은 여전히 ​​Selection 개체입니다. Selection 개체와 동일한 내용을 가진 Range 개체를 만들려면 다음과 유사한 코드를 사용할 수 있습니다.
코드 복사 코드는 다음과 같습니다.

var getRangeObject = function(selectionObject) {
if (selectionObject.getRangeAt)
return SelectionObject.getRangeAt(0);
else { // 이전 버전의 Safari!
var range = document.createRange();
range.setStart(selectionObject.anchorNode,selectionObject.anchorOffset)
range.setEnd(selectionObject.focusNode) ,selectionObject.focusOffset);
반환 범위;
}
}
var rangeObject = getRangeObject(userSelection);
이상적으로는 Selection 개체의 getRangeAt() 메서드를 통해 W3C Range 개체를 가져올 수 있습니다. 이 메소드는 주어진 인덱스 값의 범위 객체를 반환할 수 있습니다. 일반적으로 JavaScript에서 첫 번째 Range의 인덱스 값은 0입니다.

프로그램을 사용하여 Range 생성

Safari 1.3은 getRangeAt()를 지원하지 않으므로 이 브라우저를 고려하려면 다른 방법을 사용하여 새 Range를 생성해야 합니다. 물체. 당연히 객체가 생성됩니다.

var range = document.createRange()
위 코드 줄은 콘텐츠를 삽입하려면 setStart() 및 setEnd를 전달해야 합니다. () 메소드는 시작점과 끝점을 정의합니다.

이 두 메서드에는 두 개의 매개변수가 필요합니다.
1. Range의 시작 및 끝 DOM 노드
2. Range의 시작 및 끝 텍스트 오프셋. 오프셋은 텍스트 노드에서 선택한 텍스트의 첫 번째 및 마지막 문자 위치를 나타냅니다.

setStart()의 두 매개변수 속성은 startContainer와 startOffset이고, setEnd()의 두 매개변수 속성은 endContainer와 endOffset입니다.

다음 예를 들어보세요.

남자들은 50세가 되어도 26세 이상이고 아직 결혼하지 않은 여자를 절대 만져서는 안 됩니다. 그녀는 이혼하거나 사별할 수 있지만, 결코 미혼일 수는 없습니다. 26세 이후에 결혼하지 않았다면 이런 여성은 일반적으로 정신적으로 비정상이거나 심각한 문제를 갖고 있는 것입니다. 시장은 실수를 거의 하지 않습니다. 실수를 하더라도 보물을 획득할 확률은 매우 낮습니다.


향후 결혼시장의 변화는 매우 흥미로운 질문이 될 것이며, 이는 향후 본토 경제의 동향에도 결정적인 영향을 미칠 것입니다. 산업의 분포와 경제의 전반적인 효율성.


  1. 왜 정확한 숫자가 26인가요?

  2. 여기서 Range는 두 번째

    노드에서 시작하여 첫 번째

  3. (보통 텍스트 노드의 첫 번째 문자의 인덱스는 0입니다.)

    노드의 텍스트 오프셋 값은 8이고,

  4. 노드의 오프셋 값은 5입니다. ,


    var startP = [the p 노드];
    var endLi = [두 번째 li 노드];
    range.setStart(startP, 8)
    range.setEnd(endLi, 5)


    선택한 콘텐츠의 시작과 끝 읽기

    setStart(startContainer, startOffset) 및 setEnd(endContainer, endOffset)는 위에 언급되어 있습니다. 실제 상황을 고려하면, 사용자가 선택한 텍스트의 시작 위치를 정확하게 알기는 어렵습니다. 따라서 위의 오프셋 값을 한눈에 할당하는 방법에는 분명히 큰 한계가 있습니다. 다행히(위의 호환성 표 참조) Range 개체에는 선택 항목의 시작 및 끝 지점을 정의하는 데 사용되는 4개의 속성이 Selection 개체와 유사하지만 이름이 다릅니다. AnchorNode/anchorOffset은 선택 항목을 정의합니다. focusNode/focusOffset 정의가 종료됩니다.

    따라서 선택 항목을 생성하는 위 스크립트는 다음 코드를 사용하여 구현할 수 있습니다.

    range.setStart(selectionObject.anchorNode,selectionObject.anchorOffset)
    range.setEnd(selectionObject); .focusNode,selectionObject .focusOffset);

    Safari에 대한 우려

    벌써 2011년, Shi Xiaolong이 스캔들에 연루되었고 Safari 5가 나온 지 꽤 되었습니다. 따라서 단지 사파리 하위 버전만을 고려하여 Range를 생성하는 프로그램을 사용한다면 전혀 필요하지 않다고 생각합니다. 특히 우리가 사는 이 마법 같은 나라에서는 Safari를 먼저 사용하는 사람이 거의 없고 낮은 버전을 사용하는 사람도 거의 없습니다. Safari는 오랫동안 getRangeAt()를 지원해 왔으며 Chrome 브라우저도 마찬가지입니다.

    여기를 클릭할 수 있습니다: Safari에서 getRangeAt 테스트 데모

    데모 페이지에서 텍스트의 일부를 선택한 다음 테스트 버튼을 클릭하면 최신 버전의 Safari에 표시됩니다. browser 아래 그림과 비슷한 결과가 나타납니다.


    따라서 현재 환경에서 Selection 개체를 Range 개체로 변환하려면 다음 코드를 사용하세요(풀 버전). JS Range HTML 문서/텍스트 컨텐츠 선택, 라이브러리 및 애플리케이션 소개_javascript 기술

    var userSelection, rangeObject
    if ( window.getSelection) {
    //최신 브라우저
    userSelection = window.getSelection();
    } else if (document.selection) {
    //IE 브라우저는 Opera를 고려하므로 배치해야 합니다.
    userSelection = document .selection.createRange();
    }

    //Range 객체
    rangeObject = userSelection
    if (userSelection.getRangeAt) {
    // 최신 브라우저
    rangeObject = userSelection.getRangeAt(0)
    }


    七、rangy – JavaScript Range&Selection库
    项目地址:http://code.google.com/p/rangy/

    就在几天前,rangy更新到了版本1.1,作者还新更新了四五个示意的页面,展示了相关的API,方法和属性等。虽然如此,由于实例较少,还是让人很难知道此JavaScript库如何使用。这里就举几个简单的例子示意下。//zxx:此插件非压缩达115K,个人觉得有些庞大,在实际项目中的应用价值不大
    JS Range HTML 문서/텍스트 컨텐츠 선택, 라이브러리 및 애플리케이션 소개_javascript 기술
    示例1,获取用户选中的文字:

    您可以狠狠地点击这里:rangy获取用户选中文字demo

    选中部分文字点击按钮,会有如下弹出(截自Firefox3.6):
    JS Range HTML 문서/텍스트 컨텐츠 선택, 라이브러리 및 애플리케이션 소개_javascript 기술
    相关JavaScript代码如下:
    复制代码 代码如下:

    var sel = rangy.getSelection();
    alert(sel.toString());

    示例2,给选中文字添加背景

    您可以狠狠地点击这里:文字选中添加背景图demo

    选中页面上一段文字,然后失去焦点,就会看到文字后面有了个美女背景图,如下截图,截自IE7浏览器:
    JS Range HTML 문서/텍스트 컨텐츠 선택, 라이브러리 및 애플리케이션 소개_javascript 기술
    完整JavaScript代码如下:
    复制代码 代码如下:



    <script> <br>var cssApplier; <br>window.onload = function() { <br>rangy.init(); <br>cssApplier = rangy.createCssClassApplier("selectClass", true); <br>document.body.onmouseup = function() { <br>cssApplier.toggleSelection(); <br>}; <br>}; <br></script>

    如果您看到下面的文字,可能是由于在其他网站或是RSS中阅读本文,本文原地址:http://www.zhangxinxu.com/wordpress/?p=1591,本文作者:张鑫旭,来自张鑫旭-鑫空间-鑫生活,访问原出处更多优秀技术文章。
    八、实际的应用
    微博之插入话题

    差不多去年这个时候,自己折腾过JS 文本域光标处添加文字并选中的内容,也是拿的新浪微博示例的,文章是“新浪微博插入话题后部分文字选中的js实现”,但是去年这篇文章多实现的话题插入效果是比较弱的:
    1. 选中普通文字不能作为话题插入
    2. 话题只能插在文本域最后二不是光标处
    3. 默认文字的话题可以重复插入

    所以,趁这个机会,正好把微博之插入话题这个功能完善下。

    您可以狠狠地点击这里:微博插入话题的效果实现demo

    欢迎输入内容,点击测试。大致会有类似下面的效果(截自Chrome):
    JS Range HTML 문서/텍스트 컨텐츠 선택, 라이브러리 및 애플리케이션 소개_javascript 기술

    源代码有些高度,为了节约篇幅,这里就不展示出来了,您可以在demo页面中看到完整的CSS/HTML/JS代码。不过JS部分半封装,您要是有兴趣可以在外面包裹一个函数使其插件化,我是懒得再去折腾了。

    九、结语相关

    对于Range相关的知识即使到现在都是半生不熟的,所以文章的内容更多的算是翻译性质的内容。自己并没有从深入理解的基础上很浅显地剖析相关知识点,文章很多地方会显得不怎么通俗易懂。

    文中多展示的Range等兼容性表格的数据都是N年前的,还是Safari 1.3时代的数据,老的牙都掉了,实用价值大打折扣,不过可以告知的是先前现代浏览器所不支持的个别属性现早就支持了。

    跌跌撞撞,滚滚爬爬。文章难免有表述不准确的地方,欢迎指正。也欢迎提交相关的脚本的bug。

    参考文章及相关页面:
    1. 레인지 소개
    2. W3C DOM 호환성 – 범위
    3. rangy – 브라우저 간 JavaScript 범위 및 선택 라이브러리
    4. 텍스트 선택 시 배경 이미지 공개

    원래 기사, Zhang Xinxu-Xin Space-Xin Life에서 재인쇄할 때 표시해 주세요

성명:
본 글의 내용은 네티즌들의 자발적인 기여로 작성되었으며, 저작권은 원저작자에게 있습니다. 본 사이트는 이에 상응하는 법적 책임을 지지 않습니다. 표절이나 침해가 의심되는 콘텐츠를 발견한 경우 admin@php.cn으로 문의하세요.