2016年5月30日 星期一

CSS3 Box Model

CSS3 Box Model

簡介

所謂的方塊模型 (box model) 是流覽器排版的基本模型,在流覽器中每一個元件都使用這個模型來表示其佔據的版面空間。方塊模型分為四大區域,由內至外為:內容(content), 留白 (padding), 邊框 (border) 及 邊界 (margin) 四個區域,除了中央的內容區 (content) 為完整的區塊外,其它三個區域都以外框的形式存在,又各依上 (top)、右 (right)、下 (bottom)、左 (left) 四個方位,分成四個小區域。模型的各區域名稱及用途如下圖所示,特別注意背景色 (background color) 及背景圖片 (background image) 所佔的區域包含了留白的區域,因此將圖片設定為內容或背景時,兩者所會佔據的空間並不相同。

CSS 的屬性 box-sizing 用來設定方塊模型所要使用的模式。有二種模式可以設定:content-box 及 border-box;content-box 為流覽器的預設模型。

當 box-sizing 設定為 content-box 時,屬性 width 及 height 的值設定內容 (content) 區域的寬及高。整個元件所佔的空間為 width 及 height 的值,疊加四方的留白、邊框及邊界的寬度。

當 box-sizing 設定為 border-box 時,屬性 width 及 height 的值設定邊框 (border) 區域外圍的寬及高(包含邊框四方的寬度)。整個元件所佔的空間為 width 及 height 的值,加上四方邊界的寬度。

一般在排版時,會先考慮整體版面的寬度,因為寬度會受到螢幕大小的限制,所以會先決定元件的寬度、左右留白、及左右邊界。高度則因為可以延長,超過螢幕高度時,可以產生捲動軸 (scroll bar) 捲動螢幕查看超出螢幕的內容部份,上下留白及上下邊界的主要作用在區分垂直排列的元件,因此可以設定為 auto。除非是像一般的桌上型應用程式,所謂的單頁式 (one page design) 設計;版面的寛和高都以螢幕的寬和高為基準,只改變各區域的內容,此時比較有機會同時設定固定的寬度和高度。另一個要考慮的是元件是否具有邊框或背景顏色,不具邊框及背景顏色的元件其邊界和留白會連接在一起,在這種情況下同時設定邊界和留白,在視覺上很可能會造成左右相隣元件或上下相隣元件之間的間距過寬。

範例

範例中設定了一個背景為淡綠色的容器,內含兩個區塊,區塊的 width 和 height 都設定為 150px;四個方向的留白、邊框和邊界都為 10px;但 box-sizing 屬性的設定上,一個為 content-box,另一個為 border-box。當顯示在流覽器中時,可以明顯的看出兩個區塊在尺寸上的差異。box-sizing 設定為 content-box 的區塊(位於容器上方的區塊),所佔據的空間寬度和高度為 210px * 210px;而 box-sizing 設定為 border-box 的區塊(位於容器下方的區塊),所佔據的空間寬度和高度則只有 170px * 170px。

CSS

<style>
html {
    width: 100%;
    height: 100%;
}
body {
    margin: 0 auto;
    width: 1000px;
    padding: 20px;
}
.container {
    width: 400px;
    height: 400px;
    border: 10px solid black;
    background-color: lightgreen;
}
.element {
    width: 150px;
    height: 150px;
    margin: 10px;
    border: 10px solid gray;
    padding: 10px;
    background-color: coral;
}
.content {
    box-sizing: content-box;
}
.border {
    box-sizing: border-box;
}
</style>

在 CSS 中,使用 CSS 類別的方式來設定元件的屬性。.element{} 設定了兩個元件在 width, height, margin, border, padding 等屬性都具有相同的值,而 .content{} 及 .border{} 則為 box-sizing 設定了不同的值,藉以比較不同的設定在所佔空間上的差異。

HTML

<body>
    
content-box
border-box
</body>

HTML 中簡單的建立了三個區塊,其中一個為容器,包含在容器中的為兩個元件區塊。

2016年5月23日 星期一

CSS3 Columns

CSS3 Columns

簡介

我們在報紙或雜誌上時常看到直欄的排版方式,這是因為當文字列過長,在讀到列尾時,眼睛要回頭找下一列文字的開頭並不容易;因此,將長列的文字以直欄的方式排列,縮短列寬,閱讀起來就輕鬆多了。CSS3 有一組相關的屬性專門用在直欄的排版,但時至今日 (2016-05-22) 各大流覽器的支援尚未一致,行為模式也略有不同,使用時需多加留意。Chrome 及 Safari 在屬性前需加前綴 -webkit-,Firefox 在屬性前需加 -mz-,至於 IE,直到 IE10 才有原生支援,使用時無須加前綴。

各直欄屬性的定義如下:

column-count
預設值為 auto,直欄個數由其它屬性 (column-width) 決定。賦予值為整數值,指定直欄個數。
column-width
預設值為 auto,直欄個數由其它屬性 (column-count) 決定。賦予值為 CSS3 的長度值,指定直欄的最小寬度。通常直欄的寬度會略大於 column-width 指定的寬度,因為流覽器是這麼處理的:將 "父元件的寬度" 除以 column-width 的值,所得商數即是直欄的個數,餘下的長度又會平均分配給各直欄。所以除非正好整除,否則直欄的寬度都會略大於 column-width 的指定值。
columns
為 column-count 和 column-width 的組合式簡寫。寫法為 columns: column-count column-width; 。這是最佳的定義方式,同時設定 column-count 及 column-width,讓視窗在改變大小時,直欄也可以相應改變其欄位數。
column-gap
設定直欄間的間隔寬度。預設值為 normal (1em),或直接賦予一個寬度值。
column-rule-width
設定直欄分隔線的寬度。有三個字串值:thin (1px), medium (3px), thick (5px),預設值為 "medium",或直接賦予一個寬度值。
column-rule-style
設定直欄分隔線的樣式。預設值為 none,就是沒有直欄分隔線。其它的樣式允許值和 border 的樣式允計值相同。
column-rule-color
設定直欄分隔線的顏色。預設值為 initial,通常就是黑色。
column-rule
column-rule: column-rule-width column-rule-style column-rule-color; 此為同時設定 column-rule-width, column-rule-style 及 column-rule-color 的簡式寫法;語法就像設定邊框 (border) 時的簡式寫一樣。
column-span
設定元件所要橫跨的欄數,預設值為 1。
column-fill
設定直欄中元件的排版方式,預設值為 balance,表示平均分配所有元件,盡可能讓所有直欄具有相同高度。

範例

範例中有一幀圖片及一段文字,用來展示如何使用 CSS3 的 column-* 屬性。當流覽器改變尺寸時,所顯示的內容也會跟著重新調整版面,當畫面縮小時,排版會從 3 直欄變成 2 直欄,最後變成一直欄。範例中將 body 的寬度設為 1000px,減去 .newspaper 左右各 20px 的 padding,正好留下 960px 的內容寬度。

CSS

<style>
html {
    width: 100%;
    height: 100%; 
}
body {
    margin: 0 auto;
    max-width: 1000px;
    background-color: #FFFFFF;  
    font-family: 'Arial', '文泉驛正黑', 'WenQuanYi Zen Hei', '儷黑 Pro', 'LiHei Pro', '微軟正黑體', 'Microsoft JhengHei';
    font-style: normal;
    font-weight: 100;
    font-stretch: normal;
    font-size: 16px;
    line-height:1.7;
    letter-spacing: 0.087em;
}
.newspaper {
    padding: 0px 20px;
    -webkit-column-count: 3;
    -moz-column-count: 3;
    column-count: 3;
    -webkit-column-width: 300px;
    -moz-column-width: 300px;
    column-width: 300px;
    /*-webkit-column-gap: 20px; */
    /*-moz-column-gap: 20px;*/
    /*column-gap: 20px;*/
    -webkit-column-rule: 1px solid gray;
    -moz-column-rule: 1px solid gray;
    column-rule: 1px solid gray;
}
.newsItem {
    margin: 0 10px;
    /*-webkit-column-break-inside: avoid;*/ /* Chrome, Safari */
    /*page-break-inside: avoid;*/           /* Theoretically FF 20+ */
    /*break-inside: avoid-column; */        /* IE 11, Opera */
    border-bottom: 1px solid gray;
}
.photo {
    width: 100%;
    height:auto;
    cursor: pointer;
}
</style>

.newspaper{} 設定了整個直欄的版面,當有足夠空間時,會排成 3 個直欄,每個直欄最小需 300px 的寬度。
.newsItem{} 設定在右 margin 為 10px,如果把註解的部份拿掉,則整個 .newsItem 會保持在同一直欄中。
.photo{} 設定圖片的寬度正好為直欄的寬度,高度則自動調整,以保持寬和高的比率。

HTML

<body>
    

摩訶般若波羅蜜多心經

觀自在菩薩。行深般若波羅蜜多時。照見五蘊皆空。度一切苦厄。舍利子。色不異空。空不異色。色即是空。空即是色。受想行識。亦復如是。舍利子。是諸法空相。不生不滅。不垢不淨。不增不減。是故空中無色。無受想行識。無眼耳鼻舌身意。無色身香味觸法。無眼界。乃至無意識界。無無明。亦無無明盡。乃至無老死。亦無老死盡。無苦集滅道。無智。亦無得。以無所得故。菩提薩埵。依般若波羅蜜多故。心無罣礙。無罣礙故。無有恐怖。遠離顛倒夢想。究竟涅槃。三世諸佛依波若波羅蜜多故。得阿藐多羅三藐三菩提。故知般若波羅蜜多咒。是大神咒。是大明咒。是無上咒。是無等等咒。能除一切苦。真實不虛。故說般若波羅蜜多咒。即說咒曰。揭諦揭諦。波羅揭諦。波羅僧揭諦。菩提薩婆訶。

</body>

HTML 中將所有的元件包覆在 .newItem 的區塊中,每個區塊則包含一個抬頭、一幀圖片及一段內容。新增的 .newsItem 都會直動以直欄的方式排列。

2016年5月19日 星期四

jQuery Loading Overlay

jQuery Loading Overlay

簡介

這篇介紹一個 jQuery 的插件 (plugin),功能是在下載文件或資料時,在螢幕或區塊中顯示遮罩 (overlay);遮罩中可以有動畫或訊息,告訴使用者流覽器正在進行下載,電腦沒有掛掉,也沒有在偷懶。網路上有很多類似功能的插件,個人覺得這個最簡單,用起來也方便;但這個插件只能用在有支援 CSS3 的流覽器上。插件的下載點和詳細說明可以在 gasparesganga.com/labs/jquery-loading-overlay/ 網址中找到。這個插件的遮罩可以遮蔽整個流覽器的螢幕,或只遮蔽指定的元件;在遮蔽元件時,螢幕上可以有多個遮罩同時存在。當遮蔽的元件改變尺寸時,遮罩也會跟著改變尺寸。顯示的動畫可以替換或自訂,或使用 Font Awesome 裡的圖像,如果要使用 Font Awesome 裡的圖像,要記得在網頁中包含 Font Awesome 的樣式表。插件只有三個函式,但函式名稱並沒有遵照一般的命名規範,第一個字母小寫,後繼再用駝峰式 (camel case),這點要留意:

$.LoadingOverlaySetup(options)
這個函式用來設定遮罩整體的各項屬性,透過這個函式設定的屬性會適用於所有後繼產生的遮罩。在隨後有各項屬性作用的介紹。
$.LoadingOverlay(action [,options])
設定全螢幕遮罩。action 參數有兩個字串值: "show" 顯示全螢幕的遮罩,"hide" 則取消全螢幕遮罩。options 屬性為選項參數,設定的屬性只會適用於這次函式所產生的遮罩。
$(selector).LoadingOverlay(action [,options])
設定指定元件的遮罩。selector 的語法和 CSS3 的選取器相容。action 和 options 參數的用法和上述函式相同。

options 的屬性如下:

color
預設值為 "rgba(255, 255, 255, 0.8)"。賦予值設定遮罩的顏色及透明度。
custom
預設值為 ""。賦予值可以是一個 DOM 元件或 jQuery 物件,這個物件會出現在遮罩的上面。設定為 "" (空字串)或 false 值時,此屬性無作用。
fade
預設值為 true,淡入歷時 400 ms, 淡出歷時 200ms。賦予值設定淡入 (fadeIn) 及淡出 (fadeOut) 所經歷的時間。只賦予一個數值時,單位為 ms;淡入及淡出的時間都等於該數值。賦予一個數值陣列時,第一個陣列數值為淡入的歷時,第二個數值為淡出的歷時;例如:[400, 200]。賦予值也可為字串 "fast" (200ms) 或 "slow" (400ms)。賦予值為 0 或 false 時,此屬性無作用。
fontawesome
預設值為 ""。賦予值為 Font Awesome 中圖像的 CSS 類別名,指定所要使用的圖像。賦予值為 "" 或 false 時,此屬性無作用。
image
預設值為 "loading.gif"。賦予值為遮罩上動畫檔案的所在位置。賦予值為 "" 或 false 時,不使用動畫。
maxSize
預設值為 "100px"。賦予值為數值或字串,設定動畫或圖像的最大尺寸,單位為 px。賦予值為 0 或 false 時,沒有限制最大尺寸。
minSzie
預設值為 "20px"。賦予值為數值或字串,設定動畫或圖像的最大尺寸,單位為 px。賦予值為 0 或 false 時,沒有限制最小尺寸
resizeInterval
預設值為 0。賦予值為數值,單位為 ms。賦予值設定當被遮蔽元件改變其尺寸時,對應遮罩改變尺寸的歷時。只有在元件被遮罩遮蔽時,同時會改變其尺寸時,才會用到這個設定。
size
預設值為 "50%"。賦予值為數值,單位為 %,用來調整遮罩動畫或圖像的尺寸,遮罩動畫或圖像的大小不會受到元件尺寸的限制,但會所限於 maxSize 及 minSize 所設定的值。賦予值為 0 或 false 時,此屬性無作用。

範例

範例中產生三個遮罩,一個全螢幕的遮罩,兩個元件遮罩,兩個元件遮罩會同時出現在螢幕上。每隔 3 秒執行一個動作,直到最終的螢幕出現。出現全螢幕遮罩前,會先看到最終的螢幕出現一下。如果要解決這個問題,可以把顯示全螢幕的 javascript 程式碼移到 <body> 的下方。圖片中所展示的是當兩個元件遮罩同時出現在螢幕的情況。

CSS

<style>
    html {
        width: 100%;
        height: 100%;
        background-color: white;
    }
    body {
        margin: 0 auto;
        width: 960px;
        height: 100%;
        padding: 20px;
        background-color: antiquewhite;
    }
    .area {
        box-sizing: border-box;
        margin: 20px;
        width:100px;
        height:100px;
        border: 1px solid black;
        float: left;
    }
    .coral {
        background-color: coral;
    }
    .lightgreen {
        background-color: lightgreen;
    }
</style>

.area{} 設定兩個區塊的共通屬性。.coral{} 及 .lightgreen{} 各設定兩個區塊的顏色。

HTML

<body>
    
</body>

HTML 中建立兩個區塊。

Script

<script>
$(function(){
    $.LoadingOverlaySetup({
        image: "../images/loading.gif",
        color: "rgb(238, 238, 238, 1)",
        // custom: $("<div>", {text: "Loading..."}),
        maxSize: "50px",
        minSize: "20px"
        
    });
    $.LoadingOverlay("show");

    // Hide it after 3 seconds
    setTimeout(function(){
        $.LoadingOverlay("hide");
        setTimeout(function(){
            $("#area_1").LoadingOverlay("show", {size: 10});
            $("#area_2").LoadingOverlay("show", {color: "rgb(238, 238, 238, 0.5)"});
            setTimeout(function(){
                $("#area_1").LoadingOverlay("hide");
                $("#area_2").LoadingOverlay("hide");
            }, 3000);
        }, 3000);
    }, 3000);
});
</script>

第 3~10 行,先設定遮罩的整體屬性值。
第 17 行,設定 #area_1 區塊的動畫縮小為原來的 10%。size 的值可以賦予 10 或 "10%"。
第 18 行,設定 #area_2 區塊的遮罩透明度為 0.5, 顏色不變。

2016年5月17日 星期二

jQuery Page Preloader

jQuery Page preloader

簡介

當使用一些網頁介面的程式庫時,如果沒有特別的處理,在網頁的介面元件眾多時,網頁常常會先出現預設的使用者介面元件,在程式庫下載完畢,對介面元件做完外觀的修改後,使用者才能看到完整的頁面;此時就是使用者口中常說的頁面閃動,造成不良的使用經驗。所以程式設計師常使用一種技巧,在下載頁面時先在螢幕上顯示一個動畫,或網頁下載中的訊息,請使用者稍安勿燥,耐心等候;而將網頁於背景處理完畢後,才顯示在螢幕上。雖然目前的網路速度比起從前要快上許多,然而一般的網頁也變得更為複雜,互動式的網頁還要多下載一些 javascript 的程式碼。雖然 jQuery 和 jQuery-ui 的程式庫都不大,下載的速度也快,但當網頁的元件很多,網路塞車時,使用上述的這種技巧,還是對提高使用者的滿意度很有幫助的。本篇所介紹的技巧是使用者在造訪主網頁時使用,動畫和下載中的訊息會遮蔽整個畫面;在使用網頁的過程中,只有局部畫面需要下載資料時,得用另一種方法,雖然兩者的基本原理是一樣的。

範例

在範例中,當下載網頁時(假裝這是個很複雜的主網頁),螢幕上會出現一個動畫及英文 Loading 的訊息;5 秒後動畫和訊息會消失,出現主網頁(在這個範例裡,主網頁中沒有任何元件)。

CSS

<style>
    html {
        width:100%;
        height:100%;
        background-color: white;
    }
    body {
        margin:0 auto;
        width:960px;
        height:100%;
        padding-top:20px;
        background-color: antiquewhite;
    }
    #pageOverlay {
        position:fixed;
        top:0; 
        left:0; 
        z-index:999; 
        height:100%; 
        width:100%; 
        padding-top:25%; 
        background:#eeeeee; 
        color:#666666;
        text-align:center;
    }
    #pageOverlay>img {
        padding:10px;
        border-radius:8px;
        background:#aaaaaa;
    }
</style>

CSS 中設定了 html 及 body 的背景底色。#pageOverlay{} 設定遮蔽的範圍為流覽器的視界 (viewport),z-index 設為 999,應該會在出現在所有元件的前面了。 #pageOverlay>img{} 則設定了動畫的小區塊背景底色及圓邊角。

HTML

<body>
    
Loading
Loading...
</body>

HTML 中建立了一個含有 <img> 的 <div> 區塊。這是使用的 gif 動畫,可以按右鍵下載

Script

<script>
$(function(){
    // Put javascript code here
    setTimeout(function(){
        jQuery('#overlay').fadeOut().empty();
    }, 5000);
});
</script>

第 5 行最好放在程式的最後一行,以確保程式庫己處理完所有介面元件的外觀,整個主網頁都己就緒。範例中為了展示,所以將它放在 setTimeout() 函式中,真正實作時,是不會這麼做的。

CSS3 Concentric Circles

CSS3 Concentric Circles

簡介

這篇介紹如何利用 CSS3 中 border-radius 及 box-shadow 的屬性繪製同心圓。只要瞭解了基本作法,可以加以變化,以逹到不同的效果。同心圓的繪製主要利用了幾個技巧,首先,利 border-radius: 50%; 的設定繪製圓形,再利用 CSS3 允許 box-shadow 元件同時可以定義數個值的特性(每個定義值以 "," 逗號分隔),逐一加上其它圓形,這個作法只能製作實心圓,不能製作空心圓。

作法有兩種,一種先定最內圓的大小,再一層一層往外加環形。這種作法要設定足夠的 margin 空間,讓外環圓有必要的空間,否則很容易侵入到週遭的元件。另一種作法是先設定同心圓的最大尺寸,由外往內縮,這種作法比較容易判斷同心圓所需要佔據的空間。

範例

範例中建立四個不同顏色的同心圓,中心的圓形直徑為 100px,其它三個外環則具有 20px 的寬度。中間的文字則置於同心圓的正中。這個範例是先設定內圓,由內往外擴充。

CSS

<style>
html {
    width: 100%;
    height: 100%;
    overflow: auto;
}
body {
    margin: 0 auto;
    width: 960px;
    padding: 20px;
}
.circle {
    display: flex;
    justify-content: center;
    align-items: center;
    margin: 60px;
    width: 100px;
    height: 100px;
    border-radius: 50%;
    background-color: red;
    box-shadow: 0px 0px 0px 20px coral,
        0px 0px 0px 40px lightgreen,
        0px 0px 0px 60px skyblue;
}
</style>

.circle{} 設定了同心圓的尺寸和外觀。第 13~15 行利用 flex box 的設定讓圓中的文字置於正中央。margin 至少需設定為 60px,讓外環有足夠的空間擴充,background-color 則是最內圓的顏色。box-shadow 則設定了外面三環的顏色及寬度,注意,環的寬度必須累加。

HTML

<body>
    
Bull's eye
</body>

HTML 的設定很簡單,就建立一個 <div> 即可。

範例

範例中建立四個不同顏色的同心圓,最外的圓形直徑為 220px,其它三個內環則具有 20px 的寬度,中間的文字置於同心圓的正中。這個範例是先設定外圓的尺寸,由外往內縮。要注意的是在 box-shadow 的設定中,各環顏色的設定次序並沒有改變,但在顯示時各環的顏的次序和上一個範例卻是相反的。

CSS

<style>
html {
    width: 100%;
    height: 100%;
    overflow: auto;
}
body {
    margin: 0 auto;
    width: 960px;
    padding: 20px;
}
.circle {
    display: flex;
    justify-content: center;
    align-items: center;
    width: 220px;
    height: 220px;
    border-radius: 50%;
    background-color: red;
    box-shadow: 0px 0px 0px 20px coral inset,
        0px 0px 0px 40px lightgreen inset,
        0px 0px 0px 60px skyblue inset;
}
</style>

.circle{} 設定了同心圓的尺寸和外觀。第 13~15 行利用 flex box 的設定讓圓中的文字置於正中央。margin 沒有設定,因為 box-shadow 會出現在元件的內部,設定時就是元件正常的 margin。background-color 則是最內圓的顏色。box-shadow 則設定了內三環的顏色及寬度,注意環的寬度必須累加,inset 設定會讓 box-shadow 出現在元件的內部,而非外圍。

HTML

<body class="claro">
    
Bull's eye
</body>

HTML 的設定很簡單,就建立一個 <div> 即可。

2016年5月10日 星期二

CSS3 Flex Box - Part 5

CSS3 Flex Box - Part 5

簡介

在彈性元件 (flex item) 中,尚有數個屬性可以動態的調整彈性元件在主軸 (main axis) 走向的長度。這些屬性在設計自適應 (Responsive Web Design) 的網頁應用時特別有用,根據不同的裝置螢幕大小,各彈性元件可以動態的調整尺寸,以配合螢幕的尺寸,逹到排版的效果。一般來說,在彈性元件使用這幾個屬性時,都不會明確的使用 width, height 如果設定了,也會被 flex-basis 的設定覆蓋; 但設定 min-width, min-height 或 max-width, max-height 則會限制其對應於 flex-* 各屬性的作用;例如 flex-shrink 在作用時,縮小的尺寸就不能低於 min-* 的設定,而 flex-grow 在作用時,放大的尺寸也不能高於 max-* 的設定。有些相片或圖形,如果長、寛縮放的比例差距太大,就會造成失真過度,此時就可能會限制縮放時的最小或最大尺寸。

flex-basis
彈性元件在未做任何調整前的基本尺寸。
auto
以彈性元件的內容決定其基本尺寸。
size
size 是一般用來定義尺寸,具有單位的數值。例: 50%, 100px, 3em 等等。
flex-grow
賦予值為無單位數值,不可為負數,預設值為 1。此數值是一個比例值,代表當有空間剩餘時,將剩餘空間分配給此彈性元件的份額。
flex-shrink
賦予值為無單位數值,不可為負數,預設值為 1。此數值代表一個比例值,代表當空間不足時,將縮減此彈性元件以彌補不足空間的份額。
flex
這個屬性是前三個屬性綜合的簡式寫法。語法為:
flex: flex-grow flex-shrink flex-basis;

配合上其它的排列屬性時,看起來排列方式千變萬化,似乎相當複雜;但只要掌握到要點後,卻也不難理解。首先,以上四個屬性(包含 flex 這個簡式寫法)只作用在主軸走向,對側軸走向沒有作用。
其次,在 flex-wrap:wrap; 的設定下,彈性容器先依照其它各排列屬性的定義排列所有的彈性元件,此時彈性元件的尺寸便以 flex-basis 中的設定值為依據,該換列的換列,該換欄的換欄,該調先後次序的調先後次序,等到所有的彈性元件都就定位了,再一列一列檢查。如果檢查列有多餘的空間存在,便將此列中所有彈性元件的 flex-grow 的值加總,多餘的空間除以加總值便是要分配的單位份額,每一彈性元件再依其 flex-grow 的設定值放大單位份額的量。如此將所有的列或欄走完一遍,排版也就結束了。在 flex-wrap 設定為 wrap 的情況下,因為只要剩餘空間不足以容納下一個要排入的彈性元件,便會換列或換欄,因此不會碰到有空間不足的情況,所以 flex-shrink 的設定也不會有作用。
只有在 flex-wrap:nowrap; 的設定下,彈性容器強迫將所有的彈性元件擠入一列或一欄中,此時才有可能出現空間不足的情況,而 flex-shrink 才能有作用。如果在不換列或換欄的情況下,依然有多餘的空間,則比照上述 flex-grow 的作法分配多餘的空間,若真碰到空間不足的情況,排版方式也不難,先將所有的彈性元件的長度加總,減去彈性容器的內容 (content) 的長度,便是不足的空間;將所有的彈性元件的 flex-shrink 值加總,再將不足空間除以加總值,便是要縮減的單位份額,每一彈性元件再依其 flex-shrink 的設定值縮減相對的單位份額,這樣排版就圓滿結束了。

範例

範例中的彈性容器有五個正方形的彈性元件。上圖是會換列的情況, flex-wrap:wrap; ,彈性元件會放大以填滿彈性容器,第一列中的三個彈性元件 flex-grow 值都為 1 ,所以放大的比例是一樣的。第二列中的編號 4 的彈性元件 flex-grow 值為 3 ,所以在該列中放得比編號 5 大。下圖中則是不換列的情況, flex-wrap:nowrap; ,其中只有編號 5 的彈性元件 flex-shrink 值為 3 ,其它都是 1 ,因此編號 5 的彈性元件縮得特別小。

CSS

<style>
html {
    width:100%;
    height:auto;
    font:normal normal normal 1em Arial, '文泉驛正黑', 'WenQuanYi Zen Hei', '儷黑 Pro', 'LiHei Pro', '微軟正黑體', 'Microsoft JhengHei';
}
body {
    margin: 0 auto;
    width: 800px;
    padding:20px;
}
.container {
    display: flex;
    flex-direction:row;
    flex-wrap:wrap;
    width: 200px;
    padding:20px;
    background-color: lightgreen;
}
.basis {
    flex-basis: 50px;
    height:50px;
    border: 1px solid black;
}
.center {
    display:flex;
    justify-content: center;
    align-items: center;
    font-size: 2em;
}
.item_1 {
    flex-grow:1;
    flex-shrink:1;
    background-color: coral;
}
.item_2 {
    flex-grow:1;
    flex-shrink:1;
    background-color: skyblue;
}
.item_3 {
    flex-grow:1;
    flex-shrink:1;
    background-color: hotpink;
}
.item_4 {
    flex-grow:3;
    flex-shrink:1;
    background-color: gold;
}
.item_5 {
    flex-grow:1;
    flex-shrink:3;
    background-color: fuchsia;
}
</style>

.container{} 設定彈性容器的外觀、尺寸和彈性元件的排列方式。
.basis{} 設定彈性元件的基本尺寸及邊框,height 也設定為 50px,如果彈性元件不曾縮放時,元件外觀應為正方形。
.center{} 的設定會將彈性元件的編號置中。
.item_* 設定各彈性元件的縮放比例及背景顏色。

HTML

<body>
    
1
2
3
4
5
</body>

HTML 中建立一個含有五個彈性元件的彈性容器。

CSS3 Flex Box - Part 4

CSS3 Flex Box - Part 4

簡介

在彈性容器中 (flex container) 排列各彈性元件 (flex item) 時,預設都是以彈性元件在 DOM tree 中平輩的前後次序,依序排列。但在彈性元件中設定屬性 order 卻可以改變彈性元件的排列次序。

order
這是個設定在彈性元件中的屬性,賦予值為一無單位的數值,可以為負值,預設值為 0。若為負值,負數愈大的彈性元件則愈先排列;若為正值,正數愈大的彈性元件則愈晚排列。具有相同的數值的彈性元件,則依 DOM tree 中平輩的先後次序排列。與其說 order 設定了彈性元件的排列先後次序,不如說 order 設定了彈性元件的先後排列權值。彈性容器先分析所有彈性元件的權值,依權值分成群組,再依權值由高至底,將每一個群組中的彈性元件依其在 DOM tree 中平輩的先後次序排列,一直到所有的權值群組都排列完畢為止。

範例

範例中建立一個含有七個彈性元件的彈性容器,每個彈性元件依照其在 DOM tree 中平輩的次序標號,但在其 CSS 類別中設定 order 屬性以改變其排列的先後次序。可以試著改變 order 的設定值,以瞭解其排列的規則。

CSS

<style>
html {
    width:100%;
    height:auto;
    font:normal normal normal 1em Arial, '文泉驛正黑', 'WenQuanYi Zen Hei', '儷黑 Pro', 'LiHei Pro', '微軟正黑體', 'Microsoft JhengHei';
}
body {
    margin: 0 auto;
    width: 800px;
    padding:20px;
}
.container {
    display: flex;
    flex-direction:row;
    width: 400px;
    padding:20px;
    background-color: lightgreen;
}
.basis {
    width:40px;
    height:40px;
    border: 1px solid black;
    background-color: coral;
}
.center {
    display:flex;
    justify-content: center;
    align-items: center;
    font-size: 2em;
}
.item_1 {
    order:0;
}
.item_2 {
    order:0;
}
.item_3 {
    order:2;
}
.item_4 {
    order:-1;
}
.item_5 {
    order:2;
}
.item_6 {
    order:-2;
}
.item_7 {
    order:1;
}
</style>

.container{} 設定了彈性容器的外觀、尺寸及基本的排列方式。
.basis{} 設定了各彈性元件的外觀及尺寸。
.center{} 將彈性元件的編號置於元件中央。
.item_*{} 則為各彈性元件設定 order 屬性,決定其排列時的權值。

HTML

<body>
    
1
2
3
4
5
6
7
</body>

HTML 中依編號的次序建立七個彈性元件,如果沒有在彈性元件中設定 order 屬性,則應編號的次序排列。

CSS3 Flex Box - Part 3

CSS3 Flex Box - part 3

簡介

在完成彈性容器中大的排版布局後,現在要看看如何微調彈性元件在列或欄中,於側軸走向上的位置調整。這方面有兩個屬性:align-items 和 align-self。align-items 設定於彈性容器的元件中,所有的彈性元件都會遵循這個設定調整位置;除非在某一或某些彈性元件中有設定 align-self,此時這些彈性元件會脫離 align-items 的設定,而以 align-self 的設定為調整的依據。

align-items
以側軸的走向為基準,調整所有彈性元件在列或欄內的位置。當各彈性元件在側軸走向的長度不一,或在彈性元件的側軸走向的長度是由計算得出時,特別有用。
flex-start
列或欄中的所有彈性元件,以列或欄的範圍為限,靠近側軸的起點 (cross start) 線。
flex-end
列或欄中的所有彈性元件,以列或欄的範圍為限,靠近側軸的終點 (cross end) 線。
center
列或欄中的所有彈性元件,元件的中線對齊列或欄的中心線。彈性元件中若有文字,則不同彈性元件中之文字的底線可能不在同一高度。
baseline
將列或欄中的彈性元件以元件中的文字底線 (baseline) 為準對齊。這樣會使各彈性元件中之文字的底線在同一個高度上。對齊各彈性元件的文字底線後,所有彈性元件的最邊緣會靠近側軸的起點線。
stretch
這是預設值。縮放彈性元件在側軸走向的長度以配合彈性容器的側軸長度,倘若彈性元件中有明確的定義側軸走向的長度,例如:側軸走向為垂直,而彈性元件中有明確的定義 height 或 min-height, max-height,則會以定義為優先,不會強制縮放成側軸的長度。
align-self
這個是定義在彈性元件中的屬性,屬性值及作用都和 align-items 一樣,是用來讓單一彈性元件脫離 align-items 的設定,獨立設定該彈性元件的布局方式。

align-items:stretch;

align-items:flex-start;

align-items:flex-end;

align-items:center;

align-items:baseline;

align-items:flex-start; align-self:flex-end;

範例

在範例中建立了六個區塊,區塊中各有一小段文字,其中有兩區塊的文字字型特別小,這樣在做各種不同設定時,可以看出設定間的差別;特別是在設定 align-items:baseline 時,更容易看出是如何以文字的底線對齊的,如果和 align-items:center 的圖片比對,則更容易看出分別。要測試 align-self 時只要在 CSS 宣告中取消 align-self 的註解,更改設定後,重新載入網頁,便可看到改變了。

CSS

<style>
html {
    width:100%;
    height:auto;
    font:normal normal normal 1em Arial, '文泉驛正黑', 'WenQuanYi Zen Hei', '儷黑 Pro', 'LiHei Pro', '微軟正黑體', 'Microsoft JhengHei';
}
body {
    margin: 0 auto;
    width: 800px;
    padding:20px;
}
.container {
    display: flex;
    flex-direction:row;
    flex-wrap:wrap;
    align-items: flex-start;
    width: 400px;
    height:150px;
    padding:20px;
    background-color: lightgreen;
}
.normal {
    padding:8px;
    border: 1px solid black;
    background-color: coral;
    font-size: 2em;
}
.blacksheep {
    padding:8px;
    /* align-self:flex-end; */
    border: 1px solid black;
    background-color: skyblue;
    font-size: 1em;
}
</style>

CSS 中,.normal{} 設定了四個彈性元件的外觀,具有比較大的字型。.blacksheep{} 則設定了兩個彈性元件的外觀,具有比較小的字型; align-self 的屬性設定暫時被註解掉了,取消註解後,改變其設定便可以測試 align-self 屬性值所造成的排版效果。

HTML

<body>
    
Normal
Blacksheep
Normal
Normal
Normal
Blacksheep
</body>

HTML 中建立了六個區塊,其中有兩個區塊的 CSS 類別為 blacksheep,用來和其它 CSS 類別為 normal 的區塊作區分。

2016年5月9日 星期一

CSS3 Flex Box - Part 2

CSS3 Flex Box - Part 2

簡介

在瞭解了 flex box 如何排列子元件的大原則後,這篇來討論一下如何調整彈性元件的位置。以下有兩個調整彈性元件位置相關的屬性,兩屬性都擁有三、四個屬性值,組合各屬性及其值的方式很多樣,但掌握大原則後,再寫程式測一下就很容易明白了。

以下的解說用 {flex-direction:row; flex-wrap:wrap;} 的設定為範例來解釋行為模式,其它的設定則可類推。

justify-content
依主軸 (main axis) 的走向為基準(要記住主軸的走向是由 flex-direction 的設定所決定的),在列或欄中調整各彈性元件的位置。
flex-start
此為預設值。依主軸的走向依次排列彈性元件,排列完後,將整體的起始邊緣對齊向主軸的起點 (main start),。
flex-end
依主軸的走向依次排列彈性元件,排列完後,將整體的結束邊緣對齊向主軸的終點 (main end)。
center
依主軸的走向依次排列彈性元件,排列完後,將整體的中線對齊向主軸的中間點。
space-between
依主軸的走向依次排列彈性元件,將多餘的空間平均分配在各個彈性元件之間。
space-around
依主軸的走向依次排列彈性元件,將多餘的空間平均分配在各個彈性元件的兩旁。
align-content
依側軸 (cross axis) 的走向為基準,調整各列或各欄的位置。行為模式和 justify-content 一模一樣,只是 justify-content 以主軸為基準,在各列或各欄中調整各彈性元件在主軸走向的位置;而 align-content 則以側軸為基準,在彈性容器中調整各列或各欄的位置。如果彈性容器中只有一列或一欄時,這個屬性就沒有作用了,當 flex-direction 為 row 或 row-reverse,且彈性容器的 height 設定為 auto 時,因為彈性容器的 height 是計算出來的值,其值會正好等於所有列高的和,也就不會有多餘的空間可以調整,所以不論如何設定,彈性元件的位置看起來都是一樣的。
flex-start
所有的列或欄,都靠向側軸的起點 (cross start)。這是預設值。
flex-end
所有的列或欄,都靠向側軸的終點 (cross end)
center
所有列或欄的整體中線對齊側軸的中間點。
space-between
將多餘的空間平均分配於各列或各欄之間。
space-around
將多餘的空間平均分配於各列或各欄的兩旁。

justify-content:flex-start

justify-content:flex-end

justify-content:center

justify-content:space-between

justify-content:space-around

以下的圖片 justify-content 的設定都是 flex-start。

align-content:flex-start

align-content:flex-end

align-content:center

align-content:space-between

align-content:space-around

CSS

<style>
html {
    width:100%;
    height:auto;
    font:normal normal normal 1em Arial, '文泉驛正黑', 'WenQuanYi Zen Hei', '儷黑 Pro', 'LiHei Pro', '微軟正黑體', 'Microsoft JhengHei';
}
body {
    margin: 0 auto;
    width: 800px;
    padding:20px;
}
.container {
    display: flex;
    flex-direction:row;
    flex-wrap:wrap;
    justify-content:flex-start;
    align-content:flex-start;
    width: 200px;
    height:150px;
    padding:20px;
    background-color: lightgreen;
}
.center {
    display:flex;
    justify-content: center;
    align-items:center;
}
.item {
    width:40px;
    height:40px;
    border:1px solid black;
    background-color: coral;
    font-size:2em;
}
</style>

.container{} 中 width:200px; 這樣會讓它個彈性元件分成兩列,height:150px; 會讓列高較大,有足夠的空間讓 align-content 屬性可以發揮。只要改變 justify-content 及 align-content 的值,再重新下載網頁,就可以看到彈性元件在彈性容器中不同的排列方式。

HTML

<body>
1
2
3
4
5
6
7
</body>

2016年5月7日 星期六

CSS3 Flex Box - Part 1

CSS3 Flex Box - Part 1

簡介

CSS3 的規範裡提供了一個新的 box model,稱為「彈性盒」(flexible or flex box),讓網頁設計師在設計時更容易排版。當某元件的 display 屬性值定為 flex 或 inline-flex 時,該元件便成為一個彈性盒的元件。設定值為 flex 時,彈性盒在許多基礎的設定及行為模式都和一般區塊級 (block-level) 的區塊相同,width 和 height 的預設值都是 auto;除非有明確的設定,否則都是由計算而來。在彈性盒元件的後面也會自動換行。雖然和一般的區塊元件極為雷同,但彈性盒還是有些特別的地方,例如:float, clear, vertical-align, column-* 這些屬性在彈性盒的排版中都不起作用。彈性盒依據數個屬性的設定,對其子元件有其自己的排版方式。當 display 設定值為 inline-flex 時,則產生一個行內級 (inline-level) 的元件,在彈性盒元件之後不自動換行。

首先介紹一些名詞及術語以方便未來的解釋之用。下方是一幅由 W3C 文件中所擷取的圖片。

參與彈性 (flex) 排版的元件分成兩大類:

flex container
當元件的 display 屬性值定為 flex 或 inline-flex 時,該元件便成為一個「彈性容器」(flex container)。每一個彈性容器都具有兩條軸線:主軸 (main axis) 及側軸 (cross axis),各軸又各具有起點 (start) 及終點 (end) 用以決定在容器中各彈性元件在排版時的走向。主軸的走向並非固定,而側軸的走向則永遠和主軸垂直。主軸的走向是由 flow-direction 屬性的設定值所決定,當設定值為 row 或 row-reverse 時,主軸成水平走向,預設為由左至右;側軸則為垂直走向,預設為由上至下。當設定值為 column 或 column-reverse 時,主軸成垂直走向,預設走向為從上至下;側軸成水平走向,預設為為從左至右。當設定值為 *-reverse 時,主軸的起點和終點的位置互換,主軸的走向會反轉,側軸的走向不變;也就是說 flow-direction 的 *-reverse 設定值只會反轉主軸的走向。
flex item
flex container 元件中的子元件,都稱為「彈性元件」(flex item)。彈性盒的模式可以形成結構式的方式存在,也就是說,一個彈性元件可以再行定義成一個彈性容器以包含其它的彈性元件,以此類推,以形成多層式的結構。

以下為 flex-direction 及 flex-wrap 兩個屬性的設定值及意義:

flex-direction
設定彈性容器主軸的走向。
row
定義主軸為水平走向,預設為由左至右。此為預設值。
row-reverse
定義主軸為水平走向,但將預設的起點和終點互換,反轉主軸的預設走向為由右至左。
column
定義主軸為垂直走向,預設為由上至下。
column-reverse
定義主軸為垂直走向,但將預設的起點和終點互換,反轉主軸的預設走向為由下至上。
flex-wrap
設定主軸長度不足以容納所有彈性元件時,是否要換行。
nowrap
設定為不換列,壓縮各彈性元件以擠入同一列或同一欄。此為預設值。
wrap
設定為換列,在剩餘空間不足以容納下一個彈行元件時換列。
wrap-reverse
將側軸的起點和終點互換,反軸側軸的走向。

以下的解說及圖均以 display:row 為例,略去 column 及 *-reverse 的部份。在預設的情形下,彈性容器的排版以單「列」(row) 或單「欄」(column) 為主,彈性容器會試圖將所有的彈性元件排在同一列或同一欄中。在主長度足夠容納所有的彈性元件時,如下圖所示:

當主長度不足以容納所有的彈性元件時,彈性容器會平均壓縮每一彈性元件,盡可能將所有的彈性元件擠在同一列中,如下圖所示:

flex-direction 設定為 row-reverse,則反轉主軸的走向,結果如下圖所示:

如果在主長度不足,卻又希望能保持彈性元件的原形,則可以設定 flex-wrap 的屬性值為 wrap,將在同列排不下的元件,排到下一列去,彈性容器會在剩餘空間不足以完全容納下一個彈性元件時,便移至下一列開始排起,若此時彈性容器的 height 值為 auto,彈性容器會計算出最小所需高度,則結果如下圖所示:

若 flex-wrap 設定為 wrap-reverse,則會反轉側軸的走向,結果如下圖所示:

若彈性容器的 height 值有明確設定的值時,這個值等於側軸長度;彈性容器會將 height 值除以所需的列數做為每列的高度,此時結果會如下圖所示,若設定的高度不足以容納,則彈性元件會超出彈性容器的範圍。

範例

在範例中,設定一個具有七個正方形彈性元件的彈性容器。每個彈性元件都有標號,可以看清主軸的走向。範例中的圖像只顯示橫向排列的結果,直向排列的結果就不顯示了。最重要的是把排列的邏輯理清楚。

CSS

<style>
html {
    width:100%;
    height:auto;
    font:normal normal normal 1em Arial, '文泉驛正黑', 'WenQuanYi Zen Hei', '儷黑 Pro', 'LiHei Pro', '微軟正黑體', 'Microsoft JhengHei';
}
body {
    margin: 0 auto;
    width: 800px;
    padding:20px;
}
.container {
    display: flex;
    flex-direction:row;
    /* flex-wrap:wrap; */  /* unmark this line to wrap */
    width: 200px;
    /* height:150px; */    /* unmark to set height */
    padding:20px;
    background-color: lightgreen;
}
.center {
    display:flex;
    justify-content: center;
    align-items:center;
}
.item {
    width:40px;
    height:40px;
    border:1px solid black;
    background-color: coral;
    font-size:2em;
}
</style>

.container{} 設定彈性容器的屬性: display: flex; ,設定為區塊級的彈性容器。 flex-direction: row; 設定子元件的排列以列方向前行,此時主軸走向為水平,排列方式為從左到右。width: 400px; 將寬度設為 400px 足以容納七個長寬各為 40px 的正方形子元件;稍後,將寬度改成 200px,同時取消flex-wrap:wrap; 這行的註解,彈性容器便會壓繪各彈性元件以便擠入一列之中。
height 屬性則先註解掉,彈性容器會自行計算足夠的高度。取消註解後,上下兩列就會分的比較開。
.center{} 也是定義元件為彈性容器,因為每個彈性元件又同時具有 .center 類別,所以每個彈性元件同時又是彈性容器,成為一個兩層式的結構。 justify-content:center 設定將內容於主軸走向置中, align-item:center 設定將子元件於副軸走向置中。兩個屬性都設定為 center 時,會將所有子元件集合而成的內容置於 flex container 的正中央。這兩個屬性以後再討論。

HTML

<body>
1
2
3
4
5
6
7
</body>

2016年5月4日 星期三

jQuery attr() vs. prop()

jQuery attr() vs. prop()

簡介

在 jQuery 中有兩個函式 attr() 和 prop() 用以取得選取元件的 attribute 和 property 的屬性值。在中文裡 attribute 和 property 都譯成「屬性」,而 attr() 和 prop() 兩個函式的功能和用法似乎也一樣,那為什麼要分成兩個函式呢?原來,在 jQuery v1.6 之前,這兩個函式確實沒有什麼分別,幾乎是共通的;但在 jQuery v1.6 後, jQuery 的開發人員針對 attribute 和 property 作了更精準的定義,為的是讓這兩個函式有明確的功能區分。

新的定義大略是這樣的:attribute 代表的是 DOM 元件中所定義的屬性,而 property 是 DOM tree 中元件之的屬性當時的狀態。這是我能想到的最佳的解釋了。我的理解是這樣的:HTML 文件實質上是一份文檔,在流覽器將這份文檔讀入後,在記憶體中建立了 DOM tree,以節點的方式記錄了 HTML 文件中對各元件所設定的屬性 (attribute) 及其屬性值。jQuery 為了運作方便,又將元件以 jQuery Object 包裝起來,用 property 屬性來表示這些 attribute 屬性目前的狀態。按理說,修改了其中的一個值,應該也會修改另一個值,也就是兩個值理當是同步的。實際上並非如此,像是 text 或 number input 欄位中的 value 屬性,代表的是 input 欄位的預設值,只要不曾用 attr() 函式去改變其設定值,每次 attr() 都會取得原先在 HTML 文件中設定的值。而 property 中也有個 value 屬性,代表的卻是使用者目前在欄位中的輸入值,一開始兩者的值是一樣的,但只要使用者在欄位中有輸入任何值,便會改變 property 中 value 屬性的值。此兩者的定義不同,名稱雖然一樣,屬性值卻不會同步,也的確不該同步。然而其它的的屬性,例如: autofocus, checked 這類屬性,在 HTML 中有兩種寫法:<input type="text" autofocus> 或 <input type="text" autofocus="autofocus">,這兩種寫法都可以,也都能得到正確的結果,以 attr() 取得其屬性值時,傳回值為 "autofocus" 的字串或是 undefined ;而使用 prop() 取得的值卻是 true 和 false 的布林值。checked 屬性也是一樣的情況。這一類的屬性就造成了一些混亂。在範例程式碼中做了一些測試,有個情況看其來確實不合理,不知道算不算 jQuery 的 bug。

結論是,attr() 的傳回值不是字串,就是 undefined。prop() 的傳回值卻會因屬性的不同而有各種可能。在使使用 jQuery 開發時,盡可能使用 prop() 去操作屬性的值,除了像 input 中的 value 欄位那一類型的屬性,和 property 的屬性同名,卻有不同的定義,要在程式中改變欄位的預設值,不得不用 attr() 函式外,其它的都用 prop(),就安全多了。

範例

範例中建立了一個文字輸入欄位及兩個檢核框 (checkbox) 用來測試 value, autofocus 及 checked 等屬性。網頁下載完畢時,在輸入欄位中隨便輸入一個值,按下 submit 按鈕後,打開「開發者工具」的「主控台」查看輸入的結果。

CSS

<style>
html {
    width:100%;
    height:auto;
    font:normal normal normal 16px Arial, '文泉驛正黑', 'WenQuanYi Zen Hei', '儷黑 Pro', 'LiHei Pro', '微軟正黑體', 'Microsoft JhengHei';
    line-height:1.7;
    letter-spacing: 0.087em;
}
body {
    margin:0 auto;
    width:1000px;
    height:100%;
    padding-top:20px;
}
input {
    font-size: 1em;
}
</style>

CSS 中沒什麼重要的樣式設定,一般流覽器中對 input 欄位的字型預設的都比較小,所以 input{} 中將字型大小設為 1em,也就是 16px,比較容易看清楚。

HTML

<body>
    
    


</body>

HTML 中建立一個文字輸入欄位,預設值為 "someone",這個值在網頁出現時,就會放在文字輸入框中做為預設值,並設定 autofocus,該該輸入欄位自動取得焦點。另建立兩個檢核框,以測試 checked 屬性,兩個檢核框各以不同的設定方法設定檢核框為核取狀態。

Script

<script>
$(function(){
 $("#submit").button().click(function(){
  var input = $("#input");
        console.log('----- input text field -----');
        console.log('$("#input").attr("nodeType") = %o', input.attr("nodeType"));   // undefined
        console.log('$("#input").prop("nodeType") = %o', input.prop("nodeType"));   // 1
        console.log('$("#input").attr("value") = %o', input.attr("value"));         // "someone"
        console.log('$("#input").prop("value") = %o', input.prop("value"));         // "john"
        console.log('$("#input").attr("autofocus") = %o', input.attr("autofocus")); // "autofocus"
        console.log('$("#input").prop("autofocus") = %o', input.prop("autofocus")); // true
        var cb1 = $("#cb1");
        var cb2 = $("#cb2");
        console.log('----- checkbox -----');
        console.log('$("#cb1").attr("checked") = %o', cb1.attr("checked")); // "checked"
        console.log('$("#cb1").prop("checked") = %o', cb1.prop("checked")); // true
        console.log('$("#cb2").attr("checked") = %o', cb2.attr("checked")); // "checked"
        console.log('$("#cb2").prop("checked") = %o', cb2.prop("checked")); // true
        
        $("#cb1").prop("checked", false);
        console.log('----- after $("#cb1").prop("checked", false);" -----');
        console.log('$("#cb1").attr("checked") = %o', cb1.attr("checked")); // "checked"
        console.log('$("#cb1").prop("checked") = %o', cb1.prop("checked")); // false

        $("#cb2").attr("checked", false);
        console.log('----- after $("#cb2").attr("checked", false);" -----');
        console.log('$("#cb2").attr("checked") = %o', cb2.attr("checked")); // undefined
        console.log('$("#cb2").prop("checked") = %o', cb2.prop("checked")); // false

        $("#cb1").prop("checked", true);
        console.log('----- after $("#cb1").prop("checked", true);" -----');
        console.log('$("#cb1").attr("checked") = %o', cb1.attr("checked")); // "checked"
        console.log('$("#cb1").prop("checked") = %o', cb1.prop("checked")); // true

        $("#cb2").attr("checked", true);
        console.log('----- after $("#cb2").attr("checked", true);" -----');
        console.log('$("#cb2").attr("checked") = %o', cb2.attr("checked")); // "checked"
        console.log('$("#cb2").prop("checked") = %o', cb2.prop("checked")); // false
    });
});
</script>

注意第 6 行和第 7 行的值,nodeType 這個屬性,在 attribute 中沒有定義,在 property 中的值為 1,代表 element node。
當 checked 屬性有定義時,attr("checked") 的傳回值為 "checked" 字串, prop("checked") 傳回值為 true。當沒有定義 checked 值時,attr("checked") 的傳回值為 undefined,prop("checked") 傳回值為 false。一切看起來都很正常,直到第 35 行,用 attr("checked", true); 去設定 checked 時,第 39 行 prop("checked") 的傳回值卻是 false,螢幕上的檢核框也沒有顯示核取的狀態,表示 attribute 和 property 屬性的值在此時並沒有同步。我想這應該算是個 bug,解決方案就是用 prop() 函式來處理。目前用的是 jQuery 2.2.2 版,不知下一版會不會修改。

CSS3 line-height, word-spacing, letter-spacing

CSS3 line-height, word-spacing, letter-spacing

簡介

要讓網頁的文章變得容易閱讀,除了使用不同字體,改變字型的大小之外,還可以調整「行高」(有時也稱「行距」),以及調整「字距」。在 CSS3 中用來設定行高的屬性是 line-height;word-spacing 及 letter-spacing 這兩個屬性是以英文的角度命名,從中文的角度而言,所調整間距的位置,則和屬性之英文名字的字義略有出入。現說明如下:

line-height
這個屬性在英文和中文之間沒有歧義,代表的都是行高。單位可以是 px, pt, em, rem, % (百分比)或倍數,其中 em, 百分比及倍數是以目前的 font-size 值作為基準計算,rem 則以 <html> 中所設定的 font-size 為基準,若 <html> 中未設定該屬性值,則以流覽器預設的 16px 為基準。這個屬性的預設值是 normal,但實際上預設值在呈現行高時的表現一點都不正常,不論是在不同的流覽器中,或是在相同的流覽器中使用不同的字體,其結果可以說是千奇百怪,似乎毫無規則可尋;實在令人訝異。 line-height-abnormal 這篇英文文章裡有詳細的說明。另外有一點比較奇特的是,雖然預設值是 normal,但只要元件的先輩元件中,有設定 line-height 的值,不論是用絕對單位,或是相對單位,該元件會自行繼承其值,這和設定其值為 inherit 行為一樣。但在繼承時,是繼承計算後的結果,而不是設定。例如:父輩元件設定為 font-size:18px; line-height:1.5em;,此時,若其子輩元件不曾設定 line-height 值,不論該子輩元件的 font-size 設定為何,其繼承到的 line-height 值固定都為 18px,並非繼承到 1.5em,再去計算其行高的 px 值。所以網路上眾人的建議都是將值設定為倍數,不給單位,隨著目前的 font-size 計算得出行高。具國外研究報告指出,最佳的行高是 font-size 的 1.7 倍,我也不知是那篇報告,人家這麼說,我就這麼聽,自行設定後,看起來確實滿舒服的。1.5 倍也還可以,但看起來隱隱約約就顯得有點擠。
letter-spacing
由字面上解釋,它是在設定英文字母間的間距,對英文而言,名符其實,它也確實在設定英文字母間的間距。但中文是沒有字母的,所以在中文的情況下,這個屬性被用來設定每個中文字之間的間距。預設值也是 normal,其實就是 0。在這個設定下,對中文而言,特別是黑體,字跟字之間看起來很擠,閱讀上稍為有點吃力。和 line-height 一樣,只要先輩元件中有設定 letter-spacing,子輩元件的行為就很像將 letter-spacing 設定為 inherit,會繼承先輩的設定;和 line-height 不同的是,letter-spacing 是繼承設定,在呈現時才計算,而非直接繼承先輩的計算值。根據國外那篇我不知道名字的報告說,最佳的英文字母間隔是 0.087em,試了一下好像真有這麼一回事,也就不去管報告的來源了。可惜對中文的字距來說,我覺得有點窄,我認為中文黑體字的字距以 0.25em 看起來最舒服,但對英文而言字母間的間距就有點過寬了。折衷的值是 0.125em,中、英文看起來都可以接受。但每個人的對讀起來舒服的觀點不一樣,就各人做做實驗,找出自己最滿意的設定值吧!
word-spacing
這個是設定英文字與字之間的間距,因為英文字是以半形空白做為區分,wording-spacing 便以半形空白做為標的加間距,在原本半形空白的邊上再加上設設定值,全形空白則不受影響。預設值也是 normal,也就是 0px;可以賦予負值,縮小字和字之間的間距,也就是吃掉原本半形空白的字寬。在通篇是中文字的文章中,這個屬性不起作用,但若不小心在文章中打了一個半形空白,空白邊的寬度就會受到影響。

範例

範例中有三段文字,每段文字是一小段中文,加上其英文翻譯。用來顯示 line-height 及 letter-spacing 設定的作用。第二段的英文另設了一個 CSS 的類別,讓英文字母間的間距變小一點。這個作法在整段都是英文時,還可以湊和著用,如果是一段中文中夾雜著許多英文單字,這種解法就很累人了。

CSS

<style>
html {
 width:100%;
 font:normal normal normal 1em Arial, '文泉驛正黑', 'WenQuanYi Zen Hei', '儷黑 Pro', 'LiHei Pro', '微軟正黑體', 'Microsoft JhengHei';
    line-height:1.7;
    letter-spacing: 0.125em;
}
body {
    width:600px;
    margin: 0 auto;
    padding-top: 20px;
}
.en {
    letter-spacing:0.087em;
    
}
.newSize {
    font-size: 1.5rem;
}
.useRem {
    font-size: 1rem;
    
}
.useEm {
    font-size: 1em;
   /* word-spacing: -10px;*/
}
</style>

CSS 中只在 html{} 中設定了 line-height 及 letter-sapcing 屬性,讓子元件可以繼承。注意:line-height 的設定值為倍數,並沒有給單位值,可以試著給單位值,再重新下載網頁,看看有什麼變化。
.en{} 中重設了 letter-spacing 的值為 0.087em,這也是第二段的英文字母間距變窄的原因。

HTML

<body>
 

色即是空,空即是色,色不異空,空不異色,受想行識亦復如是。
form is emptiness and the very emptiness is form; emptiness does not differ from form, form does not differ from emptiness, whatever is emptiness, that is form, the same is true of feelings, perceptions, impulses, and consciousness.

色即是空,空即是色,色不異空,空不異色,受想行識亦復如是。
form is emptiness and the very emptiness is form; emptiness does not differ from form, form does not differ from emptiness, whatever is emptiness, that is form, the same is true of feelings, perceptions, impulses, and consciousness.

色即是空,空即是色,色不異空, 空不異色,受想行識亦復如是。
form is emptiness and the very emptiness is form; emptiness does not differ from form, form does not differ from emptiness, whatever is emptiness, that is form, the same is true of feelings, perceptions, impulses, and consciousness.

</body>

HTML 中,第二段的英文段落以 <span> 標記包覆,同時給於 CSS 類別名稱為 "en",以套用類別設定,改變字母間的間距。在 HTML5 中,還可以自訂標記,做起來更方便;但如果考慮到舊版的流覽器,這個作法是比較安全的。

2016年5月3日 星期二

CSS3 font-size

CSS3 font-size

簡介

在設計網頁或寫文章時,常常藉著改變字型、字體及字的大小和顏色等等技巧,以標示文章中的標題,或凸顯某一段文字,在在都是為了讓讀者易於閱讀。而在網路的中文環境中,因為中文在字數的龐大,造成中文字型檔的體積碩大,下載耗時,加以各作業系統預設所提供的中文字型,不論在數量上或字體上都不一致,使得中文在撰寫跨作業系統的網頁應用上能使用的字體相當的受限,只能靠其它的技巧來彌補。這篇探討如何在網頁中改變字型的大小的技巧。

在 CSS3 中改變字型大小的是 font-size 屬性,這個屬性可以使用多種不同的單位,這些單位分成「絕對單位」(absolute) 及「相對單位」(relative) 兩大類,共 15 種,絕對單位有 6 種,相對單位有 9 種。這裡只講解常用的絕對單位 2 種,相對單位 3 種。分別敘述如下:

絕對單位

元件在設定 font-size 時使用這些絕對單位,流覽器在呈現元件時會以固定大小呈現,不受到其它元件設定的影響。

px
px 是pixel 的縮寫,表示像素,也是所有其它單位的基本單位,其它單位最終通常都會轉成以 px 為基準。這是網路程式設計師最常用的絕對單位,很直覺,1px 就是螢幕上的一個像素。流覽器一般預設的字型大小,就是 16px。
pt
pt 是 point 的縮寫,是出版業者在排版時常用的單位。12 pt 約等於 16px。大多數文書處理器,像 Microsoft Word 裡用的單位就是 pt。

相對單位

元件在設定 font-size 時使用這些相對單位,流覽器在呈現元件時會參考到其它元件對 font-size 的設定。

em
em 是 element 的縮寫。1em 就是 1 個 element 的大小,1.5em 就是1.5 倍 element 的大小。在某元件中設定 font-size= 1em;,在螢幕上到底以多少 px 的大小呈現,完全取決於元件在 DOM tree 中的位置,以及其先輩元件對 font-size 屬性的設定;也就是說,流覽器會從該元件的父輩元件開始回遡,一直回遡其直屬先輩直到 <html> 為止,若在回遡途中有任何一先輩元件有明確的設定字型的大小,也就是說以絕對單位設定,則停止回遡,以該先輩的設定字型大小為 1em 進行計算。若先輩的設定也是以相對單位,則繼續往上回遡,這過程有點像「遞迴」 (recursive) 。若一直回遡至 <html>,而回遡途中都沒有任何一先輩元件有明確的設定 font-size 屬性,則以流覽器的預設字型大小,也就是以 16px 為基準計算。
rem
rem 是 root element 的縮寫。其計算方式和 em 相同,唯一的不同點是 rem 不進行先輩回遡,直接以 <html> 中的 font-size 設定作為基準進行計算。若 <html> 中也沒有設定,則以流覽器的預設值 16px 作為基準。
%
百分比表示式。這個單位的計算方式和 em 完全相同,也會進行回遡。其實,font-size=150%;font-size:1.5em; 這兩種設定,得到的字型大小是一樣的。就算在計算過程中有小數上的落差,人眼也看不出來。
在「響應式網頁設計」(Responsive Web Design) 大為流行的今天,使用相對單位來設定字型的大小,是一個比較好的方式。特別是在網頁於不同尺寸的螢幕上呈現時,由於螢幕的大小改變,若字型大小不能相應變更,很多時候在版面上看起來就會很不順眼。但要以單一基準,其它元件都用 rem 設定,或依元件的模組化,每一元件有一基準,而在模組內使用 em 設定,則完全視網頁的設計架構而定,這是沒有標準答案的。

範例

範人例中顯示了三段文字,前二段文字的大小是一樣的,第三段文字則比較大,主要在展示設定 font-size 時,使用 em 和 rem 所得到的結果。字體用的是黑體字,純粹是個人喜好,我認為細明體及新細明體的字體都太單薄,黑體字看起來比較紮實點。而且現在多數的作業系統預設都有提供黑體字。不過黑體字因為厚重,字與字的間距如果不寬,則顯得黑黑的一片,這是黑體字的缺點。

CSS

<style>
html {
 width:100%;
 font:normal normal normal 16px Arial, '文泉驛正黑', 'WenQuanYi Zen Hei', '儷黑 Pro', 'LiHei Pro', '微軟正黑體', 'Microsoft JhengHei';
}
body {
    width:600px;
    margin: 0 auto;
    padding-top: 20px; 
}
.newSize {
    font-size: 1.5em;
}
.useRem {
    font-size: 1rem;
}
.useEm {
    font-size: 1em;
}
</style>

html{} 中設定了所要使用的字體,也明確的設定了字型的大小為 16px。
.newSize{} 調整了字型的大小為 1.5em 若回遡之後,計算結果為 24px。
.useRem{} 使用 rem 為單位,會直接參考到 html{} 中的設定,計算結果應該是 16px。
.useEm{} 使用 em 為單位,因為在 HTML 程式碼中,.newSize{} 為 .useEm{} 的父輩,所以會參考到 .newSize{} 的設定,1em 的計算結果為 24px。

HTML

<body>
    

寒蟬凄切,對長亭晚,驟雨初歇。都門帳飲無緒,方留戀處,蘭舟催發。執手相看淚眼,竟無語凝咽。念去去,千里煙波,暮靄沉沉楚天闊!多情自古傷別離,更那堪冷落清秋節!今宵酒醒何處?楊柳岸,曉風殘月。此去經年,應是良辰好景虛設,便縱有千種風情,更與何人說。

寒蟬凄切,對長亭晚,驟雨初歇。都門帳飲無緒,方留戀處,蘭舟催發。執手相看淚眼,竟無語凝咽。念去去,千里煙波,暮靄沉沉楚天闊!多情自古傷別離,更那堪冷落清秋節!今宵酒醒何處?楊柳岸,曉風殘月。此去經年,應是良辰好景虛設,便縱有千種風情,更與何人說。

寒蟬凄切,對長亭晚,驟雨初歇。都門帳飲無緒,方留戀處,蘭舟催發。執手相看淚眼,竟無語凝咽。念去去,千里煙波,暮靄沉沉楚天闊!多情自古傷別離,更那堪冷落清秋節!今宵酒醒何處?楊柳岸,曉風殘月。此去經年,應是良辰好景虛設,便縱有千種風情,更與何人說。

</body>

HTML 中,建立一個 <div> 其 CSS 類別為 .newSize。其子輩有二個 <p> 標記,在 CSS 類別中分別用 rem 及 em 作為單位為設定其 font-size,藉以觀察設定後字型大小的計算及變化。

2016年5月2日 星期一

jQuery Object

jQuery Object

簡介

用過 jQuery 的人都熟悉 $(selector, context) 這個語法,並用它來搜尋 context 這個指定範圍中符合 selector 所描述的所有元件。許多初學者常誤認傳回值是一個包含了符合條件的 DOM 元件陣列;實則不然,它的傳回值其實是一個包含了 jQuery Object 的集合 ( collection)。這篇就探究這個傳回的集合,以及其中所包含的 jQuery Object。

首先,我們得區分 DOM 元件和 jQuery Object 有何不同。DOM 元件一般被視為整篇 HTML 文件中的一小片段,在使用時得透過 DOM 的 javascript API 來運作,像是 var target = document.getElementById("target"); 以取得 id="target" 的 DOM 元件。在 jQuery 裡,則用 $("#target") 來取得 jQuery Object,這個 jQuery Object (實質上就是一個 Javascript 的物件),其中含有 id="target" 的 DOM 元件,和許多 jQuery 為這個物件擴充的函式,像是 html(), text(), css() 。。。等等。使用 jQuery Object 的函式來運作 DOM tree 有很多的優點,例如程式碼比較精簡,功能可以跨流覧器等等。能夠區分 DOM 元件和 jQuery Object 的不同在撰寫程式時是很重要的,這樣才能知道那些物件具有 jQuery 的函式可以呼叫,那些物件只是單純的 DOM 元件,並不具有 jQuery 函式。

其次,我們看看 jQuery 是如何建立 jQuery Object。當 $(selector, context) 被呼叫時,jQuery 便從 DOM tree 中搜尋符合 selector 條件的 DOM 元件,每搜尋到一個符合的元件,便將其包覆在一個 jQuery Object 中,以 DOM 元件的 tag, id 及 class 的值組合成 jQuery Object 的名稱,並將其加入要傳回的集合 (collection) 中。此外,這個集合還包含了另外三個屬性:

prevObject
prevObject 的值是一個指標 (pointer),它的值指到上一個搜尋的結果,這是 jQuery 內部在使用的指標,end() 函式就是靠這個屬性值回遡到上一次搜尋的結果。
context
context 的值也是個指標 (pointer) 指到本次搜尋的範圍。也就是 $(selector, context) 中 context 參數的賦予值,如果沒給 context 參數,則預設為指向 document。
selector
selector 的值是一字串,也就是 $(selector, context) 中 selector 參數的賦予值。
其它部份,看程式碼的說明。

範例

範例中在流覧器中顯示兩個方塊,表示 HTML 文件已下載完畢,可以進到「開發者工具」的「主控台」去看範例輸出的結果,在不同的流覧器的主控台中,輸出的格式略有不同,在 Chrome 中,某些輸出格式有時會讓人分不清是物件還是陣列,這點也很惱人,只能說:「習慣就好!」Firefox 的輸出就明確的多,連指標 (pointer) 都標示的很清礎。

CSS

<style>
html {
 width:100%;
 height:100%;
}
body {
 margin:0 auto;
 width:1000px;
 height:100%;
 padding-top:20px;
}
.box {
    margin:10px;
    width:100px;
    height:100px;
    background-color: coral;
}
</style>

CSS 中,.box{} 定義兩個方塊的外觀,只是用來顯示 HTML 文件已經下載完畢。

HTML

<body>
    
</body>

HTML 中很簡單的定義了兩個 <div>,用來顯示方塊和做為搜尋元件之用。

Script

<script>
$(function(){
    // retrieve the jquery version number
    console.log("jQuery version is %s", $.fn.jquery);
    var elem = $("div");

    // elem is a collection, not an Array
    console.log("elem = %o", elem);
    console.log("elem.length = %d", elem.length); // 2
    console.log(Array.isArray(elem));             // false

    // elem.prevObject is a function, returns previous matched result  
    console.log("elem.prevObject = %o", elem["prevObject"]); 
    console.log("elem.prevObject = %o", elem.prevObject);
    console.log("elem.context = %o", elem.context);
    console.log("elem.selector = %o", elem.selector);

    console.log("DOM Element");
    // return all matched elements as an array
    console.log("\t %o", elem.get());

    // the following expressions return the same result
    console.log("\t %o", elem.get(0));
    console.log("\t %o", elem.get(-1));
    console.log("\t %o", elem[0]);
    console.log("\t %o", elem["0"]);

    console.log("jQuery Object")
    console.log("\t %o", elem.eq(0));
    console.log("\t %o", elem.eq());
});
</script>

第 4 行,印出目前使用的 jQuery 版本。
第 5 行,進行一次搜尋,條件為標記為 div 的所有元件。
第 6 行,輸出搜尋後的傳回集合 (collection),內中的各元素所代表的意思,在前面都有解釋了。
第 7 行,輸出符合條件的元件數,如果搜尋不到任何符合條件的元件,這個值就會是 0,可以用這個數值來判斷是否有搜尋到符合條件的元件。
第 8 行,輸出值為 false,證明傳回值並不是個陣列型態的物件。
第 13~16 行,輸出 prevObject, context, 及 selector 的屬性值。第 13 行及第 14 行顯示兩種不同取得屬性值的方法。
第20 行,將所有符合條件的元件,包裝成 jQuery Object 後,以陣列的方式傳回。這裡的傳回值就真的是個陣列了。
第23~26 行,用各種不同的方式取得 DOM 元件,用 get(number) 的好處是 number 參數可以傳入負值,由未端起算,取回元件。
第 29 行,取回第一個 jQuery Object。注意:get() 傳回的是 jQuery Object 的陣列,get(number) 傳回的是 DOM 元件,eq(number) 傳回的是 jQuery Object,別混淆了。特別是 get() 有給參數和沒給參數時,傳回的物件完全不一樣,最容易出錯。eq() 沒給參數時,則傳回的物件中不含任何 jQuery Object,length 值為 0。

2016年5月1日 星期日

jQuery Widget Factory - Part 4

jQuery Widget Factory - Part 4

簡介

這一篇應用前幾篇的知識,實作一個很簡單的 Widget。這個 widget 是一個網路商店中展示產品的基本元件,做的不是很炫麗,主要是在示範如何在實作一個 widget 時會用到的一些基本技術。圖像的部份用的是 holder.js 用 svg 的方式所模擬出來的圖像,因此在 <img> 標記中沒有設定 src 屬性,而是設定 data-src 屬性,否則流覽器會抛出錯誤訊息,抱怨找不到影像檔。

範例

這個範例中,用水平分隔線分隔了上、下兩塊區域,水平線的上方是一個用來展示產品的 widget,wdiget 中除了產品的圖像(這部份得用一點想像力),還標示了產品的名稱及價格,最下端還有一個標示為 Buy 按鈕,按下按鈕後會讓 widget 觸發一個型態名為 buy 的事件。在「開發者工具」(Development Tools) 的「主控台」(console) 中會顯示訊息,並將產品資訊列印出來。
水平線的下方有兩個標示為 Raise 及 Destroy 的按鈕,每按下 Raise 按鈕一次,會將產品價格提高一元。按下 Destroy 按鈕,會「摧毀」水平線上方的 widget。此時打開「開發者工具」(Development Tools) 的「元件」(Elements) 窗格,可以看到 HTML 程式碼的變化。

CSS

<style>
html {
    width: 100%;
    height: auto;
}
body {
    margin:0 auto;
    width: 800px;
    height:100%;
    padding-top: 20px;
    font:normal normal 16px Arial, '文泉驛正黑', 'WenQuanYi Zen Hei', '儷黑 Pro', 'LiHei Pro', '微軟正黑體', 'Microsoft JhengHei';
}
.item {
    box-sizing:border-box;
    width: 180px;
    height: auto;
    padding: 10px;
    border-radius: 8px;
    background-color:#eee;
}
.item:hover {
    outline:2px solid blue;
}
.item-thumbnail {
    width:160px;
    height:160px;
}
.item-caption {
    maring-top:10px;
    padding-top: 10px;
    padding-bottom:2px;
    border-bottom: 2px solid lightgreen;
    color: black;
    font-size: 1.1em;
}
.item-name {
    color: blue;
}
.item-price {
    color: red;
}
.item-button {
    margin-top:8px;
    text-align: center;
}
.item-desc {    
    font-size: 1em;
}
</style>

CSS 中對應 widget 及各 widget 的子元件,以 CSS 類別定義其外觀。

HTML

<body>
    

</body>

HTML 中 id="item" 的 <div> 是 widget 的掛載點。另定義一條水平分隔線及二個按鈕。

Script

<script>
// widget created by widget factory
(function($, undefined) {
    $.widget( "prod.item", {
        version:"1.0.0",
        options:{
            image:"holder.js/160x160?theme=lava",
            name:"Coffee",
            price:80,
        },     
        _create:function(){
            var html = 
                '
' + '
' + '
' + '
'; var elem = this.element; elem.addClass("item").html(html); // construct DOM elem.find("button").button(); this._on({"click button": this._handler}); this._super(); }, _init:function(){ this._setData(); this._super(); }, _setOption:function(key, value){ this._super(key, value); }, _setOptions:function(opts){ this._super(opts); this._setData(); }, _destroy:function(){ this._super(); var elem = this.element; elem.empty(); elem.removeClass("item"); }, _setData: function() { var elem = this.element; var opts = this.options; elem.find(".item-thumbnail img").attr("data-src", opts.image); elem.find(".item-name").html(opts.name) elem.find(".item-price").html(opts.price); }, _handler:function(evt){ this._trigger("buy", null, {name: this.options.name, price:this.options.price}); // evt.stopPropagation(); } }); })(jQuery); $(function(){ $("#item").item(); $("#destroy").button().click(function(evt){ $("#item").item("destroy"); }); $("#raise").button().click(function(evt){ var elem = $("#item"); elem.item("option", "price", (elem.item("option", "price") + 1)); }); $("#item").bind("itembuy", function(evt, data){ console.log("buy product %o", data); }); }); </script>

第 12~16 行,直接把 widget 的 DOM 結構寫成一個字串,並用 html() 函式置入到 DOM tree 之中,也可以用 append(), before(), after() 。。。等各函式逐一構建,純粹就看各人的喜好做法為何了。
第 20 行,監聽子元件 <button> 的 click 事件,當事件觸發時,則呼叫 this._handler() 內部函式以觸發型態名為 buy 的事件。外部程式則監聽型態名為 itembuy 的事件。
第 24 行,呼叫內部函式 this._setData() 把 this.optins 中的資料顯示在 widget 中。
第 32 行,在修改 this.options 之後呼叫 this._setData() 函式,將更新後的資料顯示在 widget 中。
第 34~39 行,實作 destroy() 函式,將 DOM tree 回復到 widget 建立前的狀態。