Ð ÑÑой главе Ð¼Ñ ÑаÑÑмоÑÑим вÑделение как в докÑменÑе, Ñак и в полÑÑ
ÑоÑмÑ, ÑакиÑ
как <input>.
JavaScript позволÑÐµÑ Ð¿Ð¾Ð»ÑÑаÑÑ ÑÑÑеÑÑвÑÑÑее вÑделение, вÑделÑÑÑ Ð¸ ÑнимаÑÑ Ð²Ñделение как Ñеликом, Ñак и по ÑаÑÑÑм, ÑбиÑаÑÑ Ð²ÑделеннÑÑ ÑаÑÑÑ Ð¸Ð· докÑменÑа, обоÑаÑиваÑÑ ÐµÑ Ð² Ñег и Ñак далее.
ÐÑ Ð¼Ð¾Ð¶ÐµÑе полÑÑиÑÑ Ð³Ð¾ÑовÑе ÑеÑÐµÐ½Ð¸Ñ Ð² ÑекÑии «ÐÑого» в конÑе ÑÑаÑÑи, но ÑзнаеÑе гоÑаздо болÑÑе, еÑли пÑоÑиÑаеÑе Ð³Ð»Ð°Ð²Ñ Ñеликом. ÐÑполÑзÑемÑе Ð´Ð»Ñ Ð²ÑÐ´ÐµÐ»ÐµÐ½Ð¸Ñ Ð²ÑÑÑоеннÑе клаÑÑÑ Range и Selection пÑоÑÑÑ Ð´Ð»Ñ Ð¿Ð¾Ð½Ð¸Ð¼Ð°Ð½Ð¸Ñ, и поÑле иÑ
изÑÑÐµÐ½Ð¸Ñ Ð²Ð°Ð¼ Ñже не понадобÑÑÑÑ Â«Ð³Ð¾ÑовÑе ÑеÑепÑÑ», ÑÑÐ¾Ð±Ñ ÑделаÑÑ Ð²ÑÑ, ÑÑо заÑ
оÑиÑе.
Range
РоÑнове вÑÐ´ÐµÐ»ÐµÐ½Ð¸Ñ Ð»ÐµÐ¶Ð¸Ñ Range â диапазон. Ðн пÑедÑÑавлÑÐµÑ Ñобой паÑÑ Â«Ð³ÑаниÑнÑÑ ÑоÑек»: наÑало и ÐºÐ¾Ð½ÐµÑ Ð´Ð¸Ð°Ð¿Ð°Ð·Ð¾Ð½Ð°.
ÐÐ°Ð¶Ð´Ð°Ñ ÑоÑка пÑедÑÑавлена как ÑодиÑелÑÑкий DOM-Ñзел Ñ Ð¾ÑноÑиÑелÑнÑм ÑмеÑением Ð¾Ñ Ð½Ð°Ñала. ÐÑли ÑÑÐ¾Ñ Ñзел â DOM-ÑлеменÑ, Ñо ÑмеÑение â ÑÑо Ð½Ð¾Ð¼ÐµÑ Ð´Ð¾ÑеÑнего ÑлеменÑа, а Ð´Ð»Ñ ÑекÑÑового Ñзла ÑмеÑение â позиÑÐ¸Ñ Ð² ÑекÑÑе. СкоÑо бÑдÑÑ Ð¿ÑимеÑÑ.
ÐавайÑе ÑÑо-нибÑÐ´Ñ Ð²Ñделим.
ÐÐ»Ñ Ð½Ð°Ñала Ð¼Ñ Ñоздадим диапазон (конÑÑÑÑкÑÐ¾Ñ Ð½Ðµ Ð¸Ð¼ÐµÐµÑ Ð¿Ð°ÑамеÑÑов):
let range = new Range();
ÐаÑем Ð¼Ñ ÑÑÑановим гÑаниÑÑ Ð²ÑделениÑ, иÑполÑзÑÑ range.setStart(node, offset) и range.setEnd(node, offset).
ÐапÑимеÑ, ÑаÑÑмоÑÑим ÑÑÐ¾Ñ ÑÑÐ°Ð³Ð¼ÐµÐ½Ñ HTML-кода:
<p id="p">Example: <i>italic</i> and <b>bold</b></p>
ÐзглÑнем на его DOM-ÑÑÑÑкÑÑÑÑ, обÑаÑиÑе внимание на ÑекÑÑовÑе ÑзлÑ, они Ð²Ð°Ð¶Ð½Ñ Ð´Ð»Ñ Ð½Ð°Ñ:
ÐÑделим "Example: <i>italic</i>". ÐÑо пеÑвÑе два доÑеÑниÑ
Ñзла Ñега <p> (ÑÑиÑÑÐ²Ð°Ñ ÑекÑÑовÑе ÑзлÑ):
<p id="p">Example: <i>italic</i> and <b>bold</b></p>
<script>
let range = new Range();
range.setStart(p, 0);
range.setEnd(p, 2);
// toString, вÑзваннÑй Ñ ÑкземплÑÑа Range, возвÑаÑÐ°ÐµÑ ÐµÐ³Ð¾ ÑодеÑжимое в виде ÑекÑÑа (без Ñегов)
alert(range); // Example: italic
// пÑименим ÑÑÐ¾Ñ Ð´Ð¸Ð°Ð¿Ð°Ð·Ð¾Ð½ к вÑÐ´ÐµÐ»ÐµÐ½Ð¸Ñ Ð´Ð¾ÐºÑменÑа (обÑÑÑнÑеÑÑÑ Ð´Ð°Ð»ÐµÐµ)
document.getSelection().addRange(range);
</script>
range.setStart(p, 0)â ÑÑÑÐ°Ð½Ð°Ð²Ð»Ð¸Ð²Ð°ÐµÑ Ð½Ð°Ñало диапазона на нÑлевом доÑеÑнем ÑлеменÑе Ñега<p>(ÐÑо ÑекÑÑовÑй Ñзел"Example: ").range.setEnd(p, 2)â ÑаÑÑиÑÑÐµÑ Ð´Ð¸Ð°Ð¿Ð°Ð·Ð¾Ð½ до 2го (но не вклÑÑÐ°Ñ ÐµÐ³Ð¾) доÑеÑнего ÑлеменÑа Ñега<p>(ÑÑо ÑекÑÑовÑй Ñзел" and ", но Ñак как ÐºÐ¾Ð½ÐµÑ Ð½Ðµ вклÑÑÑн, поÑледний вклÑÑÑннÑй Ñзел â ÑÑо Ñег<i>).
Ðиже пÑедÑÑавлен ÑаÑÑиÑеннÑй пÑимеÑ, в коÑоÑом Ð²Ñ Ð¼Ð¾Ð¶ÐµÑе попÑобоваÑÑ Ð´ÑÑгие ваÑианÑÑ:
<p id="p">Example: <i>italic</i> and <b>bold</b></p>
From <input id="start" type="number" value=1> â To <input id="end" type="number" value=4>
<button id="button">Click to select</button>
<script>
button.onclick = () => {
let range = new Range();
range.setStart(p, start.value);
range.setEnd(p, end.value);
// пÑименим вÑделение, обÑÑÑнÑеÑÑÑ Ð´Ð°Ð»ÐµÐµ
document.getSelection().removeAllRanges();
document.getSelection().addRange(range);
};
</script>
РпÑимеÑÑ, вÑделение Ñ 1 до 4 возвÑаÑÐ°ÐµÑ ÑледÑÑÑий диапазон <i>italic</i> and <b>bold</b>.
Ðе обÑзаÑелÑно иÑполÑзоваÑÑ Ð¾Ð´Ð¸Ð½ и ÑÐ¾Ñ Ð¶Ðµ ÑÐ»ÐµÐ¼ÐµÐ½Ñ Ð² setStart и setEnd. Ðиапазон Ð¼Ð¾Ð¶ÐµÑ Ð¾Ñ
ваÑÑваÑÑ Ð¼Ð½Ð¾Ð¶ÐµÑÑво не ÑвÑзаннÑÑ
Ð¼ÐµÐ¶Ð´Ñ Ñобой ÑлеменÑов. Ðажно лиÑÑ ÑÑÐ¾Ð±Ñ ÐºÐ¾Ð½ÐµÑ ÑÑл поÑле наÑала.
ÐÑделение ÑаÑÑей ÑекÑÑовÑÑ Ñзлов
ÐавайÑе вÑделим ÑекÑÑ ÑаÑÑиÑно, как показано ниже:
ÐÑо Ñакже возможно, нÑжно пÑоÑÑо ÑÑÑановиÑÑ Ð½Ð°Ñало и ÐºÐ¾Ð½ÐµÑ ÐºÐ°Ðº оÑноÑиÑелÑное ÑмеÑение в ÑекÑÑовÑÑ ÑÐ·Ð»Ð°Ñ .
Ðам нÑжно ÑоздаÑÑ Ð´Ð¸Ð°Ð¿Ð°Ð·Ð¾Ð½, коÑоÑÑй:
- наÑинаеÑÑÑ Ñо вÑоÑой позиÑии пеÑвого доÑеÑнего Ñзла Ñега
<p>(Ð·Ð°Ñ Ð²Ð°ÑÑваем вÑÑ, кÑоме пеÑвÑÑ Ð´Ð²ÑÑ Ð±Ñкв "Example: ") - заканÑиваеÑÑÑ Ð½Ð° 3 позиÑии пеÑвого доÑеÑнего Ñзла Ñега
<b>(Ð·Ð°Ñ Ð²Ð°ÑÑваем пеÑвÑе ÑÑи бÑÐºÐ²Ñ Â«bold», но не более):
<p id="p">Example: <i>italic</i> and <b>bold</b></p>
<script>
let range = new Range();
range.setStart(p.firstChild, 2);
range.setEnd(p.querySelector('b').firstChild, 3);
alert(range); // ample: italic and bol
// пÑименим вÑделение к докÑменÑÑ (обÑÑÑнÑеÑÑÑ Ð´Ð°Ð»ÐµÐµ)
window.getSelection().addRange(range);
</script>
ÐбÑÐµÐºÑ Ð´Ð¸Ð°Ð¿Ð°Ð·Ð¾Ð½Ð° Range Ð¸Ð¼ÐµÐµÑ ÑледÑÑÑие ÑвойÑÑва:
startContainer,startOffsetâ Ñзел и наÑалÑное ÑмеÑение,- в пÑимеÑе вÑÑе: пеÑвÑй ÑекÑÑовÑй Ñзел внÑÑÑи Ñега
<p>и2.
- в пÑимеÑе вÑÑе: пеÑвÑй ÑекÑÑовÑй Ñзел внÑÑÑи Ñега
endContainer,endOffsetâ Ñзел и конеÑное ÑмеÑение,- в пÑимеÑе вÑÑе: пеÑвÑй ÑекÑÑовÑй Ñзел внÑÑÑи Ñега
<b>и3.
- в пÑимеÑе вÑÑе: пеÑвÑй ÑекÑÑовÑй Ñзел внÑÑÑи Ñега
collapsedâ boolean,true, еÑли диапазон наÑинаеÑÑÑ Ð¸ заканÑиваеÑÑÑ Ð½Ð° одном и Ñом же меÑÑе (ÑледоваÑелÑно, в диапазон ниÑего не Ð²Ñ Ð¾Ð´Ð¸Ñ),- в пÑимеÑе вÑÑе:
false
- в пÑимеÑе вÑÑе:
commonAncestorContainerâ ближайÑий обÑий пÑедок вÑÐµÑ Ñзлов в пÑÐµÐ´ÐµÐ»Ð°Ñ Ð´Ð¸Ð°Ð¿Ð°Ð·Ð¾Ð½Ð°,- в пÑимеÑе вÑÑе:
<p>
- в пÑимеÑе вÑÑе:
ÐеÑÐ¾Ð´Ñ Range
СÑÑеÑÑвÑÐµÑ Ð¼Ð½Ð¾Ð¶ÐµÑÑво ÑдобнÑÑ Ð¼ÐµÑодов Ð´Ð»Ñ Ð¼Ð°Ð½Ð¸Ð¿ÑлиÑÐ¾Ð²Ð°Ð½Ð¸Ñ Ð´Ð¸Ð°Ð¿Ð°Ð·Ð¾Ð½Ð°Ð¼Ð¸.
УÑÑановиÑÑ Ð½Ð°Ñало диапазона:
setStart(node, offset)ÑÑÑановиÑÑ Ð½Ð°ÑалÑнÑÑ Ð³ÑаниÑÑ Ð² позиÑиÑoffsetвnodesetStartBefore(node)ÑÑÑановиÑÑ Ð½Ð°ÑалÑнÑÑ Ð³ÑаниÑÑ Ð¿ÑÑмо пеÑедnodesetStartAfter(node)ÑÑÑановиÑÑ Ð½Ð°ÑалÑнÑÑ Ð³ÑаниÑÑ Ð¿ÑÑмо поÑлеnode
УÑÑановиÑÑ ÐºÐ¾Ð½ÐµÑ Ð´Ð¸Ð°Ð¿Ð°Ð·Ð¾Ð½Ð° (Ð¿Ð¾Ñ Ð¾Ð¶Ð¸ на пÑедÑдÑÑие меÑодÑ):
setEnd(node, offset)ÑÑÑановиÑÑ ÐºÐ¾Ð½ÐµÑнÑÑ Ð³ÑаниÑÑ Ð² позиÑиÑoffsetвnodesetEndBefore(node)ÑÑÑановиÑÑ ÐºÐ¾Ð½ÐµÑнÑÑ Ð³ÑаниÑÑ Ð¿ÑÑмо пеÑедnodesetEndAfter(node)ÑÑÑановиÑÑ ÐºÐ¾Ð½ÐµÑнÑÑ Ð³ÑаниÑÑ Ð¿ÑÑмо поÑлеnode
Ðак бÑло показано, node Ð¼Ð¾Ð¶ÐµÑ Ð±ÑÑÑ ÐºÐ°Ðº ÑекÑÑовÑм Ñзлом, Ñак и ÑлеменÑом: Ð´Ð»Ñ ÑекÑÑовÑÑ
Ñзлов offset пÑопÑÑÐºÐ°ÐµÑ Ñказанное колиÑеÑÑво Ñимволов, в Ñо вÑÐµÐ¼Ñ ÐºÐ°Ðº Ð´Ð»Ñ ÑлеменÑов â Ñказанное колиÑеÑÑво доÑеÑниÑ
Ñзлов.
ÐÑÑгие:
selectNode(node)вÑделиÑÑnodeÑеликомselectNodeContents(node)вÑделиÑÑ Ð²ÑÑ ÑодеÑжимоеnodecollapse(toStart)еÑли ÑказаноtoStart=true, ÑÑÑановиÑÑ ÐºÐ¾Ð½ÐµÑнÑÑ Ð³ÑаниÑÑ Ð² наÑало, инаÑе ÑÑÑановиÑÑ Ð½Ð°ÑалÑнÑÑ Ð³ÑаниÑÑ Ð² конеÑ, ÑÑ Ð»Ð¾Ð¿ÑÐ²Ð°Ñ Ñаким обÑазом диапазонcloneRange()ÑоздаÑÑ Ð½Ð¾Ð²Ñй диапазон Ñ Ð¸Ð´ÐµÐ½ÑиÑнÑми гÑаниÑами
ЧÑÐ¾Ð±Ñ Ð¼Ð°Ð½Ð¸Ð¿ÑлиÑоваÑÑ ÑодеÑжимÑм в пÑÐµÐ´ÐµÐ»Ð°Ñ Ð´Ð¸Ð°Ð¿Ð°Ð·Ð¾Ð½Ð°:
deleteContents()â ÑдалиÑÑ ÑодеÑжимое диапазона из докÑменÑаextractContents()â ÑдалиÑÑ ÑодеÑжимое диапазона из докÑменÑа и веÑнÑÑÑ ÐºÐ°Ðº DocumentFragmentcloneContents()â ÑклониÑоваÑÑ ÑодеÑжимое диапазона и веÑнÑÑÑ ÐºÐ°Ðº DocumentFragmentinsertNode(node)â вÑÑавиÑÑnodeв докÑÐ¼ÐµÐ½Ñ Ð² наÑале диапазонаsurroundContents(node)â обеÑнÑÑÑnodeвокÑÑг ÑодеÑжимого диапазона. ЧÑÐ¾Ð±Ñ ÑÑÐ¾Ñ Ð¼ÐµÑод ÑÑабоÑал, диапазон должен ÑодеÑжаÑÑ ÐºÐ°Ðº оÑкÑÑваÑÑие, Ñак и закÑÑваÑÑие Ñеги Ð´Ð»Ñ Ð²ÑÐµÑ ÑлеменÑов внÑÑÑи ÑебÑ: не допÑÑкаÑÑÑÑ ÑаÑÑиÑнÑе Ð´Ð¸Ð°Ð¿Ð°Ð·Ð¾Ð½Ñ Ð¿Ð¾ ÑипÑ<i>abc.
ÐÑполÑзÑÑ ÑÑи меÑодÑ, Ð¼Ñ Ð¼Ð¾Ð¶ÐµÐ¼ делаÑÑ Ñ Ð²ÑделеннÑми Ñзлами ÑÑо Ñгодно.
ÐÑовеÑим опиÑаннÑе меÑÐ¾Ð´Ñ Ð² дейÑÑвии:
ÐажмиÑе на кнопкÑ, ÑÑÐ¾Ð±Ñ ÑооÑвеÑÑÑвÑÑÑий меÑод оÑÑабоÑал на вÑделении, или на "resetExample", ÑÑÐ¾Ð±Ñ Ð²Ð¾ÑÑÑановиÑÑ Ð²Ñделение как бÑло.
<p id="p">Example: <i>italic</i> and <b>bold</b></p>
<p id="result"></p>
<script>
let range = new Range();
// ÐаждÑй опиÑаннÑй меÑод пÑедÑÑавлен здеÑÑ:
let methods = {
deleteContents() {
range.deleteContents()
},
extractContents() {
let content = range.extractContents();
result.innerHTML = "";
result.append("ÐзвлеÑено: ", content);
},
cloneContents() {
let content = range.cloneContents();
result.innerHTML = "";
result.append("ÐлониÑовано: ", content);
},
insertNode() {
let newNode = document.createElement('u');
newNode.innerHTML = "ÐÐÐЫРУÐÐÐ";
range.insertNode(newNode);
},
surroundContents() {
let newNode = document.createElement('u');
try {
range.surroundContents(newNode);
} catch(e) { alert(e) }
},
resetExample() {
p.innerHTML = `Example: <i>italic</i> and <b>bold</b>`;
result.innerHTML = "";
range.setStart(p.firstChild, 2);
range.setEnd(p.querySelector('b').firstChild, 3);
window.getSelection().removeAllRanges();
window.getSelection().addRange(range);
}
};
for(let method in methods) {
document.write(`<div><button onclick="methods.${method}()">${method}</button></div>`);
}
methods.resetExample();
</script>
Также ÑÑÑеÑÑвÑÑÑ Ð¼ÐµÑÐ¾Ð´Ñ ÑÑÐ°Ð²Ð½ÐµÐ½Ð¸Ñ Ð´Ð¸Ð°Ð¿Ð°Ð·Ð¾Ð½Ð¾Ð², но они Ñедко иÑполÑзÑÑÑÑÑ. Ðогда они вам понадобÑÑÑÑ, Ð²Ñ Ð¼Ð¾Ð¶ÐµÑе пÑоÑиÑаÑÑ Ð¾ Ð½Ð¸Ñ Ð² ÑпеÑиÑикаÑии или ÑпÑавоÑнике MDN.
Selection
Range ÑÑо обÑий обÑÐµÐºÑ Ð´Ð»Ñ ÑпÑÐ°Ð²Ð»ÐµÐ½Ð¸Ñ Ð´Ð¸Ð°Ð¿Ð°Ð·Ð¾Ð½Ð°Ð¼Ð¸ вÑделениÑ. ÐÑ Ð¼Ð¾Ð¶ÐµÐ¼ ÑоздаваÑÑ Ð¸ пеÑедаваÑÑ Ð¿Ð¾Ð´Ð¾Ð±Ð½Ñе обÑекÑÑ. Сами по Ñебе они ниÑего визÑалÑно не вÑделÑÑÑ.
ÐÑделение в докÑменÑе пÑедÑÑавлено обÑекÑом Selection, коÑоÑÑй Ð¼Ð¾Ð¶ÐµÑ Ð±ÑÑÑ Ð¿Ð¾Ð»ÑÑен как window.getSelection() или document.getSelection().
ÐÑделение Ð¼Ð¾Ð¶ÐµÑ Ð²ÐºÐ»ÑÑаÑÑ Ð½Ð¾Ð»Ñ Ð¸Ð»Ð¸ более диапазонов. Ðо кÑайней меÑе, Ñак ÑÑвеÑждаеÑÑÑ Ð² СпеÑиÑикаÑии Selection API. Ðа пÑакÑике же вÑделиÑÑ Ð½ÐµÑколÑко диапазонов в докÑменÑе можно ÑолÑко в Firefox, иÑполÑзÑÑ Ctrl+click (Cmd+click Ð´Ð»Ñ Mac).
Ðиже пÑедÑÑавлен ÑкÑинÑÐ¾Ñ Ð²ÑÐ´ÐµÐ»ÐµÐ½Ð¸Ñ Ñ 3 диапазонами, ÑделаннÑй в Firefox:
ÐÑÑалÑнÑе бÑаÑзеÑÑ Ð¿Ð¾Ð´Ð´ÐµÑживаÑÑ Ð¼Ð°ÐºÑимÑм 1 диапазон. Ðак Ð¼Ñ Ñвидим далее, некоÑоÑÑе меÑÐ¾Ð´Ñ Selection подÑазÑмеваÑÑ, ÑÑо Ð¼Ð¾Ð¶ÐµÑ Ð±ÑÑÑ Ð½ÐµÑколÑко диапазонов, но, как бÑло Ñказано Ñанее, во вÑеÑ
бÑаÑзеÑаÑ
, кÑоме Firefox, Ð¼Ð¾Ð¶ÐµÑ Ð±ÑÑÑ Ð½Ðµ более одного диапазона.
СвойÑÑва Selection
ÐналогиÑно диапазонÑ, вÑделение Ð¸Ð¼ÐµÐµÑ Ð½Ð°ÑалÑнÑÑ Ð³ÑаниÑÑ, именÑемÑÑ Â«ÑкоÑем», и конеÑнÑÑ, назÑваемÑÑ Â«ÑокÑÑом».
ÐÑновнÑе ÑвойÑÑва вÑделениÑ:
anchorNodeâ Ñзел, Ñ ÐºÐ¾ÑоÑого наÑинаеÑÑÑ Ð²Ñделение,anchorOffsetâ ÑмеÑение вanchorNode, где наÑинаеÑÑÑ Ð²Ñделение,focusNodeâ Ñзел, на коÑоÑом вÑделение заканÑиваеÑÑÑ,focusOffsetâ ÑмеÑение вfocusNode, где вÑделение заканÑиваеÑÑÑ,isCollapsedâtrue, еÑли диапазон вÑÐ´ÐµÐ»ÐµÐ½Ð¸Ñ Ð¿ÑÑÑ Ð¸Ð»Ð¸ не ÑÑÑеÑÑвÑеÑ.rangeCountâ колиÑеÑÑво диапазонов в вÑделении, макÑимÑм1во вÑÐµÑ Ð±ÑаÑзеÑÐ°Ñ , кÑоме Firefox.
СÑÑеÑÑвÑÐµÑ Ð½ÐµÑколÑко меÑодов вÑделиÑÑ ÑодеÑжимое, в завиÑимоÑÑи Ð¾Ñ ÑÑÑÑойÑÑва полÑзоваÑелÑ: мÑÑÑ, гоÑÑÑие клавиÑи, нажаÑÐ¸Ñ Ð¿Ð°Ð»ÑÑем и дÑÑгие.
ÐекоÑоÑÑе из Ð½Ð¸Ñ , Ñакие как мÑÑÑ, позволÑÑÑ ÑоздаваÑÑ Ð²Ñделение в Ð¾Ð±Ð¾Ð¸Ñ Ð½Ð°Ð¿ÑавлениÑÑ : Ñлева напÑаво и ÑпÑава налево.
ÐÑли наÑало (ÑкоÑÑ) вÑÐ´ÐµÐ»ÐµÐ½Ð¸Ñ Ð¸Ð´ÑÑ Ð² докÑменÑе пеÑед конÑом (ÑокÑÑ), говоÑÑÑ, ÑÑо Ñакое вÑделение «напÑавлено впеÑÑд».
РпÑимеÑÑ, еÑли полÑзоваÑÐµÐ»Ñ Ð½Ð°ÑÐ¸Ð½Ð°ÐµÑ Ð²Ñделение Ñ Ð¿Ð¾Ð¼Ð¾ÑÑÑ Ð¼ÑÑи в напÑавлении Ð¾Ñ Â«Example» до «italic»:
ÐнаÑе, еÑли вÑделение идÑÑ Ð¾Ñ Â«italic» до «Example», вÑделение идÑÑ Ð² «обÑаÑном» напÑавлении, его ÑокÑÑ Ð±ÑÐ´ÐµÑ Ð¿ÐµÑед ÑкоÑем:
ÐÑо оÑлиÑаеÑÑÑ Ð¾Ñ Ð¾Ð±ÑекÑов Range, коÑоÑÑе вÑегда напÑÐ°Ð²Ð»ÐµÐ½Ñ Ð²Ð¿ÐµÑÑд: наÑало диапазона не Ð¼Ð¾Ð¶ÐµÑ ÑÑоÑÑÑ Ð¿Ð¾Ñле его конÑа.
СобÑÑÐ¸Ñ Ð¿Ñи вÑделении
СÑÑеÑÑвÑÑÑ ÑобÑÑиÑ, позволÑÑÑие оÑÑлеживаÑÑ Ð²Ñделение:
elem.onselectstartâ когда Ñ elem наÑинаеÑÑÑ Ð²Ñделение, напÑÐ¸Ð¼ÐµÑ Ð¿Ð¾Ð»ÑзоваÑÐµÐ»Ñ Ð½Ð°ÑÐ¸Ð½Ð°ÐµÑ Ð´Ð²Ð¸Ð³Ð°ÑÑ Ð¼ÑÑкой Ñ Ð·Ð°Ð¶Ð°Ñой кнопкой.- preventDefault() оÑменÑÐµÑ Ð½Ð°Ñало вÑделениÑ.
document.onselectionchangeâ когда вÑделение изменено.- ÐамеÑÑÑе: ÑÑÐ¾Ñ Ð¾Ð±ÑабоÑÑик можно поÑÑавиÑÑ ÑолÑко на
document.
- ÐамеÑÑÑе: ÑÑÐ¾Ñ Ð¾Ð±ÑабоÑÑик можно поÑÑавиÑÑ ÑолÑко на
Ðемо оÑÑÐ»ÐµÐ¶Ð¸Ð²Ð°Ð½Ð¸Ñ Ð²ÑделениÑ
Ðиже пÑедÑÑавлено неболÑÑое демо. РнÑм гÑаниÑÑ Ð²ÑÐ´ÐµÐ»ÐµÐ½Ð¸Ñ Ð²ÑводÑÑÑÑ Ð´Ð¸Ð½Ð°Ð¼Ð¸ÑеÑки по меÑе Ñого, как оно менÑеÑÑÑ:
<p id="p">ÐÑдели менÑ: <i>кÑÑÑив</i> и <b>жиÑнÑй</b></p>
ÐÑ <input id="from" disabled> â Ðо <input id="to" disabled>
<script>
document.onselectionchange = function() {
let {anchorNode, anchorOffset, focusNode, focusOffset} = document.getSelection();
from.value = `${anchorNode && anchorNode.data}:${anchorOffset}`;
to.value = `${focusNode && focusNode.data}:${focusOffset}`;
};
</script>
Ðемо полÑÑÐµÐ½Ð¸Ñ Ð²ÑделениÑ
ЧÑÐ¾Ð±Ñ Ð¿Ð¾Ð»ÑÑиÑÑ Ð²ÑÑ Ð²Ñделение:
- Ðак ÑекÑÑ: пÑоÑÑо вÑзовиÑе
document.getSelection().toString(). - Ðак DOM-ÑлеменÑÑ: полÑÑиÑе вÑделеннÑе Ð´Ð¸Ð°Ð¿Ð°Ð·Ð¾Ð½Ñ Ð¸ вÑзовиÑе иÑ
меÑод
cloneContents()(ÑолÑко пеÑвÑй диапазон, еÑли Ð¼Ñ Ð½Ðµ поддеÑживаем мÑлÑÑивÑделение в Firefox).
Ðиже пÑедÑÑавлено демо полÑÑÐµÐ½Ð¸Ñ Ð²ÑÐ´ÐµÐ»ÐµÐ½Ð¸Ñ ÐºÐ°Ðº в виде ÑекÑÑа, Ñак и в виде DOM-Ñзлов:
<p id="p">ÐÑдели менÑ: <i>кÑÑÑив</i> и <b>жиÑнÑй</b></p>
СклониÑовано: <span id="cloned"></span>
<br>
Ðак ÑекÑÑ: <span id="astext"></span>
<script>
document.onselectionchange = function() {
let selection = document.getSelection();
cloned.innerHTML = astext.innerHTML = "";
// ÐлониÑÑем DOM-ÑлеменÑÑ Ð¸Ð· диапазонов (здеÑÑ Ð¼Ñ Ð¿Ð¾Ð´Ð´ÐµÑживаем множеÑÑвенное вÑделение)
for (let i = 0; i < selection.rangeCount; i++) {
cloned.append(selection.getRangeAt(i).cloneContents());
}
// ÐолÑÑаем как ÑекÑÑ
astext.innerHTML += selection;
};
</script>
ÐеÑÐ¾Ð´Ñ Selection
ÐеÑÐ¾Ð´Ñ Selection Ð´Ð»Ñ Ð´Ð¾Ð±Ð°Ð²Ð»ÐµÐ½Ð¸Ñ Ð¸ ÑÐ´Ð°Ð»ÐµÐ½Ð¸Ñ Ð´Ð¸Ð°Ð¿Ð°Ð·Ð¾Ð½Ð¾Ð²:
getRangeAt(i)â взÑÑÑ i-Ñй диапазон, наÑÐ¸Ð½Ð°Ñ Ñ0. Ðо вÑÐµÑ Ð±ÑаÑзеÑÐ°Ñ , кÑоме Firefox, иÑполÑзÑеÑÑÑ ÑолÑко0.addRange(range)â добавиÑÑrangeв вÑделение. ÐÑе бÑаÑзеÑÑ, кÑоме Firefox, пÑоигноÑиÑÑÑÑ ÑÑÐ¾Ñ Ð²Ñзов, еÑли в вÑделении Ñже еÑÑÑ Ð´Ð¸Ð°Ð¿Ð°Ð·Ð¾Ð½.removeRange(range)â ÑдалиÑÑrangeиз вÑделениÑ.removeAllRanges()â ÑдалиÑÑ Ð²Ñе диапазонÑ.empty()â ÑокÑаÑение длÑremoveAllRanges.
Также ÑÑÑеÑÑвÑÑÑ Ð¼ÐµÑÐ¾Ð´Ñ ÑпÑÐ°Ð²Ð»ÐµÐ½Ð¸Ñ Ð´Ð¸Ð°Ð¿Ð°Ð·Ð¾Ð½Ð°Ð¼Ð¸ вÑÐ´ÐµÐ»ÐµÐ½Ð¸Ñ Ð½Ð°Ð¿ÑÑмÑÑ, без обÑаÑÐµÐ½Ð¸Ñ Ðº Range:
collapse(node, offset)â замениÑÑ Ð²ÑделеннÑй диапазон новÑм, коÑоÑÑй наÑинаеÑÑÑ Ð¸ заканÑиваеÑÑÑ Ð½Ð°node, на позиÑииoffset.setPosition(node, offset)â Ñо же Ñамое, ÑÑоcollapse(дÑблиÑÑÑÑий меÑод-пÑевдоним).collapseToStart()â ÑÑ Ð»Ð¾Ð¿Ð½ÑÑÑ (замениÑÑ Ð½Ð° пÑÑÑой диапазон) к наÑÐ°Ð»Ñ Ð²ÑделениÑ,collapseToEnd()â ÑÑ Ð»Ð¾Ð¿Ð½ÑÑÑ Ð´Ð¸Ð°Ð¿Ð°Ð·Ð¾Ð½ к конÑÑ Ð²ÑделениÑ,extend(node, offset)â пеÑемеÑÑиÑÑ ÑокÑÑ Ð²ÑÐ´ÐµÐ»ÐµÐ½Ð¸Ñ Ðº данномÑnode, Ñ Ð¿Ð¾Ð·Ð¸Ñииoffset,setBaseAndExtent(anchorNode, anchorOffset, focusNode, focusOffset)â замениÑÑ Ð´Ð¸Ð°Ð¿Ð°Ð·Ð¾Ð½ вÑÐ´ÐµÐ»ÐµÐ½Ð¸Ñ Ð½Ð° заданнÑе наÑалоanchorNode/anchorOffsetи конеÑfocusNode/focusOffset. ÐÑÐ´ÐµÑ Ð²Ñделено вÑÑ ÑодеÑжимое Ð¼ÐµÐ¶Ð´Ñ ÑÑими гÑаниÑамиselectAllChildren(node)â вÑделиÑÑ Ð²Ñе доÑеÑние ÑÐ·Ð»Ñ Ð´Ð°Ð½Ð½Ð¾Ð³Ð¾ Ñзлаnode.deleteFromDocument()â ÑдалиÑÑ ÑодеÑжимое вÑÐ´ÐµÐ»ÐµÐ½Ð¸Ñ Ð¸Ð· докÑменÑа.containsNode(node, allowPartialContainment = false)â пÑовеÑÑеÑ, ÑодеÑÐ¶Ð¸Ñ Ð»Ð¸ вÑделениеnode(ÑаÑÑиÑно, еÑли вÑоÑой аÑгÑÐ¼ÐµÐ½Ñ Ñавенtrue)
Так ÑÑо Ð´Ð»Ñ Ð¼Ð½Ð¾Ð³Ð¸Ñ
Ð·Ð°Ð´Ð°Ñ Ð¼Ñ Ð¼Ð¾Ð¶ÐµÐ¼ вÑзÑваÑÑ Ð¼ÐµÑÐ¾Ð´Ñ Selection, не обÑаÑаÑÑÑ Ðº ÑвÑÐ·Ð°Ð½Ð½Ð¾Ð¼Ñ Ð¾Ð±ÑекÑÑ Range.
РпÑимеÑÑ, вÑделение вÑего паÑагÑаÑа <p>:
<p id="p">ÐÑдели менÑ: <i>кÑÑÑив</i> и <b>жиÑнÑй</b></p>
<script>
// вÑделиÑÑ Ð²ÑÑ ÑодеÑжимое Ð¾Ñ Ð½Ñлевого поÑомка Ñега <p> до поÑледнего
document.getSelection().setBaseAndExtent(p, 0, p, p.childNodes.length);
</script>
То же Ñамое Ñ Ð¿Ð¾Ð¼Ð¾ÑÑÑ Range:
<p id="p">ÐÑдели менÑ: <i>кÑÑÑив</i> и <b>жиÑнÑй</b></p>
<script>
let range = new Range();
range.selectNodeContents(p); // или selectNode(p), ÑÑÐ¾Ð±Ñ Ð²ÑделиÑÑ Ð¸ Ñег <p>
document.getSelection().removeAllRanges(); // оÑиÑÑиÑÑ ÑекÑÑее вÑделение, еÑли оно ÑÑÑеÑÑвÑеÑ
document.getSelection().addRange(range);
</script>
ÐÑли вÑделение Ñже ÑÑÑеÑÑвÑеÑ, ÑнаÑала ÑнимиÑе его, иÑполÑзÑÑ removeAllRanges(), и ÑолÑко заÑем добавлÑйÑе новÑе диапазонÑ. РпÑоÑивном ÑлÑÑае вÑе бÑаÑзеÑÑ, кÑоме Firefox, пÑоигноÑиÑÑÑÑ Ð´Ð¾Ð±Ð°Ð²Ð»ÐµÐ½Ð¸Ðµ.
ÐÑклÑÑением ÑвлÑÑÑÑÑ Ð½ÐµÐºÐ¾ÑоÑÑе меÑÐ¾Ð´Ñ Ð²ÑделениÑ, коÑоÑÑе заменÑÑÑ ÑÑÑеÑÑвÑÑÑее вÑделение, напÑимеÑ, setBaseAndExtent.
ÐÑделение в ÑлеменÑÐ°Ñ ÑоÑм
ÐлеменÑÑ ÑоÑм, Ñакие как input и textarea, пÑедоÑÑавлÑÑÑ Ð¾ÑделÑное API Ð´Ð»Ñ Ð²ÑделениÑ. Так как знаÑÐµÐ½Ð¸Ñ Ð¿Ð¾Ð»ÐµÐ¹ пÑедÑÑавлÑÑÑ Ñобой пÑоÑÑой ÑекÑÑ, а не HTML, и нам не нÑÐ¶Ð½Ñ Ñакие ÑложнÑе обÑекÑÑ, как Range и Selection.
СвойÑÑва:
input.selectionStartâ позиÑÐ¸Ñ Ð½Ð°Ñала вÑÐ´ÐµÐ»ÐµÐ½Ð¸Ñ (ÑÑо ÑвойÑÑво можно изменÑÑÑ),input.selectionEndâ позиÑÐ¸Ñ ÐºÐ¾Ð½Ñа вÑÐ´ÐµÐ»ÐµÐ½Ð¸Ñ (ÑÑо ÑвойÑÑво можно изменÑÑÑ),input.selectionDirectionâ напÑавление вÑделениÑ, одно из: «forward» (впеÑÑд), «backward» (назад) или «none» (без напÑавлениÑ, еÑли, к пÑимеÑÑ, вÑделено Ñ Ð¿Ð¾Ð¼Ð¾ÑÑÑ Ð´Ð²Ð¾Ð¹Ð½Ð¾Ð³Ð¾ клика мÑÑи).
СобÑÑиÑ:
input.onselectâ ÑÑабаÑÑваеÑ, когда вÑделение завеÑÑено.
ÐеÑодÑ:
-
input.select()â вÑделÑÐµÑ Ð²ÑÑ ÑодеÑжимоеinput(Ð¼Ð¾Ð¶ÐµÑ Ð±ÑÑÑtextareaвмеÑÑоinput), -
input.setSelectionRange(start, end, [direction])â измениÑÑ Ð²Ñделение, ÑÑÐ¾Ð±Ñ Ð½Ð°ÑиналоÑÑ Ñ Ð¿Ð¾Ð·Ð¸Ñииstart, и заканÑивалоÑÑend, в данном напÑавленииdirection(необÑзаÑелÑнÑй паÑамеÑÑ). -
input.setRangeText(replacement, [start], [end], [selectionMode])â заменÑÐµÑ Ð²ÑделеннÑй ÑекÑÑ Ð² диапазоне новÑм.ÐÑли аÑгÑменÑÑ
startиendÑказанÑ, Ñо они задаÑÑ Ð½Ð°Ñало и ÐºÐ¾Ð½ÐµÑ Ð´Ð¸Ð°Ð¿Ð°Ð·Ð¾Ð½Ð°, инаÑе иÑполÑзÑеÑÑÑ ÑекÑÑее вÑделение.ÐоÑледний аÑгÑменÑ,
selectionMode, опÑеделÑеÑ, как бÑÐ´ÐµÑ Ð²ÐµÑÑи ÑÐµÐ±Ñ Ð²Ñделение поÑле Ð·Ð°Ð¼ÐµÐ½Ñ ÑекÑÑа. ÐозможнÑе знаÑениÑ:"select"â ÑолÑко ÑÑо вÑÑавленнÑй ÑекÑÑ Ð±ÑÐ´ÐµÑ Ð²Ñделен."start"â диапазон вÑÐ´ÐµÐ»ÐµÐ½Ð¸Ñ ÑÑ Ð»Ð¾Ð¿Ð½ÐµÑÑÑ Ð¿ÑÑмо пеÑед вÑÑавленнÑм ÑекÑÑом (Ñак ÑÑо кÑÑÑÐ¾Ñ Ð¾ÐºÐ°Ð¶ÐµÑÑÑ Ð½ÐµÐ¿Ð¾ÑÑедÑÑвенно пеÑед ним)."end"â диапазон вÑÐ´ÐµÐ»ÐµÐ½Ð¸Ñ ÑÑ Ð»Ð¾Ð¿Ð½ÐµÑÑÑ Ð¿ÑÑмо поÑле вÑÑавленного ÑекÑÑа (кÑÑÑÐ¾Ñ Ð¾ÐºÐ°Ð¶ÐµÑÑÑ ÑÑÐ°Ð·Ñ Ð¿Ð¾Ñле него)."preserve"â пÑÑаеÑÑÑ ÑÐ¾Ñ ÑаниÑÑ Ð²Ñделение. ÐнаÑение по ÑмолÑаниÑ.
ÐавайÑе поÑмоÑÑим на ÑÑи меÑÐ¾Ð´Ñ Ð² дейÑÑвии.
ÐÑимеÑ: оÑÑлеживание вÑделениÑ
РпÑимеÑÑ, ÑÑÐ¾Ñ ÐºÐ¾Ð´ иÑполÑзÑÐµÑ ÑобÑÑие onselect, ÑÑÐ¾Ð±Ñ Ð¾ÑÑлеживаÑÑ Ð²Ñделение:
<textarea id="area" style="width:80%;height:60px">
ÐÑделиÑе ÑÑо-нибÑÐ´Ñ Ð² ÑÑом ÑекÑÑе, ÑÑÐ¾Ð±Ñ Ð¾Ð±Ð½Ð¾Ð²Ð¸ÑÑ Ð·Ð½Ð°ÑÐµÐ½Ð¸Ñ Ð½Ð¸Ð¶Ðµ.
</textarea>
<br>
ÐÑ <input id="from" disabled> â Ðо <input id="to" disabled>
<script>
area.onselect = function() {
from.value = area.selectionStart;
to.value = area.selectionEnd;
};
</script>
ÐамеÑÑÑе:
onselectÑÑабаÑÑÐ²Ð°ÐµÑ Ð¿Ñи вÑделении Ñего-либо, но не пÑи ÑнÑÑии вÑделениÑ.- ÑобÑÑие
document.onselectionchangeне должно ÑÑабаÑÑваÑÑ Ð¿Ñи вÑделении внÑÑÑи ÑлеменÑа ÑоÑÐ¼Ñ Ð² ÑооÑвеÑÑÑвии Ñо ÑпеÑиÑикаÑией, Ñак как оно не ÑвлÑеÑÑÑ Ð²Ñделением ÑлеменÑов вdocument. ХоÑÑ Ð½ÐµÐºÐ¾ÑоÑÑе бÑаÑзеÑÑ Ð³ÐµÐ½ÐµÑиÑÑÑÑ ÑÑо ÑобÑÑие, полагаÑÑÑÑ Ð½Ð° ÑÑо не ÑÑоиÑ.
ÐÑимеÑ: изменение позиÑии кÑÑÑоÑа
ÐÑ Ð¼Ð¾Ð¶ÐµÐ¼ изменÑÑÑ selectionStart и selectionEnd, ÑÑÑÐ°Ð½Ð°Ð²Ð»Ð¸Ð²Ð°Ñ Ð²Ñделение.
ÐажнÑй гÑаниÑнÑй ÑлÑÑай â когда selectionStart и selectionEnd ÑÐ°Ð²Ð½Ñ Ð´ÑÑг дÑÑгÑ. Ð ÑÑом ÑлÑÑае они ÑказÑваÑÑ Ð½Ð° позиÑÐ¸Ñ ÐºÑÑÑоÑа. ÐнÑми Ñловами, когда ниÑего не вÑбÑано, вÑделение ÑÑ
лопнÑÑо на позиÑии кÑÑÑоÑа.
Таким обÑазом, Ð·Ð°Ð´Ð°Ð²Ð°Ñ selectionStart и selectionEnd одно и Ñо же знаÑение, Ð¼Ñ Ð¼Ð¾Ð¶ÐµÐ¼ пеÑедвигаÑÑ ÐºÑÑÑоÑ.
ÐапÑимеÑ:
<textarea id="area" style="width:80%;height:60px">
ÐеÑеведиÑе ÑокÑÑ Ð½Ð° менÑ, кÑÑÑÐ¾Ñ Ð¾ÐºÐ°Ð¶ÐµÑÑÑ Ð½Ð° 10-й позиÑии
</textarea>
<script>
area.onfocus = () => {
// нÑÐ»ÐµÐ²Ð°Ñ Ð·Ð°Ð´ÐµÑжка setTimeout нÑжна, ÑÑÐ¾Ð±Ñ ÑÑо ÑÑабоÑало поÑле полÑÑÐµÐ½Ð¸Ñ ÑокÑÑа ÑлеменÑом ÑоÑмÑ
setTimeout(() => {
// Ð¼Ñ Ð¼Ð¾Ð¶ÐµÐ¼ задаÑÑ Ð»Ñбое вÑделение
// еÑли наÑало и ÐºÐ¾Ð½ÐµÑ ÑовпадаÑÑ, кÑÑÑÐ¾Ñ ÑÑÑанавливаеÑÑÑ Ð½Ð° ÑÑом меÑÑе
area.selectionStart = area.selectionEnd = 10;
});
};
</script>
ÐÑимеÑ: изменение вÑделениÑ
ЧÑÐ¾Ð±Ñ Ð¸Ð·Ð¼ÐµÐ½ÑÑÑ ÑодеÑжимое вÑделениÑ, Ð¼Ñ Ð¼Ð¾Ð¶ÐµÐ¼ иÑполÑзоваÑÑ Ð¼ÐµÑод input.setRangeText. ÐонеÑно, Ð¼Ñ Ð¼Ð¾Ð¶ÐµÐ¼ ÑиÑаÑÑ selectionStart/End и, Ð·Ð½Ð°Ñ Ð¿Ð¾Ð·Ð¸Ñии вÑделениÑ, изменÑÑÑ ÑооÑвеÑÑÑвÑÑÑÑÑ Ð¿Ð¾Ð´ÑÑÑÐ¾ÐºÑ Ð² value, но setRangeText намного моÑнее и, заÑаÑÑÑÑ, Ñдобнее.
ÐÑо доволÑно ÑложнÑй меÑод. РпÑоÑÑейÑем ÑлÑÑае он пÑÐ¸Ð½Ð¸Ð¼Ð°ÐµÑ Ð¾Ð´Ð¸Ð½ аÑгÑменÑ, заменÑÐµÑ ÑодеÑжание вÑделенной облаÑÑи и ÑÐ½Ð¸Ð¼Ð°ÐµÑ Ð²Ñделение.
Ð ÑÑом пÑимеÑе вÑделеннÑй ÑекÑÑ Ð±ÑÐ´ÐµÑ Ð¾Ð±ÑÑнÑÑ Ð² *...*:
<input id="input" style="width:200px" value="Select here and click the button">
<button id="button">ÐбеÑнÑÑÑ Ð²Ñделение звÑздоÑками *...*</button>
<script>
button.onclick = () => {
if (input.selectionStart == input.selectionEnd) {
return; // ниÑего не вÑделено
}
let selected = input.value.slice(input.selectionStart, input.selectionEnd);
input.setRangeText(`*${selected}*`);
};
</script>
ÐеÑÐµÐ´Ð°Ð²Ð°Ñ Ð±Ð¾Ð»ÑÑе паÑамеÑÑов, Ð¼Ñ Ð¼Ð¾Ð¶ÐµÐ¼ ÑÑÑанавливаÑÑ start и end.
Ð ÑÑом пÑимеÑе Ð¼Ñ Ð½Ð°Ð¹Ð´Ñм "ÐТÐ" в поле ввода, заменим его и оÑÑавим заменÑннÑй ÑекÑÑ Ð²ÑделеннÑм:
<input id="input" style="width:200px" value="ÐамениÑе ÐТРв ÑекÑÑе">
<button id="button">ÐамениÑÑ ÐТÐ</button>
<script>
button.onclick = () => {
let pos = input.value.indexOf("ÐТÐ");
if (pos >= 0) {
input.setRangeText("*ÐТÐ*", pos, pos + 3, "select");
input.focus(); // ÑÑавим ÑокÑÑ, ÑÑÐ¾Ð±Ñ Ð²Ñделение бÑло видно
}
};
</script>
ÐÑимеÑ: вÑÑавка на меÑÑе кÑÑÑоÑа
ÐÑли ниÑего не вÑделено, или Ð¼Ñ Ñказали одинаковÑе start и end в меÑоде setRangeText, Ñо ÑекÑÑ Ð¿ÑоÑÑо вÑÑавлÑеÑÑÑ, и ниÑего не ÑдалÑеÑÑÑ.
ÐÑ Ñакже можем вÑÑавиÑÑ ÑÑо-нибÑÐ´Ñ Ð½Ð° ÑекÑÑей позиÑии кÑÑÑоÑа, иÑполÑзÑÑ setRangeText.
Ðнопка в пÑимеÑе вÑÑавлÑÐµÑ "ÐÐ ÐÐÐТ" на меÑÑе кÑÑÑоÑа и ÑÑÑÐ°Ð½Ð°Ð²Ð»Ð¸Ð²Ð°ÐµÑ ÐµÐ³Ð¾ поÑле вÑÑавленного ÑекÑÑа. ÐÑли какой-Ñо ÑекÑÑ Ð±Ñл вÑделен, он бÑÐ´ÐµÑ Ð·Ð°Ð¼ÐµÐ½Ñн (Ð¼Ñ Ð¼Ð¾Ð¶ÐµÐ¼ ÑзнаÑÑ Ð¾ налиÑии вÑделениÑ, пÑовеÑив selectionStart!=selectionEnd и, еÑли вÑделение еÑÑÑ, ÑделаÑÑ ÑÑо-Ñо еÑÑ):
<input id="input" style="width:200px" value="ТекÑÑ Ð¢ÐµÐºÑÑ Ð¢ÐµÐºÑÑ Ð¢ÐµÐºÑÑ Ð¢ÐµÐºÑÑ">
<button id="button">ÐÑÑавиÑÑ "ÐÐ ÐÐÐТ" на меÑÑе кÑÑÑоÑа</button>
<script>
button.onclick = () => {
input.setRangeText("ÐÐ ÐÐÐТ", input.selectionStart, input.selectionEnd, "end");
input.focus();
};
</script>
СделаÑÑ ÑÑо-Ñо невÑделÑемÑм
СÑÑеÑÑвÑÑÑ ÑÑи ÑпоÑоба ÑделаÑÑ ÑÑо-Ñо невÑделÑемÑм:
-
ÐÑполÑзÑйÑе CSS-ÑвойÑÑво
user-select: none.<style> #elem { user-select: none; } </style> <div>Ðожно вÑделиÑÑ <div id="elem">ÐелÑÐ·Ñ Ð²ÑделиÑÑ</div> Ðожно вÑделиÑÑ</div>ÐÑо ÑвойÑÑво не позволÑÐµÑ Ð½Ð°ÑаÑÑ Ð²Ñделение Ñ
elem, но полÑзоваÑÐµÐ»Ñ Ð¼Ð¾Ð¶ÐµÑ Ð½Ð°ÑаÑÑ Ð²ÑделÑÑÑ Ñ Ð´ÑÑгого меÑÑа и вклÑÑиÑÑelem.ÐоÑле ÑÑого
elemÑÑÐ°Ð½ÐµÑ ÑаÑÑÑÑdocument.getSelection(), Ñак ÑÑо на Ñамом деле вÑделение пÑоизойдÑÑ, но его ÑодеÑжимое обÑÑно игноÑиÑÑеÑÑÑ Ð¿Ñи копиÑовании и вÑÑавке. -
ÐÑедоÑвÑаÑиÑÑ Ð´ÐµÐ¹ÑÑвие по ÑмолÑÐ°Ð½Ð¸Ñ Ð² ÑобÑÑии
onselectstartилиmousedown.<div>Ðожно вÑделиÑÑ <div id="elem">ÐелÑÐ·Ñ Ð²ÑделиÑÑ</div> Ðожно вÑделиÑÑ</div> <script> elem.onselectstart = () => false; </script>ÐÑÐ¾Ñ ÑпоÑоб Ñакже не даÑÑ Ð½Ð°ÑаÑÑ Ð²Ñделение Ñ
elem, но полÑзоваÑÐµÐ»Ñ Ð¼Ð¾Ð¶ÐµÑ Ð½Ð°ÑаÑÑ Ñ Ð´ÑÑгого ÑлеменÑа, а заÑем ÑаÑÑиÑиÑÑ Ð²Ñделение доelem.ÐÑо Ñдобно, когда еÑÑÑ Ð´ÑÑгой обÑабоÑÑик ÑобÑÑÐ¸Ñ Ð½Ð° Ñом дейÑÑвии, коÑоÑое запÑÑÐºÐ°ÐµÑ Ð²Ñделение (Ñкажем,
mousedown). Так ÑÑо Ð¼Ñ Ð¾ÑклÑÑаем вÑделение, ÑÑÐ¾Ð±Ñ Ð¸Ð·Ð±ÐµÐ¶Ð°ÑÑ ÐºÐ¾Ð½ÑликÑа.Ð ÑодеÑжимое
elemпÑи ÑÑом Ð¼Ð¾Ð¶ÐµÑ Ð±ÑÑÑ ÑкопиÑовано. -
ÐÑ Ñакже можем оÑиÑÑиÑÑ Ð²Ñделение поÑле ÑÑабаÑÑÐ²Ð°Ð½Ð¸Ñ Ñ Ð¿Ð¾Ð¼Ð¾ÑÑÑ
document.getSelection().empty(). ÐÑÐ¾Ñ ÑпоÑоб иÑполÑзÑеÑÑÑ Ñедко, Ñак как он вÑзÑÐ²Ð°ÐµÑ Ð½ÐµÐ¶ÐµÐ»Ð°ÐµÐ¼Ð¾Ðµ меÑÑание пÑи поÑвлении и иÑÑезновении вÑделениÑ.
СÑÑлки
- СпеÑиÑикаÑÐ¸Ñ DOM: Range
- Selection API
- СпеÑиÑикаÑÐ¸Ñ HTML: API Ð´Ð»Ñ Ð²ÑÐ´ÐµÐ»ÐµÐ½Ð¸Ñ Ð² ÑлеменÑÐ°Ñ ÑпÑÐ°Ð²Ð»ÐµÐ½Ð¸Ñ ÑекÑÑом
ÐÑого
ÐÑ Ð¿Ð¾Ð´Ñобно ÑаÑÑмоÑÑели два ÑазнÑÑ API Ð´Ð»Ñ Ð²ÑделениÑ:
- ÐÐ»Ñ Ð´Ð¾ÐºÑменÑа: обÑекÑÑ
SelectionиRange. - ÐлÑ
input,textarea: дополниÑелÑнÑе меÑÐ¾Ð´Ñ Ð¸ ÑвойÑÑва.
ÐÑоÑое API оÑÐµÐ½Ñ Ð¿ÑоÑÑое, Ñак как ÑабоÑÐ°ÐµÑ Ñ ÑекÑÑом.
СамÑе иÑполÑзÑемÑе гоÑовÑе ÑеÑениÑ:
- ÐолÑÑиÑÑ Ð²Ñделение:
let selection = document.getSelection(); let cloned = /* ÑлеменÑ, в коÑоÑÑй Ð¼Ñ Ñ Ð¾Ñим ÑкопиÑоваÑÑ Ð²ÑделеннÑе ÑÐ·Ð»Ñ */; // заÑем пÑименÑем меÑÐ¾Ð´Ñ Range к selection.getRangeAt(0) // или, как здеÑÑ, ко вÑем диапазонам, ÑÑÐ¾Ð±Ñ Ð¿Ð¾Ð´Ð´ÐµÑживаÑÑ Ð¼Ð½Ð¾Ð¶ÐµÑÑвенное вÑделение for (let i = 0; i < selection.rangeCount; i++) { cloned.append(selection.getRangeAt(i).cloneContents()); } - УÑÑановиÑÑ Ð²Ñделение:
let selection = document.getSelection(); // напÑÑмÑÑ: selection.setBaseAndExtent(...from...to...); // или можно ÑоздаÑÑ Ð´Ð¸Ð°Ð¿Ð°Ð·Ð¾Ð½ range и: selection.removeAllRanges(); selection.addRange(range);
РпаÑÑ Ñлов о кÑÑÑоÑе. ÐозиÑÐ¸Ñ ÐºÑÑÑоÑа в ÑедакÑиÑÑемÑÑ
ÑлеменÑаÑ
, ÑакиÑ
как <textarea>, вÑегда наÑ
одиÑÑÑ Ð² наÑале или конÑе вÑделениÑ.
ÐÑ Ð¼Ð¾Ð¶ÐµÐ¼ иÑполÑзоваÑÑ ÑÑо, как Ð´Ð»Ñ Ñого, ÑÑÐ¾Ð±Ñ Ð¿Ð¾Ð»ÑÑиÑÑ Ð¿Ð¾Ð·Ð¸ÑÐ¸Ñ ÐºÑÑÑоÑа, Ñак и ÑÑÐ¾Ð±Ñ Ð¿ÐµÑемеÑÑиÑÑ ÐµÐ³Ð¾, ÑÑÑановив elem.selectionStart и elem.selectionEnd.
P.S. ÐÑли вам нÑжна поддеÑжка ÑÑаÑого IE8-, поÑмоÑÑиÑе аÑÑ Ð¸Ð²Ð½ÑÑ ÑÑаÑÑÑ.
ÐомменÑаÑии
<code>, Ð´Ð»Ñ Ð½ÐµÑколÑÐºÐ¸Ñ ÑÑÑок кода — Ñег<pre>, еÑли болÑÑе 10 ÑÑÑок — ÑÑÑÐ»ÐºÑ Ð½Ð° пеÑоÑниÑÑ (plnkr, JSBin, codepenâ¦)