清單5顯示了自動完成組件所使用的JavaScript:
清單5.JavaScript
- if (!com)
- var com = {}
- if (!com.coreJSf) {
- var focusLostTimeout
- com.coreJSf = {
- errorHandler : function(data) {
- alert("Error occurred during AJax call: " + data.description)
- },
- updateCompletionItems : function(input, event) {
- var keystrokeTimeout
- JSf.AJax.addOnError(com.coreJSf.errorHandler)
- var AJaxRequest = function() {
- JSf.AJax.request(input, event, {
- render: com.coreJSf.getListboxId(input),
- x: Element.cumulativeOffset(input)[0],
- y: Element.cumulativeOffset(input)[1]
- + Element.getHeight(input)
- })
- }
- window.clearTimeout(keystrokeTimeout)
- keystrokeTimeout = window.setTimeout(AJaxRequest, 350)
- },
- inputLostFocus : function(input) {
- var hideListbox = function() {
- Element.hide(com.coreJSf.getListboxId(input))
- }
- focusLostTimeout = window.setTimeout(hideListbox, 200)
- },
- getListboxId : function(input) {
- var clIEntId = new String(input.name)
- var lastIndex = clIEntId.lastIndexOf(':')
- return clIEntId.substring(0, lastIndex) + ':listbox'
- }
- }
- }
清單5中的Javascript包括三個函數,我把它們放置在com.coreJSf名稱空間的內部。我實現了名稱空間(從技術上說是一個JavaScript字面對象),以防止其他人有意或無意修改我的三個函數。
如果這些函數未包含在com.coreJSf中,則其他人可以實現自己的updateCompletionItems函數,從而將我的實現替換成它們。一些JavaScript庫可以實現一個updateCompletionItems函數,但最理想的情況是任何人都不用設計com.corejsf.updateCompletionItems。(相反,拋棄com,並使用coreJSf.updateCompletionItems可能已經足夠,但有時會難以控制。)
因此,這些函數做了些什麼?updateCompletionItems()函數向服務器發起Ajax請求—通過調用JSF的jsf.ajax.request()函數—要求JSF僅在Ajax調用返回時呈現列表框組件。updateCompletionItems()函數還傳遞了兩個額外的參數到jsf.ajax.request()中:列表框左上角的x和y坐標。JSf.ajax.request()函數會將這些函數參數轉換為通過AJax調用發送的請求參數。
JSF會在文本輸入失焦時調用inputLostFocus()函數。該函數的作用是使用Prototype的Element對象來隱藏列表框。
updateCompletionItems()和inputLostFocus()將它們的功能存儲在一個函數中。然後,它們安排自己的函數分別在350ms和200ms時執行。換句話說,每個函數都有各自的任務,但它會讓任務延時350ms或200ms。文本輸入會在keyup事件後延時,因此,updateCompletionItems()方法會最多每隔350ms發送一個Ajax請求。其思想是,如果用戶輸入速度極快,則不會讓AJax調用淹沒服務器。
inputLostFocus函數會在文本輸入失焦時調用,並延時其任務200ms。這種延時是必要的,因為該值會在AJax調用返回時復制到列表框之外,並且列表框必須為可見才能確保它正常運行。
最後,請注意getListBoxId()函數。這個幫助器函數會從文本輸入的客戶機標識符中獲取列表框的客戶機標識符。該函數可以完成此任務,因為它將與清單4中的autoComplete組件相結合。autoComplete組件將input和listbox分別指定為文本框和列表框的組件標識符,因此getListBoxId()函數會刪除input並附加listbox,以便獲取文本輸入的客戶機標識符。