Nhúng trình soạn thảo
Sự kiện
Bảy sự kiện của O3O.Editor: onReady, onDocumentLoaded, onModified, onSaved, onError, onClose, onLimitReached, từng cái kèm trường và ví dụ.
Trong trang này
Khai báo trong config.events. Mỗi hàm nhận MỘT đối số là đối tượng sự kiện; hàm nào vắng mặt thì bỏ qua. Ngoại lệ ném ra từ hàm của bạn bị bắt và in ra console, không làm hỏng trình soạn thảo.
| Sự kiện | Khi nào | Đối tượng |
|---|---|---|
onReady | Phiên đã tạo, iframe đã gắn, khung soạn thảo báo sẵn sàng. | {sessionId, mode} |
onDocumentLoaded | Tài liệu đã hiện. | {sessionId, mode, loadTimeMs} |
onModified | Trạng thái “có thay đổi chưa lưu” đổi. | {modified} |
onSaved | Gate đã nhận một bản lưu mới; đúng một lần cho mỗi số phiên bản. | {key, version, url, size, sha256, savedAt} |
onError | Bất kỳ lỗi nào. | {code, message, detail} |
onClose | Người dùng bấm nút đóng, hoặc trang gọi close(). | {sessionId, modified} |
onLimitReached | Xin edit nhưng đã chạm trần; trình soạn thảo vẫn mở ở chế độ chỉ đọc. | {limit, current, edition, message, mode} |
Thứ tự thông thường: onReady → onDocumentLoaded → (onModified, onSaved)* → onClose.
onReady#
onReady
sessionIdstringbắt buộcMã phiên, dạngses_+ 24 hex.mode"edit" | "view"bắt buộcChế độ thật của phiên (có thể làviewnếu đã chạm trần).
const events = {
onReady(e) {
// Khung soạn thảo đã sẵn sàng, tài liệu còn đang nạp
document.getElementById("status").textContent = "Đang mở tài liệu…";
console.log(e.sessionId, e.mode); // "ses_…", "edit" | "view"
}
};onDocumentLoaded#
onDocumentLoaded
sessionIdstringbắt buộcMã phiên.mode"edit" | "view"bắt buộcChế độ của phiên.loadTimeMsnumberbắt buộcSố mili giây từ lúc tạo trình soạn thảo tới lúc tài liệu hiện, đo trên máy người dùng.
Ngay sau sự kiện này api.js áp các tuỳ chọn ui dạng thông điệp (thanh trạng thái, thanh trình đơn).
const events = {
onDocumentLoaded(e) {
document.getElementById("status").textContent = "";
console.log("mở trong", e.loadTimeMs, "ms, mode =", e.mode);
}
};onModified#
onModified
modifiedbooleanbắt buộctruekhi có thay đổi chưa lưu.
let dirty = false;
const events = {
onModified(e) {
dirty = e.modified;
document.title = (dirty ? "● " : "") + "Hợp đồng";
}
};
// Nhắc người dùng khi rời trang lúc còn thay đổi chưa lưu
window.addEventListener("beforeunload", (ev) => { if (dirty) ev.preventDefault(); });onSaved#
onSaved
keystringbắt buộcdocument.keycủa tài liệu.versionintegerbắt buộcSố phiên bản mới, tăng dần từ 1.urlstringbắt buộcURL tải phiên bản này, có chữ ký, sống trong thời gian giữ (O3O_EMBED_RETAIN_HOURS, mặc định 24 giờ).sizeintegerbắt buộcKích thước tính bằng byte.sha256stringbắt buộcBăm SHA-256 dạng hex của tệp.savedAtstringbắt buộcThời điểm lưu, ISO 8601 UTC.
{
"key": "contract-42-v7",
"version": 3,
"url": "http://localhost:8080/o3o/embed/files/doc_9835f61009fc659dfedab8696f2d2665?v=3&exp=1790086400&sig=5f1c…",
"size": 48890,
"sha256": "b1946ac92492d2347c6235b4d2611184…",
"savedAt": "2026-09-21T10:05:00Z"
}const events = {
onSaved(e) {
// e.url là URL tải có chữ ký, sống trong thời gian giữ của máy chủ (mặc định 24 giờ)
console.log(e.key, "v" + e.version, e.size, "bytes", e.sha256, e.savedAt);
document.getElementById("download").href = e.url;
}
};Cách api.js nhận ra bản lưu: khi khung soạn thảo báo lưu thành công, hoặc khi trạng thái “có thay đổi” chuyển từ true sang false, nó hỏi GET /o3o/embed/session/{id} mỗi giây, tối đa 10 lần, cho tới khi version lớn hơn số đã biết, rồi mới phát onSaved.
onError#
onError
codestringbắt buộcMã lỗi ổn định, xem bảng mã.messagestringbắt buộcCâu tiếng Việt hiện được cho người dùng.detailobjecttuỳ chọnMặc định:{}Chi tiết thêm, ví dụerrorscủainvalid_config.
{
"code": "download_failed",
"message": "Không tải được tài liệu từ địa chỉ đã cho.",
"detail": {}
}const events = {
onError(e) {
// e.message là câu tiếng Việt, hiện được cho người dùng; e.code dùng để rẽ nhánh
console.error(e.code, e.message, e.detail);
if (e.code === "network_error") setTimeout(() => location.reload(), 5000);
}
};onClose#
onClose
sessionIdstringbắt buộcMã phiên.modifiedbooleanbắt buộcCòn thay đổi chưa lưu lúc đóng.
const events = {
onClose(e) {
// iframe đã được gỡ trước khi sự kiện này phát
if (e.modified) console.warn("đóng khi còn thay đổi chưa lưu");
location.href = "/documents";
}
};onLimitReached#
onLimitReached
limitintegerbắt buộcTrần kết nối hiệu lực.currentintegerbắt buộcSố phiên sửa đang tính.edition"community" | "enterprise"bắt buộcGói đang chạy.messagestringbắt buộcCâu tiếng Việt của máy chủ;api.jshiện đúng câu này trên băng thông báo.mode"view"bắt buộcLuôn làview.
{
"limit": 50,
"current": 50,
"edition": "community",
"message": "Hệ thống đã đạt giới hạn 50 phiên soạn thảo đồng thời của bản cộng đồng. Tài liệu của bạn vẫn an toàn. Bạn có thể mở ở chế độ chỉ đọc hoặc thử lại sau ít phút.",
"mode": "view"
}const events = {
onLimitReached(e) {
// Trình soạn thảo VẪN mở, ở chế độ chỉ đọc (e.mode === "view")
console.warn(e.limit, e.current, e.edition, e.message);
}
};Ví dụ đầy đủ: ghi mọi sự kiện#
<!doctype html>
<meta charset="utf-8">
<div id="o3o-editor" style="height: 70vh"></div>
<pre id="log" style="height: 25vh; overflow: auto; background: #f4f4f4"></pre>
<script src="http://localhost:8080/o3o/api.js"></script>
<script>
const log = (name) => (e) => {
document.getElementById("log").textContent += new Date().toISOString() + " " + name + " " + JSON.stringify(e) + "\n";
};
new O3O.Editor("o3o-editor", {
document: { url: "http://localhost:8080/o3o/demo/sample.docx", title: "sample.docx", fileType: "docx", key: "events-demo-1" },
editor: { mode: "edit", lang: "vi", user: { id: "dev-1", name: "Dev" } },
ui: { closeButton: true },
events: {
onReady: log("onReady"),
onDocumentLoaded: log("onDocumentLoaded"),
onModified: log("onModified"),
onSaved: log("onSaved"),
onError: log("onError"),
onClose: log("onClose"),
onLimitReached: log("onLimitReached")
}
});
</script>Sự kiện cho lưu thành tệp khác và cho lịch sử phiên bản.