Odak sistemi, kullanıcının Blockly düzenleyicideki konumunu (odak) takip eder. Blockly ve özel kod tarafından, şu anda hangi bileşenin (blok, alan, araç kutusu kategorisi vb.) odaklandığını belirlemek ve bu odağı başka bir bileşene taşımak için kullanılır.
Özel kodunuzun odak sistemiyle doğru şekilde çalıştığından emin olabilmek için odak sistemini anlamanız önemlidir.
Mimari
Odaklanma sistemi üç bölümden oluşur:
FocusManager
, Blockly'deki tüm odakları koordine eden tekil bir öğedir. Blockly'nin hangi bileşene odaklandığını öğrenmek ve Blockly'nin odağını farklı bir bileşene taşımak için Blockly ve özel kod tarafından kullanılır. Ayrıca, DOM odak etkinliklerini dinler, Blockly odaklanması ile DOM odaklanmasını senkronize eder ve hangi bileşenin odaklandığını belirten CSS sınıflarını yönetir.Odak yöneticisi esas olarak Blockly tarafından kullanılır. Bazen odak sistemiyle etkileşim kurmak için özel kod tarafından kullanılır.
IFocusableTree
, Blockly düzenleyicisinin bağımsız bir alanıdır (ör. çalışma alanı veya araç kutusu). Bloklar ve alanlar gibi odaklanılabilir düğümlerden oluşur. Ağaçların alt ağaçları da olabilir. Örneğin, ana çalışma alanındaki bir blokta bulunan mutasyon çalışma alanı, ana çalışma alanının bir alt ağacıdır.IFocusableTree
öncelikli olarak odak yöneticisi tarafından kullanılır. Özel bir araç kutusu yazmadığınız sürece uygulamanız muhtemelen gerekmez.IFocusableNode
, odaklanabilen bir Blockly bileşenidir (ör. blok, alan veya araç kutusu kategorisi). Odaklanılabilir düğümler, düğümü görüntüleyen ve düğüm Blockly odağına sahip olduğunda DOM odağına sahip bir DOM öğesine sahiptir. Ağaçların da odaklanılabilir düğümler olduğunu unutmayın. Örneğin, çalışma alanının tamamına odaklanabilirsiniz.IFocusableNode
bölümündeki yöntemler öncelikle odak yöneticisi tarafından çağrılır.Odaklanılan bileşeni temsil etmek için
IFocusableNode
kullanılır. Örneğin, bir kullanıcı bloğun bağlam menüsünde bir öğe seçtiğinde blok, öğenin geri çağırma işlevineIFocusableNode
olarak iletilir.Özel bileşenler yazarsanız uygulamanız
IFocusableNode
gerekebilir.
Odak türleri
Odak sistemi, çeşitli odak türlerini tanımlar.
Blockly odağı ve DOM odağı
İki ana odak türü vardır: Blockly odağı ve DOM odağı.
Blockly odaklanma, hangi Blockly bileşeninin (blok, alan, araç kutusu kategorisi vb.) odaklandığını belirtir. Blockly bileşenleri düzeyinde çalışmak için gereklidir. Örneğin, klavye ile gezinme eklentisi, kullanıcıların ok tuşlarını kullanarak bileşenler arasında (ör. bloktan alana) geçiş yapmasına olanak tanır. Benzer şekilde, içerik menüsü sistemi de mevcut bileşene uygun bir menü oluşturur. Yani çalışma alanları, bloklar ve çalışma alanı yorumları için farklı menüler oluşturur.
DOM odağı, hangi DOM öğesinin odaklandığını belirtir. DOM öğeleri düzeyinde çalışmak için gereklidir. Örneğin, ekran okuyucular, DOM odaklı olan öğeyle ilgili bilgileri sunar ve sekmeler, DOM öğesinden DOM öğesine geçiş yapar (odak değiştirir).
Odak yöneticisi, Blockly odağını ve DOM odağını senkronize tutar. Bu nedenle, bir düğüm (Blockly bileşeni) Blockly odağına sahip olduğunda temel alınan DOM öğesi DOM odağına sahip olur ve bunun tersi de geçerlidir.
Etkin ve pasif odak
Blockly odağı, etkin odak ve pasif odak olarak ikiye ayrılır. Etkin odak, bir düğümün tuşa basma gibi kullanıcı girişi alacağı anlamına gelir. Pasif odak, bir düğümün daha önce aktif odağa sahip olduğu ancak kullanıcının başka bir ağdaki bir düğüme (örneğin, çalışma alanından araç kutusuna) veya Blockly düzenleyicisinden tamamen uzaklaşmasıyla odağı kaybettiği anlamına gelir. Ağaç yeniden odaklandığında pasif olarak odaklanılan düğüm etkin odağı yeniden kazanır.
Her ağacın ayrı bir odaklanma bağlamı vardır. Yani ağaçtaki en fazla bir düğüm odaklanabilir. Bu odağın etkin mi yoksa pasif mi olduğu, ağacın odaklanıp odaklanmadığına bağlıdır. Sayfanın tamamında en fazla bir etkin odaklanma düğümü olabilir.
Odak yöneticisi, etkin ve pasif olarak odaklanmış düğümler için farklı vurgular (CSS sınıfları) kullanır. Bu özellikler, kullanıcıların bulundukları yeri ve geri dönecekleri yeri anlamalarına olanak tanır.
Geçici odak
Geçici odak adı verilen başka bir odak türü daha vardır. İletişim kutuları veya alan düzenleyiciler gibi ayrı iş akışları, odak yöneticisinden geçici odak ister. Odak yöneticisi geçici odak verdiğinde odak sistemini askıya alır. Pratik açıdan bu, bu tür iş akışlarının, odak sisteminin de bu etkinlikler üzerinde işlem yapabileceğinden endişelenmeden DOM odak etkinliklerini yakalayabileceği ve bu etkinlikler üzerinde işlem yapabileceği anlamına gelir.
Odak yöneticisi geçici odak verdiğinde, etkin olarak odaklanılan düğümü pasif odak olarak değiştirir. Geçici odak döndürüldüğünde etkin odak geri yüklenir.
Örnekler
Aşağıdaki örneklerde, Blockly'nin odak sistemini nasıl kullandığı gösterilmektedir. Bu dokümanlar, kodunuzun odak sistemine nasıl uyduğunu ve odak sistemini nasıl kullanabileceğini anlamanıza yardımcı olmalıdır.
Klavyeyle odağı taşıma
İki alan içeren bir blokta, blokun DOM öğesindeki vurgu (CSS sınıfı) ile belirtildiği gibi Blockly odağı olduğunu varsayalım. Şimdi de kullanıcının sağ oku bastığını varsayalım:
- Klavye ile gezinme
eklentisi:
- Tuşa basma etkinliği alır.
- Navigasyon sisteminden (çekirdek Blockly'nin bir parçası) odağı "sonraki" bileşene taşımasını ister.
- Navigasyon sistemi:
- Odak yöneticisine, Blockly odağına sahip bileşeni sorar. Odak yöneticisi, bloğu
IFocusableNode
olarak döndürür. IFocusableNode
öğesininBlockSvg
olduğunu belirler ve bloklarda gezinme kurallarını inceler. Bu kurallar, Blockly odağının bloktan bir bütün olarak bloktaki ilk alana taşınması gerektiğini belirtir.- Odağı yöneticiye, Blockly odağını ilk alana taşımasını söyler.
- Odak yöneticisine, Blockly odağına sahip bileşeni sorar. Odak yöneticisi, bloğu
- Odak yöneticisi:
- Durumunu, Blockly odağını ilk alana ayarlayacak şekilde günceller.
- DOM odağını alanın DOM öğesine ayarlar.
- Vurgu sınıfını bloğun öğesinden alanın öğesine taşır.
Fareyle odağı taşıma
Şimdi kullanıcının bloktaki ikinci alanı tıkladığını varsayalım. Odak yöneticisi:
- İlk alanın DOM öğesinde bir DOM
focusout
etkinliği, ikinci alanın DOM öğesinde ise birfocusin
etkinliği alır. - Odaklanan DOM öğesinin ikinci alana karşılık geldiğini belirler.
- Durumunu, Blockly odağını ikinci alana ayarlayacak şekilde günceller. (Tarayıcı bunu zaten yaptığından focus yöneticisinin DOM odağını ayarlaması gerekmez.)
- Vurgu sınıfını ilk alanın öğesinden ikinci alanın öğesine taşır.
Diğer örnekler
Diğer bazı örnekler:
Kullanıcı, araç kutusundan çalışma alanına bir blok sürüklediğinde fare etkinliği işleyicisi yeni bir blok oluşturur ve Blockly'nin bu blokta odaklanmasını sağlamak için odak yöneticisini çağırır.
Bir blok silindiğinde,
dispose
yöntemi, odağı bloğun üst öğesine taşımak için odak yöneticisini çağırır.Klavye kısayollarında, kısayolun uygulandığı Blockly bileşenini belirlemek için
IFocusableNode
kullanılır.Bağlam menüleri, menünün çağrıldığı Blockly bileşenini tanımlamak için
IFocusableNode
kullanır.
Özelleştirmeler ve odak sistemi
Blockly'yi özelleştirirken kodunuzun odak sistemiyle doğru şekilde çalıştığından emin olmanız gerekir. Ayrıca, odaklanılan düğümü belirlemek ve ayarlamak için odaklanma sistemini de kullanabilirsiniz.
Özel bloklar ve araç kutusu içerikleri
Blockly'yi özelleştirmenin en yaygın yolu özel bloklar tanımlamak ve araç kutusunun içeriğini özelleştirmektir. Bu işlemlerin hiçbiri odaklanma sistemini etkilemez.
Özel sınıflar
Özel sınıfların bir veya iki odak arayüzünü (IFocusableTree
ve IFocusableNode
) uygulaması gerekebilir. Bu durumun ne zaman geçerli olduğu her zaman açıkça belli olmaz.
Bazı sınıfların odak arayüzlerini uygulaması gerektiği açıktır. Bunlardan bazıları:
Özel bir araç kutusu uygulayan sınıf. Bu sınıfın
IFocusableTree
veIFocusableNode
uygulaması gerekir.Kullanıcıların gezinebileceği görünür bir bileşen (ör. alan veya simge) oluşturan sınıflar. Bu sınıflar
IFocusableNode
protokolünü uygulamalıdır.
Bazı sınıflar, görünür bir bileşen oluşturmasalar veya kullanıcıların gezinemeyeceği görünür bir bileşen oluştursalar bile IFocusableNode
uygulamalıdır. Bunlardan bazıları:
IFocusableNode
öğesini genişleten bir arayüz uygulayan sınıflar.Örneğin, klavye ile gezinme eklentisindeki taşıma simgesi, bloğun ok tuşlarıyla taşınabileceğini belirten dört yönlü bir ok gösterir. Simgenin kendisi görünmüyor (dört yönlü ok bir balon) ve kullanıcılar bu simgeye gidemiyor. Ancak simgeler
IIcon
öğesini uyguladığından veIIcon
,IFocusableNode
öğesini genişlettiğinden simgeninIFocusableNode
öğesini uygulaması gerekir.IFocusableNode
gerektiren bir API'de kullanılan sınıflar.Örneğin,
FlyoutSeparator
sınıfı, bir açılır listedeki iki öğe arasında boşluk oluşturur. Herhangi bir DOM öğesi oluşturmadığı için görünür bir bileşeni yoktur ve kullanıcılar bu bileşene gidemez. AncakIFocusableNode
içinde depolandığı veFlyoutItem
oluşturucusununIFocusableNode
gerektirdiği içinIFocusableNode
uygulaması gerekir.FlyoutItem
IFocusableNode
uygulayan bir sınıfı genişleten sınıflar.Örneğin,
ToolboxSeparator
,IFocusableNode
'yi uygulayanToolboxItem
'yi genişletir. Araç kutusu ayırıcılarının görünür bir bileşeni olsa da, üzerinde işlem yapılamadığından ve faydalı içerik barındırmadığından kullanıcılar bu bileşenlere gidemez.
Diğer sınıflar, kullanıcının gezinebileceği görünür bileşenler oluşturur ancak IFocusableNode
'yı uygulamaları gerekmez. Bunlardan bazıları:
- Alan düzenleyici veya iletişim kutusu gibi kendi odağını yöneten görünür bir bileşen oluşturan sınıflar. (Bu tür sınıfların, başladıklarında kısa süreli odaklanma alması ve bittiğinde geri vermesi gerektiğini unutmayın.
WidgetDiv
veyaDropDownDiv
kullanıldığında bu işlem sizin için yapılır.)
Son olarak, bazı sınıflar odak sistemiyle etkileşime girmez ve IFocusableTree
veya IFocusableNode
uygulamasına gerek duymaz. Bunlardan bazıları:
Kullanıcıların gezinemediği veya üzerinde işlem yapamadığı, ekran okuyucunun kullanabileceği hiçbir bilgi içermeyen görünür bileşenler oluşturan sınıflar. Örneğin, bir oyunda tamamen dekoratif amaçlı kullanılan arka planlar.
IMetricsManager
veyaIVariableMap
uygulayan sınıflar gibi odak sistemiyle tamamen alakasız sınıflar.
Sınıfınızın odak sistemiyle etkileşime girip girmeyeceğinden emin değilseniz
klavye gezinme eklentisiyle test edin. Bu işlem başarısız olursa IFocusableTree
veya IFocusableNode
'yi uygulamanız gerekebilir. İşlem başarılı olursa ancak yine de emin değilseniz arayüzlerden birinin gerekli olup olmadığını veya başka etkileşimlerin olup olmadığını görmek için sınıfınızı kullanan kodu okuyun.
Odaklanma arayüzlerini uygulama
IFocusableTree
veya IFocusableNode
'ı uygulamanın en kolay yolu, bu arayüzleri uygulayan bir sınıfı genişletmektir. Örneğin, özel bir araç kutusu oluşturuyorsanız Toolbox
'yı genişletin. Bu, IFocusableTree
ve IFocusableNode
'yi uygular. Özel alan oluşturuyorsanız Field
sınıfını genişletin. Bu sınıf, IFocusableNode
sınıfını uygular. Kodunuzun temel sınıftaki odak arayüzü koduyla çakışmadığından emin olun.
Odak arayüzünü uygulayan bir sınıfı genişletirseniz genellikle herhangi bir yöntemi geçersiz kılmanız gerekmez. En yaygın istisna, kullanıcıların bileşeninize gitmesini istemiyorsanız geçersiz kılmanız gereken IFocusableNode.canBeFocused
'dır.
Odak geri çağırma yöntemlerini (onTreeFocus
ve onTreeBlur
, IFocusableTree
ve onNodeFocus
ve onNodeBlur
içinde
IFocusableNode
) geçersiz kılma ihtiyacı daha az görülür. Bu yöntemlerden odak değiştirmeye (FocusManager.focusNode
veya FocusManager.focusTree
çağrısı) çalışmanın istisnaya neden olacağını unutmayın.
Özel bir bileşeni sıfırdan yazarsanız odak arayüzlerini kendiniz uygulamanız gerekir. Daha fazla bilgi için IFocusableTree
ve IFocusableNode
ile ilgili referans belgelerine göz atın.
Sınıfınızı uyguladıktan sonra, bileşeninize gidip gidemediğinizi doğrulamak için klavye navigasyonu eklentisine karşı test edin.
Odak yöneticisini kullanma
Bazı özel sınıflar odak yöneticisini kullanır. Bunun en yaygın nedenleri, şu anda odaklanılan düğümü almak ve farklı bir düğüme odaklanmaktır. Odak yöneticisini almak için Blockly.getFocusManager
işlevini çağırın:
const focusManager = Blockly.getFocusManager();
Şu anda odaklanılan düğümü almak için getFocusedNode
işlevini çağırın:
const focusedNode = focusManager.getFocusedNode();
// Do something with the focused node.
Odağı farklı bir düğüme taşımak için focusNode
işlevini çağırın:
// Move focus to a different block.
focusManager.focusNode(myOtherBlock);
Odağı bir ağaca taşımak için focusTree
işlevini çağırın. Bu işlem, düğüm odağını ağacın kök düğümüne de ayarlar.
// Move focus to the main workspace.
focusManager.focusTree(myMainWorkspace);
Odak yöneticisinin kullanılmasının bir diğer yaygın nedeni ise geçici odak almak ve döndürmektir. takeEphemeralFocus
işlevi, geçici odak döndürmek için çağırmanız gereken bir lambda döndürür.
const returnEphemeralFocus = focusManager.takeEphemeralFocus();
// Do something.
returnEphemeralFocus();
WidgetDiv
veya DropDownDiv
kullanıyorsanız geçici odak sizin için işlenir.
Sekme durakları
Odak sistemi, tüm ağaçların (ana çalışma alanı, araç kutusu ve açılır çalışma alanları) kök öğesinde bir sekme durağı (tabindex
of 0
) ayarlar. Bu sayede kullanıcılar, Blockly düzenleyicisinin ana bölgelerinde gezinmek için sekme tuşunu, bu bölgelerde gezinmek için ise (klavye gezinme eklentisini kullanarak) ok tuşlarını kullanabilir. Bu sekme duraklarını değiştirmeyin. Aksi takdirde, odak yöneticisinin bunları yönetme özelliği etkilenir.
Genel olarak, Blockly tarafından kullanılan diğer DOM öğelerinde sekme durakları ayarlamaktan kaçınmalısınız. Bu, Blockly'nin sekme tuşunu kullanarak düzenleyicinin alanları arasında ve bu alanlarda ok tuşlarını kullanarak gezinme modeline müdahale eder. Ayrıca bu tür sekme durakları, amaçlandığı gibi çalışmayabilir. Bunun nedeni, odaklanılabilir her düğümün bir DOM öğesini odaklanılabilir öğesi olarak bildirmesidir. Odaklanılabilir bir öğenin alt öğesinde sekme durağı ayarlarsanız ve kullanıcı bu öğeye sekmeyle giderse odak yöneticisi, DOM odağını belirtilen odaklanılabilir öğeye taşır.
Uygulamanızdaki Blockly düzenleyicisinin dışında kalan öğelerde sekme durakları ayarlamak güvenlidir. Kullanıcı, sekme tuşuyla düzenleyiciden bu tür bir öğeye geçtiğinde focus
manager, Blockly odağını etkin durumdan pasif duruma değiştirir. Erişilebilirlik için tabindex
özelliğinin MDN'deki açıklamasında belirtilen uyarıda önerildiği gibi tabindex
özelliğini 0
veya -1
olarak ayarlamanız gerekir.
DOM odaklanması
Erişilebilirlik nedeniyle, uygulamalar DOM öğelerinde focus
yöntemini çağırmaktan kaçınmalıdır. Bu durum, ekran okuyucu kullanan kullanıcıları şaşırtır. Çünkü bu kullanıcılar, uygulamada aniden bilinmeyen bir konuma taşınır.
Başka bir sorun da odak yöneticisinin, odaklanılabilir öğe olarak tanımlanmış odaklanılan öğenin en yakın üst öğesi veya kendisi üzerinde DOM odağı ayarlayarak odaklanma etkinliklerine tepki vermesidir. Bu, focus
öğesinin çağrıldığı öğeden farklı olabilir. (En yakın odaklanılabilir üst öğe veya kendisi yoksa (ör. focus
, Blockly düzenleyicisi dışındaki bir öğede çağrıldığında) odak yöneticisi, etkin olarak odaklanılan düğümü pasif odak olarak değiştirir.)
Konumlandırılabilir öğeler
Konumlandırılabilir öğeler, çalışma alanının üstünde konumlandırılan ve IPositionable
uygulayan bileşenlerdir.
Sırt çantası eklentisindeki çöp kutusu ve sırt çantası buna örnek olarak verilebilir.
Konumlandırılabilir öğeler henüz odak sistemine entegre edilmedi.