2010年10月11日 星期一

OPDS Catalog Validator

OPDS Catalog 是從 Atom 那邊擴充的,相關的驗證工具:



但如果想要驗證 OPDS Catalog 1.0 的規格,這些都還不夠用。而後終於找到一個可以驗證的方式:



使用方式也要稍作設定:



  • Address : 你的 opds url

  • Schemas

    • http://openpub.googlecode.com/svn/trunk/schemas/atom.rnc

    • http://openpub.googlecode.com/svn/trunk/schemas/opds_catalog.rnc



  • Preset:None

  • Parser:XML; load external entities

  • 勾選 'Be lax about HTTP Content-Type'


2010年10月8日 星期五

[Javascript] EPUB Reader 翻頁效果的原理

幾天前收到一個問題,關於坊間常見得 Javascript 版 EPUB Reader ,他們處理翻頁的效果是怎樣做的呢?


可以看看以下的 Demo:



Javascript EPUB Reader 的實作,原理就是將 EPUB 裡頭以XHTML、HTML單一檔案為單位,把整個 XHTML 弄成一個物件擺入指定的 DIV 裡頭,藉以顯示出來,就像用瀏覽器瀏覽 XHTML 檔案一樣。如此一來,只是透過 Javascript 去抽取該 XHTML 內的資料出來呈現。


至於翻頁的效果呢?假設要呈現的內容範圍是 640x480,以 ePub js 的原始碼看來,先產生一個 div-tmp ,動態把一個 XHTML 的資料,以 <p> 為單位地,慢慢地一個個加入到 div-tmp,並且動態地查看 div-tmp 的高度,若超過 480 時,則把前一個才加入的 <p> 內容,以空白切字,從後面慢慢地移出一個字出來,直到 div-tmp 的高度滿足 480 的限制,並且把移出來的內容另外建立一個新的 <p> 並擺在其後,以便下一頁的使用。而 rePublish 也是使用類似的概念,細節可以 rePublish - paginator.js 看到。


但是,以空白切字是有危險的,例如僅適用於英文字這種好切的語言,因此我嘗試使用 Monocle 發現他並沒有切字切不好的現象,再仔細一看,發現他的實作方式並非使用切字、填補的方式,並採用兩個 div 的處理機制。而後發現使採用 CSS Multi-column Layout Module (W3C Candidate Recommendation 17 December 2009)。


概念就是產生兩個 div ,一個是現在的這頁,另一個是下一頁用來顯示的,假設這兩頁是同一份的 XHTML 資料,且這個 XHTML 檔案不分頁顯示時,呈現共佔 640x800 大小,那第一頁就類似顯示 640x480,剩下的 640x(800-480) 之後的內容。然而,這樣還可能存在邊界關係,例如第一頁的最後一列,可能會整列因為視窗大小不夠顯示,而把整列的字都切了一半。實際測試,發現並沒這個問題,我用 Firebug 去觀察相關的 div style,整理一個小範例:


<html>
        <head>
                <title>Monocle Test</title>
                <style type="text/css">
                        #container
                        {   
                                width: 100%;
                                height: 100%;
                                position: relative;
                        }   
                        #show {
                                position: absolute;
                                top: 1em; bottom: 1em; left: 1em; right: 1em;
                                overflow: hidden;
                        }   
                        #content
                        {   
                                position: absolute;
                                top: 0pt; bottom: 0pt; min-width: 200%;
                                -moz-column-gap: 0pt; -moz-column-width: 1219px;
                        }   
                </style>
        </head>
        <body>
                <div id="container">
                        <div id="show">
                                <div id="content">
                                        <p>  詞曰:滾滾長江東逝水,浪花淘盡英雄。是非成敗轉頭空:青山仿舊在,幾度夕陽紅。白髮漁樵江渚上,慣看秋月春風。一壺
濁酒喜相逢:古今多少事,都付笑談中。</p>
                                        <p/>
                                        <p>  話說天下大勢,分久必合,合久必分:周末七國分爭,并入於秦。及秦滅之後,楚、漢分爭,又并入於漢。漢朝自高祖斬白蛇
而起義,一統天下。後來光武中興,傳至獻帝,遂分為三國。推其致亂之由,殆始於桓、靈二帝。桓帝禁錮善類,崇信宦官。及桓帝崩,靈帝即位,大將軍竇武、太傅陳蕃,共相>輔佐。時有宦官曹節等弄權,竇武、陳蕃謀誅之,作事不密,反為所害。中涓自此愈橫。</p>
                                        <p/>
                                        <p>  建寧二年四月望日,帝御溫德殿。方陞座,殿角狂風驟起,只見一條大青蛇,從梁上飛將下來,蟠於椅上。帝驚倒,左右急救
入宮,百官俱奔避。須臾,蛇不見了。忽然大雷大雨,加以冰雹,落到半夜方止,壞卻房屋無數。建寧四年二月,洛陽地震;又海水泛溢,沿海居民,盡被大浪捲入海中。光和元>年,雌雞化雄。六月朔,黑氣十餘丈,飛入溫德殿中。秋七月,有虹見於玉堂;五原山岸,盡皆崩裂。種種不祥,非止一端。</p>
            
                                </div>
                        </div>
                </div>
        </body>
</html>


可以使用 Firefox 瀏覽器瀏覽上述內容,並且試著把視窗的高度縮小,可以發現並不會造成最後一列字被切一半。原理就是使用 css 來處理。另外一提的,#content 裡的 -moz-column-width 是跟我的視窗大小有關,測試時要改一下囉。


而 Moncle 使用的技巧就是上面的東西,再加上一個 Display Screen 的移換,將上述的 CSS 更新:


<style type="text/css">
    #container
    {
        width: 100%;
        height: 100%;
        position: relative;
    }
    #show {
        position: absolute;
        top: 1em; bottom: 1em; left: 1em; right: 1em;
        overflow: hidden;
    }
    #content
    {
        position: absolute;
        top: 0pt; bottom: 0pt; min-width: 200%;
        -moz-column-gap: 0pt; -moz-column-width: 320px;
    }
</style>


呈現的樣貌:


CSS Pagination


因此關於切換頁面的部份,就只是移換要顯示的框框位置,上例就是左邊為第一頁,右邊是第二頁


2010年9月30日 星期四

OPDS Catalog 1.0 筆記

OPDS Catalog,一種制式的書籍資訊的呈列方式,其他對應的例子以 RSS 最廣為人知。而 RSS 也是一種制式格式,常用在 Blog 文章、新聞發布,當然,連現在流行的微網誌也有部份提供,讓各家閱讀器可以透過統一的格式讀取資訊,讓使用者可以只用一款閱讀器軟體,把他想要追蹤的資訊通通透過 RSS 訂閱起來,十分方便。而 OPDS Catalog 也是要提供這種制式的規範,以便各家閱讀器可以方便處理,只是,OPDS Catalog 著眼的是書籍資訊的傳播,產生的 OPDS Catalog 則是常用在電子書閱讀器上。


因為 OPDS Catalog 規範的事宜包括電子書可提供的交流方式,因此,除了呈列書單外,還可提供額外的連結導向到書籍供應者,例如直接下載、借書等等,在 Catalog 1.0 就定義了以下可能的情境:


http://opds-spec.org/acquisition
http://opds-spec.org/acquisition/open-access
http://opds-spec.org/acquisition/borrow
http://opds-spec.org/acquisition/buy
http://opds-spec.org/acquisition/sample
http://opds-spec.org/acquisition/subscribe


其中 acquisition 算是通用的,若要細分,則有公開書籍(open-access)、借書(borrow)、買書(buy)、部份內容(sample),而 subscribe 有時也用在其他未定義的項目。因此,關於一本書的來源之範例描述:


<link rel="http://opds-spec.org/acquisition" href="/content/free/4561.epub" type="application/epub+zip"/>
<link rel="http://opds-spec.org/acquisition" href="/content/free/4561.mobi" type="application/x-mobipocket-ebook"/>
<link rel="http://opds-spec.org/acquisition/buy" href="/content/4561.pdf" type="application/pdf">
    <opds:price currencycode="USD">18.99</opds:price>
    <opds:price currencycode="GBP">11.99</opds:price>
</link>


其中 rel 代表這本書來源的狀況,而 href 則是連結位置,type 則是檔案的型態,可以用在讓電子書閱讀器挑選它支援的格式,常見格式:


application/epub+zip
application/pdf
application/x-mobipocket-ebook


另外,書籍來源要付費時,此例是 http://opds-spec.org/acquisition/buy,則可以使用 opds:price 的標籤進行價格和貨幣的描述。


接著,既然在電子書閱讀器上使用,那來個書籍封面的顯示也不為過吧!來個一張大圖,一張小圖,讓閱讀器依狀況使用:


<link rel="http://opds-spec.org/image" href="/covers/4561.lrg.png" type="image/png"/>
<link rel="http://opds-spec.org/image/thumbnail" href="/covers/4561.thmb.gif" type="image/gif"/>


經過上述的描述後,也差不多都有提到關鍵的東西,接著看一下一則書籍的描述吧,此時就將顯示很多想得到的資訊,如書籍標題、作者、發佈日期、語言、分類、摘要、簡短內容等等:


  <entry>
    <title>Bob, Son of Bob</title>
    <id>urn:uuid:6409a00b-7bf2-405e-826c-3fdff0fd0734</id>
    <updated>2010-01-10T10:01:11Z</updated>

    <author>
      <name>Bob the Recursive</name>
      <uri>http://opds-spec.org/authors/1285</uri>
    </author>
    <dc:language>en</dc:language>
    <dc:issued>1917</dc:issued>
    <category scheme="http://www.bisg.org/standards/bisac_subject/index.html"
              term="FIC020000"
              label="FICTION / Men's Adventure"/>

    <summary type="text">The story of the son of the Bob and the gallant part
      he played in the lives of a man and a woman.</summary>
    <content type="text">The story of the son of the Bob and the gallant part
      he played in the lives of a man and a woman. Bob begins his humble life
      under the wandering eye of his senile mother, but quickly learns how to
      escape into the wilder world. Follow Bob as he uncovers his father's past
      and uses those lessons to improve the lives of others.</content>

    <link rel="http://opds-spec.org/image"
          href="/covers/4561.lrg.png"
          type="image/png"/>
    <link rel="http://opds-spec.org/image/thumbnail"
          href="/covers/4561.thmb.gif"
          type="image/gif"/>

    <link rel="self"
          href="/opds-catalogs/entries/4571.complete.xml"
          type="application/atom+xml;type=entry;profile=opds-catalog"/>

    <link rel="http://opds-spec.org/acquisition"
          href="/content/free/4561.epub"
          type="application/epub+zip"/>
    <link rel="http://opds-spec.org/acquisition"
          href="/content/free/4561.mobi"
          type="application/x-mobipocket-ebook"/>
 </entry>


接著,就是關於把一堆書整理成清單的事情了,常見的清單有熱門書籍、最新書籍、依字母順序等等的,你想的到的都差不多有了:


http://opds-spec.org/sort/new
http://opds-spec.org/sort/popular
http://opds-spec.org/featured
http://opds-spec.org/crawlable
http://opds-spec.org/shelf
http://opds-spec.org/subscriptions
subsection


其中 sort/new 顧名思義就是照發佈日期排序,而 sort/popular 則是熱門程度,其他的就沒有順序的要求,但也可以用 subsection 提供依照字母排序的清單,上述比較特別的有 crawlable 這個字樣,提供像 Search Engines 這類服務撈資料用的。


當書單很大時,該怎麼辦? OPDS Catalog 是建立在 Atom 上,因此可以提供分頁功能:


<link rel="self" href="alpha_1.xml" type="application/atom+xml;profile=opds-catalog"/>
<link rel="first" href="alpha.xml" type="application/atom+xml;profile=opds-catalog"/>
<link rel="last" href="alpha_2.xml" type="application/atom+xml;profile=opds-catalog"/>
<link rel="previous" href="alpha.xml" type="application/atom+xml;profile=opds-catalog"/>
<link rel="next" href="alpha_2.xml" type="application/atom+xml;profile=opds-catalog"/>


其中,每一頁應該都會提供 self, first 和 last 的資訊,剩下的就依照資料量跟頁數的資訊,提供 previous 跟 next 的資訊,例如第一頁不該有 previous 而最後一頁也不該有 next 等。



以上範例等資訊來自於:


http://opds-spec.org/specs/opds-catalog-1-0


更多細節請參考 OPDS Catalog 1.0


相機配腳架

相機配腳架


這是跟同事借的腳架,才過沒幾次,就覺得還挺不錯的,更多細節可以參考這邊:Joby Gorillapod - 章魚小腳架


這台相機是我家第二台數位相機,第一台相機已經壞了,是 Acer 5xxx 的相機!我家買相機都是買最便宜的,直到最近工作穩定才買了稍微好一點的相機,大概五千元吧!不多說,再放幾張這兩天是拍的,都是用夜景模式。


2010/09/30 18:10 公園宿舍 2010/09/29 公園宿舍


有時看到美景會迫不及待地想要拍,但轉個角度想想,難道在路上看到正妹就要去搭訕嗎?所以,一切還是隨緣拍吧


[Python] 使用 Comma-separated values (CSV)

Comma-separated values (CSV) 就是以逗號為欄位分隔,並以 line-based 的儲存格式,細節可參考 Wikipedia - Comma-separated values


在 Python 裡也有對應得 lib 可以用,只需 import csv 就行啦


範例:


csvfile = open( target_file , 'rb' )
dialect = csv.Sniffer().sniff(csvfile.read(1024))
dialect.escapechar = '\\'
dialect.lineterminator = '\n'

csvfile.seek(0)
for row in list(csv.reader( csvfile , dialect=dialect , delimiter=',' ) ):
        print "====" , len(row) , "===="  , row