JSF 2 內建 `jsf.ajax` 引擎處理底層 XmlHttpRequest、響應解析、局部更新。組件所需 JS 僅負責:**事件綁定、防抖節流、計算列表框位置、構造 Ajax 參數、失焦隱藏**。本文逐行解析 `autoComplete.js` 核心邏輯。
if (!com) var com = {};
if (!com.corejsf) {
var focusLostTimeout;
com.corejsf = {
// 統一錯誤處理
errorHandler: function(data) {
alert("Ajax error: " + data.description);
},
// 輸入框 keyup -> 觸發 Ajax 過濾
updateCompletionItems: function(input, event) {
var keystrokeTimeout;
// 註冊全局 Ajax 錯誤處理器 (僅首次生效)
jsf.ajax.addOnError(com.corejsf.errorHandler);
// 實際發送 Ajax 的函數
var ajaxRequest = function() {
jsf.ajax.request(input, event, {
render: com.corejsf.getListboxId(input), // 僅渲染列表框
x: Element.cumulativeOffset(input)[0], // 輸入框頁面左上角 X
y: Element.cumulativeOffset(input)[1] // 輸入框頁面左上角 Y
+ Element.getHeight(input) // + 高度 = 列表框顯示位置
});
};
// 防抖:350ms 內連續輸入只發最後一次
window.clearTimeout(keystrokeTimeout);
keystrokeTimeout = window.setTimeout(ajaxRequest, 350);
},
// 輸入框失焦 -> 延遲隱藏列表框
inputLostFocus: function(input) {
var hideListbox = function() {
Element.hide(com.corejsf.getListboxId(input));
};
// 200ms 延遲:給「點擊列表項」事件留出時間窗口
focusLostTimeout = window.setTimeout(hideListbox, 200);
},
// 根據輸入框 clientId 推導列表框 clientId
getListboxId: function(input) {
var clientId = new String(input.name); // name = clientId (JSF 生成)
var lastIndex = clientId.lastIndexOf(':');
return clientId.substring(0, lastIndex) + ':listbox';
}
};
}
| 特性 | 說明 |
|---|---|
| `jsf.ajax.request(source, event, options)` | 核心入口。`options.render` 指定需局部更新的 clientId 列表 (空格分隔)。 |
| `jsf.ajax.addOnError(fn)` | 全局 Ajax 錯誤回調,參數 `data` 含 `description`、`responseText`、`status`。 |
| `jsf.ajax.addOnEvent(fn)` | 全局 Ajax 事件回調 (begin/complete/success),可用於 Loading 指示器。 |
| 執行階段 | 預設 `execute="@this"` (僅提交觸發組件),可覆蓋 `execute="@form"` 等。 |
| 渲染階段 | `render` 指定的 clientId 組件將重新渲染,替換 DOM 中對應節點。 |
| 參數傳遞 | `options` 中除 `execute`/`render`/`delay`/`event` 外的鍵值對,作為**請求參數**發送到服務端 (如 `x`, `y`)。 |
`autoComplete.js` 體現了 JSF 2 **「薄客戶端、厚服務端、標準化 Ajax」** 的設計哲學:JS 僅處理瀏覽器原生交互 (事件、座標、防抖),業務邏輯 (過濾、狀態) 完全在 Java 端監聽器實現。這種關注點分離極大降低了前端複雜度,同時保證了組件的可測試性、可維護性、安全性。下篇將解析 Java 端監聽器 `AutocompleteListener` 的完整實現。