# 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": "<MessageId>",
      "SendTime": "<Timestamp when message is sent>",
      "Values": {
             "<key>": "<value>"
      }
}
```

`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 主機

<table border="1" id="bkmrk-messageid-values-%E8%AA%AA%E6%98%8E-" style="border-collapse: collapse; width: 100%;"><colgroup><col style="width: 19.1595%;"></col><col style="width: 34.6013%;"></col><col style="width: 46.2392%;"></col></colgroup><tbody><tr><td>**MessageID**</td><td>**Values**</td><td class="align-center">**說明**</td></tr><tr><td>`<span style="color: rgb(186, 55, 42);">App_LoadingStatus</span>`</td><td>```json
Status: <String>
DocumentLoadedTime: <Timestamp>
Features: {"VersionStates":true}
```

</td><td>Status 值如下：

- **`<span class="pre">Frame_Ready</span>`**：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)
- `<span class="pre"><strong>Document_Loaded</strong></span>`：使用者文件已經完全載入，WOPI 主機可以開始使用 PostMessage API。  
    `DocumentLoadedTime` 代表載入文件所花費的時間。
- `<span class="pre"><strong>Failed</strong></span>`：文件載入失敗，WOPI 主機可以顯示 OxOffice Online 框架，向使用者顯示錯誤訊息。

</td></tr></tbody></table>

##### WOPI 主機 🡆 編輯器

<table border="1" id="bkmrk-messageid-values-%E8%AA%AA%E6%98%8E--0" style="border-collapse: collapse; width: 100%;"><colgroup><col style="width: 22.1238%;"></col><col style="width: 31.6463%;"></col><col style="width: 46.2299%;"></col></colgroup><tbody><tr><td>**MessageID**</td><td>**Values**</td><td class="align-center">**說明**</td></tr><tr><td>`<span style="color: rgb(186, 55, 42);">Host_PostmessageReady</span>`</td><td>  
</td><td>通知 OxOffice Online，WOPI 主機已經準備好收送 PostMessage 了。</td></tr></tbody></table>

### **查詢**

WOPI 主機可以透過 PostMessage API 向編輯器查詢資料。所有來自編輯器回應的 MessageID，都會在您所傳遞的 MessageID 後面加上 "\_Resp"。

##### WOPI 主機 🡆 編輯器

<table border="1" id="bkmrk-messageid-values-%E8%AA%AA%E6%98%8E--1" style="border-collapse: collapse; width: 100%; border-width: 1px;"><colgroup><col style="width: 20.6409%;"></col><col style="width: 33.1291%;"></col><col style="width: 46.2299%;"></col></colgroup><tbody><tr style="height: 29.7969px;"><td style="height: 29.7969px; border-width: 1px;">**MessageID**</td><td style="height: 29.7969px; border-width: 1px;">**Values**</td><td class="align-center" style="height: 29.7969px; border-width: 1px;">**說明**</td></tr><tr style="height: 30.1094px;"><td style="height: 30.1094px; border-width: 1px;"><span style="color: rgb(186, 55, 42);">`Get_Views`</span></td><td style="height: 30.1094px; border-width: 1px;">  
</td><td style="height: 30.1094px; border-width: 1px;">向編輯器查詢，目前正在編輯文件所有使用者資訊。回應會以 MessageID 為 <span style="color: rgb(186, 55, 42);">`Get_Views_Resp`</span> 的格式傳回。</td></tr><tr style="height: 29.7969px;"><td style="height: 29.7969px; border-width: 1px;">`<span style="color: rgb(186, 55, 42);">Get_Export_Formats</span>`</td><td style="height: 29.7969px; border-width: 1px;">  
</td><td style="height: 29.7969px; border-width: 1px;">向編輯器查詢，目前開啟的文件，支援哪些匯出格式。</td></tr></tbody></table>

得到的回應。

##### 編輯器 🡆 WOPI 主機

<table border="1" id="bkmrk-messageid-values-%E8%AA%AA%E6%98%8E--2" style="border-collapse: collapse; width: 100%; border-width: 1px;"><colgroup><col style="width: 24.7202%;"></col><col style="width: 29.0499%;"></col><col style="width: 46.2299%;"></col></colgroup><tbody><tr style="height: 29.7969px;"><td style="height: 29.7969px; border-width: 1px;">**MessageID**</td><td style="height: 29.7969px; border-width: 1px;">**Values**</td><td class="align-center" style="height: 29.7969px; border-width: 1px;">**說明**</td></tr><tr style="height: 46.9062px;"><td style="height: 46.9062px; border-width: 1px;"><span style="color: rgb(186, 55, 42);">`Get_Views_Resp`</span></td><td style="height: 46.9062px; border-width: 1px;">```json
[
  {
    ViewId: <Number>
	UserId: <String>
	UserName: <String>
	Color: <Number>
	ReadOnly: <Boolean>
	IsCurrentView: <Boolean>
  },...
]
```

</td><td style="height: 46.9062px; border-width: 1px;">使用 `<span style="color: rgb(186, 55, 42);">Get_Views</span>` 查詢，所得到的所有使用者詳細資訊。</td></tr><tr style="height: 30.1094px;"><td style="height: 30.1094px; border-width: 1px;">`<span style="color: rgb(186, 55, 42);"><span class="pre">Get_E</span><span class="pre">xport_Formats_Resp</span></span>`</td><td style="height: 30.1094px; border-width: 1px;">```json
[
  {
    Label: <String>
	Format: <String>
  },...
]
```

</td><td style="height: 30.1094px; border-width: 1px;">使用 `<span style="color: rgb(186, 55, 42);">Get_Export_Formats</span>` 查詢，所得到的回應。

- `Label` 是解釋該格式的本地語系內容。
- `Format` 是該格式的副檔名。

</td></tr></tbody></table>

### **編輯者管理**

##### WOPI 主機 🡆 編輯器

<table border="1" id="bkmrk-messageid-values-%E8%AA%AA%E6%98%8E--3" style="border-collapse: collapse; width: 100%;"><colgroup><col style="width: 22.1238%;"></col><col style="width: 31.6463%;"></col><col style="width: 46.2299%;"></col></colgroup><tbody><tr><td>**MessageID**</td><td>**Values**</td><td class="align-center">**說明**</td></tr><tr><td>`<span style="color: rgb(186, 55, 42);">Action_RemoveView</span>`</td><td>```
ViewId: <Number>
```

</td><td>移除指定 Id 的編編者，也就是將某位編輯者踢出共編行列。</td></tr></tbody></table>

##### 編輯器 🡆 WOPI 主機

<table border="1" id="bkmrk-messageid-values-%E8%AA%AA%E6%98%8E--4" style="border-collapse: collapse; width: 100%;"><colgroup><col style="width: 22.1238%;"></col><col style="width: 31.6463%;"></col><col style="width: 46.2299%;"></col></colgroup><tbody><tr><td>**MessageID**</td><td>**Values**</td><td class="align-center">**說明**</td></tr><tr><td>`<span style="color: rgb(186, 55, 42);">Views_List</span>`</td><td>與 <span style="color: rgb(186, 55, 42);">`Get_Views_Resp`</span> 相同。</td><td>所有正在參與該文件編輯的使用者詳細資訊。每次有編輯者加入或離開都會觸發此資訊。

</td></tr></tbody></table>

### **各類指令**

<section id="bkmrk-wopi-%E4%B8%BB%E6%A9%9F-%F0%9F%A1%86-%E7%B7%A8%E8%BC%AF%E5%99%A8-messag">##### WOPI 主機 🡆 編輯器

<section id="bkmrk-messageid-values-des"><section id="bkmrk-messageid-values-des-0"><div class="wy-table-responsive"><table border="1" style="border-collapse: collapse; width: 100%; border-width: 1px; border-style: solid;"><thead><tr class="row-odd" style="height: 35.3906px;"><th class="head" style="width: 22.1247%; height: 35.3906px; border-width: 1px;">MessageId

</th><th class="head" style="width: 31.769%; height: 35.3906px; border-width: 1px;">Values

</th><th class="head" style="width: 46.1063%; height: 35.3906px; border-width: 1px;">**說明**

</th></tr></thead><tbody><tr class="row-even" style="height: 363.047px;"><td style="width: 22.1247%; height: 363.047px; border-width: 1px;"><span style="color: rgb(186, 55, 42);">`<span class="pre">Action_Save</span>`</span>

</td><td style="width: 31.769%; height: 363.047px; border-width: 1px;">```json
DontTerminateEdit: <boolean>
DontSaveIfUnmodified: <boolean>
Notify: <boolean>
ExtendedData: <String>
```

</td><td style="width: 46.1063%; height: 363.047px; border-width: 1px;">儲存文件。

- `<span class="pre">DontTerminateEdit</span>` 和試算表相關，這會中斷編輯模式（文字游標消失）。設為 true 的話，就能儲存檔案，而不會終止編輯模式，也不會中斷使用者編輯試算表。
- `<span class="pre">DontSaveIfUnmodified</span>` 如果文件內容沒有變更（只是移動了游標），這會阻止 OxOffice Online 把檔案回存雲端硬碟， 如此可防止不必要的版本修訂。
- `<span class="pre">Notify</span>` 設為 true 時，會在文件儲存完後，通知 WOPI 主機。詳情請參考 <span style="color: rgb(186, 55, 42);">`<span class="pre">Action_Save_Resp</span>`</span>
- `<span class="pre">ExtendedData</span>` 如果標頭`<span class="pre">X-LOOL-WOPI-ExtendedData</span>` 有資料，則會原封不動地傳給WOPI 主機。  
    資料內容不可是空白、換行或其他不可列印字元。  
    OxOffice Online 可以傳遞多個值，然後 WOPI 主機可以進一步對處理這些值。

</td></tr><tr class="row-odd" style="height: 126.953px;"><td style="width: 22.1247%; height: 126.953px; border-width: 1px;">`<span class="pre"><span style="color: rgb(186, 55, 42);">Action_SaveAs</span></span>`

</td><td style="width: 31.769%; height: 126.953px; border-width: 1px;">```
Filename: <String>
Notify: <boolean>
```

</td><td style="width: 46.1063%; height: 126.953px; border-width: 1px;">建立文件副本，並給予新檔名（另存新檔）。

- `<span class="pre">Filename</span>` 新文件檔名。
- `<span class="pre">Notify</span>` 設為 true 時，會在文件儲存完後，通知 WOPI 主機。詳情請參考 <span style="color: rgb(186, 55, 42);">`<span class="pre">Action_Save_Resp</span>`</span>

</td></tr><tr class="row-even" style="height: 78.0469px;"><td style="width: 22.1247%; height: 78.0469px; border-width: 1px;"><span style="color: rgb(186, 55, 42);">`<span class="pre">Action_FollowUser</span>`</span>

</td><td style="width: 31.769%; height: 78.0469px; border-width: 1px;">```
Follow: <Boolean>
ViewId: <Number>
```

</td><td style="width: 46.1063%; height: 78.0469px; border-width: 1px;">開啟或關閉跟隨特定編輯者功能。這會讓編輯畫面和指定對象同步。

- `<span class="pre">Follow</span>` true 開啟/ false 關閉。
- `<span class="pre">ViewId</span>` 要跟隨的編輯者 ID。

</td></tr><tr class="row-odd" style="height: 35.3906px;"><td style="width: 22.1247%; height: 35.3906px; border-width: 1px;">`<span class="pre"><span style="color: rgb(186, 55, 42);">Action_Close</span></span>`

</td><td style="width: 31.769%; height: 35.3906px; border-width: 1px;">  
</td><td style="width: 46.1063%; height: 35.3906px; border-width: 1px;">關閉文件。

</td></tr><tr class="row-even" style="height: 35.3906px;"><td style="width: 22.1247%; height: 35.3906px; border-width: 1px;"><span style="color: rgb(186, 55, 42);">`<span class="pre">Action_Print</span>`</span>

</td><td style="width: 31.769%; height: 35.3906px; border-width: 1px;">  
</td><td style="width: 46.1063%; height: 35.3906px; border-width: 1px;">列印文件。

</td></tr><tr class="row-odd" style="height: 80.1719px;"><td style="width: 22.1247%; height: 80.1719px; border-width: 1px;"><span style="color: rgb(186, 55, 42);">`<span class="pre">Action_Export</span>`</span>

</td><td style="width: 31.769%; height: 80.1719px; border-width: 1px;">```
Format: <String>
```

</td><td style="width: 46.1063%; height: 80.1719px; border-width: 1px;">以 `<span class="pre">Format</span>` 指定的格式下載文件。格式只能是 <span style="color: rgb(186, 55, 42);">`<span class="pre">Get_Export_Formats</span>` </span>所指定列表其中之一。

</td></tr><tr class="row-even" style="height: 61.3906px;"><td style="width: 22.1247%; height: 61.3906px; border-width: 1px;">`<span class="pre"><span style="color: rgb(186, 55, 42);">Action_InsertGraphics</span></span>`

</td><td style="width: 31.769%; height: 61.3906px; border-width: 1px;">```
url: <String>
```

</td><td style="width: 46.1063%; height: 61.3906px; border-width: 1px;">從指定的位址下載圖片並插入文件中。

</td></tr><tr class="row-odd" style="height: 61.3906px;"><td style="width: 22.1247%; height: 61.3906px; border-width: 1px;">`<span class="pre"><span style="color: rgb(186, 55, 42);">Action_ShowBusy</span></span>`

</td><td style="width: 31.769%; height: 61.3906px; border-width: 1px;">```
Label: <String>
```

</td><td style="width: 46.1063%; height: 61.3906px; border-width: 1px;">顯示具有 Lable 文字的忙碌畫面，類似存檔中的畫面。

</td></tr><tr class="row-even" style="height: 35.3906px;"><td style="width: 22.1247%; height: 35.3906px; border-width: 1px;">`<span class="pre"><span style="color: rgb(186, 55, 42);">Action_HideBusy</span></span>`

</td><td style="width: 31.769%; height: 35.3906px; border-width: 1px;">  
</td><td style="width: 46.1063%; height: 35.3906px; border-width: 1px;">如果有忙碌畫面的話，關掉忙碌畫面。

</td></tr><tr class="row-odd" style="height: 92.4219px;"><td style="width: 22.1247%; height: 92.4219px; border-width: 1px;"><span style="color: rgb(186, 55, 42);">`<span class="pre">Action_ChangeUIMode</span>`</span>

</td><td style="width: 31.769%; height: 92.4219px; border-width: 1px;">```
Mode:'classic' 或 'notebookbar'
```

</td><td style="width: 46.1063%; height: 92.4219px; border-width: 1px;">變更使用者介面：

- classic：傳統下拉選單＋工具列。
- notebookbar：分頁式介面。

</td></tr><tr class="row-even" style="height: 102.562px;"><td style="width: 22.1247%; height: 102.562px; border-width: 1px;">`<span class="pre"><span style="color: rgb(186, 55, 42);">Action_Paste</span></span>`

</td><td style="width: 31.769%; height: 102.562px; border-width: 1px;">```
Mimetype: <string>
Data: <string>
```

</td><td style="width: 46.1063%; height: 102.562px; border-width: 1px;">繞過內部貼上機制，直接貼上資料到文件內。

例如：

`<span class="pre">Values:</span> <span class="pre">{Mimetype:</span> <span class="pre">"text/plain;charset=utf-8",</span> <span class="pre">Data:</span> <span class="pre">"haha"}};</span>`

</td></tr></tbody></table>

</div></section><section id="bkmrk-%E7%B7%A8%E8%BC%AF%E5%99%A8-%F0%9F%A1%86-wopi-%E4%B8%BB%E6%A9%9F%EF%BC%88%E5%9B%9E%E6%87%89%EF%BC%89-me">##### 編輯器 🡆 WOPI 主機（回應）

<div class="wy-table-responsive"><table border="1" style="border-collapse: collapse; width: 100%; border-width: 1px; border-style: solid;"><colgroup><col style="width: 25.5885%;"></col><col style="width: 28.3052%;"></col><col style="width: 46.1063%;"></col></colgroup><thead><tr class="row-odd" style="height: 35.3906px;"><th class="head" style="height: 35.3906px; border-width: 1px;">MessageId

</th><th class="head" style="height: 35.3906px; border-width: 1px;">Values

</th><th class="head" style="height: 35.3906px; border-width: 1px;">**說明**

</th></tr></thead><tbody><tr class="row-even" style="height: 126.953px;"><td style="height: 126.953px; border-width: 1px;"><span style="color: rgb(186, 55, 42);">`<span class="pre">Action_Load_Resp</span>`</span>

</td><td style="height: 126.953px; border-width: 1px;">```
success: <boolean>
result:  <string>
errorMsg: <string>
```

</td><td style="height: 126.953px; border-width: 1px;">文件載入完成。

- `<span class="pre">success</span>` true 成功、false 失敗。
- `<span class="pre">result</span>` 文件未載入的原因。
- `<span class="pre">errorMsg</span>` 載入失敗時的詳細錯誤訊息。也可能包含從 WOPI 主機傳回的錯誤訊息。

</td></tr><tr class="row-odd" style="height: 256.641px;"><td style="height: 256.641px; border-width: 1px;"><span style="color: rgb(186, 55, 42);">`<span class="pre">Action_Save_Resp</span>`</span>

</td><td style="height: 256.641px; border-width: 1px;">```
success: <boolean>
result: <string>
errorMsg: <string>
fileName: <string>
```

</td><td style="height: 256.641px; border-width: 1px;">文件儲存完成。只有<span style="color: rgb(186, 55, 42);">`<span class="pre">Action_Save</span>`</span> 或 `<span class="pre"><span style="color: rgb(186, 55, 42);">Action_SaveAs</span></span>` PostMessage API 將 `<span class="pre">Notify</span>` 參數設為 true 時，才會得到這個回應。

- `<span class="pre">success</span>` true 成功、false 失敗。
- `<span class="pre">result</span>` 文件未儲存的原因。如果文件因未修改而未儲存，則此參數包含字串「unmodified」。 這種情況下，WOPI 主機可以確保不會儲存到位編耕的文件。
- `<span class="pre">errorMsg</span>` 儲存失敗時的詳細錯誤訊息。 也可能包含從 WOPI 主機傳回的錯誤訊息。
- `<span class="pre">fileName</span>` 如果 `success `為 true 則包含已儲存的檔案名稱。

</td></tr><tr class="row-even" style="height: 144.062px;"><td style="height: 144.062px; border-width: 1px;"><span style="color: rgb(186, 55, 42);">`<span class="pre">FollowUser_Changed</span>`</span>

</td><td style="height: 144.062px; border-width: 1px;">```
FollowedViewId: <Number>
IsFollowUser: <Boolean>
IsFollowEditor: <Boolean>
```

</td><td style="height: 144.062px; border-width: 1px;">跟隨狀態變更。

- `<span class="pre">FollowedViewId</span>` 哪個編輯者被跟隨。
- `<span class="pre">IsFollowUser</span>`是否啟用跟隨編輯者。
- `<span class="pre">IsFollowEditor</span>` 是否啟用跟隨編輯器。
- 如果 `<span class="pre">IsFollowUser</span>` 和 `<span class="pre">IsFollowEditor</span>` 都是 false，表示取消跟隨功能。

</td></tr><tr class="row-odd" style="height: 54px;"><td style="height: 54px; border-width: 1px;"><span style="color: rgb(186, 55, 42);">`<span class="pre">Action_ChangeUIMode_Resp</span>`</span>

</td><td style="height: 54px; border-width: 1px;">```
Mode: <string>
```

</td><td style="height: 54px; border-width: 1px;">變更使用介面。

`<span class="pre">Mode</span>` 使用哪種介面。

</td></tr></tbody></table>

</div></section></section><section id="bkmrk-version-restore-wopi">### **文件版本復原**

<section id="bkmrk-wopi-host-to-editor-">##### WOPI 主機 🡆 編輯器

<div class="wy-table-responsive"><table border="1" style="border-collapse: collapse; width: 100%; border-style: solid;"><colgroup><col style="width: 23.6094%;"></col><col style="width: 26.4559%;"></col><col style="width: 49.9347%;"></col></colgroup><thead><tr class="row-odd"><th class="head">MessageId

</th><th class="head">Values

</th><th class="head">**說明**

</th></tr></thead><tbody><tr class="row-even"><td><span style="color: rgb(186, 55, 42);">`<span class="pre">Host_VersionRestore</span>`</span>

</td><td>```
Status: <string>
```

</td><td>復原版本。唯一可能的值是 Pre\_Restore

此訊息由主機在實際復原文件<span style="color: rgb(186, 55, 42);">之前</span>以及使用者確定復原<span style="color: rgb(186, 55, 42);">之後</span>傳送。

這樣，如果目前文件，還有未儲存的修改，OxOffice Online 可以在恢復文件之前將它們儲存到雲端硬碟中。

</td></tr></tbody></table>

</div></section><section id="bkmrk-editor-to-wopi-host-">##### 編輯器 🡆 WOPI 主機

<div class="wy-table-responsive"><table border="1" style="border-collapse: collapse; width: 100%; border-style: solid;"><colgroup><col style="width: 23.8566%;"></col><col style="width: 26.3143%;"></col><col style="width: 49.8291%;"></col></colgroup><thead><tr class="row-odd"><th class="head">MessageId

</th><th class="head">Values

</th><th class="head">說明

</th></tr></thead><tbody><tr class="row-even"><td><span style="color: rgb(186, 55, 42);">`<span class="pre">App_VersionRestore</span>`</span>

</td><td>```
Status: <string>
```

</td><td>這是對 <span style="color: rgb(186, 55, 42);">`Host_VersionRestore`</span> 訊息的回應。

目前 `<span class="pre">Status</span>` 的值為 `<span class="pre">Pre_Restore_Ack</span>`

表示 WOPI 主機可以繼續將文件回復到較早的版本。

</td></tr></tbody></table>

</div><p class="callout success">只有當 `<span style="color: rgb(186, 55, 42);">App_LoadingStatus</span>` 包含功能中的 **VersionStates** 時，才會發出這些訊息。 否則，主機可以立即將版本還原到早期版本。</p>

</section></section><section id="bkmrk-miscellaneous-wopi-h">### **其他**

<section id="bkmrk-wopi-host-to-editor--0">##### WOPI 主機 🡆 編輯器

<div class="wy-table-responsive"><table border="1" style="border-collapse: collapse; width: 100%; border-width: 1px; border-style: solid;"><colgroup><col style="width: 24.9691%;"></col><col style="width: 25.3399%;"></col><col style="width: 49.691%;"></col></colgroup><thead><tr class="row-odd" style="height: 35.3906px;"><th class="head" style="height: 35.3906px; border-width: 1px;">MessageId

</th><th class="head" style="height: 35.3906px; border-width: 1px;">Values

</th><th class="head" style="height: 35.3906px; border-width: 1px;">說明

</th></tr></thead><tbody><tr class="row-even" style="height: 430.828px;"><td style="height: 430.828px; border-width: 1px;"><span style="color: rgb(186, 55, 42);">`<span class="pre">Insert_Button</span>`</span>

</td><td style="height: 430.828px; border-width: 1px;">```json
id: <string>
imgurl: <string>
hint: <string>
accessKey: <string>
mobile: <boolean>
tablet: <boolean>
insertBefore: <string>
unoCommand: <string>
```

</td><td style="height: 430.828px; border-width: 1px;">在頂端工具列插入自訂按鈕（僅顯示在傳統介面）。該按鈕被點擊時，若未指定 `unoCommand` 屬性，會觸發 <span style="color: rgb(186, 55, 42);">`<span class="pre">Clicked_Button</span>`</span> 的事件給 WOPI 主機，讓 WOPI 主機做相應處理。

- `<span class="pre">id</span>` 代表該按鈕的不可重複 ID。為了避免和原先工具列的其他按鈕 ID 衝突，建議在此類 ID 前，加上主機特有的名稱。  
    如果和其他按鈕衝突，則不會新增按鈕。
- `<span class="pre">imgurl</span>` 按鈕圖示位址。建議的大小為 24x24 px。圖片位址應和 WOPI 主機為同一來源，易免違反 `<span class="pre">Content-Security-Policy</span>`。
- `<span class="pre">hint</span>` 按鈕的提示。
- `accessKey` 快捷鍵。使用者可以搭配 Alt 或 Alt+Shift 加上此鍵。注意不要和其他快捷鍵衝突。
- `<span class="pre">mobile</span>` 手機模式時，是否顯示該按鈕。
- `<span class="pre">tablet</span>` 平板模式時，是否顯示該按鈕。
- `<span class="pre">insertBefore</span>` 新增在哪個 按鈕 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)
- `<span class="pre">unoCommand</span>` UNO 命令（[請參閱此處](https://wiki.documentfoundation.org/Development/DispatchCommands)）。 設置這個屬性，就不會傳送 `Clicked_Button` 訊息給 WOPI 主機，而會交由 LibreOffice 直接執行此命令。

</td></tr><tr class="row-odd" style="height: 61.3906px;"><td style="height: 61.3906px; border-width: 1px;"><span style="color: rgb(186, 55, 42);">`<span class="pre">Hide_Button</span>`</span>

</td><td style="height: 61.3906px; border-width: 1px;">```
id: <string>
```

</td><td style="height: 61.3906px; border-width: 1px;">隱藏工具列按鈕。`<span class="pre">id</span>` 為按鈕 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)）

</td></tr><tr class="row-even" style="height: 61.3906px;"><td style="height: 61.3906px; border-width: 1px;"><span style="color: rgb(186, 55, 42);">`<span class="pre">Show_Button</span>`</span>

</td><td style="height: 61.3906px; border-width: 1px;">```
id: <string>
```

</td><td style="height: 61.3906px; border-width: 1px;">顯示工具列按鈕。`<span class="pre">id</span>` 為按鈕 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)）

</td></tr><tr class="row-odd" style="height: 61.3906px;"><td style="height: 61.3906px; border-width: 1px;"><span style="color: rgb(186, 55, 42);">`<span class="pre">Remove_Button</span>`</span>

</td><td style="height: 61.3906px; border-width: 1px;">```
id: <string>
```

</td><td style="height: 61.3906px; border-width: 1px;">移除工具列按鈕。`<span class="pre">id</span>` 為按鈕 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)）

</td></tr><tr class="row-even" style="height: 61.3906px;"><td style="height: 61.3906px; border-width: 1px;"><span style="color: rgb(186, 55, 42);">`<span class="pre">Remove_Statusbar_Element</span>`</span>

</td><td style="height: 61.3906px; border-width: 1px;">```
id: <string>
```

</td><td style="height: 61.3906px; border-width: 1px;">移除狀態列元件。 `<span class="pre">id</span>` 是狀態列元件 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)）

</td></tr><tr class="row-odd" style="height: 35.3906px;"><td style="height: 35.3906px; border-width: 1px;"><span style="color: rgb(186, 55, 42);">`<span class="pre">Hide_Menubar</span>`</span>

</td><td style="height: 35.3906px; border-width: 1px;">  
</td><td style="height: 35.3906px; border-width: 1px;">隱藏下拉選單列。

</td></tr><tr class="row-even" style="height: 35.3906px;"><td style="height: 35.3906px; border-width: 1px;"><span style="color: rgb(186, 55, 42);">`<span class="pre">Show_Menubar</span>`</span>

</td><td style="height: 35.3906px; border-width: 1px;">  
</td><td style="height: 35.3906px; border-width: 1px;">顯示下拉選單列。

</td></tr><tr class="row-odd" style="height: 108.938px;"><td style="height: 108.938px; border-width: 1px;"><span style="color: rgb(186, 55, 42);">`<span class="pre">Grab_Focus</span>`</span>

</td><td style="height: 108.938px; border-width: 1px;">  
</td><td style="height: 108.938px; border-width: 1px;">喚醒休眠中的編輯器。通常編輯者在一段時間後沒有任何動作時，編輯器會進入休眠狀態（編輯介面變暗，並有訊息顯示），必要時，會中斷與伺服器連線。<span style="color: rgb(186, 55, 42);">`<span class="pre">Grab_Focus</span>`</span> 會重新喚醒編輯器，必要時重新連線伺服器。

</td></tr><tr class="row-even" style="height: 35.3906px;"><td style="height: 35.3906px; border-width: 1px;"><span style="color: rgb(186, 55, 42);">`<span class="pre">Hide_Ruler</span>`</span>

</td><td style="height: 35.3906px; border-width: 1px;">  
</td><td style="height: 35.3906px; border-width: 1px;">隱藏水平尺規（僅適用文字文件 Writer）。

</td></tr><tr class="row-odd" style="height: 35.3906px;"><td style="height: 35.3906px; border-width: 1px;"><span style="color: rgb(186, 55, 42);">`<span class="pre">Show_Ruler</span>`</span>

</td><td style="height: 35.3906px; border-width: 1px;">  
</td><td style="height: 35.3906px; border-width: 1px;">隱藏水平尺規（僅適用文字文件 Writer）。

</td></tr><tr class="row-even" style="height: 148.391px;"><td style="height: 148.391px; border-width: 1px;"><span style="color: rgb(186, 55, 42);">`<span class="pre">Hide_Menu_Item</span>`</span>

</td><td style="height: 148.391px; border-width: 1px;">```
id: <string>
```

</td><td style="height: 148.391px; border-width: 1px;">隱藏下拉選單中的選項。`<span class="pre">id</span>` 是指選項 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)

</td></tr><tr class="row-odd" style="height: 61.3906px;"><td style="height: 61.3906px; border-width: 1px;"><span style="color: rgb(186, 55, 42);">`<span class="pre">Show_Menu_Item</span>`</span>

</td><td style="height: 61.3906px; border-width: 1px;">```
id: <string>
```

</td><td style="height: 61.3906px; border-width: 1px;">顯示下拉選單中的選項。`<span class="pre">id</span>` 是指選項 ID。請參閱前項 <span style="color: rgb(186, 55, 42);">`<span class="pre">Hide_Menu_Item</span>`</span>

</td></tr><tr class="row-even" style="height: 585.641px;"><td style="height: 585.641px; border-width: 1px;"><span style="color: rgb(186, 55, 42);">`<span class="pre">Disable_Default_UIAction</span>`</span>

</td><td style="height: 585.641px; border-width: 1px;">```
action: <string>
disable: <Boolean>
```

</td><td style="height: 585.641px; border-width: 1px;">停用或啟用某個 UI 命令的預設行為。

- `<span class="pre">action</span>` 動作名稱。
- `<span class="pre">disable</span>` 表示停用 (**true**) 或啟用 (**false**) 預設行為。

設為 true 時，指定的動作只會發出 `<span class="pre">postMessage</span>` 而不會執行預設行為。這讓 WOPI 主機可以根據 `<span class="pre">postMessage</span>` 事件，進行必要處理。

請注意，某些動作沒有任何預設行為（如 `UI_SaveAs` 和 `UI_Share`），因此，這對它們沒有影響；但無論如何，他們只會發出 `<span class="pre">postMessage</span>` 通知，而不會採取預設行為

舉例來說，`UI_Save` 預設會呼叫儲存命令（透過選單、工具列按鈕或鍵盤快捷鍵）。如果透過 `Disable_Default_UIAction` 停用 `UI_Save`，則不會呼叫儲存命令。 停用 `UI_Save` 的 WOPI 主機，應該在文件需要儲存時，自行發出<span style="color: rgb(186, 55, 42);"> `Action_Save`</span>。

同樣地，當停用 `UI_Close` 時，呼叫 `UI_Close`，並不會真的文件關閉，而是會發出 postMessage 通知，並且由 WOPI 主機在需要時發出 <span style="color: rgb(186, 55, 42);">`Action_Close`</span>。

WOPI 主機必須很小心，不要在啟用預設行為的狀態下，發出重複的`Action_xxyyzz` 等指令。相反地，只能在停用預設行為時，才能自行發出操作。 注意：目前也只有 `UI_Save` 和 `UI_Close` 以及 `UI_Hyperlink` 能停用🤣

</td></tr><tr class="row-odd" style="height: 76px;"><td style="height: 76px; border-width: 1px;"><span style="color: rgb(186, 55, 42);">`<span class="pre">Send_UNO_Command</span>`</span>

</td><td style="height: 76px; border-width: 1px;">```json
Command: <string>
Args: <object>
```

</td><td style="height: 76px; border-width: 1px;">向編輯器傳送 UNO 命令。請參考：[framed.doc.html](https://github.com/OSSII/oxool-community/blob/v4/loleaflet/html/framed.doc.html)

</td></tr></tbody></table>

</div></section><section id="bkmrk-finding-toolbar-butt-0">### **查詢工具列按鈕 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 會穩定存在。

</section><section id="bkmrk-finding-status-bar-e-0">### **查詢狀態列元件 ID**

狀態列元件 ID 定義在 [Control.StatusBar.js](https://github.com/OSSII/oxool-community/blob/v4/loleaflet/src/control/Control.StatusBar.js) 的 `<span class="pre">onDocLayerInit</span>` 函數中。通常不會改變，但並不保證這些 ID 會穩定存在。

### **事件通知**

</section><section id="bkmrk-editor-to-wopi-host--0">##### 編輯器 🡆 WOPI 主機

<div class="wy-table-responsive"><table border="1" style="border-collapse: collapse; border-style: solid; width: 100%; height: 817.672px;"><colgroup><col style="width: 21.2608%;"></col><col style="width: 30.4064%;"></col><col style="width: 48.3328%;"></col></colgroup><thead><tr class="row-odd" style="height: 35.3906px;"><th class="head" style="height: 35.3906px;">MessageId

</th><th class="head" style="height: 35.3906px;">Values

</th><th class="head" style="height: 35.3906px;">說明

</th></tr></thead><tbody><tr class="row-even" style="height: 53.1719px;"><td style="height: 53.1719px;"><span style="color: rgb(186, 55, 42);">`<span class="pre">Clicked_Button</span>`</span>

</td><td style="height: 53.1719px;">```
id: <string>
```

</td><td style="height: 53.1719px;">點擊透過前面的 <span style="color: rgb(186, 55, 42);">`Insert_Button`</span> API 新增的自訂按鈕時會發出此事件。

</td></tr><tr class="row-odd" style="height: 147.344px;"><td style="height: 147.344px;"><span style="color: rgb(186, 55, 42);">`<span class="pre">Download_As</span>`</span>

</td><td style="height: 147.344px;">```
Type: 'print'|'slideshow'|'export'
URL: <string>
```

</td><td style="height: 147.344px;">當使用者選擇「列印」或「全螢幕投影」或「下載為…」，且 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-) 的`<span class="pre">DownloadAsPostMessage</span>` 屬性中，指定要接管時，就會觸發此事件。

這應用於無法依賴瀏覽器下載的情況，例如手機的 Web view 模式。

</td></tr><tr><td><span style="color: rgb(0, 0, 0);"><span class="pre"><span style="color: rgb(186, 55, 42);">`UI_Close`</span></span></span>

</td><td>```json
EverModified: true | false
```

</td><td>當使用者選擇關閉文件，或點擊關閉按鈕，將觸發此事件。`EverModified` 指出此文件是否修改過。

</td></tr><tr><td><span style="color: rgb(186, 55, 42);">`<span class="pre">UI_Save</span>`</span>

</td><td>```json
source: 'filemenu' | 'notebookbar' | 'toolbar'
```

</td><td>使用者選擇儲存。`source` 指出透過何種方式儲存。

</td></tr><tr class="row-even" style="height: 102.562px;"><td style="height: 102.562px;"><span style="color: rgb(186, 55, 42);">`<span class="pre">UI_CreateFile</span>`</span>

</td><td style="height: 102.562px;">```json
DocumentType: 'text' | 'spreadsheet' | 'presentation' | 'drawing'
```

</td><td style="height: 102.562px;">要求 WOPI 主機開啟新的瀏覽器分頁，並建立新文件。 文件類型以 DocumentType 參數傳遞，可以是「text（文字文件）」、「spreadsheet（試算表）」、「presentation（簡報）」或「drawing（繪圖）」。

</td></tr><tr class="row-odd" style="height: 80.1719px;"><td style="height: 80.1719px;"><span style="color: rgb(186, 55, 42);">`<span class="pre">UI_SaveAs</span>`</span>

</td><td style="height: 80.1719px;">  
</td><td style="height: 80.1719px;">要求 WOPI 主機顯示另存新檔 UI，以便使用者可以選擇路徑和檔案名稱來建立目前檔案的副本。 若使用者確定存檔，則 WOPI 主機需以 <span style="color: rgb(186, 55, 42);">`Action_SaveAs`</span> 命令編輯器發送檔案內容。

</td></tr><tr class="row-even" style="height: 57.7812px;"><td style="height: 57.7812px;"><span style="color: rgb(186, 55, 42);">`<span class="pre">UI_Cancel_Password</span>`</span>

</td><td style="height: 57.7812px;">  
</td><td style="height: 57.7812px;">通知 WOPI 主機使用者在開啟有密碼保護的檔案時，點擊了「取消」，而不是輸入密碼。

</td></tr><tr class="row-odd" style="height: 171.516px;"><td style="height: 171.516px;"><span style="color: rgb(186, 55, 42);">`<span class="pre">UI_Hyperlink</span>`</span>

</td><td style="height: 171.516px;">  
</td><td style="height: 171.516px;">通知 WOPI 主機只用者點擊了超連結，並確認確實想要離開文件以開啟超連結。這對於將 OxOffice Online 嵌入到行動裝置 iframe 中的 App 特別有用，實際嘗試開啟新視窗，應觸發在 Android 上的 Activity（或在 iOS 上類似的操作）。

WOPI 主機可能也想利用 <span style="color: rgb(186, 55, 42);">`<span class="pre">Disable_Default_UIAction</span>`</span> 來接管 <span style="color: rgb(186, 55, 42);">`UI_Hyperlink`</span>

</td></tr><tr class="row-even" style="height: 169.734px;"><td style="height: 169.734px;"><span style="color: rgb(186, 55, 42);">`<span class="pre">Doc_ModifiedStatus</span>`</span>

</td><td style="height: 169.734px;">```json
Modified: true | false
```

</td><td style="height: 169.734px;">更新文件的修改狀態。如果文件自上次儲存後被修改，則 `Modified `將為 **true**，否則，如果文件已儲存，則 `Modified `為 **false**。

請注意，這個通知可能會在不更改先前值的情況下觸發，因此必須檢查 `Modified `的值，不要假設這個通知暗示文件的修改狀態。

</td></tr></tbody></table>

</div></section></section><section id="bkmrk-calling-python-scrip-0"><span id="bkmrk--0"></span>### **呼叫 Python 巨集**

<section id="bkmrk-wopi-host-to-editor--1">##### WOPI 主機 🡆 編輯器

<div class="wy-table-responsive"><table border="1" style="border-collapse: collapse; width: 100%; border-width: 1px; border-style: solid;"><colgroup><col style="width: 20.2719%;"></col><col style="width: 31.0212%;"></col><col style="width: 48.5832%;"></col></colgroup><thead><tr class="row-odd" style="height: 35.3906px;"><th class="head" style="height: 35.3906px; border-width: 1px;">MessageId

</th><th class="head" style="height: 35.3906px; border-width: 1px;">Values

</th><th class="head" style="height: 35.3906px; border-width: 1px;">說明

</th></tr></thead><tbody><tr class="row-even" style="height: 87.219px;"><td style="height: 87.219px; border-width: 1px;"><span style="color: rgb(186, 55, 42);">`<span class="pre">CallPythonScript</span>`</span>

</td><td style="height: 87.219px; border-width: 1px;">```
ScriptFile: <string>
Function: <string>
Values: <object>
```

</td><td style="height: 87.219px; border-width: 1px;">執行指定功能的 Python 巨集：

- ScriptFile：巨集檔名
- Function：函數名稱
- Values：參數內容（key: value, ...）

</td></tr></tbody></table>

</div></section><section id="bkmrk-editor-to-wopi-host%EF%83%81-1">##### 編輯器 🡆 WOPI 主機

<div class="wy-table-responsive"><table border="1" style="border-collapse: collapse; width: 100%; border-style: solid;"><colgroup><col style="width: 27.9357%;"></col><col style="width: 23.739%;"></col><col style="width: 48.3253%;"></col></colgroup><thead><tr class="row-odd"><th class="head">MessageId

</th><th class="head">Values

</th><th class="head">說明

</th></tr></thead><tbody><tr class="row-even"><td><span style="color: rgb(186, 55, 42);">`<span class="pre">CallPythonScript-Result</span>`</span>

</td><td>```
commandName: <string>
Values: <object>
```

</td><td>傳回 Python 執行結果。`commandName `放的是巨集的 URL。</td></tr></tbody></table>

</div></section></section></section>