قبل إنشاء نوع حقل جديد، فكِّر في ما إذا كانت إحدى الطرق الأخرى لتخصيص الحقول تناسب احتياجاتك. إذا كان تطبيقك بحاجة إلى تخزين نوع قيمة جديد، أو إذا كنت تريد إنشاء واجهة مستخدم جديدة لنوع قيمة حالي، من المحتمل أنّك بحاجة إلى إنشاء نوع حقل جديد.
لإنشاء حقل جديد، اتّبِع الخطوات التالية:
- تنفيذ دالة إنشائية
- تسجيل مفتاح JSON وتنفيذ
fromJson
- التعامل مع عملية إعداد واجهة المستخدم الخاصة بالحظر ومعالجة الأحداث
- التعامل مع إيقاف أدوات معالجة الأحداث (يتم التعامل مع إيقاف واجهة المستخدم نيابةً عنك).
- تنفيذ معالجة القيم:
- أضِف تمثيلاً نصيًا لقيمة الحقل لتسهيل الاستخدام.
- إضافة وظائف إضافية، مثل:
- اضبط جوانب إضافية للحقل، مثل:
يفترض هذا القسم أنّك قرأت محتوى مقالة بنية الحقل وتعرفه جيدًا.
للاطّلاع على مثال على حقل مخصّص، يمكنك الانتقال إلى العرض التوضيحي للحقول المخصّصة.
تنفيذ دالة إنشائية
يكون منشئ الحقل مسؤولاً عن إعداد القيمة الأولية للحقل وإعداد أداة التحقّق المحلية بشكل اختياري. يتم استدعاء أداة إنشاء الحقل المخصّص أثناء عملية تهيئة حزمة المصدر بغض النظر عمّا إذا كانت حزمة المصدر معرَّفة في JSON أو JavaScript. لذلك، لا يمكن للحقل المخصّص الوصول إلى كتلة المصدر أثناء الإنشاء.
ينشئ نموذج الرمز البرمجي التالي حقلًا مخصّصًا باسم GenericField
:
class GenericField extends Blockly.Field {
constructor(value, validator) {
super(value, validator);
this.SERIALIZABLE = true;
}
}
توقيع الطريقة
تتلقّى دوال إنشاء الحقول عادةً قيمة وأداة تحقق محلية. القيمة اختيارية، وفي حال عدم تمرير قيمة (أو تمرير قيمة لا تجتاز عملية التحقّق من صحة الفئة)، سيتم استخدام القيمة التلقائية للفئة الأصل. بالنسبة إلى الفئة الافتراضية Field
، تكون هذه القيمة null
. إذا كنت لا تريد استخدام القيمة التلقائية، احرص على إدخال قيمة مناسبة. لا تظهر مَعلمة المدقّق إلا للحقول القابلة للتعديل، ويتم عادةً وضع علامة "اختياري" عليها. يمكنك الاطّلاع على مزيد من المعلومات حول أدوات التحقّق في مستندات أدوات التحقّق.
البنية
يجب أن تتبع منطق الدالة الإنشائية التسلسل التالي:
- استدعِ الدالة الإنشائية الفائقة الموروثة (يجب أن ترث جميع الحقول المخصّصة من
Blockly.Field
أو إحدى فئاتها الفرعية) لتهيئة القيمة بشكل صحيح وضبط أداة التحقّق المحلية للحقل. - إذا كان الحقل قابلاً للتسلسل، اضبط السمة المقابلة في الدالة الإنشائية. يجب أن تكون الحقول القابلة للتعديل قابلة للتسلسل، وتكون الحقول قابلة للتعديل تلقائيًا، لذا من المفترض أن تضبط هذه السمة على "صحيح" ما لم تكن على علم بأنّه لا يجب أن تكون قابلة للتسلسل.
- اختياري: طبِّق تخصيصًا إضافيًا (على سبيل المثال، تسمح حقول التصنيف بتمرير فئة CSS، والتي يتم تطبيقها بعد ذلك على النص).
ملف JSON والتسجيل
في تعريفات
كتلة JSON، يتم وصف الحقول
بواسطة سلسلة (مثل field_number
وfield_textinput
). يحتفظ Blockly بخريطة من هذه السلاسل إلى عناصر الحقول، ويستدعي fromJson
على
العنصر المناسب أثناء الإنشاء.
استدعِ الدالة Blockly.fieldRegistry.register
لإضافة نوع الحقل إلى هذه الخريطة،
مع تمرير فئة الحقل كمعلَمة ثانية:
Blockly.fieldRegistry.register('field_generic', GenericField);
عليك أيضًا تحديد الدالة fromJson
. يجب أن يزيل التنفيذ أولاً أي إشارات إلى رموز التوطين باستخدام replaceMessageReferences
، ثم يمرّر القيم إلى الدالة الإنشائية.
GenericField.fromJson = function(options) {
const value = Blockly.utils.parsing.replaceMessageReferences(
options['value']);
return new CustomFields.GenericField(value);
};
جارٍ الإعداد
عند إنشاء الحقل، لا يحتوي بشكل أساسي إلا على قيمة. في مرحلة التهيئة، يتم إنشاء نموذج DOM، وإنشاء النموذج (إذا كان الحقل يتضمّن نموذجًا)، وربط الأحداث.
العرض على شاشة القفل
أثناء عملية التهيئة، تقع عليك مسؤولية إنشاء أي شيء ستحتاج إليه لعرض الحقل على مستوى البلوك.
الإعدادات التلقائية والخلفية والنص
تنشئ الدالة التلقائية initView
عنصر rect
بلون فاتح وعنصر text
. إذا كنت تريد أن يتضمّن الحقل كلاً من هذين العنصرين، بالإضافة إلى بعض الميزات الإضافية، استدعِ الدالة initView
الخاصة بالفئة الرئيسية قبل إضافة بقية عناصر نموذج المستند (DOM). إذا كنت تريد أن يحتوي الحقل على أحد هذين العنصرين فقط، يمكنك استخدام الدالتَين createBorderRect_
أو createTextElement_
.
تخصيص إنشاء DOM
إذا كان الحقل عبارة عن حقل نص عام (مثل Text
Input)، سيتم التعامل مع إنشاء نموذج DOM نيابةً عنك. بخلاف ذلك، عليك إلغاء وظيفة initView
لإنشاء عناصر DOM التي ستحتاج إليها أثناء العرض المستقبلي للحقل.
على سبيل المثال، قد يحتوي حقل القائمة المنسدلة على صور ونصوص. في initView
، يتم إنشاء عنصر صورة واحد وعنصر نص واحد. بعد ذلك، أثناء render_
،
يتم عرض العنصر النشط وإخفاء العنصر الآخر استنادًا إلى نوع
الخيار المحدّد.
يمكن إنشاء عناصر DOM باستخدام الطريقة Blockly.utils.dom.createSvgElement
أو باستخدام طرق إنشاء DOM التقليدية.
في ما يلي متطلبات عرض حقل في قسم "على البلوك":
- يجب أن تكون جميع عناصر نموذج المستند (DOM) عناصر فرعية من
fieldGroup_
الحقل. يتم إنشاء مجموعة الحقول تلقائيًا. - يجب أن تبقى جميع عناصر نموذج المستند (DOM) داخل الأبعاد المُبلغ عنها للحقل.
راجِع قسم العرض للحصول على مزيد من التفاصيل حول تخصيص العرض على مستوى البلوك وتعديله.
إضافة رموز نصية
إذا أردت إضافة رموز إلى نص حقل (مثل رمز الدرجة في حقل
الزاوية)، يمكنك إلحاق عنصر الرمز (المضمّن عادةً في
<tspan>
) مباشرةً بعنصر textElement_
الخاص بالحقل.
أحداث الإدخال
تسجّل الحقول تلقائيًا أحداث تلميحات الأدوات وأحداث النقر بالزر الأيسر للفأرة (التي سيتم استخدامها لعرض أدوات التعديل).
إذا كنت تريد الاستماع إلى أنواع أخرى من الأحداث (على سبيل المثال، إذا كنت تريد التعامل مع عملية سحب حقل)، عليك إلغاء وظيفة bindEvents_
للحقل.
bindEvents_() {
// Call the superclass function to preserve the default behavior as well.
super.bindEvents_();
// Then register your own additional event listeners.
this.mouseDownWrapper_ =
Blockly.browserEvents.conditionalBind(this.getClickTarget_(), 'mousedown', this,
function(event) {
this.originalMouseX_ = event.clientX;
this.isMouseDown_ = true;
this.originalValue_ = this.getValue();
event.stopPropagation();
}
);
this.mouseMoveWrapper_ =
Blockly.browserEvents.conditionalBind(document, 'mousemove', this,
function(event) {
if (!this.isMouseDown_) {
return;
}
var delta = event.clientX - this.originalMouseX_;
this.setValue(this.originalValue_ + delta);
}
);
this.mouseUpWrapper_ =
Blockly.browserEvents.conditionalBind(document, 'mouseup', this,
function(_event) {
this.isMouseDown_ = false;
}
);
}
لربط حدث، عليك عمومًا استخدام الدالة
Blockly.utils.browserEvents.conditionalBind
. تعمل طريقة ربط الأحداث هذه على فلترة اللمسات الثانوية أثناء عمليات السحب. إذا كنت تريد أن يتم تشغيل المعالج حتى في منتصف عملية سحب قيد التقدّم، يمكنك استخدام الدالة Blockly.browserEvents.bind
.
التخلّص من
إذا سجّلت أي أدوات معالجة أحداث مخصّصة داخل الدالة bindEvents_
الخاصة بالحقل، عليك إلغاء تسجيلها داخل الدالة dispose
.
إذا بدأت بشكل صحيح
عرض
الحقل (عن طريق إلحاق جميع عناصر DOM بـ fieldGroup_
)، سيتم التخلص تلقائيًا من DOM الخاص بالحقل.
التعامل مع القيم
→ للحصول على معلومات حول قيمة الحقل مقارنةً بنصه، اطّلِع على بنية الحقل.
ترتيب التحقّق من الصحة
تنفيذ أداة التحقّق من صحة الفئة
يجب أن تقبل الحقول قيمًا معيّنة فقط. على سبيل المثال، يجب أن تقبل حقول الأرقام الأرقام فقط، ويجب أن تقبل حقول الألوان الألوان فقط، وما إلى ذلك. ويتم ضمان ذلك من خلال أدوات التحقّق الخاصة بالفئات والمحلية. تتّبع أداة التحقّق من صحة الفئة القواعد نفسها المتّبعة في أدوات التحقّق المحلية، باستثناء أنّها يتم تشغيلها أيضًا في الدالة الإنشائية، وبالتالي، يجب ألا تشير إلى رمز المصدر.
لتنفيذ أداة التحقّق من صحة فئة الحقل، عليك إلغاء وظيفة doClassValidation_
.
doClassValidation_(newValue) {
if (typeof newValue != 'string') {
return null;
}
return newValue;
};
التعامل مع القيم الصالحة
إذا كانت القيمة التي تم تمريرها إلى حقل يتضمّن setValue
صالحة، ستتلقّى ردّ الاتصال doValueUpdate_
. تلقائيًا، تعمل الدالة doValueUpdate_
على النحو التالي:
- تضبط هذه السمة قيمة
value_
علىnewValue
. - تضبط هذه السمة قيمة
isDirty_
علىtrue
.
إذا كنت تحتاج فقط إلى تخزين القيمة ولا تريد تنفيذ أي معالجة مخصّصة،
ليس عليك إلغاء doValueUpdate_
.
بخلاف ذلك، إذا كنت تريد تنفيذ إجراءات مثل:
- مساحة تخزين مخصّصة تبلغ
newValue
- تغيير خصائص أخرى استنادًا إلى
newValue
- احفظ ما إذا كانت القيمة الحالية صالحة أم لا.
عليك تجاهل doValueUpdate_
باتّباع الخطوات التالية:
doValueUpdate_(newValue) {
super.doValueUpdate_(newValue);
this.displayValue_ = newValue;
this.isValueValid_ = true;
}
التعامل مع القيم غير الصالحة
إذا كانت القيمة التي تم تمريرها إلى الحقل الذي يتضمّن setValue
غير صالحة، ستتلقّى ردّ اتصال doValueInvalid_
. لا تنفّذ الدالة doValueInvalid_
أي إجراء تلقائيًا. وهذا يعني أنّه لن يتم عرض القيم غير الصالحة تلقائيًا. ويعني ذلك أيضًا أنّه لن يتم إعادة عرض الحقل، لأنّه لن يتم ضبط السمة isDirty_
.
إذا أردت عرض قيم غير صالحة، عليك إلغاء doValueInvalid_
.
في معظم الحالات، يجب ضبط السمة displayValue_
على القيمة غير الصالحة، وضبط isDirty_
على true
، وتجاوز render_ لعرض الإعلان على مستوى الحظر ليتم تعديله استنادًا إلى displayValue_
بدلاً من value_
.
doValueInvalid_(newValue) {
this.displayValue_ = newValue;
this.isDirty_ = true;
this.isValueValid_ = false;
}
قيم متعدّدة الأجزاء
عندما يحتوي الحقل على قيمة متعددة الأجزاء (مثل القوائم والمتجهات والكائنات)، قد تحتاج إلى التعامل مع الأجزاء كقيم فردية.
doClassValidation_(newValue) {
if (FieldTurtle.PATTERNS.indexOf(newValue.pattern) == -1) {
newValue.pattern = null;
}
if (FieldTurtle.HATS.indexOf(newValue.hat) == -1) {
newValue.hat = null;
}
if (FieldTurtle.NAMES.indexOf(newValue.turtleName) == -1) {
newValue.turtleName = null;
}
if (!newValue.pattern || !newValue.hat || !newValue.turtleName) {
this.cachedValidatedValue_ = newValue;
return null;
}
return newValue;
}
في المثال أعلاه، يتم التحقّق من صحة كل سمة من سمات newValue
بشكلٍ فردي. بعد ذلك،
في نهاية الدالة doClassValidation_
، إذا كان أي موقع فردي غير صالح، يتم تخزين القيمة مؤقتًا في الموقع cacheValidatedValue_
قبل
عرض null
(غير صالح). يسمح تخزين العنصر مؤقتًا مع خصائص تم التحقّق من صحتها بشكل فردي للدالة
doValueInvalid_
بالتعامل معها بشكل منفصل، وذلك ببساطة عن طريق إجراء عملية التحقّق من !this.cacheValidatedValue_.property
، بدلاً من إعادة التحقّق من صحة كل خاصية بشكل فردي.
يمكن أيضًا استخدام هذا النمط للتحقّق من صحة القيم المتعددة الأجزاء في أدوات التحقّق المحلية، ولكن لا تتوفّر حاليًا طريقة لفرض هذا النمط.
isDirty_
isDirty_
هو علامة مستخدَمة في الدالة
setValue
، بالإضافة إلى أجزاء أخرى من الحقل، لتحديد ما إذا كان يجب إعادة عرض الحقل. إذا تغيّرت قيمة العرض للحقل، يجب عادةً ضبط isDirty_
على true
.
نص
→ للحصول على معلومات حول مكان استخدام نص الحقل وكيفية اختلافه عن قيمة الحقل، اطّلِع على بنية الحقل.
إذا كان نص الحقل مختلفًا عن قيمة الحقل، عليك تجاهل الدالة getText
لتقديم النص الصحيح.
getText() {
let text = this.value_.turtleName + ' wearing a ' + this.value_.hat;
if (this.value_.hat == 'Stovepipe' || this.value_.hat == 'Propeller') {
text += ' hat';
}
return text;
}
إنشاء محرِّر
إذا حدّدت الدالة showEditor_
، سيستمع Blockly تلقائيًا إلى النقرات ويستدعي الدالة showEditor_
في الوقت المناسب. يمكنك عرض أي رمز HTML في المحرّر من خلال تضمينه في أحد الرمزَين الخاصَّين div
، وهما DropDownDiv
وWidgetDiv
، اللذان يظهران فوق بقية واجهة مستخدم Blockly.
DropDownDiv vs WidgetDiv
يتم استخدام DropDownDiv
لتوفير أدوات تعديل مضمّنة في مربّع مرتبط بحقل. ويتم ضبط موضعها تلقائيًا لتكون بالقرب من الحقل مع البقاء ضمن الحدود المرئية. يُعدّ كل من أداة اختيار الزاوية وأداة اختيار اللون مثالَين جيدَين على DropDownDiv
.
يُستخدم WidgetDiv
لتوفير أدوات تعديل لا تظهر داخل مربّع. تستخدم حقول الأرقام
WidgetDiv
لتغطية الحقل بمربّع إدخال نص HTML. بينما تتولّى
DropDownDiv
تحديد الموضع نيابةً عنك، لا تتولّى WidgetDiv
ذلك. يجب تحديد موضع العناصر يدويًا. نظام الإحداثيات هو إحداثيات البكسل بالنسبة إلى أعلى يمين النافذة. يُعدّ محرّر إدخال النصوص مثالاً جيدًا على WidgetDiv
.
نموذج الرمز البرمجي DropDownDiv
showEditor_() {
// Create the widget HTML
this.editor_ = this.dropdownCreate_();
Blockly.DropDownDiv.getContentDiv().appendChild(this.editor_);
// Set the dropdown's background colour.
// This can be used to make it match the colour of the field.
Blockly.DropDownDiv.setColour('white', 'silver');
// Show it next to the field. Always pass a dispose function.
Blockly.DropDownDiv.showPositionedByField(
this, this.disposeWidget_.bind(this));
}
عيّنة التعليمات البرمجية الخاصة بـ WidgetDiv
showEditor_() {
// Show the div. This automatically closes the dropdown if it is open.
// Always pass a dispose function.
Blockly.WidgetDiv.show(
this, this.sourceBlock_.RTL, this.widgetDispose_.bind(this));
// Create the widget HTML.
var widget = this.createWidget_();
Blockly.WidgetDiv.getDiv().appendChild(widget);
}
تنظيف
يتولّى كل من DropDownDiv
وWidgetDiv
مهمة إتلاف عناصر HTML الخاصة بالأداة، ولكن عليك التخلّص يدويًا من أي أدوات معالجة أحداث طبّقتها على هذه العناصر.
widgetDispose_() {
for (let i = this.editorListeners_.length, listener;
listener = this.editorListeners_[i]; i--) {
Blockly.browserEvents.unbind(listener);
this.editorListeners_.pop();
}
}
يتم استدعاء الدالة dispose
في سياق null
على DropDownDiv
. في WidgetDiv
، يتم استدعاء WidgetDiv
في سياق WidgetDiv
. في كلتا الحالتين، من الأفضل استخدام الدالة bind عند تمرير دالة dispose، كما هو موضّح في المثالين DropDownDiv
وWidgetDiv
أعلاه.
→ للحصول على معلومات حول التخلص من العناصر غير المخصّصة للتخلص من المحرِّرين، يُرجى الاطّلاع على التخلص من العناصر.
تعديل العرض على البلوك
يتم استخدام الدالة render_
لتعديل عرض الحقل على مستوى الكتلة بما يتوافق مع قيمته الداخلية.
تشمل الأمثلة الشائعة ما يلي:
- تغيير النص (القائمة المنسدلة)
- تغيير اللون (color)
الإعدادات التلقائية
تضبط الدالة التلقائية render_
نص العرض على نتيجة الدالة
getDisplayText_
. تعرض الدالة getDisplayText_
السمة value_
للحقل
محوَّلة إلى سلسلة، وذلك بعد اقتطاعها بما يتوافق مع الحد الأقصى لطول النص.
إذا كنت تستخدم العرض التلقائي عند الحظر، وكان السلوك التلقائي للنص مناسبًا للحقل، لن تحتاج إلى إلغاء render_
.
إذا كان السلوك التلقائي للنص يعمل مع الحقل، ولكن عرض الحقل على مستوى الكتلة يتضمّن عناصر ثابتة إضافية، يمكنك استدعاء الدالة التلقائية render_
، ولكن سيظل عليك إلغاء الدالة لتتمكّن من تعديل حجم الحقل.
إذا لم يكن السلوك التلقائي للنص مناسبًا لحقلك، أو إذا كان عرض الحقل على مستوى البلوك يتضمّن عناصر ديناميكية إضافية، عليك تخصيص render_
الدالة.
تخصيص العرض
إذا لم يكن سلوك العرض التلقائي مناسبًا لحقلك، عليك تحديد سلوك عرض مخصّص. ويمكن أن يشمل ذلك أي شيء، بدءًا من ضبط نص عرض مخصّص، إلى تغيير عناصر الصورة، إلى تعديل ألوان الخلفية.
جميع تغييرات سمات DOM قانونية، والأمران الوحيدان اللذان يجب تذكّرهما هما:
- يجب التعامل مع إنشاء نموذج DOM أثناء عملية الإعداد، لأنّ ذلك أكثر فعالية.
- يجب تعديل السمة
size_
دائمًا لتتطابق مع حجم الإعلان المعروض داخل الوحدة.
render_() {
switch(this.value_.hat) {
case 'Stovepipe':
this.stovepipe_.style.display = '';
break;
case 'Crown':
this.crown_.style.display = '';
break;
case 'Mask':
this.mask_.style.display = '';
break;
case 'Propeller':
this.propeller_.style.display = '';
break;
case 'Fedora':
this.fedora_.style.display = '';
break;
}
switch(this.value_.pattern) {
case 'Dots':
this.shellPattern_.setAttribute('fill', 'url(#polkadots)');
break;
case 'Stripes':
this.shellPattern_.setAttribute('fill', 'url(#stripes)');
break;
case 'Hexagons':
this.shellPattern_.setAttribute('fill', 'url(#hexagons)');
break;
}
this.textContent_.nodeValue = this.value_.turtleName;
this.updateSize_();
}
تعديل الحجم
يُعدّ تعديل السمة size_
الخاصة بأحد الحقول أمرًا مهمًا جدًا، لأنّه يخبر الرمز البرمجي لعرض الحظر بكيفية تحديد موضع الحقل. وأفضل طريقة لمعرفة قيمة size_
هي التجربة.
updateSize_() {
const bbox = this.movableGroup_.getBBox();
let width = bbox.width;
let height = bbox.height;
if (this.borderRect_) {
width += this.constants_.FIELD_BORDER_RECT_X_PADDING * 2;
height += this.constants_.FIELD_BORDER_RECT_X_PADDING * 2;
this.borderRect_.setAttribute('width', width);
this.borderRect_.setAttribute('height', height);
}
// Note how both the width and the height can be dynamic.
this.size_.width = width;
this.size_.height = height;
}
مطابقة ألوان المربّعات
إذا أردت أن تتطابق عناصر الحقل مع ألوان البلوك المرتبطة به، عليك إلغاء طريقة applyColour
. ستحتاج إلى الوصول إلى اللون من خلال سمة النمط الخاصة بالكتلة.
applyColour() {
const sourceBlock = this.sourceBlock_;
if (sourceBlock.isShadow()) {
this.arrow_.style.fill = sourceBlock.style.colourSecondary;
} else {
this.arrow_.style.fill = sourceBlock.style.colourPrimary;
}
}
تعديل إمكانية التعديل
يمكن استخدام الدالة updateEditable
لتغيير طريقة ظهور الحقل استنادًا إلى ما إذا كان قابلاً للتعديل أم لا. تتيح الدالة التلقائية أن يكون/لا يكون للخلفية استجابة عند التمرير (حدود) إذا كانت/لم تكن قابلة للتعديل.
يجب ألا يتغير حجم العرض على مستوى الكتلة حسب إمكانية تعديله، ولكن يُسمح بإجراء جميع التغييرات الأخرى.
updateEditable() {
if (!this.fieldGroup_) {
// Not initialized yet.
return;
}
super.updateEditable();
const group = this.getClickTarget_();
if (!this.isCurrentlyEditable()) {
group.style.cursor = 'not-allowed';
} else {
group.style.cursor = this.CURSOR;
}
}
نشر الحلقات على نحو متسلسِل
التسلسل هو عملية حفظ حالة الحقل ليتم تحميلها مجددًا في مساحة العمل لاحقًا.
تتضمّن حالة مساحة العمل دائمًا قيمة الحقل، ولكن يمكن أن تتضمّن أيضًا حالة أخرى، مثل حالة واجهة المستخدم الخاصة بالحقل. على سبيل المثال، إذا كان الحقل عبارة عن خريطة يمكن تكبيرها وتصغيرها وتتيح للمستخدم اختيار البلدان، يمكنك أيضًا تسلسل مستوى التكبير/التصغير.
إذا كان الحقل قابلاً للتسلسل، يجب ضبط السمة SERIALIZABLE
على true
.
توفّر Blockly مجموعتَين من خطافات التسلسل للحقول. تعمل إحدى مجموعتَي الخطافات مع نظام تسلسل JSON الجديد، بينما تعمل المجموعة الأخرى مع نظام تسلسل XML القديم.
saveState
وloadState
saveState
وloadState
هما وسيطا تسلسل يعملان مع نظام تسلسل JSON الجديد.
في بعض الحالات، لن تحتاج إلى تقديم هذه المعلومات، لأنّ عمليات التنفيذ التلقائية ستعمل. إذا كان (1) الحقل الخاص بك هو فئة فرعية مباشرة من الفئة الأساسية Blockly.Field
، و(2) كانت القيمة الخاصة بك من النوع القابل للتسلسل بتنسيق JSON، و (3) كنت بحاجة فقط إلى تسلسل القيمة، فسيعمل التنفيذ التلقائي بشكل جيد تمامًا.
بخلاف ذلك، يجب أن تعرض الدالة saveState
عنصرًا/قيمة يمكن تسلسله بتنسيق JSON ويمثّل حالة الحقل. ويجب أن تقبل الدالة loadState
الكائن/القيمة نفسها القابلة للتسلسل بتنسيق JSON، وأن تطبّقها على الحقل.
saveState() {
return {
'country': this.getValue(), // Value state
'zoom': this.getZoomLevel(), // UI state
};
}
loadState(state) {
this.setValue(state['country']);
this.setZoomLevel(state['zoom']);
}
النشر على نحو متسلسِل الكامل والبيانات الاحتياطية
تتلقّى الدالة saveState
أيضًا المَعلمة الاختيارية doFullSerialization
. يتم استخدام هذا النوع من الحقول عادةً للإشارة إلى حالة تم تسلسلها بواسطة مسلسل مختلف (مثل نماذج البيانات الأساسية). تشير المَعلمة إلى أنّ الحالة المشار إليها لن تكون متاحة عند إلغاء تسلسل الحظر، لذا يجب أن ينفّذ الحقل عملية التسلسل بأكملها بنفسه. على سبيل المثال، يكون هذا صحيحًا عند تسلسل كتلة فردية أو عند نسخ كتلة ولصقها.
في ما يلي حالتا استخدام شائعتان لذلك:
- عند تحميل جزء فردي في مساحة عمل لا يتوفّر فيها نموذج البيانات الأساسي، يحتوي الحقل على معلومات كافية في حالته الخاصة لإنشاء نموذج بيانات جديد.
- عند نسخ فقرة ولصقها، ينشئ الحقل دائمًا نموذج بيانات جديدًا بدلاً من الإشارة إلى نموذج حالي.
أحد الحقول التي تستخدم ذلك هو حقل المتغيّر المضمّن. عادةً ما يتم تحويل معرّف المتغيّر الذي تتم الإشارة إليه إلى سلسلة، ولكن إذا كانت قيمة doFullSerialization
صحيحة، يتم تحويل جميع حالاته إلى سلسلة.
saveState(doFullSerialization) {
const state = {'id': this.variable_.getId()};
if (doFullSerialization) {
state['name'] = this.variable_.name;
state['type'] = this.variable_.type;
}
return state;
}
loadState(state) {
const variable = Blockly.Variables.getOrCreateVariablePackage(
this.getSourceBlock().workspace,
state['id'],
state['name'], // May not exist.
state['type']); // May not exist.
this.setValue(variable.getId());
}
يفعل حقل المتغيّر ذلك للتأكّد من أنّه إذا تم تحميله في مساحة عمل لا يتوفّر فيها المتغيّر، يمكنه إنشاء متغيّر جديد للإشارة إليه.
toXml
وfromXml
toXml
وfromXml
هما وسيطا تسلسل يعملان مع نظام تسلسل XML القديم. لا تستخدِم هذه الخطافات إلا إذا كان ذلك ضروريًا (مثلاً، إذا كنت تعمل على قاعدة رموز قديمة لم يتم نقلها بعد)، وإلا استخدِم saveState
وloadState
.
يجب أن تعرض الدالة toXml
عقدة XML تمثّل حالة الحقل. ويجب أن تقبل الدالة fromXml
عقدة XML نفسها وتطبّقها على الحقل.
toXml(fieldElement) {
fieldElement.textContent = this.getValue();
fieldElement.setAttribute('zoom', this.getZoomLevel());
return fieldElement;
}
fromXml(fieldElement) {
this.setValue(fieldElement.textContent);
this.setZoomLevel(fieldElement.getAttribute('zoom'));
}
السمات القابلة للتعديل والتسلسل
تحدّد السمة EDITABLE
ما إذا كان يجب أن يتضمّن الحقل واجهة مستخدم للإشارة إلى أنّه يمكن التفاعل معه. القيمة التلقائية هي true
.
تحدّد السمة SERIALIZABLE
ما إذا كان يجب تسلسل الحقل. القيمة التلقائية هي false
. إذا كانت قيمة هذه السمة هي true
، قد تحتاج إلى توفير دالتَي تسلسل وإلغاء تسلسل (راجِع التسلسل).
التخصيص باستخدام CSS
يمكنك تخصيص الحقل باستخدام CSS. في طريقة initView
، أضِف فئة مخصّصة إلى fieldGroup_
في الحقل، ثم أشِر إلى هذه الفئة في CSS.
على سبيل المثال، لاستخدام مؤشر مختلف:
initView() {
...
// Add a custom CSS class.
if (this.fieldGroup_) {
Blockly.utils.dom.addClass(this.fieldGroup_, 'myCustomField');
}
}
.myCustomField {
cursor: cell;
}
تخصيص المؤشر
تستخدم الصفوف التي توسّع FieldInput
تلقائيًا مؤشر text
عندما يمرّر المستخدم مؤشر الماوس فوق الحقل، وتستخدم الحقول التي يتم سحبها مؤشر grabbing
، وتستخدم جميع الحقول الأخرى مؤشر default
. إذا أردت استخدام مؤشر مختلف، يمكنك ضبطه باستخدام CSS.