İçeriğe geç
academia.sh

Ders 12 / 25

Tablolar

İki eksenli konumun işaretlemede kurulması, satır ve sütun başlığı ilişkisi, sıralama durumunun bildirimi ile duyurusu ve yoğun veride sekme sırasının denetim altında tutulması.

İçindekiler

Önceki ders sonuç listesinin konumunu bildirir hâle getirdi. Katalogda aynı veri çoğu zaman bir listeden daha fazlasıdır: raf kodu, başlık, yıl ve durum sütunlara ayrılır, sütunlar sıralanabilir ve satır sayısı yüzleri bulur. Bu yapıya tablo denir ve tabloda konum iki eksenlidir — kullanıcı hem bir satırda hem bir sütundadır.

Görsel okuyucu bu iki ekseni bakışla birleştirir: bir hücreye bakar, yukarı doğru sütun başlığını, sola doğru satır başlığını görür. Ekranı görmeyen kullanıcı bu birleştirmeyi yapamaz; hücrenin hangi başlıklara bağlı olduğu işaretlemede yazılı olmak zorundadır.

Kalıbın Çözdüğü Sorun ve Kullanılmayacağı Yer

Tablo, iki boyutlu ilişkisel veriyi sunar: her satır bir varlık, her sütun o varlığın bir niteliğidir. Bir veri tablonun içine ancak bu ilişki gerçekten varsa girer.

Düzen kurmak için tablo kullanmak bu ilişkiyi uydurur: ekranı görmeyen kullanıcıya var olmayan bir satır–sütun yapısı bildirilir ve içerik anlamsız bir ızgaraya dönüşür. Düzen işi Düzen Sistemleri kursundaki ızgara modellerinin işidir; tablo ögesi yalnız veri tablosu içindir.

Yerel Öge Önce ve Başlık İlişkisi

Tablonun yerel karşılığı eksiksizdir: tablo ögesi, özet başlığı, başlık hücreleri ve veri hücreleri. Başlık hücresi sütun ya da satır başlığı olduğunu kapsam bildirimiyle söyler. Bu bildirim yazıldığında hücre–başlık ilişkisi kendiliğinden kurulur; ARIA’ya gerek kalmaz.

Aşağıdaki hesap bu ilişkiyi bir model üzerinde kuruyor ve satır başlığı işaretlenmediğinde neyin kaybolduğunu sayıyor.

// tablo.mjs — baslik-hucre iliskisi, siralama durumu ve yogun veride gezinme

// Tablo modeli: basliklar, satirlar ve her hucrenin degeri.
const TABLO = {
  ozet: "Kuzey Yamaç ölçüm kayıtları",
  sutunlar: [
    { anahtar: "kod", ad: "Raf kodu", tur: "metin", siralanabilir: true },
    { anahtar: "baslik", ad: "Başlık", tur: "metin", siralanabilir: true, satirBasligi: true },
    { anahtar: "yil", ad: "Yıl", tur: "sayi", siralanabilir: true },
    { anahtar: "durum", ad: "Durum", tur: "metin", siralanabilir: false },
  ],
  satirlar: [
    { kod: "QB-141", baslik: "Gökbilim El Kitabı", yil: 1998, durum: "rafta" },
    { kod: "QB-212", baslik: "Kuzey Gökyüzü Atlası", yil: 2004, durum: "ödünçte" },
    { kod: "QC-018", baslik: "Ölçüm Yöntemleri", yil: 2011, durum: "rafta" },
  ],
};

// 1. Baslik-hucre iliskisi: her veri hucresinin bagli oldugu basliklar.
// Kural: sutun basligi tablonun ust satirindan, satir basligi o satirin
// "satirBasligi" isaretli sutunundan gelir.
const satirBasligiSutunu = TABLO.sutunlar.find((s) => s.satirBasligi);
console.log("--- baslik-hucre iliskisi ---");
console.log("hucre                     bagli basliklar");
let baglisiz = 0;
for (const satir of TABLO.satirlar) {
  for (const sutun of TABLO.sutunlar) {
    if (sutun.satirBasligi) continue;
    const basliklar = [sutun.ad, satirBasligiSutunu ? satir[satirBasligiSutunu.anahtar] : null].filter(Boolean);
    if (basliklar.length < 2) baglisiz++;
    console.log(`  ${String(satir[sutun.anahtar]).padEnd(24)} ${basliklar.join(" / ")}`);
  }
}
console.log(`iki baslikla da eslesmeyen hucre: ${baglisiz}`);

// 2. Ayni tablo satir basligi isaretlenmeden kurulursa.
const satirBasligisiz = { ...TABLO, sutunlar: TABLO.sutunlar.map((s) => ({ ...s, satirBasligi: false })) };
const eksikEslesme = satirBasligisiz.satirlar.length * (satirBasligisiz.sutunlar.length - 0);
console.log(`\nsatir basligi isaretlenmezse: her hucre yalniz sutun adiyla eslesir`);
console.log(`  eslesme sayisi: hucre basina 1 (satir kimligi kayboluyor)`);
console.log(`  etkilenen hucre: ${eksikEslesme}`);

// 3. Siralama durumu: yalniz bir sutun siralanmis olabilir.
function siralamaDurumu(sutunAnahtari, yon) {
  return TABLO.sutunlar.map((s) => ({
    ad: s.ad,
    siralanabilir: s.siralanabilir,
    durum: !s.siralanabilir ? "-" : s.anahtar === sutunAnahtari ? yon : "none",
  }));
}
const durum = siralamaDurumu("yil", "ascending");
console.log("\n--- siralama durumu ---");
console.log("sutun        siralanabilir  aria-sort");
for (const d of durum) console.log(`  ${d.ad.padEnd(11)} ${(d.siralanabilir ? "evet" : "hayir").padEnd(14)} ${d.durum}`);
const isaretli = durum.filter((d) => d.durum !== "none" && d.durum !== "-").length;
console.log(`isaretli sutun: ${isaretli} (kural: en cok 1)`);

// 4. Siralamadan sonra duyurulacak dizgi.
const yonAdi = { ascending: "artan", descending: "azalan" };
function duyuru(sutunAd, yon, satirSayisi) {
  return `${sutunAd} sütununa göre ${yonAdi[yon]} sıralandı, ${satirSayisi} satır`;
}
console.log(`\nduyuru: "${duyuru("Yıl", "ascending", TABLO.satirlar.length)}"`);
console.log(`duyuru: "${duyuru("Başlık", "descending", TABLO.satirlar.length)}"`);

// 5. Siralamanin kendisi: veri turu karsilastirmayi belirler.
const karsilastir = (tur) =>
  tur === "sayi" ? (a, b) => a - b : (a, b) => String(a).localeCompare(String(b), "tr");
console.log("\n--- siralama sonucu (yil, artan) ---");
for (const s of [...TABLO.satirlar].sort((a, b) => karsilastir("sayi")(a.yil, b.yil))) {
  console.log(`  ${String(s.yil).padEnd(6)} ${s.baslik}`);
}
console.log("--- siralama sonucu (baslik, artan; tr harf sirasi) ---");
for (const s of [...TABLO.satirlar].sort((a, b) => karsilastir("metin")(a.baslik, b.baslik))) {
  console.log(`  ${s.baslik}`);
}

// 6. Yogun veride sekme duragi sayisi: her hucre odaklanabilir yapilirsa ne olur?
const SATIR = 200, SUTUN = 4;
const hepsiOdaklanabilir = SATIR * SUTUN;
const yalnizEylemler = SATIR * 1 + SUTUN;      // satir basina bir eylem + sutun basliklari
console.log("\n--- sekme duragi sayisi (200 satir, 4 sutun) ---");
console.log(`  her hucre odaklanabilir : ${hepsiOdaklanabilir}`);
console.log(`  yalniz eylemler + basliklar: ${yalnizEylemler}`);
console.log(`  oran: ${(hepsiOdaklanabilir / yalnizEylemler).toFixed(1)} kat`);

// 7. Sutun sayisi tutarliligi: eksik hucre denetimi.
const bozukSatir = { kod: "QC-100", baslik: "Eksik Kayıt" }; // yil ve durum yok
const denetlenen = [...TABLO.satirlar, bozukSatir];
console.log("\n--- sutun sayisi tutarliligi ---");
for (const s of denetlenen) {
  const eksik = TABLO.sutunlar.filter((c) => s[c.anahtar] === undefined).map((c) => c.ad);
  console.log(`  ${(s.kod || "-").padEnd(8)} eksik alan: ${eksik.length ? eksik.join(", ") : "yok"}`);
}
--- baslik-hucre iliskisi ---
hucre                     bagli basliklar
  QB-141                   Raf kodu / Gökbilim El Kitabı
  1998                     Yıl / Gökbilim El Kitabı
  rafta                    Durum / Gökbilim El Kitabı
  QB-212                   Raf kodu / Kuzey Gökyüzü Atlası
  2004                     Yıl / Kuzey Gökyüzü Atlası
  ödünçte                  Durum / Kuzey Gökyüzü Atlası
  QC-018                   Raf kodu / Ölçüm Yöntemleri
  2011                     Yıl / Ölçüm Yöntemleri
  rafta                    Durum / Ölçüm Yöntemleri
iki baslikla da eslesmeyen hucre: 0

satir basligi isaretlenmezse: her hucre yalniz sutun adiyla eslesir
  eslesme sayisi: hucre basina 1 (satir kimligi kayboluyor)
  etkilenen hucre: 12

--- siralama durumu ---
sutun        siralanabilir  aria-sort
  Raf kodu    evet           none
  Başlık      evet           none
  Yıl         evet           ascending
  Durum       hayir          -
isaretli sutun: 1 (kural: en cok 1)

duyuru: "Yıl sütununa göre artan sıralandı, 3 satır"
duyuru: "Başlık sütununa göre azalan sıralandı, 3 satır"

--- siralama sonucu (yil, artan) ---
  1998   Gökbilim El Kitabı
  2004   Kuzey Gökyüzü Atlası
  2011   Ölçüm Yöntemleri
--- siralama sonucu (baslik, artan; tr harf sirasi) ---
  Gökbilim El Kitabı
  Kuzey Gökyüzü Atlası
  Ölçüm Yöntemleri

--- sekme duragi sayisi (200 satir, 4 sutun) ---
  her hucre odaklanabilir : 800
  yalniz eylemler + basliklar: 204
  oran: 3.9 kat

--- sutun sayisi tutarliligi ---
  QB-141   eksik alan: yok
  QB-212   eksik alan: yok
  QC-018   eksik alan: yok
  QC-100   eksik alan: Yıl, Durum

Satır Başlığı Kimliği Taşır

Çıktının ilk bölümü her veri hücresinin iki başlığa bağlandığını gösteriyor: sütun adı ve satırın kimliği. “1998” değeri tek başına bir sayıdır; “Yıl / Gökbilim El Kitabı” bağlamı onu bir bilgiye çevirir.

İkinci bölüm satır başlığı işaretlenmediğinde ne olduğunu sayıyor: on iki hücrenin her biri yalnız sütun adıyla eşleşiyor, satır kimliği kayboluyor. Hücreler arasında gezen kullanıcı “1998” duyar ama hangi kaydın yılı olduğunu bilemez. Her satırda bir hücre — genellikle adı ya da kimliği taşıyan hücre — satır başlığı olarak işaretlenir.

Sıralama Durumu Bir Bildirimdir

Üçüncü bölüm sıralama durumunu denetliyor. Kural iki parçalıdır. Birincisi, sıralanabilir her sütun başlığının sıralama durumunu bildirmesi gerekir; sıralanabilir olmayan sütun bu bildirimi hiç taşımaz. İkincisi, aynı anda en çok bir sütun sıralanmış olabilir; iki sütunun birden işaretli görünmesi, kullanıcıya çelişkili bir durum bildirir.

Sıralama denetiminin kendisi başlık hücresinin içindeki bir düğmedir. Başlık hücresini tıklanabilir yapmak yerine düğme kullanmanın nedeni Bağlantı ve Düğme Ayrımı dersinde kurulmuştu: eylem düğmedir, düğme klavyeden erişilir ve rolüyle bildirilir.

Sıralamadan Sonra Ne Duyurulur

Dördüncü bölüm duyuru dizgisini üretiyor. Sıralama sayfayı değiştirmez, tablonun içeriğini yeniden düzenler; bu değişiklik görsel olarak anında görünür ama duyurulmazsa ekranı görmeyen kullanıcı için sessizdir.

Duyuru üç bilgiyi taşır: hangi sütun, hangi yön, kaç satır. Satır sayısının bulunması önemlidir, çünkü sıralama süzgeçle birlikte çalıştığında satır sayısı da değişebilir. Duyuru kibar bir canlı bölgeden verilir; sıralama kullanıcının kendi eylemidir ve kesintiye uğratmayı gerektirmez.

Beşinci bölüm sıralamanın kendisini gösteriyor: karşılaştırma veri türüne bağlıdır. Sayı sütunu sayısal, metin sütunu dile duyarlı karşılaştırmayla sıralanır. Türkçe metinlerde dizgi karşılaştırması yerel ayara verilmezse harf sırası bozulur — bu, Uluslararasılaştırma API’si dersinde kurulan kuralın tablo tarafındaki karşılığıdır.

Yoğun Veride Gezinme

Altıncı bölüm bir sayıyı ortaya koyuyor: iki yüz satırlık bir tabloda her hücre odaklanabilir yapılırsa sekme sırasına sekiz yüz durak girer. Yalnız eylemler ve sütun başlıkları odaklanabilir olduğunda bu sayı iki yüz dörde iner — yaklaşık dörtte bir.

Tablo hücreleri arasında ok tuşlarıyla gezinme, ancak tablo bir ızgara denetimi olarak kurulduğunda gerekir: hücreler düzenlenebiliyorsa ya da hücre seçimi bir eylemse. Salt okunur bir veri tablosunda hücreler odaklanabilir yapılmaz; kullanıcı içeriği okuma kipiyle gezer ve sekme sırası yalnız eylemleri taşır.

Son bölüm sütun sayısı tutarlılığını denetliyor. Eksik hücre bırakan bir satır, başlık eşlemesini kaydırır ve okuma sırasında değerler yanlış başlıkla eşleşir. Boş bir hücre bilinçli olarak boş bırakılabilir; eksik hücre bir kusurdur.

Klavye Sözleşmesi

Tuş Davranış
Tab Bir sonraki eyleme geçer: sıralama düğmesi, satır içi eylem, sayfalama
Enter / Boşluk Odaktaki sıralama düğmesini çalıştırır, yönü değiştirir
Ok tuşları Salt okunur tabloda tablo kısayolu değildir; okuma kipinin kendi gezinmesi çalışır

Ölçülebilir Kısıtlar

  • Sıralanabilir her başlık hücresi sıralama durumunu bildirir ve aynı anda en çok biri sıralanmış olur.
  • Her satırda bir hücre satır başlığı olarak işaretlenir; sütun başlıkları kapsamını bildirir (WCAG 1.3.1).
  • Sıralama düğmesinin hedef boyutu 24×24 pikselden küçük olamaz (WCAG 2.5.8); başlık hücresinin tamamı tıklanabilir yapılıyorsa bu ölçü zaten sağlanır.
  • Sıralama yönü yalnız bir ok simgesiyle bildirilemez; durum bildirimi metinsel kanaldır (WCAG 1.4.1).
  • Yatay kaydırma gereken geniş tablolarda kaydırılabilir kap klavyeyle erişilebilir olmalıdır.

Sık Yapılan Hata

En sık hata, tabloyu düzen aracı olarak kullanmaktır. İkincisi, başlık hücrelerini biçimlendirilmiş veri hücresi olarak yazmaktır: kalın ve ortalanmış bir veri hücresi görsel olarak başlığa benzer ama hiçbir hücreyle ilişkilendirilmez. Üçüncüsü, sıralamayı yalnız simgeyle bildirmek ve durum bildirimini atlamaktır; bu durumda sıralamanın hangi sütunda olduğu klavye kullanıcısına hiç ulaşmaz.

Özet

  • Tabloda konum iki eksenlidir; hücrenin hangi satır ve sütun başlığına bağlı olduğu işaretlemede yazılır, bakışla kurulan ilişki varsayılamaz.
  • Satır başlığı işaretlenmediğinde her hücre yalnız sütun adıyla eşleşir ve satır kimliği kaybolur; modelde on iki hücrenin tamamı etkileniyor.
  • Sıralanabilir sütun sıralama durumunu bildirir, aynı anda en çok bir sütun işaretlidir ve sıralama sonrası duyuru sütun, yön ve satır sayısını taşır.
  • Karşılaştırma veri türüne bağlıdır; metin sütunları dile duyarlı sıralanır.
  • Salt okunur tabloda hücreler odaklanabilir yapılmaz: iki yüz satırlık tabloda bu karar sekme durağı sayısını sekiz yüzden iki yüz dörde indirir.

Sonraki Adım

Bu bileşenlerin hepsinde içerik yerinde durdu ve kullanıcı ona kendi hızıyla ulaştı. Katalog ana sayfasındaki öne çıkan kayıtlar şeridi ise tersini yapar: içerik kendiliğinden değişir, kullanıcı okumayı bitirmeden bir sonraki karta geçer. Sonraki ders bu kalıbı ele alır ve otomatik geçişin maliyetini ölçütlerle yazar: hareketin durdurulabilir olması, okuma süresiyle geçiş aralığı arasındaki ilişki ve kendiliğinden değişen içeriğin duyurulmasının neden çoğu zaman yanlış olduğu.

İlerlemeni kaydetmek ve not almak için Giriş yap

Notlarım

Not almak için giriş yapmalısın.

Aramak için yazmaya başlayın.

↑↓ Esc gezin · aç · kapat