תפריט הקשר מכיל רשימה של פעולות שהמשתמש יכול לבצע ברכיב, כמו מרחב עבודה, בלוק או תגובה במרחב העבודה. תפריט ההקשר מוצג בתגובה ללחיצה ימנית או ללחיצה ארוכה במכשיר עם מסך מגע. אם משתמשים בתוסף @blockly/keyboard-navigation
, הוא מוצג גם עם מקש קיצור, שמוגדר כברירת מחדל ל-Ctrl+Enter
ב-Windows או ל-Command+Enter
ב-Mac.
תפריטי הקשר הם מקום טוב להוסיף פעולות שהמשתמש מבצע לעיתים רחוקות, כמו הורדת צילום מסך. אם לדעתכם פעולה מסוימת תשמש אתכם לעיתים קרובות, כדאי ליצור דרך קלה יותר להפעלת הפעולה.
תפריטי הקשר נתמכים בסביבות עבודה, בבלוקים, בתגובות בסביבת העבודה, בבועות ובחיבורים. אפשר גם להטמיע אותם ברכיבים מותאמים אישית משלכם. Blockly מספקת תפריטי הקשר רגילים שאפשר להתאים אישית. אפשר גם להתאים אישית את תפריטי ההקשר בסביבות עבודה ובבלוקים, לכל סביבת עבודה או לכל בלוק בנפרד.
איך פועלים תפריטי הקשר
ל-Blockly יש מאגר שמכיל תבניות לכל הפריטים האפשריים בתפריט. כל תבנית מתארת איך ליצור פריט יחיד בתפריט הקשר. כשהמשתמש מפעיל תפריט הקשר ברכיב, הרכיב:
הבקשה מבקשת מהרישום ליצור מערך של פריטי תפריט שרלוונטיים לרכיב. המאגר שואל כל תבנית אם היא חלה על הרכיב, ואם כן, מוסיף פריט תפריט מתאים למערך.
אם הרכיב הוא סביבת עבודה או בלוק, המערכת בודקת אם לסביבת העבודה או לבלוק הספציפיים שבהם הופעל התפריט יש פונקציה להתאמה אישית של תפריט ההקשר. אם כן, המערך מועבר לפונקציה, שיכולה להוסיף, למחוק או לשנות רכיבים במערך.
הפונקציה מציגה את תפריט ההקשר באמצעות המערך (שעשוי להיות שונה) של פריטי תפריט ההקשר.
Blockly מגדיר קבוצה סטנדרטית של תבניות לתפריטי ההקשר של סביבות עבודה, בלוקים ותגובות בסביבת העבודה. הוא טוען מראש את התבניות של סביבות העבודה והבלוקים במרשם. אם רוצים להשתמש בתבניות של תגובות ב-Workspace, צריך לטעון אותן לרישום בעצמכם.
מידע על הוספה, מחיקה ושינוי של תבניות במאגר זמין במאמר התאמה אישית של המאגר.
היקף
תפריטי הקשר מיושמים על ידי סוגים שונים של רכיבים, כולל סביבות עבודה, תגובות בסביבת עבודה, חיבורים, בלוקים, בועות ורכיבים מותאמים אישית משלכם. תפריטי ההקשר של כל אחד מסוגי הרכיבים האלה עשויים להכיל פריטים שונים, וההתנהגות של הפריטים עשויה להיות שונה בהתאם לסוג הרכיב. לכן, מערכת תפריט ההקשר צריכה לדעת על איזה רכיב היא הופעלה.
כדי לטפל בבעיה הזו, המאגר משתמש באובייקט Scope
. הרכיב שבו הופעל תפריט ההקשר מאוחסן במאפיין focusedNode
כאובייקט שמטמיע את IFocusableNode
. (IFocusableNode
מיושם על ידי כל הרכיבים שהמשתמשים יכולים להתמקד בהם, כולל אלה שמיישמים תפריטי הקשר. מידע נוסף זמין במאמר בנושא מערכת המיקוד).
האובייקט Scope
מועבר לכמה מהפונקציות בתבנית. בכל פונקציה שמקבלת אובייקט Scope
, אפשר להחליט מה לעשות על סמך סוג האובייקט במאפיין focusedNode
. לדוגמה, אפשר לבדוק אם הרכיב הוא בלוק באמצעות:
if (scope.focusedNode instanceof Blockly.BlockSvg) {
// do something with the block
}
לאובייקט Scope
יש מאפיינים אופציונליים אחרים שלא מומלץ יותר להשתמש בהם, אבל עדיין אפשר להגדיר אותם:
- הערך של
block
מוגדר רק אם הרכיב שהתפריט שלו מוצג הואBlockSvg
. - המאפיין
workspace
מוגדר רק אם הרכיב הואWorkspaceSvg
. - המאפיין
comment
מוגדר רק אם הרכיב הואRenderedWorkspaceComment
.
המאפיינים האלה לא כוללים את כל סוגי הרכיבים שעשויים לכלול תפריט הקשר, ולכן מומלץ להשתמש במאפיין focusedNode
.
הסוג RegistryItem
התבניות הן מסוג ContextMenuRegistry.RegistryItem
, והן מכילות את המאפיינים הבאים. שימו לב שהמאפיינים preconditionFn
, displayText
ו-callback
הם בלעדיים למאפיין separator
.
מזהה
המאפיין id
צריך להיות מחרוזת ייחודית שמציינת מה פריט התפריט בהקשר עושה.
const collapseTemplate = {
id: 'collapseBlock',
// ...
};
פונקציית תנאי מוקדם
אפשר להשתמש ב-preconditionFn
כדי להגביל את הזמן והאופן שבהם יוצג פריט בתפריט ההקשר.
היא צריכה להחזיר אחת ממחרוזות הערכים הבאות: 'enabled'
, 'disabled'
או 'hidden'
.
ערך | תיאור | תמונה |
---|---|---|
'enabled'
|
מציין שהפריט פעיל. | ![]() |
'disabled'
|
מציין שהפריט לא פעיל. | ![]() |
'hidden' |
הפריט יוסתר. |
הרכיב preconditionFn
מקבל גם את Scope
, שבעזרתו אפשר לקבוע את סוג הרכיב שבו נפתח התפריט ואת המצב של הרכיב הזה.
לדוגמה, יכול להיות שתרצו שפריט יופיע רק בבלוקים, ורק כשהבלוקים האלה נמצאים במצב מסוים:
const collapseTemplate = {
// ...
preconditionFn: (scope) => {
if (scope.focusedNode instanceof Blockly.BlockSvg) {
if (!scope.focusedNode.isCollapsed()) {
// The component is a block and it is not already collapsed
return 'enabled';
} else {
// The block is already collapsed
return 'disabled';
}
}
// The component is not a block
return 'hidden';
},
// ...
}
הטקסט שיוצג
הערך displayText
הוא מה שצריך להציג למשתמש כחלק מפריט התפריט.
הטקסט שמוצג יכול להיות מחרוזת, HTML או פונקציה שמחזירה מחרוזת או HTML.
const collapseTemplate = {
// ...
displayText: 'Collapse block',
// ...
};
אם רוצים להציג תרגום מ-Blockly.Msg
, צריך להשתמש בפונקציה. אם תנסו להקצות את הערך ישירות, יכול להיות שההודעות לא ייטענו ותקבלו במקום זאת את הערך undefined
.
const collapseTemplate = {
// ...
displayText: () => Blockly.Msg['MY_COLLAPSE_BLOCK_TEXT'],
// ...
};
אם משתמשים בפונקציה, מועבר אליה גם הערך Scope
. אפשר להשתמש בזה כדי להוסיף מידע על הרכיב לטקסט המוצג.
const collapseTemplate = {
// ...
displayText: (scope) => {
if (scope.focusedNode instanceof Blockly.Block) {
return `Collapse ${scope.focusedNode.type} block`;
}
// Shouldn't be possible, as our preconditionFn only shows this item for blocks
return '';
},
// ...
}
משקל
ההגדרה weight
קובעת את הסדר שבו מוצגים הפריטים בתפריט ההקשר.
ערכים חיוביים גבוהים יותר מוצגים בחלק התחתון של הרשימה, וערכים חיוביים נמוכים יותר מוצגים בחלק העליון של הרשימה.
(אפשר לדמיין שפריטים עם משקלים גבוהים יותר הם 'כבדים' יותר ולכן הם שוקעים לתחתית).
const collapseTemplate = {
// ...
weight: 10,
// ...
}
המשקלים של הפריטים המובנים בתפריט הקשר מסודרים בסדר עולה, החל מ-1, וגדלים ב-1.
פונקציית קריאה חוזרת
המאפיין callback
הוא פונקציה שמבצעת את הפעולה של פריט התפריט בהקשר. היא מקבלת כמה פרמטרים:
-
scope
: אובייקט מסוגScope
שמספק הפניה לרכיב שהתפריט שלו נפתח. -
menuOpenEvent
: המקשEvent
שהפעיל את פתיחת תפריט ההקשר. יכול להיות שזה יהיהPointerEvent
אוKeyboardEvent
, בהתאם לאופן שבו המשתמש פתח את התפריט. -
menuSelectEvent
:Event
שבחר את הפריט הזה בתפריט ההקשר. יכול להיות שהערך יהיהPointerEvent
אוKeyboardEvent
, בהתאם לאופן שבו המשתמש בחר את הפריט. -
location
: הערךCoordinate
בקואורדינטות פיקסל שבהן התפריט נפתח. כך אפשר, למשל, ליצור בלוק חדש במיקום של הקליק.
const collapseTemplate = {
// ...
callback: (scope, menuOpenEvent, menuSelectEvent, location) => {
if (scope.focusedNode instanceof Blockly.BlockSvg) {
scope.focusedNode.collapse();
}
},
}
אתם יכולים להשתמש ב-scope
כדי לעצב תבניות שפועלות בצורה שונה בהתאם לרכיב שבו הן נפתחו:
const collapseTemplate = {
// ...
callback: (scope) => {
if (scope.focusedNode instance of Blockly.BlockSvg) {
// On a block, collapse just the block.
const block = scope.focusedNode;
block.collapse();
} else if (scope.focusedNode instanceof Blockly.WorkspaceSvg) {
// On a workspace, collapse all the blocks.
let workspace = scope.focusedNode;
collapseAllBlocks(workspace);
}
}
}
מפריד
המאפיין separator
יוצר קו בתפריט ההקשר.
בתבניות עם המאפיין separator
אי אפשר להשתמש במאפיינים preconditionFn
, displayText
או callback
, ואפשר להגדיר את ההיקף שלהן רק באמצעות המאפיין scopeType
. ההגבלה השנייה אומרת שאפשר להשתמש בהם רק בתפריטי הקשר של סביבות עבודה, בלוקים ותגובות בסביבת העבודה.
const separatorAfterCollapseBlockTemplate = {
id: 'separatorAfterCollapseBlock',
scopeType: Blockly.ContextMenuRegistry.ScopeType.BLOCK,
weight: 11, // Between the weights of the two items you want to separate.
separator: true,
};
צריך להשתמש בתבנית אחרת לכל מפריד בתפריט ההקשר. משתמשים במאפיין weight
כדי למקם כל מפריד.
היקף הרישיון
המאפיין scopeType
יצא משימוש. בעבר, הוא שימש כדי לקבוע אם צריך להציג פריט בתפריט הקשר של בלוק, הערה או סביבת עבודה. מכיוון שאפשר לפתוח תפריטי הקשר ברכיבים אחרים, המאפיין scopeType
מגביל מדי. במקום זאת, צריך להשתמש ב-preconditionFn
כדי להציג או להסתיר את האפשרות עבור הרכיבים המתאימים.
אם יש לכם תבניות קיימות של תפריט הקשר שמשתמשות ב-scopeType
, Blockly ימשיך להציג את הפריט רק לרכיב המתאים.
const collapseTemplate = {
// ...
scopeType: Blockly.ContextMenuRegistry.ScopeType.BLOCK,
// ...
};
התאמה אישית של הרישום
אפשר להוסיף, למחוק או לשנות תבניות במאגר. תבניות ברירת המחדל מופיעות ב-contextmenu_items.ts
.
הוספת תבנית
אפשר להוסיף תבנית לרישום על ידי רישום שלה. צריך לעשות את זה פעם אחת בטעינת הדף. הפעולה יכולה לקרות לפני או אחרי שמזריקים את סביבת העבודה.
const collapseTemplate = { /* properties from above */ };
Blockly.ContextMenuRegistry.registry.register(collapseTemplate);
מחיקת תבנית
כדי להסיר תבנית מהמאגר, צריך לבטל את הרישום שלה לפי מזהה.
Blockly.ContextMenuRegistry.registry.unregister('someID');
שינוי תבנית
אפשר לשנות תבנית קיימת על ידי שליפת התבנית מהמאגר ואז שינוי שלה במקום.
const template = Blockly.ContextMenuRegistry.registry.getItem('someID');
template?.displayText = 'some other display text';
השבתת תפריטי הקשר של בלוקים
כברירת מחדל, לחסימות יש תפריט הקשר שמאפשר למשתמשים לבצע פעולות כמו הוספת תגובות לחסימות או שכפול חסימות.
כדי להשבית את תפריט ההקשר של בלוק ספציפי, אפשר להשתמש בפקודה:
block.contextMenu = false;
בהגדרת ה-JSON של סוג בלוק, משתמשים במפתח enableContextMenu
:
{
// ...,
"enableContextMenu": false,
}
התאמה אישית של תפריטי הקשר לפי סוג הבלוק או סביבת העבודה
אחרי ש-Blockly יוצר מערך של פריטים בתפריט ההקשר, אפשר להתאים אותו אישית לבלוקים או לסביבות עבודה ספציפיים. כדי לעשות את זה, מגדירים את BlockSvg.customContextMenu
או את WorkspaceSvg.configureContextMenu
לפונקציה שמשנה את המערך במקום.
לאובייקטים במערך שמועבר לבלוקים יש את הסוג
ContextMenuOption
או שהם מטמיעים את הממשק
LegacyContextMenuOption
. הסוג של אובייקטים שמועברים לסביבות עבודה הוא ContextMenuOption
. Blockly משתמש במאפיינים הבאים מהאובייקטים האלה:
text
: הטקסט שמוצג.-
enabled
: אםfalse
, הפריט מוצג בטקסט אפור. -
callback
: הפונקציה שמופעלת כשלוחצים על הפריט. -
separator
: הפריט הוא מפריד. המאפיין הזה בלעדי ביחס לשלושת המאפיינים האחרים.
במסמכי העזרה אפשר למצוא מידע על סוגי נכסים וחתימות של פונקציות.
לדוגמה, הנה פונקציה שמוסיפה פריט Hello, World!
לתפריט ההקשר של סביבת עבודה:
workspace.configureContextMenu = function (menuOptions, e) {
const item = {
text: 'Hello, World!',
enabled: true,
callback: function () {
alert('Hello, World!');
},
};
// Add the item to the end of the context menu.
menuOptions.push(item);
}
הצגת תפריט הקשר באובייקט בהתאמה אישית
כדי להציג תפריטי הקשר לרכיבים מותאמים אישית, פועלים לפי השלבים הבאים:
- מטמיעים את
IFocusableNode
או מרחיבים כיתה שמטמיעה אתIFocusableNode
. הממשק הזה משמש במערכת של תפריט ההקשר כדי לזהות את הרכיב. היא גם מאפשרת למשתמשים לנווט לרכיב באמצעות התוסף לניווט במקלדת. מטמיעים את
IContextMenu
, שמכיל את הפונקציהshowContextMenu
. הפונקציה הזו מקבלת את הפריטים של תפריט ההקשר מהרישום, מחשבת את המיקום במסך שבו התפריט יוצג, ובסופו של דבר מציגה את התפריט אם יש פריטים להצגה.const MyBubble implements IFocusableNode, IContextMenu { ... showContextMenu(menuOpenEvent) { // Get the items from the context menu registry const scope = {focusedNode: this}; const items = Blockly.ContextMenuRegistry.registry.getContextMenuOptions(scope, menuOpenEvent); // Return early if there are no items available if (!items.length) return; // Show the menu at the same location on screen as this component // The location is in pixel coordinates, so translate from workspace coordinates const location = Blockly.utils.svgMath.wsToScreenCoordinates(new Coordinate(this.x, this.y)); // Show the context menu Blockly.ContextMenu.show(menuOpenEvent, items, this.workspace.RTL, this.workspace, location); } }
מוסיפים handler לאירוע שמפעיל את
showContextMenu
כשהמשתמש לוחץ לחיצה ימנית על הרכיב. שימו לב: התוסף לניווט באמצעות מקלדת מספק handler של אירועים שקורא ל-showContextMenu
כשמשתמש לוחץ עלCtrl+Enter
(Windows) או עלCommand+Enter
(Mac).מוסיפים תבניות לרישום של הפריטים בתפריט ההקשר.