ZK-1220 (又)是一個抓蟲三刻鐘,除蟲三秒鐘的 issue。
故事是這樣的,在 ZK 6.0 之後 InputElement
/InputWidget
(Java/JS)增加了 instant
這個 attribute。
當 instant="true"
的時候,所有的改變會馬上送到 server 端。
如果 end-user 在有設定 instant
的 Textbox
輸入之後馬上(更精準地說是 350ms 內)改變游標位置,
則游標還是會回到最尾端。
以我在 Window 7(64bit)上測試的結果,Chrome 23.x、Safari 5.1.7 會炸這個問題; Firefox 16 跟 Opera(忘記那一版,後來就更新了 XD)不會; 至於 IE 9 就真的神奇了,在 zksandbox 上測試會,獨立開 webapp 跑 ZUL 不會...... Orz。
在 source code 裡頭砍殺的路徑大概是
InputWidget.doKeyUp_():直接找 _instant 的結果 XD
_startOnChanging()
在這裡發現把曲折離奇的這行拿掉、或是把 timeout 值設的很小,游標就不會亂跳了。
wgt._tidChg = setTimeout(
wgt.proxy(_onChanging), zul.inp.InputWidget.onChangingDelay);
這裡稍微解釋一下為什麼要這麼曲折離奇(至於那個 widget.proxy
的功能就自己去看 API [逃])。
雖然說是 instant,不過真的要搞到一輸入就馬上辦,
隨便幾個人一直按著按鍵不放就自動形成 DOS 了。
所以在 _startOnChange()
一開始就先呼叫 _stopOnChanging()
清掉之前設定的 setTimeout()
,
然後再重新註冊一次 setTimeout()
--
也就是嚴格來說是 keyin 告一段落才送資料給 server。
回到 bug 上,第一直覺是有那一行程式重新 assign 一次 value 值, 然後首先懷疑是 server side 重新 assign。 結果就鬧了一個笑話:
奇怪,我設了
instant="true"
為什麼Tabbox.service()
始終沒呼叫到?
廢話...... 你又沒註冊 onChange
,資料幹麼送回 server 端?
至於那個 onChanging
不管怎麼看都跟 instant="true"
+ onChange="foo()"
意思相同?
那麼還有其他 event 可以搭配 instant
嗎?
如果沒有那 client 端的 code 應該直接把兩個綁在一起判斷以增加效率?
扯遠了,上面這段跟 bug 無關 XD
因為沒掛 onChange
也依然會炸,所以兇手一定就在 client side 的程式碼當中。
接著因為腦殘懷疑到 validate 上、又眼殘的關係又繞了一大圈,
才發現是 _onChange()
裡頭呼叫的 InputWidget.updateChange_()
的這行出問題:
inp.value = value = this.coerceToString_(vi.value);
inp
到底是啥不重要,反正就是輸入框 XD。
之前不知道為什麼完全忽略掉他,只注意到後頭的 coerceToString_()
,
我只能說這種一路「等」到天涯海角的寫法真是令人想要直接跳過去 [炸]。
至於
coerceToString_()的功用是要把輸入的值改成預期的格式,
這在
FormatInputElement/
FormatWidget(Java/JS) 的 subclass 會用到;
但是為什麼卡在這裡作而不是放到
FormatWidget` 裡頭去呢? [孟獲孟獲孟獲]
好的,解法就是先檢查 inp.value
是不是等於 coerceToString_()
後的 value,
如果不是的話再 assing 進去。
至於像 Datebox
、Timebox
還是有指定 format 的 Intbox
就無法避免這個問題
,畢竟他們本來就試著要改變輸入框的值--當然,在這種有 format 的 input widget 上用 instant
也絕對不是啥好想法、太不 user friendly 了。
報告完畢。
No comments:
Post a Comment