Qo'shimcha brauzer mavzulari

Tanlash va Range

Hujjatdagi matn yoki elementlarni tanlash brauzerda ikki bosqichli tushuncha bilan ifodalanadi: Range โ€” hujjatning ma'lum bir qismi (boshlanish va tugash nuqtalari bilan), Selection esa โ€” foydalanuvchi yoki dastur belgilagan joriy tanlov. Ushbu darsda ular qanday ishlashini va dastur orqali qanday boshqarilishini ko'ramiz.

Range obyekti

Range โ€” hujjatdagi ikki nuqta orasidagi qismni ifodalaydi. Har bir nuqta ikkita qiymat bilan beriladi: tugun (node) va uning ichidagi siljish (offset).

let range = new Range();

Boshlanish va tugash nuqtalari setStart va setEnd bilan o'rnatiladi:

Bu yerda offset ikki xil ma'noga ega:

setStart va setEnd

Aytaylik, sahifada <p id="matn">Salom, dunyo!</p> bor. Matndagi 'Salom' so'zini tanlaymiz โ€” bu <p>ning birinchi matn tuguni ichidagi 0-belgidan 5-belgigacha:

let p = document.getElementById('matn');
let textNode = p.firstChild; // matn tuguni: 'Salom, dunyo!'

let range = new Range();
range.setStart(textNode, 0);  // 0-belgidan
range.setEnd(textNode, 5);    // 5-belgigacha (S-a-l-o-m)

console.log(range.toString()); // 'Salom'

range.toString() tanlangan qismning matnli ko'rinishini qaytaradi.

setEnd(textNode, 5) โ€” bu "5-belgidan keyin" degani. Ya'ni 'Salom' so'zining beshta harfi (indekslari 0..4) tanlanadi, tugash nuqtasi esa 5-pozitsiyada turadi. Nuqtalar belgilar orasida joylashadi.

Elementlarni qamrab olish

Nuqta faqat matn ichida emas, elementlar orasida ham bo'lishi mumkin. Masalan, <p> ichida <i> va <b> teglari bor deylik. Ularning bir qismini tanlash uchun offset bola tugun indeksini bildiradi:

// <p>Bu <i>muhim</i> va <b>qalin</b> matn</p>
let p = document.getElementById('matn');

let range = new Range();
range.setStart(p, 0);  // birinchi bola tugundan oldin
range.setEnd(p, 2);    // ikkinchi bola tugungacha

// natijada 'Bu <i>muhim</i>' qismi tanlanadi
console.log(range.toString());

Yana qulay usullar mavjud:

Range xususiyatlari

Range obyekti quyidagi asosiy xususiyatlarga ega:

Range bilan amallar

Range orqali tanlangan qismni nusxalash, o'chirish yoki chiqarib olish mumkin:

let range = new Range();
range.setStart(textNode, 0);
range.setEnd(textNode, 5);

// tanlangan 'Salom' qismini <mark> ichiga o'raymiz
let mark = document.createElement('mark');
range.surroundContents(mark);
surroundContents talabchan: agar Range tugunlarni "yarim" kessa (masalan, bir elementning boshi tanlansa-yu, oxiri boshqa elementda qolsa), u xatolik beradi. Bunday holatda extractContents + insertNode kombinatsiyasini qo'llash kerak.

Selection obyekti

Range โ€” bu shunchaki hujjatning bir qismi; u hali ekranda ko'rinmaydi. Foydalanuvchi ko'rgan haqiqiy tanlovni Selection obyekti ifodalaydi. Uni window.getSelection() yoki document.getSelection() orqali olamiz:

let selection = window.getSelection();

Nazariy jihatdan bir tanlov bir nechta Range'dan iborat bo'lishi mumkin (masalan, Firefox'da Ctrl bilan bir nechta qismni tanlash mumkin), ammo amalda ko'pchilik brauzerlarda bitta Range bo'ladi.

Selectionning asosiy xususiyatlari:

anchor (langar) va focus โ€” tanlovning boshi va oxiri, lekin ular hujjat tartibida oldinma-keyin bo'lishi shart emas. Agar foydalanuvchi o'ngdan chapga tanlasa, focus anchordan oldinda turadi. Rangeda esa doim start hujjat bo'yicha enddan oldin keladi.

getSelection va matnni o'qish

Foydalanuvchi tanlagan matnni olishning eng oson yo'li โ€” Selectionni matnga aylantirish:

document.onselectionchange = function() {
  let selection = document.getSelection();
  console.log('Tanlangan matn: ' + selection.toString());
};

selectionchange hodisasi tanlov har o'zgarganda ishga tushadi. Bu tanlangan matnni real vaqtda kuzatish uchun qulay.

Agar Range darajasida ishlash kerak bo'lsa:

let selection = document.getSelection();

if (selection.rangeCount > 0) {
  let range = selection.getRangeAt(0);
  console.log(range.startContainer, range.startOffset);
  console.log(range.endContainer, range.endOffset);
}

Dastur orqali tanlash

Tanlovni faqat o'qibgina qolmay, dastur orqali o'rnatish ham mumkin. Buning uchun avval Range tuzamiz, keyin uni tanlovga qo'shamiz:

let p = document.getElementById('matn');
let textNode = p.firstChild;

// 'Salom' so'zini qamrab oluvchi Range
let range = new Range();
range.setStart(textNode, 0);
range.setEnd(textNode, 5);

let selection = window.getSelection();
selection.removeAllRanges();  // avvalgi tanlovni tozalaymiz
selection.addRange(range);    // yangi tanlovni o'rnatamiz

Selectionda bir necha qulay metodlar bor:

Butun bir elementning matnini bir bosishda tanlash kerak bo'lsa, eng oson yo'l โ€” selection.selectAllChildren(elem). Bu, masalan, "kod bo'lagini bosganda hammasini tanlansin" xatti-harakati uchun juda qulay.

Form maydonlaridagi tanlash

Muhim istisno: <input> va <textarea> maydonlarida yuqoridagi Range/Selection ishlamaydi. Ular oddiy matndan iborat bo'lgani uchun o'zining alohida, soddaroq API'siga ega:

let input = document.getElementById('maydon');

input.onclick = function() {
  // birinchi 5 ta belgini tanlaymiz
  input.setSelectionRange(0, 5);
  input.focus();
};

Xulosa