# PostMessage API 當 WOPI 主機將 OxOffice Online 包在一個框架( iFrame)時,可以使用 PostMessage API 用來於和 OxOffice Online 互動。這對想要完善整合的 WOPI 主機來講,非常有用。 這個 API 主要基於 [WOPI 規範](https://docs.microsoft.com/en-us/microsoft-365/cloud-storage-partner-program/online/scenarios/postmessage),很少擴充或修改。 所有送出的訊息,都採用以下形式: ```json { "MessageId": "", "SendTime": "", "Values": { "": "" } } ``` `SendTime` 是瀏覽器的 Date.now() 傳回的時間戳記。從 WOPI 主機發送的 PostMessage 也應該使用相同的格式。 需要注意的是,如 [WOPI 規範](https://docs.microsoft.com/en-us/microsoft-365/cloud-storage-partner-program/online/scenarios/postmessage)中所提到的,如果尚未收到 Host\_PostmessageReady,OxOffice Online 框架將忽略來自 WOPI 主機框架所有訊息。 另外,由於將 OxOffice Online 嵌入 iFrame 中,因此,OxOffice Online 要求 WOPI 主機回應 [**CheckFileInfo**](https://docs.ossii.com.tw/books/oxoffice-online-8LU/page/8efb1#bkmrk-checkfileinfo%EF%BC%9A%E4%BB%A5%E4%B8%8B-url-0) 中的`PostMessageOrigin` 屬性,必須指定,否則 OxOffice Online 將不會送出任何訊息。 ### **初始化** ##### 編輯器 🡆 WOPI 主機
**MessageID****Values****說明**
`App_LoadingStatus````json Status: DocumentLoadedTime: Features: {"VersionStates":true} ``` Status 值如下: - **`Frame_Ready`**:OxOffice Online 的框架已經載入,並且顯示了。 - **`Features`**:編輯器的能力。支援的值有 - VersionStates,表示編輯器支援文件版本復原的功能。 詳請請見:[文件版本復原](https://docs.ossii.com.tw/books/oxoffice-online-8LU/page/postmessage-api#bkmrk-%E6%96%87%E4%BB%B6%E7%89%88%E6%9C%AC%E5%BE%A9%E5%8E%9F) - `Document_Loaded`:使用者文件已經完全載入,WOPI 主機可以開始使用 PostMessage API。 `DocumentLoadedTime` 代表載入文件所花費的時間。 - `Failed`:文件載入失敗,WOPI 主機可以顯示 OxOffice Online 框架,向使用者顯示錯誤訊息。
##### WOPI 主機 🡆 編輯器
**MessageID****Values****說明**
`Host_PostmessageReady` 通知 OxOffice Online,WOPI 主機已經準備好收送 PostMessage 了。
### **查詢** WOPI 主機可以透過 PostMessage API 向編輯器查詢資料。所有來自編輯器回應的 MessageID,都會在您所傳遞的 MessageID 後面加上 "\_Resp"。 ##### WOPI 主機 🡆 編輯器
**MessageID****Values****說明**
`Get_Views` 向編輯器查詢,目前正在編輯文件所有使用者資訊。回應會以 MessageID 為 `Get_Views_Resp` 的格式傳回。
`Get_Export_Formats` 向編輯器查詢,目前開啟的文件,支援哪些匯出格式。
得到的回應。 ##### 編輯器 🡆 WOPI 主機
**MessageID****Values****說明**
`Get_Views_Resp````json [ { ViewId: UserId: UserName: Color: ReadOnly: IsCurrentView: },... ] ``` 使用 `Get_Views` 查詢,所得到的所有使用者詳細資訊。
`Get_Export_Formats_Resp````json [ { Label: Format: },... ] ``` 使用 `Get_Export_Formats` 查詢,所得到的回應。 - `Label` 是解釋該格式的本地語系內容。 - `Format` 是該格式的副檔名。
### **編輯者管理** ##### WOPI 主機 🡆 編輯器
**MessageID****Values****說明**
`Action_RemoveView```` ViewId: ``` 移除指定 Id 的編編者,也就是將某位編輯者踢出共編行列。
##### 編輯器 🡆 WOPI 主機
**MessageID****Values****說明**
`Views_List``Get_Views_Resp` 相同。所有正在參與該文件編輯的使用者詳細資訊。每次有編輯者加入或離開都會觸發此資訊。
### **各類指令**
##### WOPI 主機 🡆 編輯器
MessageId Values **說明**
`Action_Save` ```json DontTerminateEdit: DontSaveIfUnmodified: Notify: ExtendedData: ``` 儲存文件。 - `DontTerminateEdit` 和試算表相關,這會中斷編輯模式(文字游標消失)。設為 true 的話,就能儲存檔案,而不會終止編輯模式,也不會中斷使用者編輯試算表。 - `DontSaveIfUnmodified` 如果文件內容沒有變更(只是移動了游標),這會阻止 OxOffice Online 把檔案回存雲端硬碟, 如此可防止不必要的版本修訂。 - `Notify` 設為 true 時,會在文件儲存完後,通知 WOPI 主機。詳情請參考 `Action_Save_Resp` - `ExtendedData` 如果標頭`X-LOOL-WOPI-ExtendedData` 有資料,則會原封不動地傳給WOPI 主機。 資料內容不可是空白、換行或其他不可列印字元。 OxOffice Online 可以傳遞多個值,然後 WOPI 主機可以進一步對處理這些值。
`Action_SaveAs` ``` Filename: Notify: ``` 建立文件副本,並給予新檔名(另存新檔)。 - `Filename` 新文件檔名。 - `Notify` 設為 true 時,會在文件儲存完後,通知 WOPI 主機。詳情請參考 `Action_Save_Resp`
`Action_FollowUser` ``` Follow: ViewId: ``` 開啟或關閉跟隨特定編輯者功能。這會讓編輯畫面和指定對象同步。 - `Follow` true 開啟/ false 關閉。 - `ViewId` 要跟隨的編輯者 ID。
`Action_Close` 關閉文件。
`Action_Print` 列印文件。
`Action_Export` ``` Format: ``` 以 `Format` 指定的格式下載文件。格式只能是 `Get_Export_Formats` 所指定列表其中之一。
`Action_InsertGraphics` ``` url: ``` 從指定的位址下載圖片並插入文件中。
`Action_ShowBusy` ``` Label: ``` 顯示具有 Lable 文字的忙碌畫面,類似存檔中的畫面。
`Action_HideBusy` 如果有忙碌畫面的話,關掉忙碌畫面。
`Action_ChangeUIMode` ``` Mode:'classic' 或 'notebookbar' ``` 變更使用者介面: - classic:傳統下拉選單+工具列。 - notebookbar:分頁式介面。
`Action_Paste` ``` Mimetype: Data: ``` 繞過內部貼上機制,直接貼上資料到文件內。 例如: `Values: {Mimetype: "text/plain;charset=utf-8", Data: "haha"}};`
##### 編輯器 🡆 WOPI 主機(回應)
MessageId Values **說明**
`Action_Load_Resp` ``` success: result: errorMsg: ``` 文件載入完成。 - `success` true 成功、false 失敗。 - `result` 文件未載入的原因。 - `errorMsg` 載入失敗時的詳細錯誤訊息。也可能包含從 WOPI 主機傳回的錯誤訊息。
`Action_Save_Resp` ``` success: result: errorMsg: fileName: ``` 文件儲存完成。只有`Action_Save` 或 `Action_SaveAs` PostMessage API 將 `Notify` 參數設為 true 時,才會得到這個回應。 - `success` true 成功、false 失敗。 - `result` 文件未儲存的原因。如果文件因未修改而未儲存,則此參數包含字串「unmodified」。 這種情況下,WOPI 主機可以確保不會儲存到位編耕的文件。 - `errorMsg` 儲存失敗時的詳細錯誤訊息。 也可能包含從 WOPI 主機傳回的錯誤訊息。 - `fileName` 如果 `success `為 true 則包含已儲存的檔案名稱。
`FollowUser_Changed` ``` FollowedViewId: IsFollowUser: IsFollowEditor: ``` 跟隨狀態變更。 - `FollowedViewId` 哪個編輯者被跟隨。 - `IsFollowUser`是否啟用跟隨編輯者。 - `IsFollowEditor` 是否啟用跟隨編輯器。 - 如果 `IsFollowUser` 和 `IsFollowEditor` 都是 false,表示取消跟隨功能。
`Action_ChangeUIMode_Resp` ``` Mode: ``` 變更使用介面。 `Mode` 使用哪種介面。
### **文件版本復原**
##### WOPI 主機 🡆 編輯器
MessageId Values **說明**
`Host_VersionRestore` ``` Status: ``` 復原版本。唯一可能的值是 Pre\_Restore 此訊息由主機在實際復原文件之前以及使用者確定復原之後傳送。 這樣,如果目前文件,還有未儲存的修改,OxOffice Online 可以在恢復文件之前將它們儲存到雲端硬碟中。
##### 編輯器 🡆 WOPI 主機
MessageId Values 說明
`App_VersionRestore` ``` Status: ``` 這是對 `Host_VersionRestore` 訊息的回應。 目前 `Status` 的值為 `Pre_Restore_Ack` 表示 WOPI 主機可以繼續將文件回復到較早的版本。

只有當 `App_LoadingStatus` 包含功能中的 **VersionStates** 時,才會發出這些訊息。 否則,主機可以立即將版本還原到早期版本。

### **其他**
##### WOPI 主機 🡆 編輯器
MessageId Values 說明
`Insert_Button` ```json id: imgurl: hint: accessKey: mobile: tablet: insertBefore: unoCommand: ``` 在頂端工具列插入自訂按鈕(僅顯示在傳統介面)。該按鈕被點擊時,若未指定 `unoCommand` 屬性,會觸發 `Clicked_Button` 的事件給 WOPI 主機,讓 WOPI 主機做相應處理。 - `id` 代表該按鈕的不可重複 ID。為了避免和原先工具列的其他按鈕 ID 衝突,建議在此類 ID 前,加上主機特有的名稱。 如果和其他按鈕衝突,則不會新增按鈕。 - `imgurl` 按鈕圖示位址。建議的大小為 24x24 px。圖片位址應和 WOPI 主機為同一來源,易免違反 `Content-Security-Policy`。 - `hint` 按鈕的提示。 - `accessKey` 快捷鍵。使用者可以搭配 Alt 或 Alt+Shift 加上此鍵。注意不要和其他快捷鍵衝突。 - `mobile` 手機模式時,是否顯示該按鈕。 - `tablet` 平板模式時,是否顯示該按鈕。 - `insertBefore` 新增在哪個 按鈕 ID 之前。請參考[查詢工具列按鈕 ID](https://docs.ossii.com.tw/books/oxoffice-online-8LU/page/postmessage-api#bkmrk-%E6%9F%A5%E8%A9%A2%E5%B7%A5%E5%85%B7%E5%88%97%E6%8C%89%E9%88%95-id) - `unoCommand` UNO 命令([請參閱此處](https://wiki.documentfoundation.org/Development/DispatchCommands))。 設置這個屬性,就不會傳送 `Clicked_Button` 訊息給 WOPI 主機,而會交由 LibreOffice 直接執行此命令。
`Hide_Button` ``` id: ``` 隱藏工具列按鈕。`id` 為按鈕 ID([查詢工具列按鈕 ID](https://docs.ossii.com.tw/books/oxoffice-online-8LU/page/postmessage-api#bkmrk-%E6%9F%A5%E8%A9%A2%E5%B7%A5%E5%85%B7%E5%88%97%E6%8C%89%E9%88%95-id))
`Show_Button` ``` id: ``` 顯示工具列按鈕。`id` 為按鈕 ID([查詢工具列按鈕 ID](https://docs.ossii.com.tw/books/oxoffice-online-8LU/page/postmessage-api#bkmrk-%E6%9F%A5%E8%A9%A2%E5%B7%A5%E5%85%B7%E5%88%97%E6%8C%89%E9%88%95-id))
`Remove_Button` ``` id: ``` 移除工具列按鈕。`id` 為按鈕 ID([查詢工具列按鈕 ID](https://docs.ossii.com.tw/books/oxoffice-online-8LU/page/postmessage-api#bkmrk-%E6%9F%A5%E8%A9%A2%E5%B7%A5%E5%85%B7%E5%88%97%E6%8C%89%E9%88%95-id))
`Remove_Statusbar_Element` ``` id: ``` 移除狀態列元件。 `id` 是狀態列元件 ID(請參考:[查詢狀態列元件 ID](https://docs.ossii.com.tw/books/oxoffice-online-8LU/page/postmessage-api#bkmrk-%E6%9F%A5%E8%A9%A2%E7%8B%80%E6%85%8B%E5%88%97%E5%85%83%E4%BB%B6-id))
`Hide_Menubar` 隱藏下拉選單列。
`Show_Menubar` 顯示下拉選單列。
`Grab_Focus` 喚醒休眠中的編輯器。通常編輯者在一段時間後沒有任何動作時,編輯器會進入休眠狀態(編輯介面變暗,並有訊息顯示),必要時,會中斷與伺服器連線。`Grab_Focus` 會重新喚醒編輯器,必要時重新連線伺服器。
`Hide_Ruler` 隱藏水平尺規(僅適用文字文件 Writer)。
`Show_Ruler` 隱藏水平尺規(僅適用文字文件 Writer)。
`Hide_Menu_Item` ``` id: ``` 隱藏下拉選單中的選項。`id` 是指選項 ID ,它們分別定義在: - 文字文件:[uiconfig/text/menubar.json](https://github.com/OSSII/oxool-community/blob/v4/loleaflet/uiconfig/text/menubar.json) - 試算表文件:[uiconfig/spreadsheet/menubar.json](https://github.com/OSSII/oxool-community/blob/v4/loleaflet/uiconfig/spreadsheet/menubar.json) - 簡報文件:[uiconfig/presentation/menubar.json](https://github.com/OSSII/oxool-community/blob/v4/loleaflet/uiconfig/presentation/menubar.json) - 繪圖文件:[uiconfig/drawing/menubar.json](https://github.com/OSSII/oxool-community/blob/v4/loleaflet/uiconfig/drawing/menubar.json)
`Show_Menu_Item` ``` id: ``` 顯示下拉選單中的選項。`id` 是指選項 ID。請參閱前項 `Hide_Menu_Item`
`Disable_Default_UIAction` ``` action: disable: ``` 停用或啟用某個 UI 命令的預設行為。 - `action` 動作名稱。 - `disable` 表示停用 (**true**) 或啟用 (**false**) 預設行為。 設為 true 時,指定的動作只會發出 `postMessage` 而不會執行預設行為。這讓 WOPI 主機可以根據 `postMessage` 事件,進行必要處理。 請注意,某些動作沒有任何預設行為(如 `UI_SaveAs` 和 `UI_Share`),因此,這對它們沒有影響;但無論如何,他們只會發出 `postMessage` 通知,而不會採取預設行為 舉例來說,`UI_Save` 預設會呼叫儲存命令(透過選單、工具列按鈕或鍵盤快捷鍵)。如果透過 `Disable_Default_UIAction` 停用 `UI_Save`,則不會呼叫儲存命令。 停用 `UI_Save` 的 WOPI 主機,應該在文件需要儲存時,自行發出 `Action_Save`。 同樣地,當停用 `UI_Close` 時,呼叫 `UI_Close`,並不會真的文件關閉,而是會發出 postMessage 通知,並且由 WOPI 主機在需要時發出 `Action_Close`。 WOPI 主機必須很小心,不要在啟用預設行為的狀態下,發出重複的`Action_xxyyzz` 等指令。相反地,只能在停用預設行為時,才能自行發出操作。 注意:目前也只有 `UI_Save` 和 `UI_Close` 以及 `UI_Hyperlink` 能停用🤣
`Send_UNO_Command` ```json Command: Args: ``` 向編輯器傳送 UNO 命令。請參考:[framed.doc.html](https://github.com/OSSII/oxool-community/blob/v4/loleaflet/html/framed.doc.html)
### **查詢工具列按鈕 ID** 工具列按鈕 ID 在下列程式中的 getToolItems/create 函數定義: - [Control.TopToolbar.js](https://github.com/OSSII/oxool-community/blob/v4/loleaflet/src/control/Control.TopToolbar.js):用於桌面或平板電腦上的頂部工具列。 - [Control.MobileTopBar.js](https://github.com/OSSII/oxool-community/blob/v4/loleaflet/src/control/Control.MobileTopBar.js):用於智慧型手機上的頂部工具列。 - [Control.MobileBottomBar.js](https://github.com/OSSII/oxool-community/blob/v4/loleaflet/src/control/Control.MobileBottomBar.js):用於智慧型手機底部工具列。 - [Control.StatusBar.js](https://github.com/OSSII/oxool-community/blob/v4/loleaflet/src/control/Control.ReadonlyBar.js):用於桌面上的狀態列。 這些通常不會改變,但並不保證這些 ID 會穩定存在。
### **查詢狀態列元件 ID** 狀態列元件 ID 定義在 [Control.StatusBar.js](https://github.com/OSSII/oxool-community/blob/v4/loleaflet/src/control/Control.StatusBar.js) 的 `onDocLayerInit` 函數中。通常不會改變,但並不保證這些 ID 會穩定存在。 ### **事件通知**
##### 編輯器 🡆 WOPI 主機
MessageId Values 說明
`Clicked_Button` ``` id: ``` 點擊透過前面的 `Insert_Button` API 新增的自訂按鈕時會發出此事件。
`Download_As` ``` Type: 'print'|'slideshow'|'export' URL: ``` 當使用者選擇「列印」或「全螢幕投影」或「下載為…」,且 WOPI 主機在 [**CheckFileInfo**](https://docs.ossii.com.tw/books/oxoffice-online-8LU/page/8efb1#bkmrk-oxoffice-online-%E5%8F%AF%E7%94%A8%E7%9A%84-) 的`DownloadAsPostMessage` 屬性中,指定要接管時,就會觸發此事件。 這應用於無法依賴瀏覽器下載的情況,例如手機的 Web view 模式。
`UI_Close` ```json EverModified: true | false ``` 當使用者選擇關閉文件,或點擊關閉按鈕,將觸發此事件。`EverModified` 指出此文件是否修改過。
`UI_Save` ```json source: 'filemenu' | 'notebookbar' | 'toolbar' ``` 使用者選擇儲存。`source` 指出透過何種方式儲存。
`UI_CreateFile` ```json DocumentType: 'text' | 'spreadsheet' | 'presentation' | 'drawing' ``` 要求 WOPI 主機開啟新的瀏覽器分頁,並建立新文件。 文件類型以 DocumentType 參數傳遞,可以是「text(文字文件)」、「spreadsheet(試算表)」、「presentation(簡報)」或「drawing(繪圖)」。
`UI_SaveAs` 要求 WOPI 主機顯示另存新檔 UI,以便使用者可以選擇路徑和檔案名稱來建立目前檔案的副本。 若使用者確定存檔,則 WOPI 主機需以 `Action_SaveAs` 命令編輯器發送檔案內容。
`UI_Cancel_Password` 通知 WOPI 主機使用者在開啟有密碼保護的檔案時,點擊了「取消」,而不是輸入密碼。
`UI_Hyperlink` 通知 WOPI 主機只用者點擊了超連結,並確認確實想要離開文件以開啟超連結。這對於將 OxOffice Online 嵌入到行動裝置 iframe 中的 App 特別有用,實際嘗試開啟新視窗,應觸發在 Android 上的 Activity(或在 iOS 上類似的操作)。 WOPI 主機可能也想利用 `Disable_Default_UIAction` 來接管 `UI_Hyperlink`
`Doc_ModifiedStatus` ```json Modified: true | false ``` 更新文件的修改狀態。如果文件自上次儲存後被修改,則 `Modified `將為 **true**,否則,如果文件已儲存,則 `Modified `為 **false**。 請注意,這個通知可能會在不更改先前值的情況下觸發,因此必須檢查 `Modified `的值,不要假設這個通知暗示文件的修改狀態。
### **呼叫 Python 巨集**
##### WOPI 主機 🡆 編輯器
MessageId Values 說明
`CallPythonScript` ``` ScriptFile: Function: Values: ``` 執行指定功能的 Python 巨集: - ScriptFile:巨集檔名 - Function:函數名稱 - Values:參數內容(key: value, ...)
##### 編輯器 🡆 WOPI 主機
MessageId Values 說明
`CallPythonScript-Result` ``` commandName: Values: ``` 傳回 Python 執行結果。`commandName `放的是巨集的 URL。