aboutsummaryrefslogtreecommitdiff
path: root/files/zh-cn/web/api/selection/index.html
blob: 828cca5fcaeaa9381385df930e6c72e8dd3d95fd (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
---
title: Selection
slug: Web/API/Selection
tags:
  - DOM
  - Gecko
  - NeedsTechnicalReview
  - NeedsTranslation
  - TopicStub
translation_of: Web/API/Selection
---
<div>{{ ApiRef("DOM") }}{{SeeCompatTable}}</div>

<p><code>Selection</code> 对象表示用户选择的文本范围或插入符号的当前位置。它代表页面中的文本选区,可能横跨多个元素。文本选区由用户拖拽鼠标经过文字而产生。要获取用于检查或修改的 Selection 对象,请调用 {{domxref("window.getSelection()")}}</p>

<p>一般来说,插入光标的位置可通过 Selection 获取,这时它被标记为 <code>Collapsed</code>,这表示选区被压缩至一点,即光标位置。但要注意它与 <code>focus</code> 事件或 {{domxref("Document.activeElement")}} 等的值没有必然联系。</p>

<p>用户可能从左到右(与文档方向相同)选择文本或从右到左(与文档方向相反)选择文本。<code>anchor</code> 指向用户开始选择的地方,而 <code>focus</code> 指向用户结束选择的地方。如果你使用鼠标选择文本的话,anchor 就指向你按下鼠标键的地方,而 focus 就指向你松开鼠标键的地方。anchor 和 focus 的概念不能与选区的起始位置和终止位置混淆,因为 anchor 指向的位置可能在 focus 指向的位置的前面,也可能在 focus 指向位置的后面,这取决于你选择文本时鼠标移动的方向(也就是按下鼠标键和松开鼠标键的位置)。</p>

<p>Selection 对象所对应的是用户所选择的 {{domxref("range","ranges")}} (区域),俗称拖蓝。默认情况下,该函数只针对一个区域,我们可以这样使用这个函数:</p>

<div style="overflow: hidden;">
<pre class="brush:js">var selObj = window.getSelection();
var range  = selObj.getRangeAt(0);</pre>
</div>

<ul>
 <li><code>selObj</code> 被赋予一个 Selection对象</li>
 <li>
  <p><code>range</code> 被赋予一个 <a href="/en-US/docs/DOM/range" title="DOM/Range">Range</a> 对象</p>
 </li>
</ul>

<p>调用 {{domxref("Selection.toString()","")}} 方法会返回被选中区域中的<strong>纯文本</strong>。要求变量为字符串的函数会自动对对象进行该处理,例如:</p>

<pre class="brush: js">var selObj = window.getSelection();
window.alert(selObj); </pre>

<h2 id="Glossary" name="Glossary">术语表</h2>

<p>本页面使用的其他关键词汇:</p>

<dl>
 <dt>锚点 (anchor)</dt>
 <dd>锚指的是一个选区的起始点(不同于HTML中的锚点链接,译者注)。当我们使用鼠标框选一个区域的时候,锚点就是我们鼠标按下瞬间的那个点。在用户拖动鼠标时,锚点是不会变的。</dd>
 <dt>焦点 (focus)</dt>
 <dd>选区的焦点是该选区的终点,当您用鼠标框选一个选区的时候,焦点是你的鼠标松开瞬间所记录的那个点。随着用户拖动鼠标,焦点的位置会随着改变。</dd>
 <dt>范围 (range)</dt>
 <dd>范围指的是文档中连续的一部分。一个范围包括整个节点,也可以包含节点的一部分,例如文本节点的一部分。用户通常下只能选择一个范围,但是有的时候用户也有可能选择多个范围(例如当用户按下Control按键并框选多个区域时,Chrome中禁止了这个操作,译者注)。“范围”会被作为 {{domxref("Range")}} 对象返回。Range对象也能通过DOM创建、增加、删减。</dd>
 <dt>可编辑元素 (editing host)</dt>
 <dd>一个用户可编辑的元素(例如一个使用 {{htmlattrxref("contenteditable")}} 的HTML元素,或是在启用了 {{domxref("Document.designMode", "designMode")}} 的 {{domxref("Document")}} 的子元素)。详见 <a href="#Selection_API_在可编辑元素焦点更改方面的行为">开发者笔记</a></dd>
</dl>

<h2 id="Properties" name="Properties">属性</h2>

<dl>
 <dt>{{domxref("Selection/anchorNode","anchorNode")}}{{ReadOnlyInline}}</dt>
 <dd>返回该选区起点所在的<span style="line-height: 1.5;">节点</span><span style="line-height: 1.5;">{{domxref("Node")}}</span><span style="line-height: 1.5;">)。</span></dd>
 <dt>{{domxref("Selection/anchorOffset","anchorOffset")}}{{ReadOnlyInline}}</dt>
 <dd>返回一个数字,其表示的是选区起点在 {{domxref("Selection/anchorNode","anchorNode")}} 中的位置偏移量。
 <ol>
  <li>如果 <code>anchorNode</code> 是文本节点,那么返回的就是从该文字节点的第一个字开始,直到被选中的第一个字之间的字数(如果第一个字就被选中,那么偏移量为零)。</li>
  <li>如果 <code>anchorNode</code> 是一个元素,那么返回的就是在选区第一个节点之前的同级节点总数。(这些节点都是 <code>anchorNode</code> 的子节点)</li>
 </ol>
 </dd>
 <dt>{{domxref("Selection/focusNode","focusNode")}}{{ReadOnlyInline}}</dt>
 <dd>返回该选区终点所在的节点。</dd>
 <dt>{{domxref("Selection/focusOffset","focusOffset")}}{{ReadOnlyInline}}</dt>
 <dd>返回一个数字,其表示的是选区终点在 {{domxref("Selection/focusNode","focusNode")}} 中的位置偏移量。
 <ol>
  <li>如果 <code>focusNode</code> 是文本节点,那么选区末尾未被选中的第一个字,在该文字节点中是第几个字(从0开始计),就返回它。</li>
  <li>如果 <code>focusNode</code> 是一个元素,那么返回的就是在选区末尾之后第一个节点之前的同级节点总数。</li>
 </ol>
 </dd>
 <dt>{{domxref("Selection/isCollapsed","isCollapsed")}}{{ReadOnlyInline}}</dt>
 <dd>返回一个布尔值,用于判断选区的起始点和终点是否在同一个位置。</dd>
 <dt>{{domxref("Selection/rangeCount","rangeCount")}}{{ReadOnlyInline}}</dt>
 <dd>返回该选区所包含的连续范围的数量。</dd>
</dl>

<h2 id="Methods" name="Methods">方法</h2>

<dl>
 <dt>{{domxref("Selection/getRangeAt","getRangeAt")}}</dt>
 <dd>返回选区包含的指定区域({{domxref("Range")}})的<strong>引用</strong></dd>
 <dt>{{domxref("Selection/collapse","collapse")}}</dt>
 <dd>将当前的选区折叠为一个点。</dd>
 <dt>{{domxref("Selection/extend","extend")}}</dt>
 <dd>将选区的焦点移动到一个特定的位置。</dd>
 <dt>{{domxref("Selection/modify","modify")}} {{gecko_minversion_inline("2.0")}}</dt>
 <dd>修改当前的选区。</dd>
 <dt>{{domxref("Selection/collapseToStart","collapseToStart")}}</dt>
 <dd>将当前的选区折叠到起始点。</dd>
 <dt>{{domxref("Selection/collapseToEnd","collapseToEnd")}}</dt>
 <dd>将当前的选区折叠到最末尾的一个点。</dd>
 <dt>{{domxref("Selection/selectAllChildren","selectAllChildren")}}</dt>
 <dd>将某一指定节点的子节点框入选区。</dd>
 <dt>{{domxref("Selection/addRange","addRange")}}</dt>
 <dd>一个区域({{domxref("Range")}})对象将被加入选区。</dd>
 <dt>{{domxref("Selection/removeRange","removeRange")}}</dt>
 <dd>从选区中移除一个区域。</dd>
 <dt>{{domxref("Selection/removeAllRanges","removeAllRanges")}}</dt>
 <dd>将所有的区域都从选区中移除。</dd>
 <dt>{{domxref("Selection/deleteFromDocument","deleteFromDocument")}}</dt>
 <dd>从页面中删除选区中的内容。</dd>
 <dt>{{domxref("Selection/selectionLanguageChange","selectionLanguageChange")}}</dt>
 <dd>当键盘的朝向发生改变后修改指针的Bidi优先级。</dd>
 <dt>{{domxref("Selection/toString","toString")}}</dt>
 <dd>返回当前选区的纯文本内容。</dd>
 <dt>{{domxref("Selection/containsNode","containsNode")}}</dt>
 <dd>判断某一个 {{domxref("Node")}} 是否为当前选区的一部分。</dd>
</dl>

<h2 id="开发者笔记">开发者笔记</h2>

<h3 id="选区的字符串表示">选区的字符串表示</h3>

<p>调用 {{DOMxRef("Selection.toString()")}} 方法返回包含在选区内的文本,例如:</p>

<pre class="brush: js">var selObj = window.getSelection();
window.alert(selObj);
</pre>

<p>注意,使用选择对象作为 <code>window.alert</code> 的参数将调用对象的 <code>toString</code> 方法。</p>

<h3 id="选区中的多个区域">选区中的多个区域</h3>

<p>一个 <code>Selection</code> 对象表示用户选择的 {{DOMxRef("Range")}} 的集合。通常,它只包含一个区域,访问方式如下:</p>

<pre class="brush: js"><code>var selObj = window.getSelection();
var range  = selObj.getRangeAt(0);</code></pre>

<ul>
 <li><code><var>selObj</var></code> 是一个 <code>Selection</code> 对象</li>
 <li><code><var>range</var></code> 是一个 {{domxref("Range")}} 对象</li>
</ul>

<p><code>getRangeAt</code> 方法返回对象的<strong>引用</strong>,并且对该函数返回的 <code>Range</code> 对象所运行的函数,会直接作用到选区上,并可能影响用户焦点的情况。</p>

<p>正如 <a href="http://www.w3.org/TR/selection-api/#h_note_15">Selection API 规范</a> 所指出的,Selection API 最初由 Netscape 创建,并允许多个区域(例如,允许用户从 {{HTMLElement("table")}} 中选择列)。但是,Gecko 以外的浏览器没有实现多个区域,而且规范还要求选择的内容始终(仅)具有一个范围(允许多个区域可能引起不必要的兼容性问题,例如同时从多处输入,译者注)。</p>

<h3 id="Selection_及输入焦点">Selection 及输入焦点</h3>

<p>选择和输入焦点(由 {{domxref("Document.activeElement")}} 表示)有一个复杂的关系,该关系因浏览器而异。在跨浏览器兼容的代码中,最好分别处理它们。</p>

<p>Safari和Chrome(与Firefox不同)目前在以编程方式修改 <code>Selection</code> 时会将包含选区的元素作为焦点;这可能在将来会发生变化(请参见 <a href="https://www.w3.org/Bugs/Public/show_bug.cgi?id=14383">W3C Bug 14383</a> 和 {{WebKitBug("3869")}})。</p>

<p>(目前在 WebKit 中,按钮等元素被直接点击不会修改选区,但会将焦点传递,译者注)</p>

<h3 id="Selection_API_在可编辑元素焦点更改方面的行为">Selection API 在可编辑元素焦点更改方面的行为</h3>

<p>Selection API 有一个共同的行为(即在浏览器之间共通),该行为控制在调用某些方法后<a href="#Glossary">可编辑元素</a>(原文 Editing Hosts,可编辑宿主)的焦点行为如何更改。</p>

<p>其行为如下:</p>

<ol>
 <li>如果先前的选区不在可编辑元素内,则可编辑元素将获得焦点。</li>
 <li>调用一个 Selection API 方法,从而在可编辑元素内产生一个新选区,来创造一个新的 <code>Selection</code> 区域({{domxref("Range")}})。</li>
 <li>然后焦点(此处应指显示的,译者注)移到可编辑元素。</li>
</ol>

<p><strong>注意:Selection API方法只能将焦点移动到可编辑元素,而不能移动到其他可焦点元素(例如{{HTMLElement("a")}})。</strong></p>

<p>上述行为适用于使用以下方法产生的选区:</p>

<ul>
 <li>{{domxref("Selection.collapse()")}}</li>
 <li>{{domxref("Selection.collapseToStart()")}}</li>
 <li>{{domxref("Selection.collapseToEnd()")}}</li>
 <li>{{domxref("Selection.extend()")}}</li>
 <li>{{domxref("Selection.selectAllChildren()")}}</li>
 <li>{{domxref("Selection.addRange()")}}</li>
 <li>{{domxref("Selection.setBaseAndExtent()")}}</li>
</ul>

<p>以及在 {{domxref("Range")}} 使用以下方法修改时:</p>

<ul>
 <li>{{domxref("Range.setStart()")}}</li>
 <li>{{domxref("Range.setEnd()")}}</li>
 <li>{{domxref("Range.setStartBefore()")}}</li>
 <li>{{domxref("Range.setStartAfter()")}}</li>
 <li>{{domxref("Range.setEndBefore()")}}</li>
 <li>{{domxref("Range.setEndAfter()")}}</li>
 <li>{{domxref("Range.collapse()")}}</li>
 <li>{{domxref("Range.selectNode()")}}</li>
 <li>{{domxref("Range.selectNodeContents()")}}</li>
</ul>

<h2 id="浏览器兼容性">浏览器兼容性</h2>

<p>{{Compat("api.Selection")}}</p>

<h3 id="Gecko_备注">Gecko 备注</h3>

<ul>
 <li>Gecko/Firefox 提供了其他功能,仅适用于Chrome(内置及插件)代码。 这些定义在 {{Interface("nsISelectionPrivate")}} 中。</li>
 <li>Mozilla 实现源代码:{{Source("dom/webidl/Selection.webidl")}}</li>
 <li>在Firefox 29之前,{{domxref("Selection.selectionLanguageChange()")}}{{Obsolete_Inline("gecko29")}} 都会暴露在Web内容中。</li>
</ul>

<h2 id="See_also" name="See_also">扩展</h2>

<ul>
 <li>{{domxref("window.getSelection")}}{{domxref("document.getSelection")}}{{domxref("Range")}}</li>
 <li>HTML5 DOM Range <a class="external" href="http://html5.org/specs/dom-range.html#selection" title="http://html5.org/specs/dom-range.html#selection">Interface Selection</a></li>
 <li><a class="external" href="http://lxr.mozilla.org/mozilla/source/content/base/public/nsISelection.idl">IDL definition in Mozilla cross-reference</a></li>
 <li><a href="http://www.zhihu.com/question/20874144">目前 CSS 实现竖排文本较为通用的方式是什么?</a>(页内搜索"Bidi"可了解Bidi优先顺序)</li>
</ul>