Bu bobda biz hujjatdagi tanlashni, shuningdek <input>
kabi forma maydonlaridagi tanlashni ko’rib chiqamiz.
JavaScript mavjud tanlashga kirishishi, DOM tugunlarini to’liq yoki qisman tanlashi/tanlamasligini bekor qilishi, tanlangan kontentni hujjatdan olib tashlashi, uni tegga o’rashi va hokazolarni amalga oshirishi mumkin.
Bobning oxiridagi “Xulosa” qismida umumiy vazifalar uchun ba’zi retseptlarni topishingiz mumkin. Balki bu sizning hozirgi ehtiyojlaringizni qondiradi, lekin butun matnni o’qisangiz ko’proq narsalarni olasiz.
Asosiy Range
va Selection
obyektlari tushunish oson va keyin ulardan xohlagan narsangizni qildirish uchun hech qanday retseptga ehtiyoj qolmaydi.
Range
Tanlashning asosiy kontseptsiyasi Range bo’lib, u asosan bir juft "chegara nuqtalari"dir: range boshlanishi va range tugashi.
Range
obyekti parametrlarsiz yaratiladi:
let range = new Range();
Keyin biz range.setStart(node, offset)
va range.setEnd(node, offset)
yordamida tanlash chegaralarini o’rnatishimiz mumkin.
Taxmin qilganingizdek, keyinroq biz Range
obyektlarini tanlash uchun ishlatamiz, lekin avval bunday bir necha obyektlarni yaratamiz.
Matnni qisman tanlash
Qiziqarli tomoni shundaki, ikkala usuldagi birinchi argument node
matn tuguni yoki element tuguni bo’lishi mumkin va ikkinchi argumentning ma’nosi bunga bog’liq.
Agar node
matn tuguni bo’lsa, u holda offset
uning matndagi pozitsiya bo’lishi kerak.
Masalan, <p>Hello</p>
elementi berilgan bo’lsa, biz “ll” harflarini o’z ichiga olgan range yaratishimiz mumkin:
<p id="p">Hello</p>
<script>
let range = new Range();
range.setStart(p.firstChild, 2);
range.setEnd(p.firstChild, 4);
// range ning toString usuli uning kontentini matn sifatida qaytaradi
console.log(range); // ll
</script>
Bu yerda biz <p>
ning birinchi bolasini olamiz (bu matn tuguni) va uning ichidagi matn pozitsiyalarini belgilaymiz:
Element tugunlarini tanlash
Muqobil ravishda, agar node
element tuguni bo’lsa, u holda offset
bola raqami bo’lishi kerak.
Bu tugunlarni to’liq o’z ichiga olgan range yaratish uchun qulay, ularning matnining biror joyida to’xtab qolmaslik uchun.
Masalan, bizda yanada murakkab hujjat fragmenti bor:
<p id="p">Example: <i>italic</i> and <b>bold</b></p>
Mana uning element va matn tugunlari bilan DOM tuzilishi:
Keling, "Example: <i>italic</i>"
uchun range yarataylik.
Ko’rib turganimizdek, bu ibora aniq <p>
ning ikkita bolasidan iborat, indekslari 0
va 1
:
-
Boshlanish nuqtasi
<p>
ni otanode
sifatida va0
ni offset sifatida oladi.Shuning uchun biz uni
range.setStart(p, 0)
deb o’rnatishimiz mumkin. -
Tugash nuqtasi ham
<p>
ni otanode
sifatida oladi, lekin2
ni offset sifatida oladi (u range nioffset
gacha, lekin uni o’z ichiga olmasdan belgilaydi).Shuning uchun biz uni
range.setEnd(p, 2)
deb o’rnatishimiz mumkin.
Mana demo. Agar uni ishga tushirsangiz, matnning tanlanganini ko’rishingiz mumkin:
<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);
// range ning toString usuli uning kontentini teglar o'chirilgan holda matn sifatida qaytaradi
console.log(range); // Example: italic
// bu range ni hujjat tanlashi uchun qo'llang (keyinroq tushuntiriladi)
document.getSelection().addRange(range);
</script>
Bu yerda range boshlanishi/tugashi raqamlarini o’rnatishingiz va boshqa variantlarni o’rganishingiz mumkin bo’lgan yanada moslashuvchan test standidir:
<p id="p">Example: <i>italic</i> and <b>bold</b></p>
Dan <input id="start" type="number" value=1> – Gacha <input id="end" type="number" value=4>
<button id="button">Tanlash uchun bosing</button>
<script>
button.onclick = () => {
let range = new Range();
range.setStart(p, start.value);
range.setEnd(p, end.value);
// tanlashni qo'llash, keyinroq tushuntiriladi
document.getSelection().removeAllRanges();
document.getSelection().addRange(range);
};
</script>
Masalan, bir xil <p>
da 1
dan 4
gacha offset bilan tanlash bizga <i>italic</i> and <b>bold</b>
range beradi:
setStart
va setEnd
da bir xil tugunni ishlatishimiz shart emas. Range ko’plab bog’liq bo’lmagan tugunlar bo’ylab cho’zilishi mumkin. Faqat tugash hujjatda boshlanishdan keyin kelishi muhim.
Kattaroq fragmentni tanlash
Misolimizda kattaroq tanlov qilaylik:
Buni qanday qilishni allaqachon bilamiz. Faqat boshlanish va tugashni matn tugunlaridagi nisbiy offset sifatida o’rnatishimiz kerak.
Bizga quyidagicha range yaratish kerak:
<p>
birinchi bolasining 2-pozitsiyasidan boshlanadi ("Example: " dan dastlabki ikkita harfni olib tashlab)<b>
birinchi bolasining 3-pozitsiyasida tugaydi (“bold” dan dastlabki uchta harfni olib, boshqasini olmasdan):
<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);
console.log(range); // ample: italic and bol
// bu range ni tanlash uchun ishlating (keyinroq tushuntiriladi)
window.getSelection().addRange(range);
</script>
Ko’rib turganimizdek, xohlagan range yaratish juda oson.
Agar tugunlarni to’liq olmoqchi bo’lsak, setStart/setEnd
ga elementlarni berishimiz mumkin. Aks holda, matn darajasida ishlashimiz mumkin.
Range xossalari
Yuqoridagi misolda yaratilgan range obyektining quyidagi xossalari bor:
startContainer
,startOffset
– boshlanishning tuguni va offseti,- yuqoridagi misolda:
<p>
ichidagi birinchi matn tuguni va2
.
- yuqoridagi misolda:
endContainer
,endOffset
– tugashning tuguni va offseti,- yuqoridagi misolda:
<b>
ichidagi birinchi matn tuguni va3
.
- yuqoridagi misolda:
collapsed
– boolean, agar range bir xil nuqtada boshlanib tugasatrue
(shuning uchun range ichida hech qanday kontent yo’q),- yuqoridagi misolda:
false
- yuqoridagi misolda:
commonAncestorContainer
– range ichidagi barcha tugunlarning eng yaqin umumiy ajdodi,- yuqoridagi misolda:
<p>
- yuqoridagi misolda:
Range tanlash usullari
Range larni boshqarish uchun ko’plab qulay usullar mavjud.
Biz allaqachon setStart
va setEnd
ni ko’rdik, mana boshqa shunga o’xshash usullar.
Range boshlanishini o’rnatish:
setStart(node, offset)
boshlanishni o’rnatish:node
dagioffset
pozitsiyasidasetStartBefore(node)
boshlanishni o’rnatish:node
dan darhol oldinsetStartAfter(node)
boshlanishni o’rnatish:node
dan darhol keyin
Range tugashini o’rnatish (shunga o’xshash usullar):
setEnd(node, offset)
tugashni o’rnatish:node
dagioffset
pozitsiyasidasetEndBefore(node)
tugashni o’rnatish:node
dan darhol oldinsetEndAfter(node)
tugashni o’rnatish:node
dan darhol keyin
Texnik jihatdan, setStart/setEnd
har qanday narsani qila oladi, lekin ko’proq usullar ko’proq qulaylik beradi.
Barcha bu usullarda node
ham matn ham element tuguni bo’lishi mumkin: matn tugunlari uchun offset
shuncha belgilarni o’tkazib yuboradi, element tugunlari uchun esa shuncha bola tugunlarni.
Range yaratishning yana ham ko’p usullari:
selectNode(node)
butunnode
ni tanlash uchun range ni o’rnatishselectNodeContents(node)
butunnode
kontentini tanlash uchun range ni o’rnatishcollapse(toStart)
agartoStart=true
bo’lsa end=start o’rnatish, aks holda start=end o’rnatish, shu tariqa range ni yig’ishcloneRange()
bir xil start/end bilan yangi range yaratish
Range tahrirlash usullari
Range yaratilgandan so’ng, biz uning kontentini quyidagi usullar yordamida boshqarishimiz mumkin:
deleteContents()
– range kontentini hujjatdan olib tashlashextractContents()
– range kontentini hujjatdan olib tashlash va DocumentFragment sifatida qaytarishcloneContents()
– range kontentini nusxalash va DocumentFragment sifatida qaytarishinsertNode(node)
–node
ni hujjatga range boshida kiritishsurroundContents(node)
– range kontenti atrofidanode
ni o’rash. Buning ishlashi uchun range o’z ichidagi barcha elementlar uchun ochilish va yopilish teglarini o’z ichiga olishi kerak:<i>abc
kabi qisman range lar yo’q.
Bu usullar yordamida biz tanlangan tugunlar bilan deyarli har qanday narsani qila olamiz.
Mana ularni amalda ko’rish uchun test standi:
Tanlashda usullarni ishga tushirish uchun tugmalarni bosing, uni tiklash uchun "resetExample".
<p id="p">Example: <i>italic</i> and <b>bold</b></p>
<p id="result"></p>
<script>
let range = new Range();
// Har bir ko'rsatilgan usul bu yerda ifodalangan:
let methods = {
deleteContents() {
range.deleteContents()
},
extractContents() {
let content = range.extractContents();
result.innerHTML = "";
result.append("extracted: ", content);
},
cloneContents() {
let content = range.cloneContents();
result.innerHTML = "";
result.append("cloned: ", content);
},
insertNode() {
let newNode = document.createElement('u');
newNode.innerHTML = "NEW NODE";
range.insertNode(newNode);
},
surroundContents() {
let newNode = document.createElement('u');
try {
range.surroundContents(newNode);
} catch(e) { console.log(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>
Range larni solishtirish usullari ham mavjud, lekin ular kamdan-kam ishlatiladi. Ular kerak bo’lganda, spec yoki MDN qo’llanma ga murojaat qiling.
Selection
Range
tanlash range larini boshqarish uchun umumiy obyektdir. Garchi, Range
yaratish ekranda tanlashni ko’rishimizni anglatmaydi.
Biz Range
obyektlarini yaratishimiz, ularni o’tkazishimiz mumkin – ular o’z-o’zidan vizual ravishda hech narsani tanlamaydi.
Hujjat tanlashi Selection
obyekti bilan ifodalanadi, uni window.getSelection()
yoki document.getSelection()
sifatida olish mumkin. Tanlash nol yoki ko’proq range larni o’z ichiga olishi mumkin. Hech bo’lmaganda, Selection API spetsifikatsiyasi shunday deydi. Amalda esa, faqat Firefox Ctrl+click (Cmd+click Mac uchun) yordamida hujjatda bir nechta range larni tanlashga imkon beradi.
Mana Firefox da yaratilgan 3 ta range bilan tanlashning skrinshotı:
Boshqa brauzerlar maksimal 1 ta range ni qo’llab-quvvatlaydi. Ko’rib turganimizdek, ba’zi Selection
usullari ko’plab range lar bo’lishi mumkinligini nazarda tutadi, lekin yana, Firefox bundan mustasno barcha brauzerlarda maksimal 1 ta range bor.
Mana joriy tanlashni (biror narsani tanlab, bosing) matn sifatida ko’rsatadigan kichik demo:
Selection xossalari
Aytilganidek, tanlash nazariy jihatdan bir nechta range larni o’z ichiga olishi mumkin. Biz bu range obyektlarini quyidagi usul yordamida olishimiz mumkin:
getRangeAt(i)
– i-chi range ni olish,0
dan boshlab. Firefox bundan mustasno barcha brauzerlarda faqat0
ishlatiladi.
Shuningdek, ko’pincha yaxshiroq qulaylikni taqdim etadigan xossalar mavjud.
Range ga o’xshab, selection obyekti “langar” deb ataladigan boshlanish va “fokus” deb ataladigan tugashga ega.
Asosiy selection xossalari:
anchorNode
– selection boshlangan tugun,anchorOffset
– selection boshlangananchorNode
dagi offset,focusNode
– selection tugagan tugun,focusOffset
– selection tugaganfocusNode
dagi offset,isCollapsed
– agar selection hech narsani tanlamasa (bo’sh range) yoki mavjud bo’lmasatrue
.rangeCount
– selection dagi range lar soni, Firefox bundan mustasno barcha brauzerlarda maksimal1
.
Selection langar/fokusi bilan Range
boshlanish/tugashi o’rtasida muhim farqlar bor.
Bilganimizdek, Range
obyektlari har doim tugashdan oldin boshlanishga ega.
Selection lar uchun bu har doim ham unday emas.
Sichqoncha bilan biror narsani tanlash ikkala yo’nalishda ham amalga oshirilishi mumkin: “chapdan-o’ngga” yoki “o’ngdan-chapga”.
Boshqacha qilib aytganda, sichqoncha tugmasi bosilganda va keyin hujjatda oldinga siljisa, uning tugashi (fokus) boshlanishidan (langar) keyin bo’ladi.
Masalan, agar foydalanuvchi sichqoncha bilan tanlashni boshlasa va “Example” dan “italic” ga o’tsa:
…Lekin bir xil tanlash teskari yo’nalishda ham amalga oshirilishi mumkin: “italic” dan “Example” ga (teskari yo’nalish), keyin uning tugashi (fokus) boshlanishidan (langar) oldin bo’ladi:
Selection hodisalari
Selection ni kuzatib borish uchun hodisalar mavjud:
elem.onselectstart
– tanlash aniqelem
elementida (yoki uning ichida) boshlanganda. Masalan, foydalanuvchi sichqoncha tugmasini ustiga bosib, ko’rsatkichni harakatlantira boshlasa.- Standart harakatni oldini olish tanlash boshlanishini bekor qiladi. Shuning uchun bu elementdan tanlashni boshlash imkonsiz bo’ladi, lekin element hali ham tanlanishi mumkin. Tashrif buyuruvchi faqat tanlashni boshqa joydan boshlashi kerak.
document.onselectionchange
– tanlash o’zgarganda yoki boshlanganda.- Esda tuting: bu ishlov beruvchi faqat
document
da o’rnatilishi mumkin, u undagi barcha tanlashlarni kuzatadi.
- Esda tuting: bu ishlov beruvchi faqat
Selection kuzatuv demosi
Mana kichik demo. U document
dagi joriy tanlashni kuzatadi va uning chegaralarini ko’rsatadi:
<p id="p">Meni tanla: <i>italic</i> and <b>bold</b></p>
Dan <input id="from" disabled> – Gacha <input id="to" disabled>
<script>
document.onselectionchange = function() {
let selection = document.getSelection();
let {anchorNode, anchorOffset, focusNode, focusOffset} = selection;
// anchorNode va focusNode odatda matn tugunlari
from.value = `${anchorNode?.data}, offset ${anchorOffset}`;
to.value = `${focusNode?.data}, offset ${focusOffset}`;
};
</script>
Selection nusxalash demosi
Tanlangan kontentni nusxalashning ikkita yondashuvi mavjud:
- Uni matn sifatida olish uchun
document.getSelection().toString()
dan foydalanishimiz mumkin. - Aks holda, to’liq DOM ni nusxalash uchun, masalan formatlashni saqlashimiz kerak bo’lsa,
getRangesAt(...)
bilan asosiy range larni olishimiz mumkin.Range
obyekti, o’z navbatida, uning kontentini nusxalaydigan vaDocumentFragment
obyekti sifatida qaytaradigancloneContents()
usuliga ega, buni boshqa joyga kiritishimiz mumkin.
Mana tanlangan kontentni ham matn, ham DOM tugunlari sifatida nusxalash demosi:
<p id="p">Meni tanla: <i>italic</i> and <b>bold</b></p>
Nusxalangan: <span id="cloned"></span>
<br>
Matn sifatida: <span id="astext"></span>
<script>
document.onselectionchange = function() {
let selection = document.getSelection();
cloned.innerHTML = astext.innerHTML = "";
// Range lardan DOM tugunlarini nusxalash (bu yerda multiselect ni qo'llab-quvvatlaymiz)
for (let i = 0; i < selection.rangeCount; i++) {
cloned.append(selection.getRangeAt(i).cloneContents());
}
// Matn sifatida olish
astext.innerHTML += selection;
};
</script>
Selection usullari
Biz range lar qo’shish/olib tashlash orqali tanlash bilan ishlashimiz mumkin:
getRangeAt(i)
– i-chi range ni olish,0
dan boshlab. Firefox bundan mustasno barcha brauzerlarda faqat0
ishlatiladi.addRange(range)
– tanlashgarange
qo’shish. Agar tanlash allaqachon bog’langan range ga ega bo’lsa, Firefox bundan mustasno barcha brauzerlar chaqiruvni e’tiborsiz qoldiradi.removeRange(range)
– tanlashdanrange
ni olib tashlash.removeAllRanges()
– barcha range larni olib tashlash.empty()
–removeAllRanges
ning taxallusi.
Oraliq Range
chaqiruvlarisiz to’g’ridan-to’g’ri tanlash range ni boshqarish uchun qulay usullar ham mavjud:
collapse(node, offset)
– tanlangan range ni berilgannode
da,offset
pozitsiyasida boshlanib tugaydigan yangi bilan almashtirish.setPosition(node, offset)
–collapse
ning taxallusi.collapseToStart()
– tanlash boshiga yig’ish (bo’sh range bilan almashtirish),collapseToEnd()
– tanlash oxiriga yig’ish,extend(node, offset)
– tanlashning fokusini berilgannode
ga,offset
pozitsiyasiga o’tkazish,setBaseAndExtent(anchorNode, anchorOffset, focusNode, focusOffset)
– tanlash range ni berilgan boshlang’ichanchorNode/anchorOffset
va oxirgifocusNode/focusOffset
bilan almashtirish. Ular orasidagi barcha kontent tanlanadi.selectAllChildren(node)
–node
ning barcha bolalarini tanlash.deleteFromDocument()
– tanlangan kontentni hujjatdan olib tashlash.containsNode(node, allowPartialContainment = false)
– tanlashnode
ni o’z ichiga olgan-olmaganligini tekshiradi (ikkinchi argumenttrue
bo’lsa qisman ham).
Ko’pgina vazifalar uchun bu usullar etarli, asosiy Range
obyektiga kirish kerak emas.
Masalan, <p>
paragrafning butun kontentini tanlash:
<p id="p">Meni tanla: <i>italic</i> and <b>bold</b></p>
<script>
// <p> ning 0-bolasidan oxirgi bolagacha tanlash
document.getSelection().setBaseAndExtent(p, 0, p, p.childNodes.length);
</script>
Range lar yordamida bir xil narsa:
<p id="p">Meni tanla: <i>italic</i> and <b>bold</b></p>
<script>
let range = new Range();
range.selectNodeContents(p); // yoki <p> tegini ham tanlash uchun selectNode(p)
document.getSelection().removeAllRanges(); // agar mavjud tanlash bor bo'lsa tozalash
document.getSelection().addRange(range);
</script>
Agar hujjatda tanlash allaqachon mavjud bo’lsa, avval uni removeAllRanges()
bilan bo’shating. Va keyin range lar qo’shing. Aks holda, Firefox bundan mustasno barcha brauzerlar yangi range larni e’tiborsiz qoldiradi.
Istisno ba’zi tanlash usullari bo’lib, ular mavjud tanlashni almashtiradi, masalan setBaseAndExtent
.
Forma boshqaruvlarida tanlash
input
va textarea
kabi forma elementlari Selection
yoki Range
obyektlarisiz tanlash uchun maxsus API taqdim etadi. Input qiymati HTML emas, balki sof matn bo’lgani uchun bunday obyektlarga ehtiyoj yo’q, hamma narsa ancha sodda.
Xossalar:
input.selectionStart
– tanlash boshlanish pozitsiyasi (yozish mumkin),input.selectionEnd
– tanlash tugash pozitsiyasi (yozish mumkin),input.selectionDirection
– tanlash yo’nalishi, quyidagilardan biri: “forward”, “backward” yoki “none” (masalan ikki marta sichqoncha bosish bilan tanlangan bo’lsa),
Hodisalar:
input.onselect
– biror narsa tanlanganida ishga tushadi.
Usullar:
-
input.select()
– matn boshqaruvida hamma narsani tanlaydi (input
o’rnigatextarea
bo’lishi mumkin), -
input.setSelectionRange(start, end, [direction])
– tanlashnistart
pozitsiyasidanend
gacha, berilgan yo’nalishda (ixtiyoriy) o’zgartirishadi. -
input.setRangeText(replacement, [start], [end], [selectionMode])
– matn oralig’ini yangi matn bilan almashtirish.Ixtiyoriy argumentlar
start
vaend
, agar berilgan bo’lsa, oraliq boshlanishi va tugashini belgilaydi, aks holda foydalanuvchi tanlashi ishlatiladi.Oxirgi argument,
selectionMode
, matn almashtirilgandan keyin tanlash qanday o’rnatilishini belgilaydi. Mumkin bo’lgan qiymatlar:"select"
– yangi kiritilgan matn tanlanadi."start"
– tanlash oralig’i kiritilgan matndan darhol oldin yig’iladi (kursor uning darhol oldida bo’ladi)."end"
– tanlash oralig’i kiritilgan matndan darhol keyin yig’iladi (kursor uning darhol keyin bo’ladi)."preserve"
– tanlashni saqlashga harakat qiladi. Bu standart.
Endi bu usullarni amalda ko’raylik.
Misol: tanlashni kuzatish
Masalan, bu kod tanlashni kuzatish uchun onselect
hodisasidan foydalanadi:
<textarea id="area" style="width:80%;height:60px">
Bu matndagi tanlash quyidagi qiymatlarni yangilaydi.
</textarea>
<br>
Dan <input id="from" disabled> – Gacha <input id="to" disabled>
<script>
area.onselect = function() {
from.value = area.selectionStart;
to.value = area.selectionEnd;
};
</script>
Esda tuting:
onselect
biror narsa tanlanganida ishga tushadi, lekin tanlash olib tashlanganida emas.- spec ga ko’ra, forma boshqaruvi ichidagi tanlashlar uchun
document.onselectionchange
hodisasi ishga tushmasligi kerak, chunki udocument
tanlashi va range lari bilan bog’liq emas. Ba’zi brauzerlar uni hosil qiladi, lekin biz unga tayanmasligimiz kerak.
Misol: kursorni harakatlantirish
Biz selectionStart
va selectionEnd
ni o’zgartirishimiz mumkin, bu tanlashni o’rnatadi.
Muhim chegara holati – selectionStart
va selectionEnd
bir-biriga teng bo’lganda. U holda bu aniq kursor pozitsiyasidir. Yoki boshqacha qilib aytganda, hech narsa tanlanmaganda, tanlash kursor pozitsiyasida yig’ilgan.
Shunday qilib, selectionStart
va selectionEnd
ni bir xil qiymatga o’rnatish orqali kursorni harakatlantiramiz.
Masalan:
<textarea id="area" style="width:80%;height:60px">
Menga fokuslan, kursor 10-pozitsiyada bo'ladi.
</textarea>
<script>
area.onfocus = () => {
// brauzer "focus" harakat tugagandan keyin ishga tushishi uchun nol kechikish setTimeout
setTimeout(() => {
// biz har qanday tanlash o'rnatishimiz mumkin
// agar start=end bo'lsa, kursor aniq o'sha joyda
area.selectionStart = area.selectionEnd = 10;
});
};
</script>
Misol: tanlashni o’zgartirish
Tanlash kontentini o’zgartirish uchun input.setRangeText()
usulidan foydalanishimiz mumkin. Albatta, biz selectionStart/End
ni o’qishimiz va tanlash haqida ma’lumot bilan value
ning tegishli pastki qatorini o’zgartirishimiz mumkin, lekin setRangeText
kuchliroq va ko’pincha qulayroq.
Bu biroz murakkab usul. Eng oddiy bir argumentli shaklida u foydalanuvchi tanlagan oraliqni almashtiradi va tanlashni olib tashlaydi.
Masalan, bu yerda foydalanuvchi tanlashi *...*
bilan o’raladi:
<input id="input" style="width:200px" value="Bu yerdan tanlab tugmani bosing">
<button id="button">Tanlashni yulduzchalar bilan o'rash *...*</button>
<script>
button.onclick = () => {
if (input.selectionStart == input.selectionEnd) {
return; // hech narsa tanlanmagan
}
let selected = input.value.slice(input.selectionStart, input.selectionEnd);
input.setRangeText(`*${selected}*`);
};
</script>
Ko’proq argumentlar bilan biz start
va end
oralig’ini o’rnatishimiz mumkin.
Bu misolda biz input matnida "BU"
ni topamiz, uni almashtiramiz va almashtirishni tanlangan holda saqlaymiz:
<input id="input" style="width:200px" value="Matndagi BU so'zni almashtiring">
<button id="button">BU ni almashtirish</button>
<script>
button.onclick = () => {
let pos = input.value.indexOf("BU");
if (pos >= 0) {
input.setRangeText("*BU*", pos, pos + 2, "select");
input.focus(); // tanlashni ko'rinadigan qilish uchun fokus
}
};
</script>
Misol: kursor joyiga kiritish
Agar hech narsa tanlanmagan bo’lsa yoki setRangeText
da teng start
va end
ishlatilsa, yangi matn shunchaki kiritiladi, hech narsa olib tashlanmaydi.
setRangeText
yordamida “kursor joyiga” biror narsani kiritishimiz ham mumkin.
Mana kursor pozitsiyasiga "SALOM"
kiritadigan va kursorni uning darhol keyin qo’yadigan tugma. Agar tanlash bo’sh bo’lmasa, u almashtiriladi (buni selectionStart!=selectionEnd
ni solishtirib aniqlashimiz va o’rniga boshqa narsa qilishimiz mumkin):
<input id="input" style="width:200px" value="Matn Matn Matn Matn Matn">
<button id="button">Kursor joyiga "SALOM" kiritish</button>
<script>
button.onclick = () => {
input.setRangeText("SALOM", input.selectionStart, input.selectionEnd, "end");
input.focus();
};
</script>
Tanlab bo’lmasligini ta’minlash
Biror narsani tanlab bo’lmasligi uchun uchta yo’l bor:
-
user-select: none
CSS xossasidan foydalanish.<style> #elem { user-select: none; } </style> <div>Tanlanuvchi <div id="elem">Tanlanmaydigan</div> Tanlanuvchi</div>
Bu tanlashning
elem
da boshlanishiga imkon bermaydi. Lekin foydalanuvchi tanlashni boshqa joydan boshlashi vaelem
ni unga kiritishi mumkin.Keyin
elem
document.getSelection()
ning bir qismiga aylanadi, shuning uchun tanlash haqiqatda sodir bo’ladi, lekin uning kontenti odatda nusxa-joylashtirish da e’tiborga olinmaydi. -
onselectstart
yokimousedown
hodisalaridagi standart harakatni oldini olish.<div>Tanlanuvchi <div id="elem">Tanlanmaydigan</div> Tanlanuvchi</div> <script> elem.onselectstart = () => false; </script>
Bu
elem
da tanlashni boshlashga to’sqinlik qiladi, lekin tashrif buyuruvchi uni boshqa elementda boshlashi, keyinelem
ga kengaytirishi mumkin.Bu bir xil harakatda tanlashni ishga tushiradigan boshqa hodisa ishlov beruvchisi bo’lganida qulay (masalan
mousedown
). Shuning uchun biz ziddiyatni oldini olish uchun tanlashni o’chiramiz, lekinelem
kontentlarini nusxalashga imkon beramiz. -
Shuningdek, tanlash sodir bo’lgandan keyin
document.getSelection().empty()
bilan uni tozalashimiz mumkin. Bu kamdan-kam ishlatiladi, chunki tanlash paydo bo’lib-yo’qolishi natijasida istalmagan miltillashga sabab bo’ladi.
Havolalar
Xulosa
Biz tanlashlar uchun ikkita turli API ni ko’rib chiqdik:
- Hujjat uchun:
Selection
vaRange
obyektlari. input
,textarea
uchun: qo’shimcha usullar va xossalar.
Ikkinchi API juda oddiy, chunki u matn bilan ishlaydi.
Eng ko’p ishlatiladigan retseptlar, ehtimol:
- Tanlashni olish:
let selection = document.getSelection(); let cloned = /* tanlangan tugunlarni nusxalash uchun element */; // keyin selection.getRangeAt(0) ga Range usullarini qo'llang // yoki bu kabi, multi-select ni qo'llab-quvvatlash uchun barcha range larga for (let i = 0; i < selection.rangeCount; i++) { cloned.append(selection.getRangeAt(i).cloneContents()); }
- Tanlashni o’rnatish:
let selection = document.getSelection(); // to'g'ridan-to'g'ri: selection.setBaseAndExtent(...from...to...); // yoki biz range yaratishimiz va: selection.removeAllRanges(); selection.addRange(range);
Va nihoyat, kursor haqida. <textarea>
kabi tahrirlash mumkin bo’lgan elementlardagi kursor pozitsiyasi har doim tanlashning boshida yoki oxirida bo’ladi. Biz uni kursor pozitsiyasini olish yoki elem.selectionStart
va elem.selectionEnd
ni o’rnatish orqali kursorni harakatlantirish uchun ishlatishimiz mumkin.
Izohlar
<code>
yorlig'ini ishlating, bir nechta satrlar uchun - ularni<pre>
yorlig'i bilan o'rab qo'ying, 10 satrdan ortiq bo'lsa - sandbox (plnkr, jsbin, codepen…)