לפני שיוצרים סוג שדה חדש, כדאי לבדוק אם אחת מהשיטות האחרות להתאמה אישית של שדות מתאימה לצרכים שלכם. אם האפליקציה שלכם צריכה לאחסן סוג ערך חדש, או אם אתם רוצים ליצור ממשק משתמש חדש לסוג ערך קיים, כנראה שתצטרכו ליצור סוג שדה חדש.
כדי ליצור שדה חדש:
- הטמעה של בנאי.
- רישום מפתח JSON והטמעה של
fromJson
. - טיפול באתחול של ממשק המשתמש של החסימה ובמאזיני האירועים.
- טיפול בהסרה של event listeners (הסרת ממשק המשתמש מטופלת בשבילכם).
- הטמעת טיפול בערכים.
- מוסיפים ייצוג טקסטואלי של הערך בשדה, לצורך נגישות.
- להוסיף פונקציות נוספות, כמו:
- אפשר להגדיר היבטים נוספים של השדה, כמו:
בקטע הזה אנחנו מניחים שקראתם את המאמר האנטומיה של שדה ומכירים את התוכן שלו.
דוגמה לשדה מותאם אישית מופיעה בהדגמה של שדות מותאמים אישית .
הטמעה של constructor
הקונסטרוקטור של השדה אחראי להגדרת הערך הראשוני של השדה, ואפשר גם להגדיר מאמת מקומי. הקונסטרוקטור של השדה המותאם אישית נקרא במהלך האתחול של בלוק המקור, בלי קשר לשאלה אם בלוק המקור מוגדר ב-JSON או ב-JavaScript. לכן, לשדה המותאם אישית אין גישה לבלוק המקור במהלך הבנייה.
בדוגמת הקוד הבאה נוצר שדה בהתאמה אישית בשם GenericField
:
class GenericField extends Blockly.Field {
constructor(value, validator) {
super(value, validator);
this.SERIALIZABLE = true;
}
}
חתימת השיטה
בדרך כלל, בנאים של שדות מקבלים ערך ומאמת מקומי. הערך הוא אופציונלי, ואם לא מעבירים ערך (או מעבירים ערך שלא עובר אימות של המחלקה), ייעשה שימוש בערך ברירת המחדל של מחלקת העל. במקרה של מחלקת ברירת המחדל Field
, הערך הוא null
. אם אתם לא רוצים להשתמש בערך ברירת המחדל, אתם צריכים להעביר ערך מתאים. הפרמטר validator מופיע רק בשדות שאפשר לערוך, ובדרך כלל הוא מסומן כאופציונלי. מידע נוסף על מאמתים זמין במסמכי התיעוד בנושא מאמתים.
מבנה
הלוגיקה בתוך ה-constructor צריכה לפעול לפי התהליך הבא:
- קוראים לבונה העל שעבר בירושה (כל השדות המותאמים אישית צריכים לעבור בירושה מ-
Blockly.Field
או מאחת ממחלקות המשנה שלו) כדי לאתחל את הערך בצורה נכונה ולהגדיר את מאמת המקומי לשדה. - אם השדה ניתן לסריאליזציה, מגדירים את המאפיין המתאים בקונסטרוקטור. שדות שאפשר לערוך צריכים להיות ניתנים לסריאליזציה, והשדות ניתנים לעריכה כברירת מחדל, לכן כדאי להגדיר את המאפיין הזה כ-true, אלא אם אתם יודעים שהוא לא צריך להיות ניתן לסריאליזציה.
- אופציונלי: אפשר להחיל התאמה אישית נוספת (לדוגמה, שדות תוויות מאפשרים להעביר מחלקת 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_
השדה. השדה group נוצר באופן אוטומטי. - כל רכיבי ה-DOM צריכים להישאר בתוך המידות המדווחות של השדה.
פרטים נוספים על התאמה אישית ועדכון של התצוגה בבלוק זמינים בקטע Rendering.
הוספה של סמלי טקסט
אם רוצים להוסיף סמלים לטקסט בשדה (למשל סמל המעלה בשדה זווית), אפשר לצרף את רכיב הסמל (בדרך כלל הוא נמצא בתוך <tspan>
) ישירות ל-textElement_
של השדה.
אירועי קלט
כברירת מחדל, השדות רושמים אירועי tooltip ואירועי לחיצה על העכבר (לשימוש בכלי עריכה).
אם רוצים להאזין לסוגים אחרים של אירועים (למשל, אם רוצים לטפל בגרירה של שדה), צריך לבטל את הפונקציה 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 של השדה יבוטל באופן אוטומטי.
טיפול בערכים
→ למידע על ההבדל בין הערך של שדה לבין הטקסט שלו, אפשר לעיין במאמר המאפיינים של שדה.
סדר האימות
הטמעה של כלי לאימות כיתות
השדות צריכים לקבל רק ערכים מסוימים. לדוגמה, בשדות של מספרים אפשר להזין רק מספרים, בשדות של צבעים אפשר להזין רק צבעים וכו'. כדי לוודא את זה, משתמשים במאמתים של מחלקות ומקומיים. המאמת class פועל לפי אותם כללים כמו מאמתים מקומיים, אבל הוא מופעל גם בבונה, ולכן הוא לא צריך להפנות לבלוק המקור.
כדי להטמיע את מאמת המחלקה של השדה, מחליפים את הפונקציה doClassValidation_
.
doClassValidation_(newValue) {
if (typeof newValue != 'string') {
return null;
}
return newValue;
};
טיפול בערכים תקינים
אם הערך שמועבר לשדה עם setValue
הוא תקין, תקבלו קריאה חוזרת (callback) של doValueUpdate_
. כברירת מחדל, הפונקציה doValueUpdate_
:
- הגדרת המאפיין
value_
לערךnewValue
. - הגדרת המאפיין
isDirty_
לערךtrue
.
אם אתם רק רוצים לאחסן את הערך ולא רוצים לבצע טיפול מותאם אישית, אתם לא צריכים לבטל את ברירת המחדל של doValueUpdate_
.
אחרת, אם רוצים לבצע פעולות כמו:
- אחסון בהתאמה אישית של
newValue
. - שינוי מאפיינים אחרים על סמך
newValue
. - שמירה של הערך הנוכחי, בין אם הוא תקין ובין אם לא.
תצטרכו לבטל את ההגדרה של doValueUpdate_
:
doValueUpdate_(newValue) {
super.doValueUpdate_(newValue);
this.displayValue_ = newValue;
this.isValueValid_ = true;
}
טיפול בערכים לא תקינים
אם הערך שמועבר לשדה עם setValue
לא תקין, תקבלו קריאה חוזרת (callback) של 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 לעומת 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
. בכל מקרה, כשמעבירים פונקציית dispose, מומלץ להשתמש בפונקציה bind, כמו בדוגמאות DropDownDiv
ו-WidgetDiv
שלמעלה.
→ למידע על סילוק שלא ספציפי לסילוק עורכים, אפשר לעיין במאמר בנושא סילוק.
עדכון התצוגה של הבלוק
הפונקציה render_
משמשת לעדכון התצוגה של השדה בבלוק כך שתתאים לערך הפנימי שלו.
דוגמאות נפוצות:
- שינוי הטקסט (תפריט נפתח)
- שינוי הצבע (color)
ברירות מחדל
פונקציית ברירת המחדל render_
מגדירה את הטקסט שיוצג לתוצאה של הפונקציה getDisplayText_
. הפונקציה getDisplayText_
מחזירה את המאפיין value_
של השדה אחרי שהוא עבר המרה למחרוזת, אחרי שהוא נחתך כדי להתאים לאורך הטקסט המקסימלי.
אם אתם משתמשים בתצוגה שמוגדרת כברירת מחדל לחסימה, וההתנהגות שמוגדרת כברירת מחדל של הטקסט מתאימה לשדה שלכם, אתם לא צריכים לבטל את ההגדרה של render_
.
אם התנהגות ברירת המחדל של הטקסט מתאימה לשדה, אבל לתצוגה של השדה בבלוק יש רכיבים סטטיים נוספים, אפשר לקרוא לפונקציה render_
של ברירת המחדל, אבל עדיין צריך לבטל את ברירת המחדל כדי לעדכן את הגודל של השדה.
אם התנהגות הטקסט שמוגדרת כברירת מחדל לא מתאימה לשדה שלכם, או אם לתצוגה של השדה render_
on-block יש רכיבים דינמיים נוספים, תצטרכו להתאים אישית את הפונקציה.
התאמה אישית של הרינדור
אם התנהגות ברירת המחדל של העיבוד לא מתאימה לשדה, צריך להגדיר התנהגות עיבוד מותאמת אישית. הפעולות האלה יכולות לכלול כל דבר, החל מהגדרת טקסט תצוגה מותאם אישית, דרך שינוי רכיבי תמונה ועד לעדכון צבעי הרקע.
כל השינויים במאפייני ה-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 מספק שתי קבוצות של ווים (hooks) לסריאליזציה של שדות. זוג אחד של ווים פועל עם מערכת הסריאליזציה החדשה של JSON, והזוג השני פועל עם מערכת הסריאליזציה הישנה של XML.
saveState
וגם loadState
saveState
ו-loadState
הם ווים של סריאליזציה שפועלים עם מערכת הסריאליזציה החדשה של JSON.
במקרים מסוימים לא צריך לספק את הערכים האלה, כי יישומי ברירת המחדל יפעלו. אם (1) השדה הוא מחלקת משנה ישירה של המחלקה הבסיסית Blockly.Field
, (2) הערך הוא סוג שניתן לסריאליזציה של JSON, ו-(3) צריך רק לבצע סריאליזציה של הערך, אז הטמעת ברירת המחדל תפעל בצורה תקינה.
אחרת, הפונקציה saveState
צריכה להחזיר אובייקט או ערך שניתן לסדרת JSON, שמייצגים את מצב השדה. הפונקציה שלכם צריכה לקבל את אותו אובייקט או ערך שניתן לסריאליזציה ב-JSON, ולהחיל אותו על השדה.loadState
saveState() {
return {
'country': this.getValue(), // Value state
'zoom': this.getZoomLevel(), // UI state
};
}
loadState(state) {
this.setValue(state['country']);
this.setZoomLevel(state['zoom']);
}
סדרות מלאות ונתוני גיבוי
saveState
מקבלת גם פרמטר אופציונלי doFullSerialization
. השדה הזה משמש שדות שמפנים בדרך כלל למצב שסודר על ידי סדרן אחר (כמו מודלים של נתוני גיבוי). הפרמטר מציין שהמצב שאליו יש הפניה לא יהיה זמין כשהבלוק יעבור דה-סריאליזציה, ולכן השדה צריך לבצע את כל הסריאליזציה בעצמו. לדוגמה, הערך הוא True כשמבצעים סריאליזציה של בלוק בודד, או כשמעתיקים ומדביקים בלוק.
שני תרחישי שימוש נפוצים:
- כשבלוק בודד נטען בסביבת עבודה שבה לא קיים מודל נתונים בסיסי, השדה מכיל מספיק מידע במצב שלו כדי ליצור מודל נתונים חדש.
- כשמעתיקים ומדביקים בלוק, השדה תמיד יוצר מודל נתונים חדש במקום להפנות למודל קיים.
אחד השדות שמשתמשים בזה הוא שדה המשתנה המובנה. בדרך כלל, הפונקציה מבצעת סריאליזציה של המזהה של המשתנה שאליו היא מפנה, אבל אם doFullSerialization
הוא true, היא מבצעת סריאליזציה של כל המצב שלו.
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. כדאי להשתמש ב-hooks האלה רק אם אין ברירה (לדוגמה, אם אתם עובדים על בסיס קוד ישן שלא הועבר עדיין), אחרת כדאי להשתמש ב-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
method (שיטה), מוסיפים מחלקה מותאמת אישית ל-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.