Jump to content
切換選單
切換偏好設定選單
切換個人選單
尚未登入
如果您進行編輯,系統將會為您建立一個臨時帳戶。

BenWiki UI JavaScript 是本站 application-level 前端互動元件的架構文件。

這一層負責在 MediaWiki、Page Forms、OOUI 與 Citizen 提供的基礎能力之上,補充 BenWiki 自己需要的通用互動。

架構原則

JavaScript 功能依 component 分離。

主入口不實作具體功能,只偵測目前頁面實際存在的 component,再透過 ResourceLoader 按需載入。

MediaWiki:Gadget-benwiki-ui.js
        │
        ├─ ImagePicker
        │      ↓
        │  ImageLibrary
        │
        ├─ Disclosure
        │
        ├─ OrderedMultiple
        │
        └─ InfoboxCollection
             (後續加入)

Bootstrap

入口:

對應 Gadget:

ext.gadget.benwiki-ui

這是 BenWiki UI JavaScript 中唯一預設載入的 bootstrap。

它只負責:

  1. 偵測 DOM component。
  2. 透過 ResourceLoader 載入對應 Gadget module。

不應直接包含:

  • Page Forms persistence 邏輯
  • OOUI Dialog
  • MediaWiki API query
  • multiple-instance 排序
  • Infobox interaction
  • 各 component 的 presentation 邏輯

ImagePicker

來源:

DOM contract:

.benwiki-ui-image-picker
.benwiki-ui-image-picker__raw
.benwiki-ui-image-picker__enhancement

負責:

  • 選用既有圖片
  • 上傳新圖片
  • 移除圖片
  • Page Forms image field synchronization
  • Page Forms preview refresh

Page Forms 仍然是實際 persistence 與 upload engine。

ImageLibrary

來源:

負責:

  • 查詢 Wiki 現有圖片
  • 圖片搜尋
  • 分頁載入
  • OOUI 圖片選擇 Dialog

提供:

mw.libs.benwikiImageLibrary.open()

給 ImagePicker 使用。

ImageLibrary 不負責 Page Forms persistence。

Disclosure

來源:

用於表單 optional section 的 progressive disclosure。

DOM contract:

.benwiki-ui-disclosure
.benwiki-ui-disclosure__header
.benwiki-ui-disclosure__heading
.benwiki-ui-disclosure__description
.benwiki-ui-disclosure__action
.benwiki-ui-disclosure__content

原則:

  • JavaScript 不存在時,內容仍然可見。
  • JavaScript 成功初始化後才啟用收合。
  • 有既存值時自動展開。
  • 無值時可以預設收合。

OrderedMultiple

來源:

用來同步 Page Forms multiple-template instance 的排列順序。

DOM contract:

.benwiki-ui-ordered-multiple
input.benwiki-ui-order-input

預設排序值:

100
200
300
...

在 instance 新增、刪除、重新排序與表單送出時重新同步。

InfoboxCollection

來源:

用於 Infobox repeatable collection 的 progressive disclosure。

JavaScript 不知道 SMW subobject。

是否可以收合、預設狀態與自動收合 threshold 都由 Infobox presentation schema 提供。

目前 DOM contract:

.benwiki-infobox-collection-heading
.benwiki-infobox-collection-heading__label
.benwiki-infobox-collection-heading__summary
.benwiki-infobox-collection-heading__action
.benwiki-infobox-collection-content

例如:

interaction = {
    collapsible = true,
    default = 'auto',
    collapseThreshold = 5,
    countLabel = ' 個帳號'
}

auto 模式會依 collection 實際 item 數量決定初始展開狀態。

沒有 JavaScript 時 collection 保持完整顯示,不會因互動元件失效而造成資料不可閱讀。

SMW Deferred collection 不應在初始 placeholder 階段計算資料筆數。

ext.smw.deferred 完成結果替換後會觸發:

mw.hook( 'smw.deferred.query' )

InfoboxCollection 使用此 lifecycle hook 重新同步實際 item 數量。

若 Gadget 載入時 deferred query 已經完成,則會直接檢查目前 DOM 並同步,不依賴事件先後順序。

ResourceLoader

Gadget registration 位於:

Bootstrap:

hidden
default

各 component:

hidden
非 default

由 bootstrap 依目前頁面的 DOM 實際需要載入。

MutationObserver 原則

不要建立一個全站大型 MutationObserver。

只有確實需要處理動態 DOM 的 component 才建立 observer,而且監控範圍應盡量局部。

目前:

ImagePicker
只需要處理表單內可能動態產生的圖片欄位。
Disclosure
server-rendered section 初始化一次即可,不需要長期 observer。
OrderedMultiple
只監控 Page Forms multiple-instance 相關 root。
InfoboxCollection
不使用 MutationObserver。
一般 server-rendered collection 可直接初始化。
若 collection 內容來自 Semantic MediaWiki Deferred,則透過 SMW 官方的 smw.deferred.query hook,在 deferred query 完成後同步 collection item 數量與初始收合狀態。

Progressive enhancement

BenWiki UI JavaScript 應遵守:

沒有 JavaScript
→ 核心資料仍可閱讀或編輯

JavaScript 成功
→ 提供額外便利互動

JavaScript failure 不應造成核心資料消失或無法操作。

新增 Component

新增前端 component 時:

  1. 建立獨立 Gadget JavaScript page。
  2. 在 MediaWiki:Gadgets-definition 註冊 hidden ResourceLoader module。
  3. 定義穩定的 DOM contract。
  4. 在 bootstrap registry 註冊 selector 與 module。
  5. 僅加入真正需要的 ResourceLoader dependency。
  6. 更新本頁架構文件。

不要把新功能重新塞回 bootstrap。

Rights

來源:

用於依 MediaWiki effective right 控制 BenWiki UI 入口的可見性。

DOM contract:

.benwiki-ui-requires-right
data-benwiki-right="createpage"

例如:

<div
    class="benwiki-ui-requires-right"
    data-benwiki-right="createpage"
    style="display:none"
>
...
</div>

元素在 server-rendered wikitext 中必須預設隱藏。

由於 MediaWiki wikitext sanitizer 不保留 hidden attribute, 此 component 使用 style="display:none" 作為安全的預設隱藏狀態。

JavaScript 取得目前使用者的 effective rights; 只有具備 data-benwiki-right 指定權限時, 才移除 display:none。

這只控制 UI 可見性,不作為授權機制。 實際操作權限仍由 MediaWiki server-side permission enforcement 負責。