Trình đơn theo bối cảnh chứa danh sách các thao tác mà người dùng có thể thực hiện trên một thành phần, chẳng hạn như không gian làm việc, khối hoặc bình luận trong không gian làm việc. Trình đơn theo bối cảnh xuất hiện khi người dùng nhấp chuột phải hoặc nhấn và giữ trên thiết bị cảm ứng. Nếu bạn sử dụng trình bổ trợ @blockly/keyboard-navigation
, thì trình bổ trợ này cũng xuất hiện cùng với một phím tắt, theo mặc định là Ctrl+Enter
trên Windows hoặc Command+Enter
trên máy Mac.
Trình đơn theo bối cảnh là nơi phù hợp để thêm những hành động mà người dùng hiếm khi thực hiện, chẳng hạn như tải ảnh chụp màn hình xuống. Nếu cho rằng một thao tác sẽ được sử dụng thường xuyên hơn, bạn có thể muốn tạo một cách dễ thấy hơn để gọi thao tác đó.
Trình đơn theo bối cảnh được các không gian làm việc, khối, bình luận trong không gian làm việc, bong bóng và mối kết nối hỗ trợ. Bạn cũng có thể triển khai các thành phần này trên các thành phần tuỳ chỉnh của riêng mình. Blockly cung cấp trình đơn theo bối cảnh tiêu chuẩn mà bạn có thể tuỳ chỉnh. Bạn cũng có thể tuỳ chỉnh trình đơn theo bối cảnh trên không gian làm việc và các khối theo từng không gian làm việc hoặc từng khối.
Cách hoạt động của trình đơn theo bối cảnh
Blockly có một sổ đăng ký chứa các mẫu cho tất cả các mục trình đơn có thể có. Mỗi mẫu mô tả cách tạo một mục duy nhất trong trình đơn theo bối cảnh. Khi người dùng gọi một trình đơn theo bối cảnh trên một thành phần, thành phần đó sẽ:
Yêu cầu sổ đăng ký tạo một mảng các mục trong trình đơn áp dụng cho thành phần. Sổ đăng ký sẽ hỏi từng mẫu xem mẫu đó có áp dụng cho thành phần hay không và nếu có, thì sẽ thêm một mục tương ứng trong trình đơn vào mảng.
Nếu thành phần là một không gian làm việc hoặc khối, hãy kiểm tra xem không gian làm việc hoặc khối cụ thể mà trình đơn được gọi có chức năng tuỳ chỉnh trình đơn theo bối cảnh hay không. Nếu có, nó sẽ truyền mảng đến hàm. Hàm này có thể thêm, xoá hoặc sửa đổi các phần tử của mảng.
Hiển thị trình đơn theo bối cảnh bằng cách sử dụng mảng (có thể đã được sửa đổi) gồm các mục trong trình đơn theo bối cảnh.
Blockly xác định một bộ mẫu tiêu chuẩn cho trình đơn theo bối cảnh của không gian làm việc, khối và bình luận trong không gian làm việc. Thao tác này sẽ tải trước các mẫu cho không gian làm việc và các khối vào sổ đăng ký. Nếu muốn dùng mẫu cho bình luận trong không gian làm việc, bạn phải tự tải các mẫu đó vào sổ đăng ký.
Để biết thông tin về cách thêm, xoá và sửa đổi mẫu trong sổ đăng ký, hãy xem phần Tuỳ chỉnh sổ đăng ký.
Phạm vi
Trình đơn theo bối cảnh được triển khai bằng nhiều loại thành phần, bao gồm cả không gian làm việc, bình luận trong không gian làm việc, mối kết nối, khối, bong bóng và các thành phần tuỳ chỉnh của riêng bạn. Trình đơn theo bối cảnh cho từng loại thành phần này có thể chứa các mục khác nhau và các mục có thể hoạt động khác nhau dựa trên loại thành phần. Do đó, hệ thống trình đơn theo bối cảnh cần biết thành phần nào đã được gọi.
Để giải quyết vấn đề này, sổ đăng ký sử dụng một đối tượng Scope
. Thành phần mà trình đơn theo bối cảnh được gọi sẽ được lưu trữ trong thuộc tính focusedNode
dưới dạng một đối tượng triển khai IFocusableNode
. (IFocusableNode
được tất cả các thành phần mà người dùng có thể tập trung vào triển khai, bao gồm cả những thành phần triển khai trình đơn theo bối cảnh. Để biết thêm thông tin, hãy xem phần Hệ thống tiêu điểm.)
Đối tượng Scope
được truyền đến một số hàm trong một mẫu. Trong mọi hàm nhận đối tượng Scope
, bạn có thể quyết định việc cần làm dựa trên loại đối tượng trong thuộc tính focusedNode
. Ví dụ: bạn có thể kiểm tra xem thành phần có phải là một khối hay không bằng cách:
if (scope.focusedNode instanceof Blockly.BlockSvg) {
// do something with the block
}
Đối tượng Scope
có các thuộc tính không bắt buộc khác mà bạn không nên sử dụng nữa, nhưng vẫn có thể đặt:
block
chỉ được đặt nếu thành phần có trình đơn xuất hiện là mộtBlockSvg
.workspace
chỉ được đặt nếu thành phần làWorkspaceSvg
.comment
chỉ được đặt nếu thành phần làRenderedWorkspaceComment
.
Các thuộc tính này không bao gồm tất cả các loại thành phần có thể có một trình đơn theo bối cảnh, vì vậy, bạn nên dùng thuộc tính focusedNode
.
Loại RegistryItem
Mẫu có loại ContextMenuRegistry.RegistryItem
, chứa các thuộc tính sau. Xin lưu ý rằng các thuộc tính preconditionFn
, displayText
và callback
mang tính loại trừ lẫn nhau với thuộc tính separator
.
Mã nhận dạng
Thuộc tính id
phải là một chuỗi duy nhất cho biết chức năng của mục trong trình đơn theo bối cảnh.
const collapseTemplate = {
id: 'collapseBlock',
// ...
};
Hàm điều kiện tiên quyết
Bạn có thể dùng preconditionFn
để hạn chế thời điểm và cách thức hiển thị một mục trong trình đơn theo bối cảnh.
Phương thức này sẽ trả về một trong các chuỗi sau: 'enabled'
, 'disabled'
hoặc 'hidden'
.
Giá trị | Mô tả | Hình ảnh |
---|---|---|
đang bật | Cho biết rằng mặt hàng đang hoạt động. | ![]() |
đã vô hiệu | Cho biết rằng mặt hàng không hoạt động. | ![]() |
ẩn | Ẩn mục. |
preconditionFn
cũng được truyền một Scope
mà bạn có thể dùng để xác định loại thành phần mà trình đơn được mở và trạng thái của thành phần đó.
Ví dụ: bạn có thể muốn một mục chỉ xuất hiện cho các khối và chỉ khi các khối đó ở một trạng thái cụ thể:
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';
},
// ...
}
Văn bản hiển thị
displayText
là nội dung mà người dùng sẽ thấy trong mục trình đơn.
Văn bản hiển thị có thể là một chuỗi, HTML hoặc một hàm trả về chuỗi hoặc HTML.
const collapseTemplate = {
// ...
displayText: 'Collapse block',
// ...
};
Nếu muốn hiển thị bản dịch từ Blockly.Msg
, bạn cần sử dụng một hàm. Nếu bạn cố gắng chỉ định giá trị trực tiếp, thì các thông báo có thể không được tải và bạn sẽ nhận được giá trị undefined
.
const collapseTemplate = {
// ...
displayText: () => Blockly.Msg['MY_COLLAPSE_BLOCK_TEXT'],
// ...
};
Nếu bạn sử dụng một hàm, thì hàm đó cũng sẽ được truyền một giá trị Scope
. Bạn có thể dùng thuộc tính này để thêm thông tin về phần tử vào văn bản hiển thị.
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 '';
},
// ...
}
Trọng lượng
weight
xác định thứ tự hiển thị các mục trong trình đơn theo bối cảnh.
Các giá trị dương lớn hơn sẽ xuất hiện ở vị trí thấp hơn trong danh sách so với các giá trị dương nhỏ hơn.
(Bạn có thể tưởng tượng rằng các mục có trọng số cao hơn sẽ "nặng" hơn nên chúng sẽ chìm xuống đáy.)
const collapseTemplate = {
// ...
weight: 10,
// ...
}
Trọng số cho các mục trong trình đơn ngữ cảnh tích hợp sẽ tăng dần, bắt đầu từ 1 và tăng thêm 1.
Hàm gọi lại
Thuộc tính callback
là một hàm thực hiện thao tác của mục trong trình đơn theo bối cảnh. Hàm này được truyền một số tham số:
scope
: Một đối tượngScope
cung cấp thông tin tham chiếu đến thành phần có trình đơn đang mở.menuOpenEvent
:Event
đã kích hoạt việc mở trình đơn theo bối cảnh. Đây có thể làPointerEvent
hoặcKeyboardEvent
, tuỳ thuộc vào cách người dùng mở trình đơn.menuSelectEvent
:Event
đã chọn mục này trong trình đơn theo bối cảnh. Đây có thể làPointerEvent
hoặcKeyboardEvent
, tuỳ thuộc vào cách người dùng chọn mục.location
:Coordinate
trong toạ độ pixel nơi trình đơn được mở. Ví dụ: thao tác này cho phép bạn tạo một khối mới tại vị trí nhấp.
const collapseTemplate = {
// ...
callback: (scope, menuOpenEvent, menuSelectEvent, location) => {
if (scope.focusedNode instanceof Blockly.BlockSvg) {
scope.focusedNode.collapse();
}
},
}
Bạn có thể sử dụng scope
để thiết kế các mẫu hoạt động theo cách khác nhau tuỳ thuộc vào thành phần mà chúng được mở:
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);
}
}
}
Dấu phân tách
Thuộc tính separator
vẽ một đường trong trình đơn theo bối cảnh.
Mẫu có thuộc tính separator
không thể có thuộc tính preconditionFn
, displayText
hoặc callback
và chỉ có thể được đặt phạm vi bằng thuộc tính scopeType
. Hạn chế thứ hai có nghĩa là các thao tác này chỉ có thể dùng trên trình đơn theo bối cảnh cho không gian làm việc, khối và nhận xét trong không gian làm việc.
const separatorAfterCollapseBlockTemplate = {
id: 'separatorAfterCollapseBlock',
scopeType: Blockly.ContextMenuRegistry.ScopeType.BLOCK,
weight: 11, // Between the weights of the two items you want to separate.
separator: true,
};
Bạn cần một mẫu riêng cho mỗi dấu phân cách trong trình đơn ngữ cảnh. Sử dụng thuộc tính weight
để đặt vị trí cho từng dấu phân cách.
Loại phạm vi
Thuộc tính scopeType
không được dùng nữa. Trước đây, thuộc tính này được dùng để xác định xem một mục trong trình đơn có nên xuất hiện trên trình đơn theo bối cảnh cho một khối, một bình luận trong không gian làm việc hay một không gian làm việc hay không. Vì trình đơn theo bối cảnh có thể mở trên các thành phần khác, nên thuộc tính scopeType
quá hạn chế. Thay vào đó, bạn nên dùng preconditionFn
để hiện hoặc ẩn lựa chọn cho các thành phần tương ứng.
Nếu bạn có các mẫu trình đơn theo bối cảnh hiện có sử dụng scopeType
, thì Blockly sẽ tiếp tục chỉ hiển thị mục cho thành phần thích hợp.
const collapseTemplate = {
// ...
scopeType: Blockly.ContextMenuRegistry.ScopeType.BLOCK,
// ...
};
Tuỳ chỉnh sổ đăng ký
Bạn có thể thêm, xoá hoặc sửa đổi các mẫu trong sổ đăng ký. Bạn có thể tìm thấy các mẫu mặc định trong contextmenu_items.ts
.
Thêm mẫu
Bạn có thể thêm một mẫu vào sổ đăng ký bằng cách đăng ký mẫu đó. Bạn chỉ nên thực hiện việc này một lần khi tải trang. Điều này có thể xảy ra trước hoặc sau khi bạn chèn không gian làm việc.
const collapseTemplate = { /* properties from above */ };
Blockly.ContextMenuRegistry.registry.register(collapseTemplate);
Xoá mẫu
Bạn có thể xoá một mẫu khỏi sổ đăng ký bằng cách huỷ đăng ký mẫu đó theo mã nhận dạng.
Blockly.ContextMenuRegistry.registry.unregister('someID');
Sửa đổi mẫu
Bạn có thể sửa đổi một mẫu hiện có bằng cách lấy mẫu đó từ sổ đăng ký rồi sửa đổi tại chỗ.
const template = Blockly.ContextMenuRegistry.registry.getItem('someID');
template?.displayText = 'some other display text';
Tắt trình đơn theo bối cảnh chặn
Theo mặc định, các khối có một trình đơn theo bối cảnh cho phép người dùng làm những việc như thêm bình luận vào khối hoặc sao chép khối.
Bạn có thể tắt trình đơn theo bối cảnh của một khối riêng lẻ bằng cách:
block.contextMenu = false;
Trong định nghĩa JSON của một loại khối, hãy dùng khoá enableContextMenu
:
{
// ...,
"enableContextMenu": false,
}
Tuỳ chỉnh trình đơn ngữ cảnh theo từng loại khối hoặc không gian làm việc
Sau khi Blockly tạo một mảng các mục trong trình đơn theo bối cảnh, bạn có thể tuỳ chỉnh mảng đó cho từng khối hoặc không gian làm việc. Để làm việc này, hãy đặt BlockSvg.customContextMenu
hoặc WorkspaceSvg.configureContextMenu
thành một hàm sửa đổi mảng tại chỗ.
Các đối tượng trong mảng được truyền đến các khối có kiểu ContextMenuOption
hoặc triển khai giao diện LegacyContextMenuOption
. Các đối tượng được truyền đến không gian làm việc có kiểu ContextMenuOption
. Blockly sử dụng các thuộc tính sau đây từ những đối tượng này:
text
: Văn bản hiển thị.enabled
: Nếufalse
, hãy hiển thị mục bằng văn bản màu xám.callback
: Hàm sẽ được gọi khi người dùng nhấp vào mục.separator
: Mục này là một dấu phân cách. Loại trừ lẫn nhau với 3 thuộc tính còn lại.
Hãy xem tài liệu tham khảo để biết các loại thuộc tính và chữ ký hàm.
Ví dụ: đây là một hàm thêm mục Hello, World!
vào trình đơn theo bối cảnh của một không gian làm việc:
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);
}
Hiện trình đơn ngữ cảnh trên một đối tượng tuỳ chỉnh
Bạn có thể làm cho trình đơn theo bối cảnh xuất hiện cho các thành phần tuỳ chỉnh bằng cách làm theo các bước sau:
- Triển khai
IFocusableNode
hoặc mở rộng một lớp triển khaiIFocusableNode
. Giao diện này được dùng trong hệ thống trình đơn theo bối cảnh để xác định thành phần của bạn. Thao tác này cũng cho phép người dùng chuyển đến thành phần của bạn bằng trình bổ trợ điều hướng bằng bàn phím. Triển khai
IContextMenu
, chứa hàmshowContextMenu
. Hàm này lấy các mục trong trình đơn theo bối cảnh từ sổ đăng ký, tính toán vị trí trên màn hình để hiện trình đơn và cuối cùng hiện trình đơn nếu có mục nào để hiện.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); } }
Thêm một trình xử lý sự kiện gọi
showContextMenu
khi người dùng nhấp chuột phải vào thành phần của bạn. Xin lưu ý rằng trình bổ trợ điều hướng bằng bàn phím cung cấp một trình xử lý sự kiện gọishowContextMenu
khi người dùng nhấnCtrl+Enter
(Windows) hoặcCommand+Enter
(Mac).Thêm mẫu vào sổ đăng ký cho các mục trong trình đơn theo bối cảnh.