CSS transition on visibility property

There are various occasions that I found I need to do this:

CSS


#el {
  transition: opacity 1s ease;
}

#el.fade-out {
  opacity: 0;
}

JavaScript


el.classList.add('fade-out');
el.addEventListener('transitionend', function afterFadeOut() {
  el.removeEventListener('transitionend', afterFadeOut);
  el.style.display = 'none';
});

but later I am being told that the same effect can be achieved with 0 line of JavaScript:


#el {
  transition: opacity 1s ease, visibility 1s ease;
}

#el.hide {
  opacity: 0;
  visibility: hidden;
}

Where visibility: hidden will be actually applied 1 sec later at the end of the CSS transition.

For a fade in effect (transition away from hidden), the element will be visible at the very start. Read the spec working draft for formal definition.

我也寫了輸入法,而且用 Javascript!

聽完 jserv 在 COSCUP 2012 講的新酷音輸入法專案,決定來把這篇欠很久的文章寫完,順便換個標題。

在 Mozilla 工作,加入 Boot to Gecko 專案的第一個工作是處理 Gaia 的輸入法,弄了大約一兩個月,最後做出了可以在瀏覽器獨立運作(不需要從伺服器選字)的自動選字注音輸入法:

Gaia 注音輸入法「JS 注音」瀏覽器示範網頁

詞庫

詞庫要匯進程式勢必要轉成 JSON 格式。原本是從新酷音的詞庫轉出來的,後來發現 LGPL 跟專案不相符(我們用 Apache),找了很久,最後找到 mjhsieh 維護的小麥注音詞庫。至於轉檔,本來一度寫了 phantomJS 的 script 來處理,後來改用自家的 Javascript shell。比較麻煩的就是 jsshell 要用 -U 啟動不然字串不會被當成 UTF-8。

資料庫

要把 3MB 的 JSON 整包放在記憶體也不是不行,只是這樣放手機是跑不動的。另外的後果就是這樣每次網頁載入就要每次重新下載,還不能保證會不會碰到 HTTP cache。

Gecko 提供的 database 解決方案是 IndexedDB。也說不上來好用或是不好用,反正我沒得選(笑)。比起直接用 key 從 JS Object 拿資料,IndexedDB 的 async 流程當然是比較複雜,但也不會說難用(而且 Disk I/O 本來就應該要 off main-thread 才對)。比較複雜的是一些手機輸入法的進階找字功能(例如輸入「ㄊㄅ」就要查到「台北」)就需要用到 IndexedDB 的 range search 等等。

演算法

我沒有實作像是 tree search 之類的搜尋方式,而是傻傻的用窮舉法,把 N 個音可能的斷詞通通切開然後送進資料庫查詞還有問積分。和文字雲一樣,用了很簡單的演算法但是卻很有效。

剩下的部份與接下來

剩下就是一些 code organization 的問題。牽涉到這麼多 function 的程式不太容易整理好,我自己改寫了兩次,後來被北京的同事 port 成拼音輸入法的時候他又改成 prototype 的寫法,看起來又更整齊。Boot to Gecko(產品名 Firefox OS)最初的上市目標是南美洲,所以中文支援的功能就先放著,先去處理系統的部份。

我有很刻意的把注音的 JS 檔保持著可以讓其他環境與架構順利載入與 fall back 的狀況(還偷偷加了 CommonJS 的 define())。DEMO 網頁連 iPhone 都可以用,沒有 IndexedDB 的瀏覽器也會每次載入詞庫 JSON。有一些 fancy 的 idea 是像是可以用 node-gtk 或是其他方法執行,反攻桌面或是 Android 之類的。不過這記憶體消耗比別人大,演算法也沒有比別人強,要做只是證明因為做的到吧 … XD

有什麼意見還請不吝賜教。

Animate.css

Animate.css 是一組好玩的 CSS animation keyframe,提供很多誇張的 DOM 動畫效果。使用方法根據網頁是用 Script 在想要做動畫的元素上面加上 class,然後就會觸發 CSS transition。以 jQuery 為例:

$('.bouncy').addClass('bounceInDown');

但這個作法有個問題,在他的範例頁面上也是,就是在動畫結束之後沒有辦法再跑一次(因為要先拿掉 Class 再加才會有 transition)。所以最基本的,應該要在動畫跑完(預設是 1 秒鐘)之後把 class 偷偷拿掉。我還有其他的需求像是 *Out 的 transition 跑完之後就把元素藏起來、callback、如果不支援的瀏覽器就跑 jQuery 動畫這樣,最後就變成這樣一個小小的 helper plug-in 了。

jQuery.fn.animateCSS = function (className, callback) {
	var that = this;
	if (!Modernizr.csstransforms || !Modernizr.csstransitions) {
		// for old browsers we use jQuery animation
		// only fadeIn and fadeOut for now
		if (/In/.test(className)) this.fadeIn(1000);
		if (/Out/.test(className)) this.fadeOut(1000);
	}
	if (/In/.test(className)) this.show();
	setTimeout(
		function () {
			that.removeClass(className);
			if (/Out/.test(className)) that.hide();
			if (typeof callback === 'function') callback.apply(that, that);
		},
		950
	);
	return this.addClass('animated ' + className);
}

有需要請隨意複製貼上到自己的專案去囉。