2012-12-30

ZKPushState:用純 Java 處理 History API 的 ZK addon

簡介

HTML5 的規格中引入了新的 History API:

  • history 可以呼叫 pushState() 把一些資料(稱為 state)設定進目前的 session(單純的名詞,不是 HTTP 的那個 session), 並且可以更改目前的 URL(如果有給值的話)
  • history 有變動,browser 會發出一個 onpopstate event,在 window.onpopstate 可以接收到。

2012-11-18

ZK-1220 的故事

ZK-1220 (又)是一個抓蟲三刻鐘,除蟲三秒鐘的 issue。

故事是這樣的,在 ZK 6.0 之後 InputElement/InputWidget(Java/JS)增加了 instant 這個 attribute。 當 instant="true" 的時候,所有的改變會馬上送到 server 端。 如果 end-user 在有設定 instantTextbox 輸入之後馬上(更精準地說是 350ms 內)改變游標位置, 則游標還是會回到最尾端。

2012-11-14

ZK-1441 的故事

ZK-1441 的故事有點 critical,基本上他一定要「快速連續切換 tab」才會有效果,正常操作行為很難遇到這個狀況。

WTF......

終究是名副其實可以複製的 bug,也就只能硬著頭皮上。

Tab._sel()
    Tab._setSel()
        Tabpanel._sel()
            jqzk.slideDown(),在這裡 this.dimension() 會取到錯(較小)的值

基本上無力去探究 jqzk.dimension() 為什麼會取到不對的值,畢竟正常情況下運作是正確的。 只能猜測是因為 animation 的原因導致 jquery 錯亂?

中間試過 setTimeout() 來等 animation 完再換下一個 tab 操作,不過失效(細節略 XD)。 後來只能把腦筋動到弄一個 flag: Tabbox._animating,在呼叫 slideDown() 之前設定, 透過 slideDown() 的 callback function 來拿掉,然後進入 Tab._sel() 的時候用這個判斷是否要擋掉不做。

至於為什麼不用 zk.animating(),那是因為只要有其他 animation 在跑(例如檔案上傳的 Progressmeter), 就會判定不過而被卡掉。(反過來說,用 zk.animating() 來作某些事情的都有這個隱憂?)

套句死神裡頭的台詞(其實我沒看過):「其實我不想用這招的」, JS 對 field 作 CRUD 實在太方便了,一點控管辦法也沒有,只好多寫幾行註解結束這個 issue。

2012-10-31

ZK-1430 的故事

ZK-1430 真是一個曲折離奇的故事,分上下兩集來講好了 XD

上集:召喚 v/hflex="min",結束這個 issue

起手布局是一個 bandbox,然後 bandpopup 當中塞了一個 listbox。 希望這個 listbox 只顯示 5 個 row 的大小,所以設了 rows="5", 但是 bandpopup 不會跟 listbox 一樣大,自己長自己的大小。

算 bug 嗎?

2012-10-22

ZK-1411 的故事

有人說:我怎麼對 auxheader 設定 width 都沒有用? 這是 bug 吧?

一開始還真的以為是 auxheader 可以設定 width,只是剛好他人品爆發寫了奇怪的 code 踩到雷 (是說他提供的 code 實在... 唉...)。結果我 try 了一下,發現基本上 auxheader 真的完全不會管你 width 設了啥, 統統給你平均分配。

btw... 中間還耍了這樣一個白痴 code

<grid width="900px">
    <auxhead>
        <auxheader width="300px" label="aux 300px" />
        <auxheader width="500px" label="aux 500px" />
        <auxheader label="aux" />
    </auxhead>
</grid>
<!-- 喔喔喔喔... 難道只有第二個的 width 才會有問題嗎? [死] -->

不帶任何希望地爬了一下 ZK 文件(總比去 source code 慢慢 farm 來得好 [逃]), 結果在 component reference 找到這段:

The other limitation is that the width of the Auxheader component depend on the Column component. Thus, if you'd like to specify the width in the Column component, it means it will take some space even when there are no label in all Column components.

除非去質疑 spec,不然這個 issue 是不成立的。 但反過來說,為什麼不在 auxheader 試圖設定 width 的時候炸 exception 呢? 所以我改去發了 ZK-1422,至於後續如何發展,請待下回分解(慢慢等吧你 XD)。

這個 ZK-1411 的故事有點像是來騙文章數的 [毆飛]。

2012-10-16

ZK-1391 的故事

這是一個說難絕對不難,但是卻讓我這個低能苦手著實糾結了好一陣子的 issue

故事很簡單,就是在 Window 這個 component 在某些 mode 下可以用 lefttop 設定位置, 當然也可以設定 visible 來設定顯示與否。 怪事就這麼發生了(我覺得更怪的是:為什麼到現在才有人踩到 XD), 如果一開始 visible="false",另外只單純設定 lefttop 而沒有設定另外一個, 那麼在重新設定成 visible="true" 時,設定的 left / top 就會沒效果,直接跑到 (0, 0) 的位置。 但是假若 lefttop 都有設定,又能顯示正確結果。

第一直覺是 JS 那邊的 setVisible() 出了什麼紕漏,結果在 _updDomPos() 裡頭繞了很久,發現根本不是那麼一回事情。 毫無頭緒之下只能一步一步慢慢跑,看 jq("#"+uuid) 的 style 什麼時候被改掉。 結果是在 setVisible(true) 之後,bind_() 會去呼叫 _doOverlapped() (Vincent:早就跟你說了阿 [指]), 這裡頭原本的邏輯是:

if (!pos && (!n.style.top || !n.style.left)) {
    var xy = $n.revisedOffset();
    n.style.left = jq.px(xy[0]);
    n.style.top = jq.px(xy[1]);
}

也就是當 Window 沒有設定 pos 而且 topleft 有一個沒有設定, 就會去呼叫 revisedOffset() 來重新決定位置。 至於 revisedOffset() 怎麼運作的根本不重要--因為這傢伙根本還沒出現在 DOM 當中(不然幹麼呼叫 bind_()), 也就根本取不到值;這也可以說明了如果同時設定 topleft,那麼就不會進來這一段啦。 在不知道當初為什麼會寫 !pos && (!n.style.top || !n.style.left) 的前提下,也只好這樣改來避開了:

    if (!pos && (!n.style.top || !n.style.left)) {
        var xy = $n.revisedOffset();
        if (!n.style.left) {
            n.style.left = jq.px(xy[0]);
        }
        if (!n.style.top) {
            n.style.top = jq.px(xy[1]);
        }           
    }

唉... 好心的大爺們... 多寫點註解阿...... Orz

2012-10-03

ZK-1380 的故事

來寫一篇 ZK-1380 的報告。

故事開場還是來自一個 forum thread。 developer 發現他要 forward 到放在 zk 底下的 zul 就會炸 HTTP 404, 但是只要不是放在 zk 底下就沒問題,而且觸發條件還是得在 Tomcat 7.0.29 以後的版本。

結果我在 Tomcat 7.0.27(剛好手邊就是這個版本 XD)可以重現這個問題, 但是 Jetty 6.1.26 不會...... 雖然很怪不過還是去發 issue 了。

因為沒有稿費,所以直接快轉到跳結果:這是 Tomcat 7.0.29 以後改變 webapp 的啟動流程。 changelog 的原文是這樣寫得

As per section 1.6.2 of the Servlet 3.0 specification and clarification from the Servlet Expert Group, the servlet specification version declared in web.xml no longer controls if Tomcat scans for annotations. Annotation scanning is now always performed - regardless of the version declared in web.xml - unless metadata complete is set to true.

而 ZK 在 6.0(應該) 之後有用 web-fragment.xml 來註冊 /zkau/zk 的 servlet mapping, 以支援 servlet 2.5/3.0 的規格。 在 Tomcat 7.0.29 之後就一定會去讀 web-fragment.xml, 所以 /zk/* 就會被 DHtmlLayoutServlet 給處理掉。

所以如果 forum 的那個原 po 好死不死把 /zk 改成 /zkau 基本上也是一樣會炸 HTTP 404。 至於為什麼我在 Tomcat 7.0.27 也能重現這個問題呢? 因為我測試的 project 當中,已經把 web.xml 當中的 <web-app> 設定 version="3.0", 所以 Tomcat 也會去讀 web-fragment.xml ...... 囧>

報告完畢......

2012-09-14

Cardlayout:用 swipe 來切換 view

簡介

我們在 ZK 6.5 版提供了一個新的 component Cardlayout ,讓使用者可以像操作卡片一樣在 component 之間切換。 在 Tablet 上還支援用 swipe 動作來改變畫面。

2012-09-13

Dropupload:用 HTML5 打造新的上傳 component

簡介

在 ZK 6.1 EE 版中,我們設計了一個新的元件 Dropupload。這個元件使用 HTML5 的技術,讓使用者可以透過拖曳的方式指定要上傳的檔案,並保有原本檔案上傳的功能與操作習慣。另外,相較於傳統的 File Upload 方式,Dropupload 也可以省去 pooling server 以取得 progress 的 overhead,大幅降低 server 負荷。

Live Demo

(請到 ZK Blog 觀賞 XD)

新屬性:detection

因應 Drag and Drop 的行為,我們增加了 detection 這個屬性,讓你可以設定當使用者將檔案 drag 到哪裡的時候會顯示 Dropupload 以及提示資訊。detection 接受下列四種值: * none : 無視 DnD 的動作,永遠顯示 Dropupload 與提示資訊。 * browser (default) : 正常狀況下並不會顯示。當使用者將檔案拖曳進 browser 時就會顯示 Dropupload 以及提示資訊。 * self : 正常狀況下會顯示 Dropupload 但不會顯示提示資訊,當使用者將檔案拖曳進 Dropupload 元件的範圍時顯示提示資訊。 * 其他元件的 id : 與 self 相同,但觸發的範圍是指定 id 的元件。

轉換原有的 File Viewer

就跟傳統的 File Upload 一樣,在 Dropupload 可以設定 viewerClass 屬性來使用指定的 File Viewer。而過去寫好的客製化 File Viewer 也可以繼續沿用,只需要作一點小改變: * $init() 的第二個參數從原本的 filenm(String)改變成 file(File)物件。增加 var filenam = file.name 就解決了。此外還可以透過 file.size 取得檔案大小(Bytes)、file.type 取得檔案的 MIME 資訊。 * update() 的第一個參數 send,原本會傳入一個介於 0~100 的整數值,代表已經上傳的百分比;現在則是改為傳入已上傳的資料量(Bytes) 就這麼多了,是不是很簡單呢?

Browser 支援度?

是的,由於 Dropupload 使用 HTML5 的技術,所以有些 browser 無法支援的。目前在 Firefox (v.13)、Chrome (v.19)、Safari (v.5.1.x) 確定是可以正常運作,而在 IE9、Opera v.11.x 無法使用這個功能。

另外,在一些有點年紀的機器上,detection 的設定會無法顯示。

Reference

2012-09-01

ZK-1310 的故事

來寫一篇 ZK-1310 的檢討報告 (誰叫我亂發 issue)

起因是這一個 forum thread。 在這裡先 murmur 一下,ZK 截至目前為止是沒有 用 MVVM 寫一個 Tree 的官方範例; MVC 版是有,可是... 只能說那個建立 TreeModel 的 code 實在是太銷魂了, 而且在我修改之前的程式碼根本不能跑。 另外也很好奇,自己從 MVC 版改裝成 MVVM 有那麼難嗎? 為什麼一堆歪果人在 forum 上頭掱呢?果然付錢用 ZK 跟拿錢用 ZK 差很多 [淚目]

啊啊... 是檢討報告、不是 complain 大會... [逃]

2012-07-31

ZK 6.5:一份程式同時解決 Desktop 與 Tablet!

官方英文版:http://blog.zkoss.org/index.php/2012/07/31/zk-6-5-responsive-design-desktop-and-tablet-applications-from-the-same-codebase/

ZK 6.5 版專注的重點在於加強開發人員建立 tablet 版 web application 的流暢度、甚至無須特別為 tablet 撰寫另外一個版本。

Desktop vs Tablet

有別於 Desktop,Tablet 的螢幕較小、沒有滑鼠、輸入得靠軟體模擬鍵盤...... 等差異。在這些先天限制下,製作 Tablet 的 web application 時,勢必得換另一種思維來思考如 layout 設計、輸入方式、swipe 行為等諸多 UX 議題。

ZK 6.5 版,已經幫你解決這些問題了。

ZK 做了什麼?

為了兼顧 End-User 的 UX 以及開發人員的負荷,ZK 的作法是:「讓同一個元件在 Desktop 與 Tablet 下,分別有不同的行為與樣式。」以 Colorbox 來說,color picker 模式下的 gradient block 與 circle bar 都變大了,按鈕之間的間距也加大避免誤按。Datebox 則是徹底改變輸入方式,不再出現月曆、而是以吃角子老虎的方式讓使用者可以輕鬆地指定日期。至於 Listbox,在 tablet 的環境下不會出現捲軸,但是會捕捉 swipe 動作讓 End-User 可以上下捲動 item 並瀏覽。

這裡只舉出幾個代表性的例子。事實上,絕大多數的 component 都精心調校過,只要設計得當,開發人員可以只寫一份程式碼,卻同時能讓使用 Tablet 與 Desktop 的 End-User 瀏覽。

真的假的?

是的,我們寫了一個 demo project:ZKForumViewer,完全使用 ZK 原生的 component、幾乎沒有覆寫原本的 CSS、也只額外寫了一點點 CSS。效果如何呢?請看這個影片:

你可以到 github 抓 source code、在自己的環境下執行看看。它是可以運作的,而且運作良好!

Enjoy ZK 6.5 and have fun!

2012-07-19

ZK MVVM 我也會 [1]

首先在 src/fooPackage 下新增一個 class,名字叫做 MyViewModel,內容是:

2012-07-15

Rikulo 之道

原文網址:http://blog.rikulo.org/posts/2012/Jul/General/the-rikulo-way/

前言

Rikulo 是一個免費、open source 的 framework,讓你可以使用 Dart 與 HTML5 創造出令人驚豔、跨平台的網頁與 native mobile application。我們的目標是提供開發人員最簡單且強而有力的方式來開發 application。為此我們提供了一個 UI 的架構。

Dart 提供了一個給 web 用的結構化程式語言,程式碼可以同時在 client 與 server 端執行。在 Rikulo 中,我們希望拓展這個思維、並應用到 UI 上。HTML 跟 CSS 對包含大量文字的網站而言是很棒的,許多強大的功能也隨著 HTML5 與 CSS3 的導入而出現。然而,在建立複雜的 application 時,複雜 layout 會導致許多 side-effect,HTML 與 CSS 是解決了一些問題、但是卻產生更多的問題。

我們提出的解決方法是「Structured UI Model」。