Uzantılar, blok oluşturulurken belirli bir türdeki her blokta çalışan işlevlerdir. Bunlar genellikle bir engellemeye özel yapılandırma veya davranış ekler.
Mutator, bir bloka özel serileştirme ve bazen de kullanıcı arayüzü ekleyen özel bir uzantı türüdür.
Uzantılar
Uzantılar, blok oluşturulurken belirli bir türdeki her blokta çalışan işlevlerdir. Özel yapılandırma (ör. engellemenin ipucunu ayarlama) veya özel davranış (ör. engellemeye bir etkinlik işleyici ekleme) ekleyebilirler.
// This extension sets the block's tooltip to be a function which displays
// the parent block's tooltip (if it exists).
Blockly.Extensions.register(
'parent_tooltip_extension',
function() { // this refers to the block that the extension is being run on
var thisBlock = this;
this.setTooltip(function() {
var parent = thisBlock.getParent();
return (parent && parent.getInputsInline() && parent.tooltip) ||
Blockly.Msg.MATH_NUMBER_TOOLTIP;
});
});
Uzantıların bir dize anahtarıyla ilişkilendirilebilmeleri için "kayıtlı" olmaları gerekir. Daha sonra, uzantıyı bloka uygulamak için bu dize anahtarını blok türünüzün JSON tanımının extensions
özelliğine atayabilirsiniz.
{
//...,
"extensions": ["parent_tooltip_extension",]
}
Ayrıca, tek seferde birden fazla uzantı da ekleyebilirsiniz. Yalnızca bir uzantı uyguluyor olsanız bile extensions
özelliğinin bir dizi olması gerektiğini unutmayın.
{
//...,
"extensions": ["parent_tooltip_extension", "break_warning_extension"],
}
Karışımlar
Blockly, bir bloka bazı özellikler/yardımcı işlevler eklemek istediğiniz ancak bunları hemen çalıştırmamak istediğiniz durumlar için de kolaylık sağlar. Bu, tüm ek özelliklerinizi/yöntemlerinizi içeren bir mixin nesnesi kaydetmenize olanak tanıyarak çalışır. Daha sonra mixin nesnesi, belirtilen blok türünün her örneği oluşturulduğunda mix'i uygulayan bir fonksiyona sarmalanır.
Blockly.Extensions.registerMixin('my_mixin', {
someProperty: 'a cool value',
someMethod: function() {
// Do something cool!
}
))`
Mix'ler ile ilişkili dize anahtarlarına JSON'da diğer uzantılar gibi referans verilebilir.
{
//...,
"extensions": ["my_mixin"],
}
Mutatörler
Mutator, bir bloka ekstra serileştirme (kaydedilen ve yüklenen ekstra durum) ekleyen özel bir uzantı türüdür. Örneğin, yerleşik controls_if
ve list_create_with
blokları, sahip oldukları giriş sayısını kaydedebilmek için ekstra serileştirmeye ihtiyaç duyar.
Bloğunuzun şeklini değiştirmenin, daha fazla serileştirmeye ihtiyacınız gerektiği anlamına gelmediğini unutmayın. Örneğin, math_number_property
blokunun şekli değişir, ancak bunu, değeri halihazırda serileştirilmiş olan bir açılır menü alanını temel alarak yapar. Bu nedenle, sadece bir alan doğrulayıcısı kullanabilir ve bir mutatöre ihtiyacı yoktur.
Ne zaman mutatöre ihtiyacınız olup olmadığı hakkında daha fazla bilgi için serileştirme sayfasını inceleyin.
Bazı isteğe bağlı yöntemler sağlarsanız mutatörler, kullanıcıların blokların şekillerini değiştirmeleri için yerleşik bir kullanıcı arayüzü de sağlar.
Serileştirme kancaları
Mutator'lar, çalıştıkları iki adet serileştirme kancasına sahiptir. Bir çift kanca, yeni JSON serileştirme sistemiyle, diğer çift ise eski XML serileştirme sistemiyle çalışır. Bu çiftlerden en az birini sağlamanız gerekir.
SaveExtraState ve loadExtraState
saveExtraState
ve loadExtraState
, yeni JSON serileştirme sistemiyle çalışan serileştirme kancalarıdır. saveExtraState
, bloğun ekstra durumunu temsil eden bir JSON serileştirilebilir değeri döndürür ve loadExtraState
, aynı JSON seri hale getirilebilir değerini kabul ederek bloka uygular.
// These are the serialization hooks for the lists_create_with block.
saveExtraState: function() {
return {
'itemCount': this.itemCount_,
};
},
loadExtraState: function(state) {
this.itemCount_ = state['itemCount'];
// This is a helper function which adds or removes inputs from the block.
this.updateShape_();
},
Sonuç olarak elde edilen JSON şöyle görünür:
{
"type": "lists_create_with",
"extraState": {
"itemCount": 3 // or whatever the count is
}
}
Durum yok
Bloğunuz seri hale getirilirken varsayılan durumundaysa saveExtraState
yönteminiz bunu belirtmek için null
döndürebilir. saveExtraState
yönteminiz null
değerini döndürürse JSON'a hiçbir extraState
özelliği eklenmez. Bu, kaydettiğiniz dosyanın boyutunu küçültür.
Tam serileştirme ve veri yedekleme
saveExtraState
, isteğe bağlı bir doFullSerialization
parametresi de alır. Bu, farklı bir serileyici tarafından serileştirilmiş referans durumu blokları (ör. yedekleme veri modelleri) tarafından kullanılır. Parametre, blok seri durumdan çıkarıldığında referans verilen durumun kullanılamayacağını belirtir. Bu nedenle, bloğun tüm yedekleme durumunu seri hale getirmesi gerekir. Örneğin, tek bir blok serileştirildiğinde veya bir blok kopyalayıp yapıştırıldığında bu doğrudur.
Bunun iki yaygın kullanım alanı vardır:
- Tek bir blok, yedekleme veri modelinin bulunmadığı bir çalışma alanına yüklendiğinde yeni bir veri modeli oluşturmak için kendi durumunda yeterli bilgiye sahip olur.
- Bir blok kopyalayıp yapıştırıldığında, mevcut bir bloka referans vermek yerine her zaman yeni bir yedekleme veri modeli oluşturur.
Bunu kullanan bazı bloklar, @blockly/block-shareable-procedures bloklarıdır. Normalde bu dosyalar, durumlarını depolayan bir yedek veri modeline bir referansı seriler.
Ancak doFullSerialization
parametresi true (doğru) değerine ayarlanırsa tüm durumlarını serilerler. Paylaşılabilir prosedür blokları, kopyalanıp yapıştırıldıklarında mevcut bir modele referans vermek yerine yeni bir yedekleme veri modeli oluşturmalarını sağlamak için bunu kullanır.
mutasyonToDom ve domToMutation
mutationToDom
ve domToMutation
, eski XML serileştirme sistemiyle çalışan serileştirme kancalarıdır. Bu kancaları yalnızca gerektiğinde kullanın (ör. henüz taşınmamış eski bir kod tabanı üzerinde çalışıyorsanız) aksi takdirde saveExtraState
ve loadExtraState
kullanın.
mutationToDom
, blokun ekstra durumunu temsil eden bir XML düğümü döndürür ve domToMutation
, aynı XML düğümünü kabul edip durumu bloka uygular.
// These are the old XML serialization hooks for the lists_create_with block.
mutationToDom: function() {
// You *must* create a <mutation></mutation> element.
// This element can have children.
var container = Blockly.utils.xml.createElement('mutation');
container.setAttribute('items', this.itemCount_);
return container;
},
domToMutation: function(xmlElement) {
this.itemCount_ = parseInt(xmlElement.getAttribute('items'), 10);
// This is a helper function which adds or removes inputs from the block.
this.updateShape_();
},
Elde edilen XML şöyle görünür:
<block type="lists_create_with">
<mutation items="3"></mutation>
</block>
mutationToDom
işleviniz null değerini döndürürse XML'e fazladan öğe eklenmez.
Kullanıcı Arayüzü Kancaları
Mutatörünüzün parçası olarak belirli işlevler sağlarsanız Blockly, blokunuza varsayılan bir "mutatör" kullanıcı arayüzü ekler.
Fazladan serileştirme eklemek istiyorsanız bu kullanıcı arayüzünü kullanmanız gerekmez. blocks-plus-minus eklentisinin sağladığı gibi özel bir kullanıcı arayüzü kullanabilir veya hiç kullanıcı arayüzünü kullanamazsınız!
oluşturmak ve ayırmak
Varsayılan kullanıcı arayüzü compose
ve decompose
işlevlerini kullanır.
decompose
, bloku hareket ettirilebilen, eklenebilen ve silinebilen daha küçük alt bloklara "patlar". Bu işlev, alt blokların bağlandığı mutatör çalışma alanında ana blok olan bir "üst blok" döndürmelidir.
compose
, daha sonra alt blokların yapılandırmasını yorumlar ve ana bloğu değiştirmek için kullanır. Bu işlev, decompose
tarafından parametre olarak döndürülen "üst blok"u kabul etmelidir.
Bu işlevlerin, "mutasyona uğrayan" blokla "karma"landığını ve bu nedenle, söz konusu bloka atıfta bulunmak için this
işlevinin kullanılabileceğini unutmayın.
// These are the decompose and compose functions for the lists_create_with block.
decompose: function(workspace) {
// This is a special sub-block that only gets created in the mutator UI.
// It acts as our "top block"
var topBlock = workspace.newBlock('lists_create_with_container');
topBlock.initSvg();
// Then we add one sub-block for each item in the list.
var connection = topBlock.getInput('STACK').connection;
for (var i = 0; i < this.itemCount_; i++) {
var itemBlock = workspace.newBlock('lists_create_with_item');
itemBlock.initSvg();
connection.connect(itemBlock.previousConnection);
connection = itemBlock.nextConnection;
}
// And finally we have to return the top-block.
return topBlock;
},
// The container block is the top-block returned by decompose.
compose: function(topBlock) {
// First we get the first sub-block (which represents an input on our main block).
var itemBlock = topBlock.getInputTargetBlock('STACK');
// Then we collect up all of the connections of on our main block that are
// referenced by our sub-blocks.
// This relates to the saveConnections hook (explained below).
var connections = [];
while (itemBlock && !itemBlock.isInsertionMarker()) { // Ignore insertion markers!
connections.push(itemBlock.valueConnection_);
itemBlock = itemBlock.nextConnection &&
itemBlock.nextConnection.targetBlock();
}
// Then we disconnect any children where the sub-block associated with that
// child has been deleted/removed from the stack.
for (var i = 0; i < this.itemCount_; i++) {
var connection = this.getInput('ADD' + i).connection.targetConnection;
if (connection && connections.indexOf(connection) == -1) {
connection.disconnect();
}
}
// Then we update the shape of our block (removing or adding iputs as necessary).
// `this` refers to the main block.
this.itemCount_ = connections.length;
this.updateShape_();
// And finally we reconnect any child blocks.
for (var i = 0; i < this.itemCount_; i++) {
connections[i].reconnect(this, 'ADD' + i);
}
},
saveConnections
İsteğe bağlı olarak, varsayılan kullanıcı arayüzüyle çalışan bir saveConnections
işlevi de tanımlayabilirsiniz. Bu işlev, ana blokunuzun (ana çalışma alanında bulunan) alt bloklarını, mutatör çalışma alanınızda bulunan alt bloklarla ilişkilendirmenize olanak tanır. Ardından bu verileri, alt bloklarınız yeniden düzenlendiğinde compose
işlevinin ana blokunuzun alt öğelerini düzgün şekilde yeniden bağladığından emin olmak için kullanabilirsiniz.
saveConnections
, decompose
işleviniz tarafından döndürülen "üst blok"u bir parametre olarak kabul etmelidir. saveConnections
işlevi tanımlıysa Blockly, compose
işlevini çağırmadan önce bunu çağırır.
saveConnections: function(topBlock) {
// First we get the first sub-block (which represents an input on our main block).
var itemBlock = topBlock.getInputTargetBlock('STACK');
// Then we go through and assign references to connections on our main block
// (input.connection.targetConnection) to properties on our sub blocks
// (itemBlock.valueConnection_).
var i = 0;
while (itemBlock) {
// `this` refers to the main block (which is being "mutated").
var input = this.getInput('ADD' + i);
// This is the important line of this function!
itemBlock.valueConnection_ = input && input.connection.targetConnection;
i++;
itemBlock = itemBlock.nextConnection &&
itemBlock.nextConnection.targetBlock();
}
},
Kaydı yapılıyor
Mutatörler, yalnızca özel bir uzantı türüdür. Bu nedenle, blok türünüzün JSON tanımında kullanabilmeniz için öncesinde mutasyonların kaydedilmesi gerekir.
// Function signature.
Blockly.Extensions.registerMutator(name, mixinObj, opt_helperFn, opt_blockList);
// Example call.
Blockly.Extensions.registerMutator(
'controls_if_mutator',
{ /* mutator methods */ },
undefined,
['controls_if_elseif', 'controls_if_else']);
name
: JSON'da kullanabilmeniz için mutatörle ilişkilendirilecek bir dize.mixinObj
: Çeşitli mutasyon yöntemlerini içeren bir nesne. Ör.saveExtraState
veloadExtraState
.opt_helperFn
: Karıştırma karıştırıldıktan sonra blokta çalışacak isteğe bağlı bir yardımcı işlev.opt_blockList
: Kullanıcı arayüzü yöntemleri de tanımlanmışsa varsayılan mutatör kullanıcı arayüzündeki uç noktaya eklenecek isteğe bağlı bir blok türleri dizisi (dize olarak).
Uzantılardan farklı olarak, her blok türünün yalnızca bir mutatörü olabilir.
{
//...
"mutator": "controls_if_mutator"
}
Yardımcı işlev
Karışımla birlikte, bir mutatör bir yardımcı fonksiyon kaydedebilir. Bu işlev, belirtilen türdeki her blokta oluşturulduktan ve mixinObj eklendikten sonra çalıştırılır. Bir mutasyona ek tetikleyiciler veya efektler eklemek için kullanılabilir.
Örneğin, liste benzeri blokunuza öğelerin başlangıç sayısını ayarlayan bir yardımcı ekleyebilirsiniz:
var helper = function() {
this.itemCount_ = 5;
this.updateShape();
}