Ders 05 / 26
Öznitelik Seçicileri
Bir özniteliğin varlığına ve değerine göre eşleme; tam eşleme, liste üyeliği, tire önekli eşleme ve alt dizgi eşlemeleri ile harf duyarlılığı işareti.
İçindekiler
Seçiciler şimdiye kadar öge adına, sınıfa, kimliğe ve ağaçtaki konuma baktı. Belgede bir bilgi katmanı daha var: öznitelikler. Bir bağlantının hedef adresi, bir form alanının türü, bir hücreye veri özniteliğiyle iliştirilen ölçüm birimi — hepsi orada durur ve hiçbiri sınıf listesine yazılmamıştır.
Bu ders öznitelik seçicilerini tanımlar. Yedi eşleme biçimi vardır ve aralarındaki farklar dizgi işlemleridir; bu yüzden hepsi çalıştırılarak gösterilebilir.
Yedi Eşleme Biçimi
Öznitelik seçicisi köşeli parantez içinde yazılır. En basit biçimi özniteliğin varlığını sorar; değerine bakmaz.
| Yazım | Koşul |
|---|---|
[ad] |
öznitelik var mı |
[ad="x"] |
değer tam olarak x mi |
[ad~="x"] |
boşlukla ayrılmış değer listesinde x var mı |
[ad|="x"] |
değer x mi, ya da x- ile mi başlıyor |
[ad^="x"] |
değer x ile mi başlıyor |
[ad$="x"] |
değer x ile mi bitiyor |
[ad*="x"] |
değer x içeriyor mu |
Son üçü alt dizgi eşlemesidir ve değeri yapısız bir metin gibi ele alır. Ortadaki ikisi
ise değerin bir yapısı olduğunu varsayar: ~= boşlukla ayrılmış liste, |= tire ile
bölümlenmiş kod.
Aşağıdaki program yedi biçimi de uygular ve istasyon sayfasından alınmış ögeler üzerinde sınar.
// oznitelik-esle.mjs — yedi oznitelik esleme bicimini uygular function esle(bicim, ad, deger, oznitelikler, duyarsiz = false) { if (!(ad in oznitelikler)) return false; let v = oznitelikler[ad]; let d = deger; if (duyarsiz) { v = v.toLowerCase(); d = d.toLowerCase(); } switch (bicim) { case "var": return true; // [ad] case "=": return v === d; // [ad="x"] case "~=": return v.split(/\s+/).includes(d); // [ad~="x"] case "|=": return v === d || v.startsWith(d + "-"); case "^=": return d !== "" && v.startsWith(d); case "$=": return d !== "" && v.endsWith(d); case "*=": return d !== "" && v.includes(d); default: throw new Error("bilinmeyen bicim: " + bicim); } } const ogeler = [ { ad: "a", oz: { href: "https://veri.ornek/istasyon.pdf", rel: "noopener yardim" } }, { ad: "a", oz: { href: "/olcumler", rel: "yardim" } }, { ad: "a", oz: { href: "mailto:gozlem@ornek" } }, { ad: "input", oz: { type: "number", name: "sicaklik", required: "" } }, { ad: "input", oz: { type: "text", name: "gozlemci" } }, { ad: "td", oz: { "data-birim": "derece-C" } }, { ad: "td", oz: { "data-birim": "derece" } }, { ad: "html", oz: { lang: "tr-TR" } }, ]; const sinamalar = [ ["[required]", "var", "required", ""], ['[type="number"]', "=", "type", "number"], ['[rel~="yardim"]', "~=", "rel", "yardim"], ['[lang|="tr"]', "|=", "lang", "tr"], ['[href^="https://"]', "^=", "href", "https://"], ['[href$=".pdf"]', "$=", "href", ".pdf"], ['[href*="olcum"]', "*=", "href", "olcum"], ['[data-birim|="derece"]', "|=", "data-birim", "derece"], ]; for (const [yazim, bicim, ad, deger] of sinamalar) { const bulunan = ogeler.filter((o) => esle(bicim, ad, deger, o.oz)); console.log(`${yazim.padEnd(26)} -> ${bulunan.length}`); for (const b of bulunan) { const oz = Object.entries(b.oz).map(([k, v]) => `${k}="${v}"`).join(" "); console.log(` <${b.ad} ${oz}>`); } } // buyuk-kucuk harf duyarliligi console.log("--- harf duyarliligi ---"); const oge = { type: "NUMBER" }; console.log('[type="number"] ->', esle("=", "type", "number", oge)); console.log('[type="number" i] ->', esle("=", "type", "number", oge, true));
[required] -> 1 <input type="number" name="sicaklik" required=""> [type="number"] -> 1 <input type="number" name="sicaklik" required=""> [rel~="yardim"] -> 2 <a href="https://veri.ornek/istasyon.pdf" rel="noopener yardim"> <a href="/olcumler" rel="yardim"> [lang|="tr"] -> 1 <html lang="tr-TR"> [href^="https://"] -> 1 <a href="https://veri.ornek/istasyon.pdf" rel="noopener yardim"> [href$=".pdf"] -> 1 <a href="https://veri.ornek/istasyon.pdf" rel="noopener yardim"> [href*="olcum"] -> 1 <a href="/olcumler" rel="yardim"> [data-birim|="derece"] -> 2 <td data-birim="derece-C"> <td data-birim="derece"> --- harf duyarliligi --- [type="number"] -> false [type="number" i] -> true
Liste Üyeliği ile Alt Dizgi Farkı
[rel~="yardim"] iki bağlantıyı da döndürdü. Birinin rel değeri "noopener yardim",
diğerininki "yardim". Tilde işareti değeri boşluklardan bölüp listede arar; bu yüzden
sıradan bağımsızdır ve kısmi bir sözcüğe takılmaz.
Aynı sonuç [rel*="yardim"] ile de alınırdı ama bu yazım yanlış eşleşmelere açıktır:
rel="yardimci-degil" değeri de eşleşirdi, oysa liste üyeliği yoktur. Bir öznitelik
boşlukla ayrılmış anahtar sözcük listesi taşıyorsa ~= yazılır, *= değil.
Aynı ayrım |= için de geçerlidir. [lang|="tr"] yazımı lang="tr" ve lang="tr-TR"
değerlerini eşler, lang="trk" değerini eşlemez. Bu, dil etiketlerinin tire ile
bölümlenmiş yapısına göre tasarlanmış bir eşlemedir. Çıktının son satırında aynı biçimin
veri özniteliğinde de işlediği görülüyor: data-birim="derece" ve data-birim="derece-C"
birlikte eşleşti.
Sınıf Seçicisi Bir Öznitelik Seçicisidir
Çıktıdaki ~= davranışı tanıdık gelmelidir. class özniteliği de boşlukla ayrılmış bir
listedir ve sınıf seçicisi tam olarak liste üyeliğini sorar. İki yazım eşdeğerdir:
.eksik { color: #8a1c1c; } [class~="eksik"] { color: #8a1c1c; }
İkinci yazım pratikte kullanılmaz, ama bir kavramı yerine oturtur: sınıf, dilin ayrıcalıklı
bir kavramı değil, bir özniteliğin üzerine konmuş bir kısayoldur. Aynı biçimde #icerik
seçicisi de [id="icerik"] ile aynı kümeyi döndürür — özgüllük hesabındaki ağırlıkları
farklı olsa da eşleme davranışları aynıdır.
Harf Duyarlılığı ve Boş Değer
Çıktının son iki satırı bir tuzağı gösteriyor. [type="number"] seçicisi, değeri NUMBER
olan bir ögeyle eşleşmedi. Öznitelik değerleri genel kural olarak harf duyarlıdır; bazı
HTML öznitelikleri için tanımlı bir duyarsızlık vardır, ancak buna bel bağlamak yerine
işaretle açıkça bildirmek daha güvenlidir:
input[type="number" i] { text-align: right; }
Kapanış parantezinden önce yazılan i işareti eşlemeyi harf duyarsız yapar. s işareti
tersini, açıkça duyarlı eşlemeyi ister.
İkinci tuzak boş dizgidir. Programdaki üç alt dizgi biçiminde d !== "" denetimi
bulunuyor ve bu, dilin kuralını yansıtır: [href*=""] yazımı hiçbir ögeyle eşleşmez.
Sezgi tersini söyler — her dizgi boş dizgiyi içerir — ama tanım bu durumu dışarıda
bırakır. Bir değeri dinamik olarak seçiciye yerleştiren bir üretim varsa, boş değer
durumunda kuralın sessizce ölmesi beklenmelidir.
Öznitelik Seçicisi Ne Zaman Doğru Araçtır
Bir sınıf eklemek her zaman mümkündür; öyleyse öznitelik seçicisi neden gereksin?
Öznitelik seçicisi, ayrımın zaten belgede olduğu durumlarda doğru araçtır. Bir form
alanının türü type özniteliğinde yazılıdır; ona ayrıca class="sayi-alani" eklemek aynı
bilgiyi iki yere yazmak ve ikisini eşzamanlı tutma yükümlülüğü almaktır. İki kaynak
ayrıştığında hangisinin doğru olduğu belirsizleşir.
Aynı gerekçe zorunluluk durumu için de geçerlidir:
/* istasyon.css — 4. adım: form alanları ve dış bağlantılar */ input[type="number"] { text-align: right; } input[required] { border-inline-start: 3px solid #8a5b00; } a[href^="http"] { padding-inline-end: 1em; } td[data-birim|="derece"] { font-variant-numeric: tabular-nums; }
İkinci kural, zorunlu alanları belgedeki required özniteliğinden okur. Alan zorunlu
olmaktan çıkarıldığında öznitelik silinir ve biçem kendiliğinden düşer; hiçbir sınıf
güncellemesi gerekmez. Doğrulama davranışı ile görsel işaret aynı tek kaynaktan beslenir.
Üçüncü kuralın gerekçesi farklıdır: dış bağlantılara yer açar. Adresin http ile başlaması
bir yazar kararı değil, adresin kendi biçimidir; onu ayrıca sınıfla bildirmek gereksiz
tekrar olurdu.
Sınırı da söylemek gerekir. Öznitelik seçicisi, ayrım belgede yoksa uydurulamaz. “Bu paragraf uyarıdır” bilgisi hiçbir özniteliğe yazılı değilse, onu taşıyacak yer bir sınıf adıdır.
Özet
- Öznitelik seçicisi köşeli parantezle yazılır; en basit biçimi özniteliğin varlığını sorar, kalan altı biçim değeri sınar.
~=değeri boşluklardan bölüp liste üyeliği arar,|=tire ile bölümlenmiş kodun önekini eşler;^= $= *=ise değeri yapısız bir metin gibi ele alır.- Sınıf seçicisi
[class~="…"]ile, kimlik seçicisi[id="…"]ile aynı kümeyi döndürür; ikisi de öznitelik eşlemesinin kısayoludur. - Öznitelik değerleri harf duyarlı eşlenir; duyarsızlık
iişaretiyle açıkça istenir. Boş dizgiyle yazılan alt dizgi eşlemeleri hiçbir ögeyle eşleşmez. - Ayrım belgede zaten bir öznitelikte duruyorsa öznitelik seçicisi yazılır; aynı bilgiyi bir de sınıfa yazmak iki kaynağı eşzamanlı tutma yükümlülüğü getirir.
Sonraki Adım
Seçicilerin tümü şimdiye kadar belgede yazılı olan bir şeye baktı: ad, sınıf, kimlik, öznitelik, konum. Belgede yazılı olmayan şeyler de vardır — bir bağlantının üzerinde durulup durulmadığı, bir alanın odakta olup olmadığı, bir satırın kaçıncı sırada bulunduğu. Sonraki ders bu durumları seçen sözde sınıfları ve belgede hiç bulunmayan içeriği üreten sözde elemanları tanımlar.
İlerlemeni kaydetmek ve not almak için Giriş yap
Notlarım
Not almak için giriş yapmalısın.