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 otanodesifatida va0ni offset sifatida oladi.Shuning uchun biz uni
range.setStart(p, 0)deb o’rnatishimiz mumkin. -
Tugash nuqtasi ham
<p>ni otanodesifatida oladi, lekin2ni offset sifatida oladi (u range nioffsetgacha, 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:nodedagioffsetpozitsiyasidasetStartBefore(node)boshlanishni o’rnatish:nodedan darhol oldinsetStartAfter(node)boshlanishni o’rnatish:nodedan darhol keyin
Range tugashini o’rnatish (shunga o’xshash usullar):
setEnd(node, offset)tugashni o’rnatish:nodedagioffsetpozitsiyasidasetEndBefore(node)tugashni o’rnatish:nodedan darhol oldinsetEndAfter(node)tugashni o’rnatish:nodedan 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)butunnodeni tanlash uchun range ni o’rnatishselectNodeContents(node)butunnodekontentini tanlash uchun range ni o’rnatishcollapse(toStart)agartoStart=truebo’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)–nodeni hujjatga range boshida kiritishsurroundContents(node)– range kontenti atrofidanodeni o’rash. Buning ishlashi uchun range o’z ichidagi barcha elementlar uchun ochilish va yopilish teglarini o’z ichiga olishi kerak:<i>abckabi 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,0dan boshlab. Firefox bundan mustasno barcha brauzerlarda faqat0ishlatiladi.
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 boshlangananchorNodedagi offset,focusNode– selection tugagan tugun,focusOffset– selection tugaganfocusNodedagi 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 aniqelemelementida (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
documentda 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.Rangeobyekti, o’z navbatida, uning kontentini nusxalaydigan vaDocumentFragmentobyekti 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,0dan boshlab. Firefox bundan mustasno barcha brauzerlarda faqat0ishlatiladi.addRange(range)– tanlashgarangeqo’shish. Agar tanlash allaqachon bog’langan range ga ega bo’lsa, Firefox bundan mustasno barcha brauzerlar chaqiruvni e’tiborsiz qoldiradi.removeRange(range)– tanlashdanrangeni olib tashlash.removeAllRanges()– barcha range larni olib tashlash.empty()–removeAllRangesning 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 berilgannodeda,offsetpozitsiyasida boshlanib tugaydigan yangi bilan almashtirish.setPosition(node, offset)–collapsening taxallusi.collapseToStart()– tanlash boshiga yig’ish (bo’sh range bilan almashtirish),collapseToEnd()– tanlash oxiriga yig’ish,extend(node, offset)– tanlashning fokusini berilgannodega,offsetpozitsiyasiga o’tkazish,setBaseAndExtent(anchorNode, anchorOffset, focusNode, focusOffset)– tanlash range ni berilgan boshlang’ichanchorNode/anchorOffsetva oxirgifocusNode/focusOffsetbilan almashtirish. Ular orasidagi barcha kontent tanlanadi.selectAllChildren(node)–nodening barcha bolalarini tanlash.deleteFromDocument()– tanlangan kontentni hujjatdan olib tashlash.containsNode(node, allowPartialContainment = false)– tanlashnodeni o’z ichiga olgan-olmaganligini tekshiradi (ikkinchi argumenttruebo’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 (inputo’rnigatextareabo’lishi mumkin), -
input.setSelectionRange(start, end, [direction])– tanlashnistartpozitsiyasidanendgacha, berilgan yo’nalishda (ixtiyoriy) o’zgartirishadi. -
input.setRangeText(replacement, [start], [end], [selectionMode])– matn oralig’ini yangi matn bilan almashtirish.Ixtiyoriy argumentlar
startvaend, 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:
onselectbiror narsa tanlanganida ishga tushadi, lekin tanlash olib tashlanganida emas.- spec ga ko’ra, forma boshqaruvi ichidagi tanlashlar uchun
document.onselectionchangehodisasi ishga tushmasligi kerak, chunki udocumenttanlashi 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: noneCSS xossasidan foydalanish.<style> #elem { user-select: none; } </style> <div>Tanlanuvchi <div id="elem">Tanlanmaydigan</div> Tanlanuvchi</div>Bu tanlashning
elemda boshlanishiga imkon bermaydi. Lekin foydalanuvchi tanlashni boshqa joydan boshlashi vaelemni unga kiritishi mumkin.Keyin
elemdocument.getSelection()ning bir qismiga aylanadi, shuning uchun tanlash haqiqatda sodir bo’ladi, lekin uning kontenti odatda nusxa-joylashtirish da e’tiborga olinmaydi. -
onselectstartyokimousedownhodisalaridagi standart harakatni oldini olish.<div>Tanlanuvchi <div id="elem">Tanlanmaydigan</div> Tanlanuvchi</div> <script> elem.onselectstart = () => false; </script>Bu
elemda tanlashni boshlashga to’sqinlik qiladi, lekin tashrif buyuruvchi uni boshqa elementda boshlashi, keyinelemga 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, lekinelemkontentlarini 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:
SelectionvaRangeobyektlari. input,textareauchun: 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…)