לפני שיוצרים סוג שדה חדש, כדאי לבדוק אם אחד מהשיטות האחרות להתאמה אישית של שדות מתאים לצרכים שלכם. אם באפליקציה שלכם צריך לאחסן סוג ערך חדש, או אם אתם רוצים ליצור ממשק משתמש חדש לסוג ערך קיים, סביר להניח שתצטרכו ליצור סוג שדה חדש.
כדי ליצור שדה חדש:
- הטמעת קונסטרוקטור
- רישום מפתח JSON והטמעת
fromJson
- טיפול באתחול של ממשק המשתמש בבלוק ושל רכיבי ההאזנה לאירועים.
- טיפול בפינוי של רכיבי מעקב אירועים (פינוי ממשק המשתמש מנוהל בשבילכם).
- מטמיעים טיפול בערכים.
- מוסיפים ייצוג טקסט של הערך בשדה, למטרות נגישות.
- להוסיף פונקציות נוספות, כמו:
- מגדירים היבטים נוספים של השדה, כמו:
בקטע הזה אנו מניחים שקראת את המאמר המבנה של שדה ושהתוכן מוכר לך.
דוגמה לשדה מותאם אישית זמינה בדמו של שדות מותאמים אישית.
הטמעת קונסטרוקטור
ה-constructor של השדה אחראי להגדרת הערך הראשוני של השדה, ואפשר גם להגדיר בו מבצע אימות מקומי. הקריאה ל-constructor של השדה המותאם אישית מתבצעת במהלך האינטוליזציה של בלוק המקור, ללא קשר לכך שבלוק המקור מוגדר ב-JSON או ב-JavaScript. לכן, לשדה המותאם אישית אין גישה לבלוק המקור במהלך היצירה.
בדוגמת הקוד הבאה נוצר שדה בהתאמה אישית בשם GenericField
:
class GenericField extends Blockly.Field {
constructor(value, validator) {
super(value, validator);
this.SERIALIZABLE = true;
}
}
חתימה של method
בדרך כלל, בקריאי השדות מקבלים ערך ואימות מקומי. הערך הוא אופציונלי, ואם לא מעבירים ערך (או מעבירים ערך שלא עובר אימות של הכיתה), המערכת תשתמש בערך ברירת המחדל של הסוג ההורה. עבור הכיתה Field
שמוגדרת כברירת מחדל, הערך הוא null
. אם אתם לא רוצים את ערך ברירת המחדל הזה, הקפידו להעביר ערך מתאים. הפרמטר של מאמת הנכונות נמצא רק בשדות שניתנים לעריכה, ובדרך כלל הוא מסומן כאופציונלי. מידע נוסף על מאמתים זמין במסמכי המאמתים.
מבנה
הלוגיקה בתוך ה-constructor צריכה לפעול לפי התהליך הבא:
- קוראים לסופר-מגדיר (כל השדות המותאמים אישית צריכים לרשת מ-
Blockly.Field
או מאחד מהתת-הסוגים שלו) כדי לאתחל את הערך בצורה נכונה ולהגדיר את מאמת השדה המקומי. - אם השדה ניתן לסריאליזציה, מגדירים את המאפיין התואם ב-constructor. שדות שניתנים לעריכה חייבים להיות ניתנים לסריאליזציה, והשדות ניתנים לעריכה כברירת מחדל, לכן מומלץ להגדיר את המאפיין הזה כ-true, אלא אם אתם יודעים שהוא לא אמור להיות ניתן לסריאליזציה.
- אופציונלי: אפשר לבצע התאמה אישית נוספת (לדוגמה, שדות תווית מאפשרים להעביר סיווג CSS, שמוחל לאחר מכן על הטקסט).
JSON והרשמה
בהגדרות של בלוקים ב-JSON, השדות מתוארים במחרוזת (למשל field_number
, field_textinput
). ב-Blockly יש מפה מהמחרוזות האלה לאובייקטים של שדות, והמערכת קוראת ל-fromJson
על האובייקט המתאים במהלך היצירה.
קוראים ל-Blockly.fieldRegistry.register
כדי להוסיף את סוג השדה למפה הזו, ומעבירים את סיווג השדה כארגומנטים השני:
Blockly.fieldRegistry.register('field_generic', GenericField);
צריך גם להגדיר את הפונקציה fromJson
. בתהליך ההטמעה, קודם צריך לבטל את ההפניה לכל הפניות לאסימונים של לוקליזציה באמצעות replaceMessageReferences, ואז להעביר את הערכים למבנה ה-constructor.
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 חייבים להישאר בתוך המאפיינים שדווחו של השדה.
בקטע עיבוד מוסבר בהרחבה איך להתאים אישית את התצוגה בבלוק ולעדכן אותה.
הוספת סמלי טקסט
אם רוצים להוסיף סמלים לטקסט של שדה (למשל סמל המעלות בשדה Angle), אפשר לצרף את אלמנט הסמל (בדרך כלל הוא נמצא ב-<tspan>
) ישירות ל-textElement_
של השדה.
אירועי קלט
כברירת מחדל, השדות מתעדים אירועי חלון עזר ואירועי mousedown (כדי להציג עורכים).
אם רוצים להאזין לאירועים מסוגים אחרים (למשל, אם רוצים לטפל בגרירה בשדה), צריך לשנות את ברירת המחדל של פונקציית 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
תקין, תקבלו קריאה חוזרת (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
ולבצע שינוי (override) של 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
. בכל מקרה, מומלץ להשתמש בפונקציה bind כשמעבירים פונקציית dispose, כפי שמוצג בדוגמאות DropDownDiv
ו-WidgetDiv
שלמעלה.
→ למידע על ניהול גרסת build שלא ספציפי לעורכים, ראו ניהול גרסת build.
עדכון התצוגה בבלוק
הפונקציה 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) השדה הוא Subclass ישיר של הכיתה הבסיסית 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
. השדה הזה משמש שדות שמפנים בדרך כלל למצב שעבר שרשור (serialization) על ידי סריאליזטור אחר (כמו מודלים של נתוני תמיכה). הפרמטר מאותת שהמצב שאליו מפנה ההפניה לא יהיה זמין כשהבלוק יתבצע סריאליזציה, ולכן השדה צריך לבצע את כל הסריאליזציה בעצמו. לדוגמה, זה נכון כשבלוק בודד עובר סריאליזציה, או כשבלוק מועתק ומוחזר.
שני תרחישים נפוצים לדוגמה:
- כשמטען בלוק ספציפי למרחב עבודה שבו מודל הנתונים התומך לא קיים, בשדה יש מספיק מידע במצב שלו כדי ליצור מודל נתונים חדש.
- כשמקלידים את הבלוק ב-copy-paste, השדה תמיד יוצר מודל נתונים חדש במקום להפנות למודל קיים.
שדה אחד שבו נעשה שימוש באפשרות הזו הוא שדה המשתנה המובנה. בדרך כלל היא מבצעת סריאליזציה של המזהה של המשתנה שאליו היא מפנה, אבל אם הערך של 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. השתמשו בהוקים האלה רק אם אתם חייבים (למשל, אם אתם עובדים על קוד מקור ישן שעדיין לא הועבר), אחרת השתמשו ב-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
, יכול להיות שתצטרכו לספק פונקציות של סריאליזציה ושל דה-סריאליזציה (ראו סריאליזציה).
התאמה אישית של הסמן
המאפיין CURSOR
קובע את הסמן שהמשתמשים רואים כשהם מעבירים את העכבר מעל השדה. צריכה להיות זו מחרוזת של סמן CSS תקינה. ערך ברירת המחדל הוא הסמן שמוגדר על ידי .blocklyDraggable
, שהוא סמן האחיזה.