:::

大家e起來互動式計分討論區

布丁布丁吃布丁

大家e起來互動式計分討論區

image

題名:大家e起來互動式計分討論區

網址:http://pbl.lins.fju.edu.tw/news/


「大家e起來互動式計分討論區」是輔仁大學林麗娟老師授課學習平台兼研究工具。這是一個以PHP與MySQL寫成的討論區系統,原始程式是由學長開發,而我接手維護。

這個討論區的功能相當基本,管理者可以設置多個討論群組,而學生就在各群組之中進行討論。原本僅能擺放純文字,我在此加上了回應、排序,也設計了自動辨識出http網址的分析器,豐富討論區的功能。林麗娟老師看中回應功能的研究價值,鼓勵我以「網路非同步互動引言機制之建置與分析」申請行政院國家科學委員會補助大專學生參與專題研究計畫,開啟了我的研究之路。

image

討論區的回應功能

之後我也設計了一個線上問卷調查系統,方便老師進行使用者問卷調查。該系統可以讓使用者填寫5點量表及開放式填答,管理者可以輕易地建置題目、設定問卷開放與關閉的期限。系統建置時,用了特殊的資料結構來記錄問卷的題目與順序。可惜網站在不知不覺的時候已經關閉,沒辦法記錄這個功能的樣貌。


由於之前在整理博士班推甄的文件,其中我介紹了幾個自己做過的系統。回頭來看看的時候,發現自己並沒有在blog中好好介紹過他們的樣子,這個系統甚至已經不能連線了。甚是可惜。

因此藉此機會,我寫一下幾個印象比較深刻的作品介紹,為自己做個記錄。

(more...)

談DSpace-DLLL系統

談DSpace-DLLL系統

image

政大圖檔所於2011年5越27日舉辦了「數位檔案加值與教學應用研討會」。早上的場次中,我的指導老師陳志銘教授(真‧教授囉!)參與主講「DSpace-DLLL開放源碼數位典藏系統建置與應用」,講述我們實驗室DSpace改良開發成DSpace-DLLL,並應用於臺灣百年圖書館史數位圖書館全國通識網課程資料庫的內容。

以下是演講時的投影片:(SkyDrive下載)


關於DSpace-DLLL

如果常常閱讀這個Blog的人,一定知道這個「DSpace-DLLL」就是我在寫書中做出來的系統。這個演講底下的意義是為了書的出版鋪路,老師也很有良心,不把研討會當廣告臺,所以演講中並沒有提到書的事情,而是私下詢問時才會透漏給有興趣的人知道。


由於之前我在準備博士班的考試,老師並沒有特別告知我要進行這篇的演講,而是在我博士班筆試都考完之後才請我做投影片,所以我是最近才知道這篇文章的內文在講些什麼。儘管作為一個熟悉者,可以看得出學弟妹整理的文章中有很多破綻,不過將自己做的作品分享出去這件事情,還是挺令人驕傲的。而且這篇文章的發表也能幫學弟妹抵免資格考,這對學生來說才是數位典藏系統的「加值應用」啊。

關於DSpace-DLLL的細節,我在書本中已經有詳細地說明。目前書本正在二校中,博士班筆試結束之後,我也比較能夠專心投入這塊。希望能儘快出版呢。


回應項潔館長的問題

在議程結束前的發問期間,項潔館長質疑我們做DSpace-DLLL是否有其必要性,應該是多跟臺大圖書館合作,這樣才是真正的「不必自行重複開發」。王梅玲老師認為小型團體仍有建置獨立數位典藏系統的需求,但項館長則反駁說,那應該是去購買雲端服務即可。而會議議程時間不夠,實際上的主講者陳老師卻沒有參與這個討論,就結束了這段議程。

說實話,我不是很清楚跟臺大合作的方式是如何。感覺上應該是類似企業外包委託案那種方式進行吧?如果真的要做大的話,臺大圖書館也的確可以用雲端運作模式來提供合作服務也說不定。

DSpace-DLLL的「不必重複建置數位典藏系統」,是真的只是在講這個技術平台。在數位典藏計畫裡面,技術平台只是一個環節,無法取代委託整個數位典藏計畫的作法。不過即使如此,對於很多人來說還是很有意義。舉例來說,教師在教數位典藏課程時,就能夠讓學生真的有一個系統平台可以去架設、管理、自行建置,讓他們真的體驗到「如何規劃、建置一個數位典藏計畫」的經驗。這種價值在政大圖檔所中也時常體現,我也從老師們教學使用上的回饋來修正DSpace-DLLL的缺點。另一方面,DSpace-DLLL可以成為想要獨自架設數位典藏系統的單位有一個比原始DSpace更好上手的起點。

尤其是後者,對我來說有著更深遠的含義。DSpace-DLLL是以開放原始碼的模式分享技術,我們站在DSpace這個巨人的肩膀上,往理想的方向踏出了一步,然後再成為其他人的基石,幫助他人更進一步。就像DSpace仍有許多缺點,而我們改善之後以DSpace-DLLL釋出一樣,未來也希望會有人再改進DSpace-DLLL,而釋出更好的開放原始碼數位典藏系統。

以一個系統開發者的角度來說,讓技術在開放原始碼的環境下自由地成長,這是很有意義的貢獻。


未來的方向

作為DSpace-DLLL的開發者,先不論老師在接手之後怎麼繼續改進,我必須補充一下老師在影片中尚未提及的幾個注意事項。

大前提是,這不是企業化、大團隊製作的成品,因此請勿期待不太會成為完美的方案,只能成為備選方案之一。

虛擬機器的限制
image

DSpace-DLLL封裝在虛擬機器VirtualBox進行安裝。我寫了一個Windows XP的安裝精靈,方便Windowx XP使用者來架設。而VirtualBox是跨平台的虛擬機器,因此熟悉的使用者也可以拿著硬碟檔架設在Linux平台上。

使用虛擬機器封裝的理由很單純:安裝簡易。DSpace的原始安裝方式是以Java Servlet來進行配置,但是技術難度高,而太多外部依賴元件需要額外下載。在DSpace-DLLL中加入的多媒體轉檔功能,也需要依賴非DSpace原始檔中的OpenOfficeFFmpegMEncoder套件。為了避免大家光是安裝就弄昏了頭,所以我把它通通打包在虛擬機器中,方便轉移與應用。這種概念可是雲端模式的基礎呢。

虛擬機器的意思是在電腦上再模擬一個電腦,對於效能不佳的電腦來說,虛擬機器的負荷很大,因此穩定度跟服務負荷量有待評估。

理論上,若將DSpace-DLLL裡面的系統移植到實體電腦上,應該是會有比較好的運作效能。不過各元件是否能夠順利搭配這點我就不敢保證,Linux最為人詬病的就是套件相依性太高,要完美地安裝一個系統,我一直都沒有確切的把握。

大量資料的處理

繼承前一點,虛擬機器的DSpace-DLLL在大量資料的存取下是否能夠正常運作,這是需要評估的。除此之外,在系統功能上也還有許多需要改進的地方。

對於數位典藏工作人員來說,最需要的就是批次匯入機制。DSpace有提供後台的匯入,但是批次檔的撰寫對一般人來說並不友善。同樣的,對於大量資料的修改、調整,DSpace也沒有批次修改的功能。因此在大量資料的管理上,還有很多的不便。

這是DSpace尚未達到的境界,而DSpace-DLLL也繼承下來,一樣有這種問題。

但是這並不是做不到:DSpace的批次匯入其實真的很好用,只是不太友善。有心要修改的人,應該是能夠輕易地將他實作成前臺網頁可以直接執行的功能吧。

權限控管與付費機制

這是非常重要的一個未解決問題,如果你的計畫想要以DSpace-DLLL作為起點,那麼權限是不得不考量的一個議題。

DSpace提供以帳號來控管權限功能,可以控制內容層級每一層的新增、遞交、編輯、刪除權限,控管上非常詳盡。但是就跟大量資料管理缺乏批次處理功能一樣,大量的權限設定也就變成一個難題。另一個問題,就是權限控管的需求不只有帳號這一種方式,常見的還有IP、國家等限制,而DSpace還沒考量到這點。

DSpace已經有良好的權限控管基礎,但仍需要有人進一步地改良,這也是DSpace-DLLL未解決的問題。

至於付費機制上,原本是為公開取用的DSpace就離這個功能更是八竿子打不著的關係,請營利公司自行加油吧。

分類與介面
image

作為一個泛用型典藏系統,DSpace的預設範本很樸實。我在DSpace-DLLL中修改了一些小細節,但是並沒有去調整他的設計,因此介面依然是很單調。

今天研討會時王老師提問說能不能更簡單地調整網頁的樣式,並且建立漂亮的分類架構。這也是她長久以來的一個疑惑。

用簡單的方式來修改網頁介面,例如拖曳、新增網頁元素、套用簡易範本,這在大多數CMS當中都已經是非常成熟的技術,不過DSpace在介面調整支援上,還不能簡單地使用。提示是XMLUI,但至今我仍未參透這個功能就是。

至於分類架構上,這可是一塊非常、非常、非常大的研究議題了。原本作為機構典藏之用的DSpace,將內容層級架構分成community、collection、item等層級,許多國外數位典藏系統也都是依照此架構在使用。但是數位典藏不像檔案管理有一套全宗原則,往往還是以客製化的方式設計分類架構為多。

這個客製化的要求並不是說DSpace的內容層級架構不能實作出來,事實上,像林巧敏老師負責的教育部中綱計畫成果資訊網就是一個很適合的例子。不過系統技術人員眼中的分類架構跟數位典藏人員來說有很大的差別。對於數位典藏人員來說,他們更在意的是對於每一種分類導覽功能的客製化。

image

以中綱計畫成果資訊網來說,在一個子計畫瀏覽中又可以依照藏品的類型來分類。若以DSpace實作,一個子計畫則是一個community,每一種藏品的類型是各自的collection,而底下每一筆資料則就是一筆item。那麼DSpace在介面呈現上能不能做到像中綱計畫成果資訊網一樣呈現?作為技術人員的我一定會跟你說:可以,但是要自己改。而這對許多不懂技術的人來說來說,其意義就與DSpace無法做到這種分類架構是同樣的答案。

總而言之,到頭來還是介面上的問題。而且這對泛用型典藏系統的DSpace來說,都已經快要是非戰之罪了。

然而,我認為DSpace在介面功能上的強大,對技術人員來說會有直接的感受。受惠於DSpace嚴謹地設計模式、詳盡的註解說明,技術人員可以輕易地利用DSpace的內容層級架構、瀏覽、搜尋功能做出各種客製化的分類架構,就像全國通識網課程資料庫一樣。我看過一些商用軟體的程式碼都還沒DSpace漂亮,這是真的。DSpace的程式非常嚴謹且靈活,不僅是容易使用,也很值得學習。


全文檢索的中文斷詞改善

在全文檢索的功能中,DSpace會依據檔案內文製作倒置索引檔,以此來達到全文檢索的功能。然而MIT與HP為西方人設計的DSpace並沒有很完美地考慮到各國的國情,中文斷詞只用二字詞的方式來切截。這會影響搜尋結果並不是十分漂亮。

中文斷詞全文檢索是一塊門檻不低的議題,DSpace-DLLL也沒有解決這個議題,但是未來仍可以從DSpace提供的plugin機制來進行修改,讓中文斷詞更為漂亮。


PDF的HTML網頁化

儘管現在PDF已經如此盛行,但我們真正要使用的時候,還是會希望他是以HTML網頁的方式呈現。只有網頁,才能讓我們能夠為他加上更多的服務,例如標註功能。

其實這幾乎脫離了DSpace原本的要求,但這也的確是我想做的一個功能。未來有機會的話再來挑戰看看吧。



DSpace-DLLL與我

如果有人欣賞DSpace-DLLL,那我會感到非常欣慰,辛苦努力總算有了代價。而DSpace-DLLL會不會像上述的未來發展一樣繼續改進,我希望會,但我也希望會有人來接手。至於我自己,也希望能有這個機緣能夠繼續改進。

機緣,那是很重要的條件。那就是有沒有繼續做下去的價值。也許很多人會認為「有!」,但那是站在使用者的立場來說的。作為開發者的我來說,有沒有價值,那又是另外一回事。


興趣來做的DSpace-DLLL,是以延畢換來的

我在政大圖檔所念了快要四年才完成學業,不瞞大家說,因為我都在玩──最後玩出這個DSpace-DLLL。

在幫忙百年圖書館史、教育部計畫、甚至是寫書的時候,儘管老師並沒有要求很多,但我卻仍會任性地挑戰自我。於是後設資料編輯功能出來了、虛擬機器出來了、更簡單的系統管理方式出來了、一本介紹DSpace的專書也快要出來了。

這並不是為了錢、也不是為了名聲、也不是為了他人(包括老師或是計畫助理),而是為了自己的興趣。那種「想看看跨越山丘之後的景色」是我持續前進的動力,這也往往讓我沉迷在此、樂在其中而不可自拔。

儘管學習的過程讓我感到開心,但我也知道,這其實並不是什麼值得驕傲的事情。當我每天在實驗室修改程式碼的時候,有些老師則是直接對我嘆氣:「唉,你怎麼都在搞這個,幹嘛還不畢業。」

我大概花了將近兩年的時間專搞DSpace,論文幾乎是寫完計劃書之後就放置不理了。每次陳老師想拿我來當學弟妹借鏡的時候,我內心其實都會為這種不顧學生畢業本分而玩樂於DSpace的行為感到汗顏。

在金錢上,因為幫忙計畫事宜,所以當時老師給的人事費仍可以補足日常生活所需。儘管如此,每學期的學雜住宿費仍得仰賴父母的支援。這對一個當時的年紀是應該在外面工作、養活自己的人來說,我這種為了興趣不顧一切的行為並不可取。


只是為了自我成就

DSpace-DLLL的發展並不像是國科會、教育部計畫一樣,是有實質的經費支援。它也不是我的畢業論文,對我的畢業也沒有實質的助力。這種基礎的系統建設並沒有太多學術上值得一提的研究價值,這也不是我想做的研究題目。

它就真的,只是我的興趣,只是一種自我成就,是幫忙計畫專案之後,學習了Java Servlet、AJAX、Linux、虛擬機器、自動安裝之後的一個成果產出與分享,就只是如此。


不能一直玩下去

人不去面對現實也要有個限度,至少這點我還是知道的。為自己設定一個折返點,做到一個程度就該收手,不能一輩子這樣玩下去。我想,這才是一個社會人應有的常識。

我玩得很開心,但是差不多了。

儘管如此,不會對DSpace-DLLL感到滿足的人總是會期望我或實驗室能夠繼續開發下去。我也希望如此,不過我更希望的是看到有人能接手,基於現在的基礎上,繼續深入開發。所以我寫書,我釋出系統,這是我的願望。

至於我自己能不能繼續做,那麼就要回歸現實問題,有沒有經費支援?對於我未來學業、工作上有沒有幫助?有多少經費做多少事情,這才是一種正常的運作模式。在沒有經費、憑著熱情來開發、供人自由取用的火柴人行為,這是可以拿來自己說笑的故事,但卻不是作為要求別人的條件。

所以誰誰誰快來聘我去工作吧,我就能名正言順地繼續玩DSpace了!!


結語

原本只是想記錄一下DSpace-DLLL的介紹投影片,沒想到越寫越多,就變成這樣落落長的一篇了。原本是打算花一個小時來寫,不過實際上似乎是寫了快三個小的樣子。都已經半夜兩點了,好睏。

那麼接下來就是努力讓DSpace-DLLL可以順利出版啦,加油~

(more...)

Evenote擷取應用:Add to Evernote書籤

布丁布丁吃布丁

Evenote擷取應用:Add to Evernote書籤

image

Evernote有很多種方式擷取網頁資料,這種是利用Evernote指定網址擷取功能來實作的Add to Evernote書籤。


Add to Evernote書籤

安裝與使用
  1. 請將底下的書籤拖曳至您的瀏覽器上,就像上圖一樣的位置Add to Evernote
  2. 在你要擷取到Evernote的網頁中,按下Add to Evernote書籤,就像上圖一樣,點下去就對了。
  3. Evernote擷取視窗會另外開啟,並讓你指定要保存此網頁的「記事本」與「標籤」
    image
    如果你沒有登入Evernote的話,他才會問你帳號密碼。
使用限制
  • 如果是需要登入才能觀看的網頁,就無法透過Evernote伺服器來擷取。例如Pixiv
  • 擷取下來的網頁會參雜大量導覽訊息,導致記事太多多餘的內容,如下圖。
    image

因此,此功能適合擷取公開、簡單的頁面,或是先儲存之後再來整理。至少他的擷取方式很簡單,連安裝擴充功能都不需要。

書籤補充擴充功能的不足

image

Google Chrome的Evernote擴充功能最近十分熱門,我自己也有安裝使用。只是擴充功能麻煩的地方在於Evernote時常會詢問你的登入狀態,Evernote預設7天就要重新登入,對於不常使用的我來說,每次要擷取都要先登入,而且擷取的時候千萬不能操控滑鼠點選其他地方,否則擴充功能會被取消、擷取也會失敗。往往是按下擷取,等待個5分鐘,然後看到Evernote擷取失敗的訊息,實在令人灰心。

儘管Evernote的擴充功能在擷取網頁上的方式上能夠智慧選擇,但對我來說只是要快速地備份這個網頁的內容、之後再修改的時候,在擴充功能操作限制之下,我會比較喜歡用Add to Evernote書籤。這也是我想寫這功能的原因之一。


結語:Bookmarklet練習

最近在看AJAX設計模式,看到Bookmarklet(或稱為favelet)技巧,忽然想到很多人都會在Google Reader加入傳送到Evernote功能,卻很少看到有人把此功能加到書籤去,於是我就自己寫了一個Add to Evernote書籤來用。

當然,現在這個Add to Evernote書籤還不夠漂亮,指定網址給Evernote伺服器去擷取,記事內容多餘的東西實在太多,只能作為記錄、備份之用而已。

不過這個技巧激發出許多我對AJAX應用的靈感。這是一種簡單的Plugin,是有需要才使用的userscript,簡單直覺又跨瀏覽器。(說到跨瀏覽器,在IE上運作時,開新視窗功能倒是一直被IE跟Google Toolbar擋下來,實在很煩耶XD)

之後有機會再用Bookmarklet做點什麼來玩玩吧。

參考資料

(more...)

JSONP跨網域傳送檔案:以POST方法實作

JSONP跨網域傳送檔案:以POST方法實作

image

網頁應用設計中的JSONP技巧可以做到跨網域資料傳送的功能,但它卻只能傳送純文字資料,而我希望能在跨網域的環境下開發AJAX上傳檔案的功能,那麼就需要一些小技巧才能進行。

雖然我想應該也有人提出這個作法了,不過實際上在之前我並沒有找到過。因此我把這個在論文中實作的技巧在此記錄、分享。

這篇用到大量的網頁設計專有名詞,主要是以AJAX設計網頁應用的人為主要對象撰寫的。


範例

image

這個範例網頁中,你可以上傳一個檔案,並填寫下面的敘述Description,再按下UPLOAD按鈕上傳。伺服器會回傳給你檔案的上傳結果、檔案名稱、檔案大小。檔案上傳最大是1MB,超過1MB的檔案,伺服器會回傳錯誤結果。

原本我是將HTML網頁放在Dropbox空間(http://dl.dropbox.com/),而伺服器則是放在You Hosting的空間(http://pulipuli.co.cc/),想用兩個不同網域來呈現透過POST方式實作JSONP跨網域檔案上傳的範例。但是因為You Hosting放著一陣子就被強制關閉了,所以很遺憾的,在此無法看到線上即時的成果。(2011/9/19更新)

此範例中用了三個檔案,請直接下載研究、並自行配置使用吧:

應用背景

使用AJAX開發網頁應用的程式設計師,大多時候都是在同個網域之下處理client(使用者端電腦)與server(伺服器)之間的訊息傳遞。更進一步的,利用jQuery框架,以JSON物件、GET方式傳遞資料的jQuery.getJSON()函數,讓處理AJAX資料傳遞更為簡單。

但是我的論文中需要使用的AJAX跟上述常見情況有個很大的差別。第一個是跨網域,client端呼叫server端資料,這兩者是位於不同的網域,因此普通的GET或POST方式都無法讓client端取得server端的資料,必須仰賴JSONP(JavaScript Object Notation with Padding)技巧;其二,這次要傳送的資料並非純文字或可以用JSON來組織的資料,而是需要上傳二進位的檔案,或是超過GET資料傳送上限的資料量。在這種情況下是不能單純使用JSONP,必須使用POST方式與form表單傳送資料才行。

因此,我將POST的傳送優勢與JSONP的跨網域AJAX特色融合,寫成以POST方式實作的JSONP跨網域檔案傳送。

角色

在此應用中是以前端的瀏覽器與遠端的伺服器進行溝通合作,因此我先簡單敘述這兩種角色。

「C」 client

在這篇文章中,我以「C」表示「client」(客戶端)瀏覽器中執行的程式語言,主要是HTML跟JavaScript,這也是AJAX的基礎。多虧了jQuery框架克服了相容性問題,因此在Chorme、Firefox或IE都可以使用。

在此範例中,「C」是擺在Dropbox的空間,他並不具備伺服器端的功能,不能判斷檔案大小。此外,我將「C」的HTML外觀寫在client.html當中,而JavaScript的邏輯運作寫在client.js當中。稍候會再敘述他們的功用。

「S」 server

另外「S」代表「server」(伺服器),在此範例中我以PHP寫成,擺在You Hosting空間。伺服器端的程式語言具備了處理檔案的能力,可以判斷檔案大小。在此利用AJAX架構,讓「C」能夠與「S」進行溝通。

為了利用POST傳送檔案,並能以JSONP進行跨網域溝通,「S」必須判斷請求方式(request method)是POST還是GET。並以session來暫存狀態。

稍微有點概念之後,接下來就是實際看看這方法要怎麼運作了。


Step1. C1:資料準備

 image

為了讓大家好理解,此範例中的檔案上傳做得跟傳統網頁一樣。這是一個<form>表單,裡面有個可以選擇檔案上傳的input,並限制只能上傳1MB大小的檔案,還有一個可以撰寫「Description」(敘述)的input,最後則是一個submit(遞交)的「UPLOAD」按鈕。

在這個表單前面,引用了大家的好朋友jQuery以及我另外寫的client.js;表單後面則有個<div>容器,負責顯示待會跟伺服器溝通的結果。

原始碼很簡單,寫在client.html中,摘錄如下:

<script src='http://www.google.com/jsapi' type='text/javascript'></script>
<script type='text/javascript'>google.load("jquery","1.2.6");</script>
<script src="client.js" type="text/javascript"></script>
<form id="form" method="post" action="http://pulipuli.co.cc/20110517-jsonp-post/server.php" enctype="multipart/form-data">
    <input type="hidden" name="max_file_size" value="1048576">
    <label>File: <input type="file" name="file" /> * Max File Size: 1MB</label>
    <br />
    <label>Description: <input type="text" name="description" value="The description of this file."></label>
    <br />    
    <button type="submit">UPLOAD</button>
</form>
<div id="output"></div>

另外,為了讓這個form表單能具備AJAX跨網域上傳的功能,我利用JavaScript幫他做了些初始化的調整,讓form的遞交會以AJAX方式進行,並設定回傳資料時所要執行的回呼函數(callback)。

這部份寫在client.js開頭,程式碼如下:

/**
 * Initialize Form
 */
$(function () {
    
    $("#form").submit(function () {
        
        if ($(this).attr("jsonp_by_post") == null)
        {
            $.jsonp_by_post(this, function (_result) {
                //...Step7時再講解... 
}); return false; } }); });

Step2. C2:AJAX式的POST遞交

當form的UPLOAD按鈕被按下時,就會開始一連串的AJAX式的POST遞交作業。

在此步驟中,JavaScript會做以下事情:

  1. 以timestamp作為辨識每次檔案上傳作業的代號。
  2. 讀取form的資料,並將timestamp設定到action的網址中,提供伺服器辨識每次檔案上傳作業的代號。
  3. 建立一個接收資料的iframe,隱藏之,並設定name。
  4. 調整form的action跟name,讓form的遞交會傳送到iframe去,而不是把整個網頁都替換掉。
  5. 給form做個記號(此範例用jsonp_by_post屬性),以免跟Step1初始化form的submit事件相衝突。
  6. 設定iframe遞交完成之後的後續動作。
  7. form執行遞交作業。

程式碼寫在client.js,摘錄如下,其中6.設定iframe遞交完成之後的動作,我會在下面的Step4詳細敘述,這邊先以略過。

$.jsonp_by_post = function (_form_ele, _callback) {
    
    var _timestamp = (new Date()).getTime();
    
    var _form_obj = $(_form_ele);
    
    var _action = _form_obj.attr("action");
    var _action_post = _action + "?timestamp=" + _timestamp;
    
    //建立接收資料的iframe
    var _iframe_name = _action + _timestamp;
    
    var _iframe_obj = $('<iframe></iframe>')
        .attr('name', _iframe_name)
        .appendTo($('body'));
        
    //隱藏iframe
    _iframe_obj.css('width', '0').css('height', '0')
        .css('position', 'absolute').css('left', '-1000px').css('top', '-1000px');
    
    //調整傳送資料的form
    _form_obj.attr('action', _action_post)
        .attr('target', _iframe_name)
        .attr('method', 'post')
        .attr('enctype', 'multipart/form-data');
    
    //防止重複觸發初始化的事件
    _form_obj.attr('jsonp_by_post', 'true');
        
    //設定iframe讀取完畢之後的動作
    
    _iframe_obj.load(function () {
        
        //...Step4時再講解...
        
    });
    
    //執行遞交
    _form_obj.submit();
};

Step3. S1:伺服器接收POST資料

伺服器端的程式會依照請求方式的不同,決定此程式是要接收檔案上傳,還是要回報檔案上傳的結果。

在Step3中,form以POST方式呼叫了位於另一個伺服器的server.php,並執行以下動作:

  1. 接收$timestamp,作為判斷這次作業的辨識代號,並與一個特定的$header組成session使用的$index。
  2. 透過透過PHP的$_SERVER['REQUEST_METHOD']來判斷請求方式。
  3. 如果是POST,則將檔案的檔名、大小、以及從POST過來的description資料儲存在session當中。
  4. 判斷檔案上傳的狀態,失敗就是「error」,成功則是「sussesful」。
  5. 顯示一些資料,作為簡單偵錯。但其實可以省略。

以下程式碼寫在server.php中,摘錄如下。請求方式是GET的情況,我會在下面的Step6再來講解。

<?php
$header = "data";
$timestamp = $_GET["timestamp"];
$index = $header . $timestamp;

session_start();

if ($_SERVER['REQUEST_METHOD'] == "POST")
{
    $description = $_POST["description"];
    
    $_SESSION[$index]['name'] = $_FILES['file']['name'];
    $_SESSION[$index]['size'] = $_FILES['file']['size'];
    $_SESSION[$index]['description'] = $description;
    
    if ($_FILES['file']['size'] == 0)
    {
        $_SESSION[$index]['state'] = 'error';
        echo "false";
    }
    else
    {
        $_SESSION[$index]['state'] = "sussesful";
        echo "true";
    }
}
else
{
    // ...Step5時再講解...
}

Step4. C3:以JSONP取得檔案上傳結果

當iframe讀取完畢之後,「C」就可以知道檔案上傳動作已經結束。但是因為POST在跨網域的狀況下是無法取得iframe裡面的資料,所以必須要改用JSONP的方式來跟「S」取得結果。

這些動作寫在Step2中省略的iframe onload事件中,大概動作如下:

  1. 設定JSONP的網址,加入jQuery.getJSON()特有的callback=?參數。
  2. 執行jQuery.getJSON(),並設定執行完後的回呼函數。

這些程式碼寫在client.js中,摘錄如下。執行完getJSON()的回呼函數會在Step6講解。

    //設定iframe讀取完畢之後的動作
    
    _iframe_obj.load(function () {
        
        //設定get方法JSONP的網址,要注意加入了JSONP特有的callback參數
        var _action_get = _action + "?timestamp=" + _timestamp 
            + "&callback=?";
          
        $.getJSON(_action_get, function (_result) {
            // ...Step6時再講解...
        });
        
    });

Step5. S2:伺服器回傳檔案上傳的結果

以JSONP方式呼叫伺服器時,「S」是以GET方式運作,他會做以下動作:

  1. 接收$timestamp,並與$header組成$index。這跟Step3做的事情一樣。
  2. 判斷請求方法為GET。
  3. 取得回呼函數的代號$callback,這是搭配jQuery.getJSON的作法。
  4. 從$index取得session資料,將檔案上傳結果存進$output字串。
  5. 刪除session資料,避免後來有心人再利用同樣的timestamp取得資料。
  6. 以JSONP方式輸出。

以下程式碼寫在server.php中,摘錄如下:

<?php
$header = "data";
$timestamp = $_GET["timestamp"];
$index = $header . $timestamp;

session_start();

if ($_SERVER['REQUEST_METHOD'] == "POST")
{
    // ...Step3講解...
}
else
{
    $callback = $_GET['callback'];

    $output = '';
    if (isset($_SESSION[$index]))
    {
        $output = $_SESSION[$index]['state'].'; ' 
            .$_SESSION[$index]['name'].'; '
            .$_SESSION[$index]['size'].'; '
            .$_SESSION[$index]['description'];
            
        unset($_SESSION[$index]);
    }

    if (is_null($callback))
        echo $output;
    else
        echo $callback."('".$output."');";    
    
}


Step6. C4:接收資料,復原form,呼叫回呼函數

以jQuery的getJSON取得資料之後,接下來就是復原form、刪除臨時建立的iframe,然後呼叫回呼函數。

這段程式碼也很簡單,寫在client.js中,摘錄如下:

        $.getJSON(_action_get, function (_result) {
            
            //復原form
            _form_obj.attr('action', _action)
                .removeAttr('target')
                .removeAttr('jsonp_by_post');
            
            //移除iframe
            _iframe_obj.remove();
            
            _callback(_result);
        });

Step7. C5:結果輸出

在Step1初始化時設定好的回乎函數會在最後接收資料,然後將結果輸出到div容器中。程式碼寫在client.js的上方,摘錄如下:

            $.jsonp_by_post(this, function (_result) {
                $("#output").html("Message: " + _result);
            });

如果檔案正常上傳,你會看到以下畫面:

image

如果你上傳超過1MB的檔案,則伺服器會記錄錯誤狀態,於是會看到以下畫面:

image

這樣就大功告成啦!


變化與應用

範例中的講解很簡單,身為能夠舉一反三的程式設計師,腦袋裡面應該已經呈現出很多不同的應用方式吧。這邊我大略提一下幾個變化的重點,還有最後應該注意的安全性問題。

資料的輸入

在此範例中,我所有資料都是來自於撰寫好的form表單。實作時,我們的原始資料不一定是真的來自form表單,通常會以JSON、陣列、變數形式存在記憶體中,以方便JavaScript進行處理。

如果是以JSON等非form的資料型態,想要進行跨網域的AJAX傳輸,那麼你還是得要自己將這些資料寫成form,這樣才能以POST進行遞交。雖然多了點步驟,但相信對於熟悉jQuery的你來說應該不是什麼問題。

安全性問題

網頁之間有很多跨網域的限制,而本篇旨在於打破這個跨網域限制來做到更多功能,但相對的就會負擔起更多安全性問題。

提供JSONP的服務,很容易就會受到跨網域指令碼(Cross-site Script)的攻擊,而被找漏洞、挖出使用者的資料。我並不是資安專家,對這方面研究還不夠深入,只能提供幾個簡單的安全性加強方向。大致上,我建議搭配身分認證的session、來源IP或網址,來判斷這個C是否有跟S溝通的資格,S再決定是否接受C的POST或GET請求。這樣應該會安全許多吧。

範例程式中為了講解方便,所以並沒有加上這些措施。如果你要將這個方法放到自己的應用程式中,請務必做好安全性的防範措施。


結語

這是我論文系統中實作的一個技巧,但因為論文無法寫出這些細節,所以我以寫blog的方式,記錄這個技巧的細節,供有需要的人參考。實際上這篇從想寫、擬完心智圖、寫了一半覺得不滿意、又改了好多次,到現在才完成。

這只是一個很基礎的AJAX技巧,可以應用到很多地方,可以進一步寫成更漂亮的framework或library。也許已經有人發表過這種方法了也說不定,不過,我另一個目的也只是給未來的自己留下一個參考而已,就作為一篇記錄吧。

(more...)

桌面離線也可動作的AutoIt指令:ControlSend跟ControlClick

桌面離線也可動作的AutoIt指令:ControlSend跟ControlClick

image

使用AutoIt撰寫的機器人可以幫Windows環境下的使用者省下很多手動操作的工作。但是有時候我們不在電腦前,也想要利用AutoIt來在特定時間排程進行工作,這時候就不能用常見的SendMouseClick函數(function)指令,而應該要用ControlSendControlClick等Control系列的函數,直接對要被控制的對話視窗送出指令。


桌面離線的情況

切換使用者

image

Windows除了「關機」、「登出」之外,還可以在不關閉現在執行中的程式的情況下,切換成其他使用者,讓其他使用者使用。

上圖是以Windows 7為例,Windows XP也有這個選項,在「開始 > 登出 > 切換使用者」裡面。

遠端桌面連線中斷

image

另一種情況是遠端桌面連線中,不進行登出或關機,而是直接將遠端桌面連線關閉。這樣子執行中的程式依舊會繼續執行。

AutoIt的Send跟MouseClick無法作用

以前我使用AutoIt來做自動安裝VirtualBox機器人的時候,是在桌面連線的前提下,讓AutoIt模仿使用者的動作,進行Send(模擬鍵盤指令輸入)MouseClick(模擬滑鼠按鍵輸入)的動作。

但是在桌面離線的情況下,AutoIt的Send跟MouseClick就會失效,這時候必須改用另外更精確的指定Control系列函數才行。

使用方法

AutoIt中以Control開頭的函數有十幾種,對製作自動操作機器人的我來說,主要使用ControlSend跟ControlClick這兩種。這兩種的使用方法都很類似,以下進一步說明:

ControlSend

對指定視窗中的指定元件輸出鍵盤的指令。

ControlSend ( "title", "text", controlID, "string" [, flag] )
  • "title":要控制的視窗標題。不必輸入完整標題,AutoIt只有開頭部分的文字也能搜尋得到。
  • "text":要控制的視窗內文。如果沒有內文,可以輸入空字串""
  • controlID:要控制的元件代號。稍後介紹。
  • "string":要輸入的指令。指令的內容詳細請參考Send
  • flag:如何處理要輸入的指令。flag = 0(預設),允許指令包含特殊字元;flag = 1,指令以原始資料輸入。這也跟Send是一樣的。
ControlClick

對指定視窗中的指定元件輸出滑鼠點擊的指令。

ControlClick ( "title", "text", controlID [, button [, clicks [, x [, y ]]]] )

"title""text"、controlID跟ControlSend是一樣的。其實Control系列函數幾乎都會有這些參數。

以下是其他選擇性的參數。

  • button:模擬滑鼠輸出的指令,預設是"left"(滑鼠左鍵),詳細按鍵列表請看ControlClick的說明
  • clicks:要點選的次數,預設是1次。
  • x:要點選元件的水平位置,預設是"center"(中間)。
  • y:要點選元件的垂直位置,預設是"center"(中間)。

擷取controlID

剛剛提到了Control系列函數中都需要有controlID參數。controlID並不像是title或text可直接從表面觀察判斷,它是軟體設計時的內部代號,對於初次使用Control系列函數的人來說,常常不知道該如何取得controlID。對於這個無法直接觀察的controlID,可以使用AutoIt v3 Window Info工具來擷取。

AutoIt v3 Window Info位置

AutoIt v3 Window Info會隨著AutoIt一同安裝,位於安裝目錄底下。預設安裝位置為:

C:\Program Files\AutoIt3\Au3Info.exe

C:\Program Files\AutoIt3\Au3Info_x64.exe

其中Au3Info_x64.exe是給64位元的作業系統使用的。

擷取controlID方法

image

開啟AutoIt v3 Window Info(以下簡稱Au3Info)的主視窗之後如上圖。Au3Info會自動維持最上層的狀態。

image

接著請打開你要指定的視窗,在此我以Windows的「我的文件」對話視窗為例。請把Au3Info中的「Finder Tool」準心拖曳到你要觀察的對話視窗元件,如上圖,我把Finder Tool拖曳到了「我的文件」中的網址輸入元件上,而原本沒有任何資料的Au3Info,這時也顯示出了元件的詳細資料。

image

在Au3Info眾多資料中,我們需要注意的是Control分頁中的Advanced Mode的值,這就是controlID參數。在此例中,「我的文件」的網址輸入元件,其controlID為"[CLASS:Edit; INSTANCE:1]"(請注意大小寫跟空白喔)。

從Send修改成ControlSend的範例

為了讓大家更好理解Send跟ControlSend的差異,在這邊舉兩個例子來說明。

Send的例子

以下是利用Send來開啟「我的文件」,並將網址切換到「桌面」的例子:

Run("explorer.exe")
WinWait("我的文件")
If Not WinActive("我的文件") Then WinActivate("我的文件")
Send("{ALTDOWN}d{ALTUP}")
Send("{SHIFTDOWN}{END}{SHIFTUP}桌面{Enter}")

這支程式第一行是開啟"explorer.exe",預設啟動時會打開「我的文件」。第二行跟第三行則是等待「我的文件」啟動,並且將它置於焦點。第四行則是跳到網址輸入元件,第五行輸入桌面,最後就能跳到桌面的畫面。

這個例子在桌面連線的情況下可以順利執行,但在桌面離線的情況下,第四行開始將會無法順利執行。

ControlSend的例子

以下是利用ControlSend來開啟「我的文件」,並將網址切換到「桌面」的例子:

Run("explorer.exe")
WinWait("我的文件")
If Not WinActive("我的文件") Then WinActivate("我的文件")
ControlSend("我的文件", "", "[CLASS:Edit;INSTANCE:1]", "{SHIFTDOWN}{END}{SHIFTUP}桌面{Enter}")

這個例子的功能跟前面的例子大致上相同。只有第四行之後改用ControlSend來輸入指令,因此它不僅能夠在桌面連線時執行,也能在桌面離線下執行。


結語

image

AutoIt的網站不知不覺地更改了網頁設計,害我以為我找錯網站orz

總之,未來有機會再繼續挖掘AutoIt的價值吧。

(more...)

學習的責任

布丁布丁吃布丁

學習的責任

趁著睡覺之前,來聊聊最近的事情吧。

讀書

蔡明月老師在上課的時候總是會感慨地對我們說:「讀書是一件幸福的事情」,而我也深深地表示贊同。

畢業之後,總算能夠放開心胸地讀起自己想要看的書。這段期間陸陸續續地讀了超越Java操作介面設計模式Ruby on Rails建置與執行等程式語言的書籍。讓我回想起以前數度跑去書店就是會拿起一本程式的書、找個地方坐下來就這樣看白書欣賞的往事。

另外因為要準備博士班的考試,所以一邊也在閱讀圖書資訊學方面的教科書與期刊,像是圖書資訊學概論資訊時代的圖書館:新敎育思潮與圖書資訊情報科學原理大學圖書館圖書資訊學刊、以及傳說中的圖書資訊學年鑑ARIST

由於從寫論文開始,我就幾乎沒有在繼續碰圖書資訊學相關的事情,本來我以為我看圖資的書應該會覺得很無聊。不過出乎意料的是,讀書的過程卻是讓我樂在其中。

舉例來說,圖書資訊學概論其實是我大學一年級圖書資訊學導論的指定教科書,理論上我應該看過,但是這次拿起來看的時候卻倍感陌生。而翻閱的過程中,呼應著章節的內容,大學與研究所的授課過程彷彿走馬燈般地歷歷在目。更勝者,以前在讀書時匆忙撇過的名詞、定義、作法,現在可以照自己興趣地深入鑽研。

幾乎每本書都會探討圖書資訊學領域的定位。傳統圖書館學是依附在機構底下,但現在則是更鑽研人們是如何獲得、吸收資訊的學問,這也是我喜歡圖資的主要理由。回頭反省待在陳志銘老師底下做數位學習的定位,我赫然發現「學習」正是資訊傳播的最末端,也就是探究使用者是如何吸收資訊、成為知識一部分的過程。

另一方面,圖資領域是結合多種研究領域的綜合體,儘管情報科學原理一書早在民國80年代就已經出版,但書中探究了資工的資訊檢索、數學的機率統計、社會學的最小努力原則、馬太效應等等,至今仍是非常受用的知識主題。

越是深讀,越是覺得圖資這塊領域既廣闊又實用,讓人覺得身在此領域是一件正確的事情。不過也許某方面來說,只是我那不管做什麼事情都很容易樂在其中的個性使然,才會讓我有這種錯覺吧。

令人欽佩的實務經驗

在閱讀期刊論文的時候,可以看到許多知名的老師(因為圖資界不大,所以總是看到那幾位老師的名字)發表各種不同主題的論文。除了專門為了某個主題進行研究的論文之外,也有許多將圖書館、圖資系所實務工作使用的方法與結果撰寫而成的論文。

特別是後者,我感到非常地敬佩。由於老師擔任館長、或是內部組員等員工,才得以進行一些一般研究生無法取得權限、資料的研究,因此他們的研究結果是很難得的實務經驗。但另一方面,身為工作者,「我很忙,沒空」的理由是家常便飯,而他們卻仍然能在進行日常業務之餘,還能夠完成這些論文。以吳政叡館長敘述輔大圖書館引進RapidILL一文來說,如果只是一般技術人員,大概只會懂得敘述如何引進的細節。然而吳館長不僅僅只是敘述過程,最後還以期刊價位成長率與RapidILL會費兩種不同方案所需要的經費做比較分析,將RapidILL的優勢具體地表現成數據資料。這對其它圖書館來說,將會是非常值得參考的實務成果。

學習的責任

看看其它老師的論文研究,有人做質性分析,有人做技術探討,都各有各的深度、一樣都有各自的精采。然而,在欽佩之餘,我開始想到一件事情:

 

我未來也是要這樣做嗎?

 

唸書唸到現在,老實說我還是不太能夠想像未來跟實務經驗結合在一起的樣子,也不覺得自己能夠做到像老師們筆下的這些研究結果。

儘管論文已經寫完了,實驗也做過了,但是別說是老師,就算最近看到學弟妹積極地進行實驗的樣子,我還是會有一種「我絕對做不到那樣的」的無力感。

很多人問我說,為什麼我還想要繼續唸書,是想要以後去當教授嗎?老實說,我並沒有想這麼多。我真的只是覺得學得還不夠,還有一些想嘗試的事情還沒去做,所以才繼續唸書、繼續學習。

最近才意識到,在學習之後是會伴隨著「責任」的到來。

我家風很自由,爸媽並沒有給我什麼具體的期望,只要我健健康康地活著即可。所以我照自己的興趣讀書,研究喜歡的程式,寫一些無關痛癢的blog文章自娛娛人。但對別人來說,這可就不一樣了。指導教授陳老師一直希望我唸完之後能夠當個教授,而有些公司也會希望學生讀完之後能夠將所學應用到工作上。

以我之前做的教育部通識課程計畫為例,我實作了多媒體轉檔功能,其實只是一種自我挑戰性質的行為,沒做好就算了,不要太認真;但對其它計畫的夥伴來說,卻把它視為該平台的主打功能,而對此功能抱有相當大的期待。對此期待,呼應的不是我,而是專任助理們。我就像是拿「寫論文」當做藉口一般,逃避了後續繁雜的debug工作。

我知道當時我的確是該寫論文,但我也覺得自己不敢對自己所作所為負起責任的態度感到心寒。我沒有想到,自己隨便做一做、只是想跟別人炫耀一下的小玩意兒,到最後居然影響會這麼大。

因為我學習,所以別人加上了期待;因為我實作,所以別人要求了責任。在碩士畢業之後,我越來越能具體地感受到「學習的責任」的存在。

我的學習到底是為了什麼?不能負起責任、保證成果的實作,對別人來說還有意義嗎?我不是為了「能更快、更好地做到更多的事情」而學習了程式語言,但為何不敢像其它接外包案的人一樣地實作呢?我喜歡在blog分享所得所學,那為什麼覺得在期刊上發表,是一件搖不可期的事情呢?

我沒有自信,是因為沒有做過。

我沒有做過,是因為沒有機會去做。

我沒有機會,是因為沒有去把握。

我沒有把握,是因為沒有理由。

我沒有理由,所以繼續學習,繼續思考,究竟未來該怎麼做才好。

(more...)

雲端同步待辦事項工具:RTM + Astrid

布丁布丁吃布丁

雲端同步待辦事項工具:RTM + Astrid

image

你有在用待辦事項(todo)嗎?以往大家常常會拿個3M浮貼紙,貼在顯眼的書桌旁;或是拿個隨身記事本,把待辦事項記著、劃掉。現在時代來到了電腦、網路、智慧型手機,以及雲端服務的技術盛行,我也打算使用電腦與手機來處理待辦事項。經過一番研究,最後我找到的方案是以知名的RTM (Remember The Milk)Android上的軟體Astrid來搭配的雲端同步待辦事項工具。


記得喝牛奶:Remember The Milk (RTM)

image

Remember The Milk,簡稱RTM,這是一個非常知名的「待辦事項」網頁服務。基本使用是免費的,只要透過網路連上RTM的網頁,就能夠像是Gmail一樣地簡單使用。只有需要透過手機同步需求的人才要付費購買額外的服務。

豐富的功能

image

RTM的功能之豐富,根本就不只是拿來應付「記得喝牛奶」這種小事情。舉例來說,RTM除了清單、地點、3等級的優先順序、筆記(多行的任意純文字記事)、日期提醒(跟Google行事曆整合)等基本功能之外,還有可離線使用、多重筆記、標籤分類、延期、清單封存等很棒的功能可以使用。特別是多重筆記功能,允許一項待辦事項記錄多篇筆記,這對我來說實在是太重要了。另一項隨著Gmail而廣為人知的Google Task只有RTM的基本功能水準,無法滿足我的需求。

附帶一提,RTM並沒有夾帶附檔的功能。儘管RTM能夠附上純文字的筆記,但是他並沒有提供像是ProducteeV的附檔功能。這部份似乎已經超過了一個待辦事項服務基本的能力,就算是ProducteeV也只有提供100MB的空間,其實也不是很堪用。我通常會利用Google DocSkyDriveDropbox的Public Link來保存待辦事項的檔案,然後將檔案的網址記錄在RTM中方便查閱。

同步付費限制

儘管RTM功能豐富,但是它僅能靠電腦網路連線使用,對手機同步有付費的這個限制讓我望之卻步。就如我之前利用XMind與Thinking Space寫論文中提到過的,在電腦前面的時候是專心作事,而離開電腦時卻比較容易想「要做什麼事」。而想到什麼就隨手記下,這是我對待辦事項的一個很重要的需求。也因此,有段期間我改用Google Task來記錄待辦事項,但卻常常苦於它功能的不足。

還好,Astrid的出現,又讓我回到了RTM的懷抱。

Android的待辦事項工具:Astrid小章魚

image

Astrid,由於他的圖示就像是上圖一樣,所以也不少人將之暱稱小章魚。

同樣豐富的功能

20110505202033

這是Android智慧型手機系統上面的一個工具,提供了幾乎能與RTM並駕齊驅的豐富功能:清單與標籤分類、分級、筆記,也能夠以2x2的Widget呈現在手機的Home畫面中。

遺憾的是它的操作並不是很流暢,而且並不支援RTM的多重筆記編輯(雖然能看到每一篇筆記內容,但僅有第一篇可以編輯而已。)

RTM同步

20110505201827

縱使Android上的待辦事項多到不勝枚舉,但是Astrid能與RTMGoogle TaskProducteeV等有名的待辦事項服務同步的功能,仍讓我對他愛不釋手(就像他的網址一樣,We Love Astrid)。 

你可能會發現到有點怪怪的,可以跟RTM同步?是的,這是讓我最驚艷的地方,Astrid可以跟RTM同步,而且沒有RTM的付費限制。似乎是RTM有開放部分的API,而Astrid應用了他的API來實作同步功能,因此我們可以在手機離線時使用Astrid增加待辦事項,連上網路時再進行同步整合資料。

不過由於RTM的使用限制,Astrid的RTM同步版本跟主要版本是分頭進行。實際上,一開始Astrid雖然把RTM同步當做主打功能之一,但是同步的結果卻有很多bug,直到現在才比較穩定。如果你是以RTM同步需求為主,請下載Astrid – RTM (No Add-ons) Version,或是我備份到SkyDrive的檔案來安裝。


RTM+Astrid新增待辦事項作法

接下來,我就以實際的說明,介紹我是怎麼利用RTM+Astrid的待辦事項來完成我日常生活中的工作。

1. 建立清單

image

RTM跟Astrid都支援了「清單」的功能,他就是一個待辦事項的列表。通常我會將一項計畫獨立一個清單,然後在該計畫完成之後,利用RTM的「清單封存」功能來封存該清單。

image

接著在Android手機中加入Astrid的widget(HTC翻譯為「小工具」)。Astrid的一大特色就是可以為widget設定「篩選條件」。除了指定單一清單之外,也可以指定多個清單混合,或是指定標籤、未列入標籤的待辦事項,並且允許使用者設定顯示待辦事項的排列順序,功能十分強大。

我以「2011碩士論文」清單為篩選條件,在HOME畫面中建立了一個2x2的Astrid widget,直接點選的話就會開啟該清單。

這樣子準備工作就完成了。

2. 新增待辦事項

image

平常生活中,待辦事項的需求總是隨時隨地會出現。如果在電腦前,我會直接使用RTM網站中的功能來新增;如果不在電腦前,那就是用Astrid來新增囉。

20110505205430

進入Astrid清單後,可以直接從最下面的快速新增列輸入文字來新增待辦事項。

20110505205243

由於手機並不適合打字,所以我通常都會用簡短、不要求正確的方法來輸入,只要自己看得懂即可。

20110505205556

Astrid的編輯功能非常豐富,但我通常只會用到「主旨」、「重要性」跟「備註」(對應到RTM的「待辦事項」、「優先順序」跟「筆記」)而已。

3. 手機同步與電腦上編輯

20110505205750

設定好Astrid與RTM的同步功能之後,以後如果在網路可以連接的地方,Astrid的menu就會出現「Sync Now!」的立即同步功能。同步速度很快,馬上就可以同步完成。但如果網路有問題導致Astrid同步失敗的話,卻也不會出現提示畫面,這讓我有點困擾。

image

同步之後,RTM很快地就會顯示剛剛新增的待辦事項。同樣的,在RTM這邊修改、新增的待辦事項,也會同步到Astrid去喔。

image

我通常會利用「筆記」的功能,幫待辦事項寫上更詳細的內容。而之後如果該事項還有需要補充的東西,則可以繼續寫在「筆記」當中。

4. 待辦導向工作法

image

每天一早起來,我還是昏昏沉沉,不知道該先做什麼的時候,一天的第一件工作就是打開待辦事項啦。

這是我在寫論文程式KALS系統時使用待辦事項的列表內容。我在撰寫程式的過程中常常使用待辦事項來管理要做的事情:

image

目前進度:我會將此待辦事項設為最高優先度,這樣每次檢視待辦事項清單時,我就可以知道我的進度到哪裡。每次做到一個段落,我就會更新這個待辦事項,並把進度的細節寫在筆記當中。

image

利用標籤分類:寫程式時也有不同的待辦事項分類,「todo」是預備要做的功能、「bug」是程式中需要修復的問題、「coding_style」則是撰寫程式時需要注意的規則。

image

每當完成一個項目時,就可以將該待辦事項設定為「完成」。每次完成一個待辦事項,並把它勾選完成的這個瞬間總是讓我感到非常有成就感。

5. 回顧已完成的待辦事項

image

RTM中你可以回顧該清單已經完成的待辦事項,也可以將已完成的事項再切換回「未完成」的狀況。

對我來說,回顧已完成功能就像是日記一樣,可以讓我回顧我到底做了些什麼、當初到底怎麼做的。這也讓RTM待辦事項添增了許多額外的價值。


結語

其實我很久之前就想寫RTM+Astrid的介紹,只是一開始我在等待Astrid對RTM同步功能的穩定,然後後來又投入寫程式、寫論文的工作中,這一篇就一直被耽擱到現在。

其實RTM的應用方式非常地多樣化,常常可以看到別人在宣揚他使用RTM的心得。不過對我來說,能隨時隨地地新增、查閱待辦事項,這才是我使用RTM+Astrid的主要目的。

在meeting的時候,常常會聽到老師唸同學「你們常常都不知道自己要做些什麼,上禮拜說過的事情這週就忘了,這樣子很糟糕」,然後就會拿出他記滿待辦事項的Word給同學參考。老師的苦口婆心甚是中肯,不過我覺得用RTM+Astrid會是一個更好的待辦事項方案。

希望大家也能做好個人管理。不知道要做什麼、或是閒閒沒事的時候,就順手打開RTM,看一看未來該前進的方向吧。

image

p.s. BLOG POST的待辦事項又可以減少一項,爽!

(more...)

用Zotero輸出中文、英文不同的APA參考文獻:我的碩士論文參考文獻製作過程

用Zotero輸出中文、英文不同的APA參考文獻:我的碩士論文參考文獻製作過程

image

雖然我使用Zotero來管理參考文獻的書目資料,但是在撰寫論文的時候一定會碰到一個問題:要怎麼區別中文跟英文的書目?大部分系所對於參考文獻的要求都會希望將「中文文獻」與「英文文獻」分開列表、各自有不同的輸出樣式,但是對Zotero來說並沒有中英之分,只能使用同一種樣式來處理。這對於剛接觸Zotero的人來說是非常地困擾,甚至有人提出了中文用Zotero、英文用EndNote的這種作法,但我個人並不喜歡將文獻分散於多個軟體,造成難以管理的困擾,所以我仍堅持用Zotero來實作中英文不同的參考文獻。

要用Zotero做到這點,其實手續非常多,不見得是一個很理想的作法。但不論如何,還是比不使用書目管理軟體、呆呆地手動輸入還來得快得多就是。


作法概述

這邊我以自己寫論文時使用中英文不同的APA格式的作法為例子,介紹整個的作法。安裝Firefox與Zotero以及額外需要使用的中文APA等資訊,請參考我之前寫的中文APA。這一篇是從這些環境已經配置好、也蒐集好必備的書目資料為前提,主要描述從撰寫正文及指定引用文獻開始,到最後整理參考文獻的作法。必須要強調的是,關於中文書目的輸入書目作法,還請參考中文APA的說明及APA規範來仔細檢查、整理,畢竟有乾淨的書目資料才能有漂亮的參考文獻格式。

步驟大致上分成三個階段,

  1. 撰寫正文前的準備
  2. 正文中的引用
  3. 參考文獻的整理與輸出

作法有點繁瑣,以下一一敘述。


步驟1. 撰寫正文前的準備

image

安裝好Zotero並建立了許多可以用的書目格式之後,現在我們要利用Microsoft Word 2007來撰寫一篇文章。在開始撰寫正文之前,我們先配置一下Zotero的相關設定。

1. 開啟增益集中的Zotero選項

image

Zotero並沒有獨立的工具列,而是包含在「增益集」裡面。

2. 選擇引用文獻樣式

image

請點選倒數第二個選項「Zotero Set Doc Prefs」。

image

這是Zotero很大的一個缺點:一份文件只能用一種樣式。而這也是這一篇文章想要解決的一個問題。

此處我們先選擇「American Psychological Association 6 th Edition」(APA),因此之後正文中的引用會以英文APA的方式顯示,而中文的書目就必須手動修改。

接下來,我們就可以開始寫正文了。


步驟2. 正文中的引用

正文中有參考到文獻的地方,都必須在正文中標示引用。這不僅是給予作者尊重,也是在最後整理參考文獻列表的重要步驟。我都是在寫作的同時,一條一條地加入引用,在撰寫正文的同時一併處理。

利用Zotero在正文中引用的情況很多變化,在這邊我舉出六種不同的引用狀況,以及各自需要修改、調整的地方來說明。

1. 英文,顯示作者

image

我寫了一段話「標註共識的構想是來自於社群指引支援(Social Navigation Support)的概念」,而我想要再這句話後面標註這是來自Dieberger等人的文章。

image

此時先將游標放在要插入引用的位置,然後點下Zotero工具列的「Zotero Insert Citation」。

image

找到你要引用的這篇文章,然後按下右下角的「確定」。

image

現在引用已經順利插入了。這是Zotero最基本的用法,不需要任何其他的修改動作。

2. 英文,不顯示作者

image

現在我寫了一段話:「閱讀理解策略中最有名的莫過於Robinson提出的SQ3R」,而我想要在「Robinson」後面標示這是引用自1970的文章。

作法一樣是將游標放在「Robinson」後面,也就是要插入引用的地方,然後開啟「Zotero Insert Citation」。

image

在「新增/編輯引用文獻」的對話視窗中,這次要勾選右下角的「不顯示作者」,然後按下「確定」。

image

這樣子插入的引用就只會顯示年份。

3. 中文,顯示作者

image

現在我寫了一段教育研究者提出的三種模式,引用自王瓊珠與陳淑麗的書本。

通常這個引用我會放在「句號」前面,所以此時將游標放在句號前,再開啟「Zotero Insert Citation」。

image

找到要引用的文獻之後,按左下角的「顯示編輯器」按鈕。

image

這邊會顯示Zotero預設要插入的格式:「(王瓊珠 & 陳淑麗, 2010)」。因為我們一開始選擇用的是英文APA,所以括弧、逗號等標點符號都是半型表示。這邊就只能手動進行修改。

image

將符號改成全型,再將「&」改成「、」,就成了叫為合適的:「(王瓊珠、陳淑麗,2010)」。這樣子再按下「確定」輸出即可。

image

輸出之後的樣子如上圖。

4. 中文,不顯示作者

image

現在我又引用了王瓊珠與陳淑麗的書本內容,這次我把他們的名字寫出來了,所以接著引用中我只需要表示年份即可。

確定游標的位置在作者名字後面,然後開啟「Zotero Insert Citation」。

image

這次一樣勾選「不顯示作者」,然後打開編輯器,將半型的括弧「(2010)」修改成全型的括弧「(2010)」,然後按下「確定」輸出。

image

這樣就完成了。

5. 中文,多重來源,顯示作者

image

這邊我寫了一段話:「許多學者不斷改進他們的方法,而提出了各種不同的閱讀理解策略」,此處的「許多學者」是引用來自多篇不同的文獻,而引用的方式也比較複雜。

一樣先將游標放在要標示引用的地方,然後開啟「Zotero Insert Citation」。

image

基本上,Zotero預設只能選擇一個來源,但他也提供了「多重來源」的模式,方便一次引用多個文獻來源。請按下左下角的「多重來源」來切換到多重來源模式。

image

接著右方會出現多重來源的列表。這時候你就可以來找你要引用的文獻,並按右方箭頭「→」圖示來將它加入列表中。

image

接著打開編輯器來調整。Zotero會聰明地依照作者名字排序,但是標點符號依然要從半型轉換成全型:「(王化龍, 1991; 林乾義、關爾嘉,2002;柯華葳,2009;馬沙諾,2003;廖仁武,1998;劉明兆、余德慧,1982)」。修改完之後再按下「確定」輸出。

image

完成。

6. 中英多重來源,顯示作者

最後必須要提醒的是中英多重來源的情況,我的論文中並沒有出現這種資料,所以在此我根據「學術論文寫作:APA規範」一書來說明。

如果同時引述中文與英文文獻時,需注意以下事項:

  • 最外為的括弧仍是以「全型」為主
  • 先引證中文文獻之作者與年代,再引述英文文獻之姓氏與年代
  • 兩者之間應以全型之分號「;」分隔
  • 年代宜統一以西元年代呈現
  • 中文文獻之標點符號一律以「全型」輸入,英文文獻之標點符號則以「半型」輸入

舉例:

  • (張保隆,2005;Chang, 2003)
  • 相關研究(張保隆、謝寶煖,1996;謝寶煖,1997;Chang & Hsieh, 1993, 1996; Good, 1990)

詳細的細節,還是請參考「學術論文寫作:APA規範」喔。

因為需要注意的事項頗多,Zotero無法聰明地幫你區分中文跟英文,所以這部份一樣得用編輯器慢慢修改才行。


步驟3. 參考文獻的整理與輸出

image

寫完正文之後,參考文獻的引用應該也差不多了。接下來,我將說明到底如何將這些參考文獻分成中文與英文兩種。

1. 輸出參考文獻列表

image

在正文最後,也就是預定插入參考文獻的地方,使用Zotero的「Zotero Insert Bibliography」功能。

image

Zotero會幫你在正文中引用的文獻彙整出一個列表,按照作者排序。這個列表就是你文章寫到最後全部引用的所有文獻了。

2. 為所引用的文獻加上標籤

接下來我們為這篇正文所引用的文獻加上「標籤」。因為這次我要寫的是碩士論文,所以我的標籤定為「2011碩士論文」。

image

對照參考文獻列表,回頭去找尋Zotero中的文獻。上圖中,我找到了引用的「讀寫新法」,並在「標籤」欄位中幫該文獻加上了「2011碩士論文」的標籤。

這個手動的步驟儘管很麻煩,但標籤只要1. 複製 2. 貼上 3. enter就能加入,其實挺快就能處理完畢。

3. 儲存英文文獻的搜尋結果

幫這篇正文被引用的文獻都加上標籤之後,我們就能用進階搜尋快速地製作參考文獻列表。

image

在Zotero面板的工具列中,打開放大鏡圖示的「進階搜尋」。

image

搜尋條件設定兩個:

  1. 標籤、是、2011碩士論文
  2. 語言、不含有、zh_

條件1能夠找出標籤是「2011碩士論文」的文獻,而條件2則是過濾掉英文文獻的作法,稍後再敘述這個用意。

image

搜尋出來的結果,請按「儲存搜尋」。

image

為存留搜尋命一個名稱:「2011碩士論文 英文文獻」。

image

這樣Zotero就會幫你把搜尋結果儲存起來。

image

接著再檢查一下這個清單裡面是否有參入中文文獻。如果有的話,則幫此文獻的語言加入正體中文「zh_TW」或簡體中文「zh_CN」的資料。

4. 儲存中文文獻的搜尋結果

image

接著來建立中文的參考文獻。作法一樣是使用進階檢索,搜尋「標籤 是 2011碩士論文;語言 含有 zh_」的結果,並儲存搜尋成為「2011碩士論文 中文文獻」。

image

這樣子就建立好中文與英文兩個參考文獻的列表了。

5. 由搜尋結果建立參考文獻

有了中文與英文兩個列表之後,接下來就以不同引用文獻樣式輸出參考文獻列表。

image

先做中文文獻的列表。在中文文獻的存留搜尋上按右鍵,選擇「由存留搜尋來建出參考書目」。

image

接著選擇引用文獻樣式。由於是中文的參考文獻,所以就選擇我自己做的American Psychological Association in Pulipuli中文APA樣式吧,同時選擇「複製到剪貼簿」,最後按下「確定」。

image

再來到Word中「貼上」,就完成中文參考文獻的輸出。

image

接著再用同樣的步驟來輸出英文文獻,只是這次的引用文獻樣式要選用英文的「American Psychological Association 6th Edition」。

image

然後貼到Word中,完成輸出。一開始由Zotero建立的中英混雜參考文獻列表則已經可以移除了。

最後還要檢查一下Zotero輸出的格式是否正確。中文APA輸出時需要注意多作者的「、等」之類的問題,詳細請看這篇的說明


結語:如果還要修改參考文獻的話

步驟3強烈建議等到論文都定稿了再來處理。然而在這個工程做完之後,如果未來因為修改內文而刪增參考文獻的話,則只要把文獻的標籤做增減即可。這種作法不能全自動地偵測、判斷,的確是Zotero力有未逮之處。希望未來他還能夠繼續改良。

在寫這篇文章的時候,我發現到有人設計了多語系Zotero (Multilingual Zotero),我想改天再來試試看這究竟能不能改善Zotero這方面的問題,希望他可以。

如果有更好的方案,也請大家多多建議喔。

(more...)