顯示具有 dojo/* 標籤的文章。 顯示所有文章
顯示具有 dojo/* 標籤的文章。 顯示所有文章

2016年4月23日 星期六

dojo/fx

dojo/fx

簡介

dojo/fx 是架構於 dojo/_base/fx 之上的另一個動畫模組,擴充了 dojo 在動畫上的另一些功能。 這些額外的動畫函式基本上都是由 dojo/_base/fx 中的 animateProperty() 函式所實作,只是另外提供一個常用動畫函式的簡式介面罷了,所需傳入的參數和 animateProperty() 一樣,如果不熟悉傳入參數的格式,可以看 dojo/_base/fx 這篇。dojo/fx 模組所提供的動畫函式有:

wipeIn()
將元件由上至下慢慢顯示,顯示前不佔螢幕位置,顯示後佔螢幕位置。
wipeOut()
將元件由下至上慢慢消失,消失後不佔螢幕位置。
slideTo()
將元件滑動至指定位置。
chain()
將數個動畫串接,依序執行;串接的動畫可以作用在不同的元件上。
combine()
將數個動畫組合,同時執行;組合的動畫可以作用在不同的元件上。

wipeIn() & wipeOut()

先介紹 wipeIn() 和 wipeOut() 兩個函式。wipeIn() 和 wipeOut() 這兩個動畫函式,其功能和使用條件及使用方式都有相當的限制。個人覺得,如果需要類似的動畫效果,實在不如自己用 animateProperty() 寫一個,用起來也許會方便一些。首先,這兩個函式基本上沒有辦法處理元件的 padding 屬性,如果元件中有定 padding 屬性的值,在動畫時顯示的效果就很奇怪。使用 wipeIn() 時,會突然出現上下 padding 總和的高度,然後再慢慢出現其它的部份,還會超出上下 padding 的高度總合,最後才回縮到正常的高度。使用 wipeOut() 時,會先從元件的下方伸長上下 padding 高度的總和,然後再開始慢慢的消失。總歸一句,如果要用 wipeIn() 和 wipeOut() 這兩個動畫函式的元件就不要定 padding 的屬性。如果用在沒有文字的影象圖片上,也不要用 padding 設定,這兩個函式就還可以用。

其次,wipeIn() 函式的要求和限制更大,它不能指定出現後的高度,元件內容佔據多大的高度,元件最終就只能有這個高度,沒得商量。但在範例中,所看到 在執行完 wipeIn() 後,方塊的高度卻沒有因為內容而縮小,這是因為在 CSS 類別中定義了 display:flex;fles:none; 的原故,如果隔隣的方塊還在,所有的方塊便會維持一樣的高度,如果隔隣的方塊不在,就成了內容的高度,這是意外的發現。很神奇,不是嗎?不過再神奇,也救不了它不支援 padding 設定的事實。再其次,要使用 wipeIn() 函式的元件,得使用 display:none; 的設定,讓它一開始時不會出現在螢幕上,這個設定一定要設在元件的樣式裡,不能設定在元件的 CSS 類別中,不然該元件永遠不會出現在螢幕上。這是因為 wipeIn() 會去修改元件的 display 屬性值,將 display 的設定取消,好讓它顯示在螢幕上,如果 display:none; 是設在 CSS 類別中,WipeIn() 函式就改不到,而元件也永遠不會有露臉的機會了。

wipeIn() 及 wipeOut() 都是透過改變元件的 height 屬性值來逹到動畫的效果。在呼叫完這兩個函式後,元件的 height 屬性值,不論原先設定為何,在函式執行完畢後, height 的值都會被設定為 auto。如果後續還要對該元件做動畫處理,這點得特別注意。

slideTo()

這個功能可以移動元件在螢幕上的位置,但位置坐標是以視野 (viewport) 的絕對位置來設定。不論先前的設定為何,在呼叫完 slideTo() 之後,display 的值都會被改成 absolute。同時 top 和 left 的值都會設成移動過後的坐標。原先元件所在的位置會空出來。

範例

範例中建立三個按鈕及三個 <div>,一個用來展示 wipeIn(),一個用來展示 wipeOut()。二個 <div>都沒有設定 padding 屬性。下方的一個用來展示 slideTo(),這個沒有設定 margin,比較容易看到移動到逹的位置,在按下 Slide To 按鈕後,下方的方塊會移到流覽器的左角,top=0 及left=0 的地方。同時,最下方的水平分隔線會上移,因為此時方塊的元件樣式被改成 style="display:absolute; top=0; left:0"。 還有三條水平分隔線,用來觀察元件顯示前及消失前後,是否佔據螢幕空間。下圖為執行時的起始狀能。

CSS

<style>
html {
    width:100%;
    height:100%;
}
body {
    margin: 0 auto;
    width:1000px;
    height:100%;
    padding-top:20px;
}
.boxContainer {
    display:flex;
}
.box {
    margin: 10px;
    width:100px;
    height:100px; 
}
.out {
    flex:none;
    background-color: skyblue;
}
.in {
    flex:none;
    background-color: lightgreen;
}
.slide {
    margin:0px;
    flex:none;
    background-color: coral;
}
</style>

.out{} 及 .in{} 分別設定兩個 <div> 的外觀屬性,不設 padding 值。.slide{} 設定第三個 <div> 的外觀屬性,margin 值設定為 0。flex 值都設定為 none,以保持方塊的高度和寬度。

HTML

<body class="claro">
    
    
    
    
Here is some text

I can slide!

</body>

注意第 8 行,將 display:none; 設在元素的樣式裡。

Script

<script>
require([
    "dojo/parser",
    "dojo/ready",
    "dojo/dom-style",
    "dojo/fx",
    "dojo/on",
    "dijit/registry"
    ], 
function(
    parser,
    ready,
    style,
    fx,
    on,
    registry
){
    parser.parse();
    ready(1, function(){
        // both wipeIn() and wipeOut() can not handle padding attribute
        // After wipeOut(), element's attributes value - height:"auto"
        registry.byId("wipeOut").on("click", function(){
            fx.wipeOut({
                node:"outBox",
                duration: 3000
            }).play();
        });
        // After wipeIn(), element's attributes value - height:"auto"
        // to hide the element before calling wipeIn(), the display:none must be set in the
        // element's style, setting in the CSS class will cause element not display
        registry.byId("wipeIn").on("click", function(){
            fx.wipeIn({
                node:"inBox",
                duration:3000
            }).play();
        });
        registry.byId("slideTo").on("click", function(){
         fx.slideTo({
         node:"slideBox",
                top:0,
                left:0,
                unit:"px",
                duration:3000
            }).play();
        });
    });
});
</script>

程式就將三個按鈕設定在點按後呼叫對應的函式執行動畫,將動畫執行旳時間設定為 3 秒,其它也沒什麼需要解釋的了。

2016年4月12日 星期二

dojo/query (part 4) NodeList-fx

dojo/query (part 4) NodeList-fx

簡介

dojo/NodeList-fx 為 dojo/query 擴充了動畫的功能。原先 dojo 中的動畫功能分拆在 dojo/_base/fx, dojo/fx, 及 dojox/fx 三個模組裡;在 dojo/NodeList-fx 擴充模組裡則含括了大部份的功能。雖然說 dojo/query 及一系列的擴充模組有點仿效 jQuery 的用法,但因為基礎架構上的差異及呼叫函式方法的不同,在使用函式的方法上和參數的傳遞上還是有些差異的。所有 dojo/NodeList-fx 的動畫函式在呼叫後,都會回傳一個 Animation 物件,必需再鏈接 play() 函式,才會執行動畫。例如:query(".box").fadeIn().play();在執行完 play() 之後傳回的物件就不是 Animation 物件了,因此不能再鏈接動畫函式了。大多數的函式在執行時的行為都還滿容易理解,也很符合預期的情況,其中只有 wipeIn() 函式的行為頗為令人費解,和 jQuery 的 wipeIn() 行為大相逕庭。詳細研究後,在範例中另用一個方塊來展示其功能。原因是 wipeIn() 函式針對 element 的樣式 (style) 做變更,似乎又為了配合某些流覽器的行為,對 padding 屬性有特別的處理,最後使得 wipeIn(properties) 函式只能用特殊的寫法來逹到某種效果。詳細情況請參照範例程式中的寫法。

以下列出各動畫函式

fadeOut(properties)
淡出。針對透明度 (opacity) 屬性做改變,動畫結束後,opacity 屬性值為 0,該元件依舊佔據螢幕上的位置。參數 properties 是個物件,指定動畫執行時的一些條件,其物件屬性如下列所示:
delay
設定動畫延遲多久後開始執行,單位為 ms。
duration
設定動畫執行經過所需的時間,單位為 ms。
rate
設定動畫畫面的間隔時間,單位為千分之一秒 (ms),預設值為 20ms,也就是 50 frames/sec。這個預設值有點高,快得讓人看不清變化,可以設低一點。將 rate 設為 25 或 30,也就是每 25ms 或 30ms 顯示一次畫面,這樣比較看得清楚變化。
auto
設定為 true 時,表示後面要鏈接其它的動畫函式。
fadeIn(properties)
淡入。針對透明度 (opacity) 屬性做改變,動畫結束後,opacity 屬性值為 1。
wipeOut(properties)
逐漸消失。針對元件的樣式做變更,會改變 height 和 display 的值,動畫結束後,height=auto,display=none。因為 display=none,此時元件在螢幕上不佔位置。
wipeIn(properties)
逐漸顯現。元件樣式的 position 值需設定為 absolute、 display 值需先設定為 none,如果需要 padding 值,必須在內層多加一個元件,並在內層元件中設定 padding 值。動畫結束後,height=auto、display 為預設值。wipeIn() 結束後的高度沒有辦法指定,只能是內容加上 padding 的高度。個人真的不推薦使用 dojo 中的 wipeIn() 和 wipeOut() 兩個函式,太麻煩了。
slideTo(properties)
移到螢幕上指定的絕對位置。針對 top 及 left 屬性做改變,動畫結束後,position 的值為 "absolute", top 及 left 的值為指定值。
animateProperty(properties)
指定動畫開始時及結束時之各屬性的指定值,想要創造精彩炫目的動畫,就靠這個函式了。詳情請看程式的解說。

範例

範例的圖片只顯示了範例起始的狀態。操作時,先按 FadeOut 按鈕,等方塊淡出後,再按 FadeIn 按鈕,該方塊淡入。按完 WipeOut 按鈕後,方塊會消失,此時,水平分隔線仍在原地不動,顯示出消失的方塊實際上還佔著螢幕的位置。按下 WipeIn 按鈕,則會在水平線下方顯示另一個黃色的方塊。按下 SlideTo 按鈕,則方塊會移動,之後,會同時改變其顏色及大小;這時注意一下水平分隔線的位置,因為是移動到絕對位置,此時,水平分隔線的位置依然是相對的,所以就被移到上方了。

CSS

<style>
html {
    width:100%;
    height:100%;
}
body {
    margin:0 auto;
    width:1000px;
    height:100%;
    padding-top:20px;
}
.box {
    box-sizing: border-box;
    margin:20px;
    width:200px;
    height:200px;
    border: 2px solid black;
    padding:50px;
    background-color:blue;
}
</style>

CSS 中設定類別 .box 之各樣式屬性的初始值。

HTML

<body class="claro">
    
    
    
    
    
    
Demo box

</body>

HTML 中設定五個按鈕,分別觸動不同的動畫效果。並設定兩個方塊以展示動畫效果,其中 id="wipeInBox" 的方塊,,特別用來展示 wipeIn() 的效果。其中的 <hr> 水平分隔線用來顯示淡出的方塊依然會佔據螢幕位置。

Script


第 21~25 行綁定按鈕觸發事件時所要執行的函式。
第 29 行設定了在 2 秒後才開始執行動畫,因此按下按鈕後,要耐心等兩秒鐘,才會開始動作。
第 54~68 行是最精彩的部份,slideTo() 先將方塊移至 top=100px, left=300px 的位置,之後再用 animateProperty() 函式,經過 5 秒的時間,將背景顏色由紅色轉成綠色,在變換顏色的同時,將尺寸由 200px x 200px 縮小至 100px x 100px。
第 58 行設定各屬性若需要使用測量單位時,單位值為 "px" 這也是預設值。
第 62 行 backgroundColor 的設定值,指定了 start 和 end 兩個屬性值,因此,在動畫執行時,會先將方塊的顏色轉成紅色,最後才變成綠色。而第 63,64 行 width 和 height 屬性都只設定了一個值,此時,便以元件的現值為起始值,在此設定的值為結束值。 注意第 59 行的 auto 屬性須設定為 true,否則就不能自動鏈接後繼的動畫函式了。

2016年4月11日 星期一

dojo/query (part 3) NodeList-traverse

dojo/query (part 3) NodeList-traverse

簡介

在 DOM Tree 中搜尋元件時,並非每次都需要搜尋整份 HTML 文件;有時,會希望以搜尋到的某一元件做為參考點,由此,再依和參考點的對應關係去搜尋相關的元件。NodeList-traverse 這個模組便為 dojo/query 模組擴充了這方面的功能;讓搜尋可以依參考點的父輩、同輩,子輩等等各種關係,找到對應關係的元件。這種作業方式,在撰寫或處理略為複雜的介面元件模組時特別方便有用; 這樣也不需要傷神為每一個在介面中的小節點或子元件取一個用來識別的 id 屬性,或 CSS 類別,才能搜尋到該元件,只要找到介面元件中的參考元件,便能依對應關係找到介面中的其它元件。

以下列出部份的函式,用法如: query(Selector).children(filter); 其中 filter 參數為選用,可以給或不給,賦予值如同 Selector,也是使用 CSS3 選擇器的篩選條件式,用來將 qeruy 選取到的元件再做進一步的篩選。

children(filter)
取得所有選取元件的子輩元件。取得子輩時,只會取得下一層子輩。
parent(filter)
取得所有選取元件的父輩元件,取得父輩時,只會取得上一層的父輩。
parents(filter)
取得所有選取元件的父輩元件,這個函式會取得所有上層的父輩,一直到 <body> 及 <html>,通常這並非所要的結果,因此,這個函式一般都會給參數 filter,以篩選取得父輩的元件。
siblings(filter)
取得所有選取元件的同輩元件。
next(filter)
取得所有選取元件的下一個同輩元件,因為 next() 只會傳回一個元件,參數 filter 在這裡的作用,比較像指定條件,而非篩選。換句話說,這個函式會傳回同一輩中,下一個符合 filter 條件的元件。
nextAll(filter)
取得所有選取元件之後的所有同輩元件(不含選取元件本身),因為 nextAll() 通常會傳回不只一個元件,參數 filter 在這裡的作用又回到篩選。換句話說,這個函式會傳回在選取元件之後的同一輩中所有符合 filter 條件的元件。
prev(filter)
取得所有選取元件的上一個同輩元件,因為 prev() 只會傳回一個元件,參數 filter 在這裡的作用,比較像指定條件,而非篩選。換句話說,這個函式會傳回同一輩中,上一個符合 filter 條件的元件。
prevAll(filter)
取得所有選取元件之前的所有同輩元件(不含選取元件本身),因為 prevAll() 通常會傳回不只一個元件,參數 filter 在這裡的作用又回到篩選。換句話說,這個函式會傳回在選取元件之前的同一輩中所有符合 filter 條件的元件。
andSelf()
將參考元件本身加入 NodeList 之中,例如在使用 next(), nextAll(), prev() 及 prevAll() 等函式時,如果希望 NodeList 中包含參考點的元件,就必須在函式之後鏈接 .andSelf() 函式。使用時,必須注意 .andSelf() 在鏈接時的所在位置,不然取得的結果可能會出乎意料。

範例

在範例中構建一個簡單的組織圖,用來展現如何透過 NodeList-traverse 來尋訪元件。要找到一個特定的元件,可以有無數種的尋訪方式,範例中的程式並非唯一的答案。實作時,還是八仙過海,各顯神通吧!

CSS

<style>
html {
 width:100%;
 height:100%;
}
body {
 margin:0 auto;
 width:1000px;
 height:100%;
 padding-top:20px;
}
.company {
 width:400px;
 border: 2px solid gray;
 padding:30px;
}
.sales,.engineers {
 border: 2px solid gray;
 padding:30px;
 
}
.employee {
 border: 2px solid gray;
 padding:10px;
}
</style>

CSS 中設定各類別的屬性,讓各組織單位具有邊框,同時讓組織圖依組織架構內縮,這樣比較容易看出組織間的階層關係。

HTML

<body class="claro">
Company
Sales
John
Jason
Judy
Julian
Engineers
Susan
Sean
Sally
</body>

HTML 中用 <div> 定義出組織之間的階層關係。

Script


第 20 行先用 query(".sales")找到 sales 部門,用 children() 取得其所有子輩元件,用 at(0) 取得子輩元件的第一個元件,再用 next() 取得其後的一個元件,將其背景色改成淺綠。當然,用 at(1) 可以直接取得子輩元件中的第二個,不須多此一舉用到 next(),但這只是範例,就別太計較了。
變數 element 中,此時存放的是 Jason 這個元件,第 21 行取得其父輩元件,自然就是 class="sales" 的 <div> 了。 將其背景改成粉紅色。
第 23 行用 silblings() 取得 sales 的同輩,也就是 class="engineers" 的 <div>,將其背景改成淺藍色。
第 24 行用 children() 取得 engineers 的所有子輩元件,並將其背景改成淺灰色。

dojo/query (part 2) - NodeList-manipulate

dojo/query (part 2) - NodeList-manipulate

簡介

NodeList-* 這幾個模組從來不會單獨使用,都是附加在 dojo/query 這個模組之上,用以擴充 dojo/query 的函式,藉以針對 query 所搜尋到的元件做類似批次作業的變更。利用 NodeList-manipulate 擴充 dojo/query 後,dojo/query 就會具有 dojo/dom-* 一系列模組的功能,只是函式名稱及傳遞的參數略有不同,函式的參數中不需傳入要改變屬性的節點或節點名稱。這個模組基本上在摸擬 jQuery 的作業方式,所有的函式都可以鏈接 (chain up);其中最大的不同在於操作 DOM Tree 的方式,幾乎完全摸擬 jQuery 的作業,和 dojo/dom-construct 模組的作業有很大的差異。還有,在改變元件樣式時,jQuery 用的是 CSS() 函式,而 NodeList-manipulate 則保留使用 dojo 的 style() 函式。在監聽事件時,jQuery 用 bind() 函式,而 NodeList-manipulate 也保留了 dojo 使用的 on() 函式。操作 DOM Tree 的這一部份,去看 jQuery 的文章也許比看 dojo 的文章要來的詳盡。

底下並未列出所有的函式。

新增元件

append(element)
將 element 加在選取元件之中,成為選取元件的最後一個子元件,element 為一個元件,或一段 HTML 程式碼。
prepend(element)
將 element 加在選取元件之中,成為選取元件的第一個子元件,element 為一個元件,或一段 HTML 程式碼。
before(element)
將 element 加在選取元件之後,成為選取元件的同輩元件,element 為一個元件,或一段 HTML 程式碼。
after(element)
將 element 加在選取元件之前,成為選取元件的同輩元件,element 為一個元件,或一段 HTML 程式碼。

移動元件

appendTo(selector)
將所有選取元件依序加到 selector 之中,成為 selector 最後的子元件,selector 為選取元件的條件。
prependTo(element)
將所有選取元件依序加到 selector 之中,成為 selector 最先的子元件,selector 為選取元件的條件。
InsertBefore(selector)
將所有選取元件依序加到 selector 之前,成為 selector 最後的同輩元件,selector 為選取元件的條件。
InsertAfter(selector)
將所有選取元件依序加到 selector 之後,成為 selector 最後的同輩件,selector 為選取元件的條件。

其它

wrap(element)
將所有選取的元件,變成 element 的子元件。
replaceWith(element)
用 element 元件取代所有選取的元件。

範例

範例很簡單,就在清單中的每一個清單項目後面加入斜體的 "pie" 字,並用鏈接的函式改變清單字體的顏色。

CSS

<style>
html {
 width:100%;
 height:100%;
}
body {
 margin:0 auto;
 width:1000px;
 height:100%;
 padding-top:20px;
}
</style>

CSS 中沒有特別需要定義的項目。

HTML

<body class="claro">
 

Fruits

  • Apple
  • Banana
  • Cherry
</body>

HTML 中建立一份清單即可。

Script


第 8 行的 "dojo/NodeList-manipulate" 只是用來擴充 dojo/query 模組,而且又是在最後一個,所以在 function() 中的參數中,可以不用列名。但如果不是放在最後面,而其後有其它的參數時需要給予參數名時,就必須給予一個參數名,不然 dojo 會在載入模組和參數名稱之間的對應造成混亂而給出錯誤訊息。
第 19 行選取 CSS 類別為 .fruit 的所有清單項目。
第 20 行,加入 <em> Pie</em> 這段 HTML 程式碼到每一個清單項目的後面,並用鏈接函式 style() 改變字體的顏色。

2016年4月8日 星期五

dojo/query (part 1)

dojo/query (part 1)

簡介

在 dojo 中,要搜尋並鎖定 DOM Tree 中的元件 (element) ,除了透過 dojo/dom 模組的 dom.byId() 及透過 dijit/registry 模組的registry.byId() 之外,還有一個 dojo/query 模組可供使用。前二者不同的地方在於: dom.byId() 根據傳入的 id 屬性值,直接傳回一個 DOM 的元件,而 registry.byId() 則根據傳入的 id 屬性值,傳回一個 dijit (dojo widget) 物件 (object),還要進一步使用 registry.byId().domNode 才能真正取得 DOM 元件;即便如此,取得的元件和 dom.byId() 所傳回的元件稍有不同,可以用 console.log() 函式將兩者的輸出比較一下,就明白了。如果要變更或使用 DOM 元件,最好直接使用 dom.byId()。這兩者都只能使用 id 的屬性值作為搜尋的條件。

dom/query 模組在搜尋條件上,使用了 CSS3 的選擇器 (selector),因此,在搜選的條件上廣泛了許多。(事實上 dojo 有好幾個選擇器可供選用,但 CSS3 的選擇器己經足以應付大多數的需求,所以也不用費事再試著去設定和使用其它的選擇器了。) id、標記名 (tag)、 CSS 類別名 (class)、屬性值等等,都可以用來搜尋 DOM 中的元件。dom/query 的傳回值為 NodeList,其中包含所有符合搜尋條件的元件,NodeList 本質上就是個 javascript 的陣列 (Array),本身具有的函式不多,但可以透過加載下列的幾個模組擴充其功能:

dojo/query 這個模組中提供最重要的函式是 instantiate(),這個函式可以用程式法將所有選取到的元件轉變成 dojo 的 dijit。

dojo/NodeList-data
在元件中添加自訂屬性的擴充功能。這個擴充功能實際上用 dojo/dom-attr 模組就可以做到大部份的功能,個人猜想它應該是因為 HTML5 之前用 "data-" 前導的自訂屬性並非標準,為此而存在的。在加載了 NodeList-manipulate 模組之後,NodeList 也具有 attr() 函式,加載這個模組就顯得有點多餘了。
dojo/NodeList-dom
模擬 dojo/dom-* 的功能。
dojo/NodeList-html
變更元件內容的擴充功能。
dojo/NodeList-manipulate
這個擴充模組可以讓 dojo 像 jQuery 一樣對 DOM Tree 運作。個人認為這個擴充模組最好用了,只要加載了這個模組,就具有 dojo/NodeList-data、dojo/NodeList-dom 及 dojo/NodeList-html 三個模組的函式,可以針對符合選取條件的所有元件做批次作業。這樣就方便許多了。
dojo/NodeList-traverse
擴充尋訪 (traverse) 的功能,這個功能也很好用,語法也跟 jQuery 很類似。
dojo/NodeList-fx
添加動畫的功能。像是 anim(), fadeIn(), fadeOut(), wipeIn(), wipeOut(), slideTo() 等等。大約就是 dojo/_base/fx, dojo/fx, 及 dojox/fx 三個模組的集合版。

範例

範例中展示如何使用 instantiate() 函式,將一個清單中,CSS 類別為 .button 的三個項目都轉變成按鈕。

CSS

<style>
html {
    width:100%;
    height:100%;
}
body {
    margin:0 auto;
    width:1000px;
    height:100%;
    padding-top:20px;
}
</style>

HTML

<body class="claro">
    

Fruit Buttons

  • Apple
  • Banana
  • Cherry
</body>

在 HTML 中建置一個具有三個項目的無序號清單。

Script


第 20~25 行使用 instantiate() 函式將清單項目轉化成 dojo 的按鈕 (Button)。
第 26 行取得第二個按鈕的 DOM 元件。

2016年3月4日 星期五

dojo/Deferred, dojo/when

dojo/Deferred, dojo/when

簡介

dojo/Deferred 是 dojo 中實作 dojo/promise/Promise 的類別,也是使用 promise 的基礎元件。當一個作業要在非同步狀態下執行,而其它作業有可能必須在此作業完成後方能執行時;該作業在實作時便應宣告且產生一個 Deferred 類別的實體 (instance),並傳回一個 promise。後繼要執行的作業則作為 promise.then() 的參數,在 promise 被「滿足」(fulfilled) 時執行。因為 promise.then() 也會傳回一個 promise;所以,整個程序可以一直串接下去,形成一個執行鏈。
dojo/when 只是 promise.then() 的一個簡單寫法。

範例


範例中建立了兩個圓形,點按左邊的圓形以模擬非同步的作業,右邊的圓形則顯示作業的進度,及顯示最終的結果。設定為點按三次左邊圓形便完成作業。修改一下程式碼可以產生「拒絕」(reject) 的結果。

CSS

<style>
html {
    width:100%;
    height:100%;
}
body {
    margin: 0 auto;
    width:1000px;
    height:100%;
    padding-top:20px;
}
#counter {
    margin:20px;
    height:100px;
    width:100px;
    border:10px solid black;
    border-radius: 50%;
    font-size: 48px;
    text-align: center;
    line-height: 100px;
    float:left;
}
#response {
    margin:20px;
    height:100px;
    width:100px;
    border:10px solid black;
    border-radius: 50%;
    font-size: 48px;
    text-align: center;
    line-height: 100px;
    background-color: white;
    float:left;
}
</style>

#counter 設定左邊圓形的屬性。
#response 設定右邊圓形的屬性。

HTML

<body class="claro">
  
0
0
</body>

HTML 則建立兩個 <div>,用來顯示左、右兩個圓形。

Script


取消第 36 ~ 40 行的註解並註解第 43 ~ 47 行;在點按左邊圓形三次後,會產生「拒絕」的結果,此時會執行第 62 ~ 70 行的程式。

第 54 ~ 80 用 when 的語法寫,則如下所示:


2016年3月2日 星期三

dojo/promise/Promise

dojo/promise/Promise

簡介

Promise(議決、承諾)是一種程式撰寫的模式 (Template),其主要功能在協調非同步執行緒 (Asynchronous Thread) 作業之間的前後順序。為了協調各執行緒執行時的先後次序,首先要在先執行的執行緒中產生並傳回一個 Promise 物件,再利用這個 Promise 物件來控制後續要執行的作業。先執行的執行緒則在完成作業時,傳回「解決」(resolved) 的訊號;或因執行條件不足或執行條件錯誤時,傳回「拒絕」(rejected) 的訊號。而 Promise 的狀態則在「未完成」 (unfulfilled)的起始狀態,依據先執行的作業結果轉換至「完成」(fulfilled)或「拒絕」(rejected) 兩個狀態之中的一個;Promise 則依不同的狀態再去執行對應的作業。

在 dojo 中,dojo/promise/Promise 是一個只定義了應用呼叫介面 (API)抽象物件,並未進行物件模組的實作;實作 dojo/promise/Promise 介面的物件模組是 dojo/Deferred。透過 dojo/Deferred 則另外實作了 dojo/promise/all, dojo/promise/first 及 dojo/when 三個物件模組。

範例

Script


then():傳入三個函式作為參數,

  1. callBack() 是在狀態為「完成」(resolved)時所要執行的作業。
  2. errBack() 則是在狀態為「拒絕」(rejected) 時所要執行的作業。
  3. progBack() 則是在作業進行時,進度改變時所要執行的作業。

cancel():為收到「取消」信號時,所要執行的作業。
isResolved(), isRejected(), isFulfilled() 及 isCanceled() 則傳回 true 或 false,表示該 Promise 在呼叫這些函式時,當時所處於的狀態。

2015年11月1日 星期日

dojo/topic

dojo/topic

簡介

dojo/topic 是另一個和 dojo/on 一樣可以藉由某事的發生,而針對某事採取對應行動的機制。不同的地方在於:dojo/on 比較偏向單一的事件,單一的對應行動;dojo/topic 則偏向於藉由發佈單一的主題訊息 (topic),而相對會有至少有一個及一個以上的對應行動。

topic 有二個常用的函式:

publish(message, obj):
用來發佈一項主題訊息,第一個參數是所要發佈的主題訊息,為字串型態,字串的內容自定。第二個是隨發佈主題訊息所傳遞的相關資料,為物件型態,物件的內容自定。
var handle = subscribe(message, action):
用來訂閱主題訊息。第一個參數是所要訂閱的主題訊息,為字串型態,字串的內容須和發佈的主題訊息內容相同。第二個參數則是收到訊息後所要採取的對應行動,型態為函式,函式的參數為 publish() 函式所傳遞的物件。傳回的變數 handle,具有 remove() 函式,用 handle.remove() 可以取消對主題訊息的訂閱。

範例

範例中建立了七個灰色方塊,點按方塊時,該方塊會訂閱主題訊息,程式每三秒會發佈一次主題訊息,有訂閱主題訊息的方塊則會在接到主題訊息時,改變其背景顏色。範例中不能取消主題訊息的訂閱。

CSS

<style>
html {
    width:100%;
    height:100%;
}
body {
    margin: 0 auto;
    width:1000px;
    height:100%;
    padding-top:20px;
}
.box {
    box-sizing:box-sizing;
    margin:10px;
    width:60px;
    height:60px;
    border:3px solid gray;
    background-color:#EEEEEE;
    float:left;
}
.box:hover {
    cursor:pointer;
}
</style>

CSS 中 .box 定義方塊的樣式, .box:hover 定義當游標移到方塊上方時,改變游標的樣式。

HTML

<body class="claro">
    
</body>

HTML 中,定義七個方塊,在點按方塊時,會呼叫 app.subscribe() 函式訂閱主題訊息。

Script


第 22 行定義一個含有彩虹七種顏色的字串陣列。
第 25~27 行則是各方塊訂閱主題訊息及所採取之行動的函式。訂閱的主題為 "changeColor"。
第 30~32 行定義每隔 3 秒鐘,,發佈一次 "changeColor" 主題訊息,發佈主題訊息時,並沒有相關的資料要傳遞,所以第二個參數為一個 null 指標。

2015年10月31日 星期六

dojo/on (double click)

dojo/on (double click)

簡介

當一個圖形介面元件需要同時用到點按 (click) 及 雙點按(double click) 時,常常會碰到一件很惱人的事;也就是每次雙點按時,都會產生三次事件,二次點按,然後一次雙點按。這是因為每次點按之間的逾時值 (timeout) 太短;所以有人建議同一個圖形介面元件上不要同時實作點按和雙點。或者,透過延長點按與點按之間的逾時值來解決這個問題。同一個圖形介面元件上,是可以同時實作點按和雙點按的。

範例

範例中建立一個灰色方塊,同時在方塊上實作點按及雙點按兩種功能。每次點按或雙點按時,都會出現視窗顯示點按的型態。

CSS

<style>
html {
    width:100%;
    height:100%;
}
body {
    margin: 0 auto;
    width:1000px;
    height:100%;
    padding-top:20px;
}
.box {
    box-sizing:box-sizing;
    width:200px;
    height:200px;
    border:3px solid gray;
    background-color: #EEEEEE;
}
.box:hover {
    cursor:pointer;
}
</style>

CSS 中.box 定義方塊的樣式,在游標移到方塊上方時,改變游標的樣式。

HTML

<body class="claro">
    
</body>

HTML 中只需定義一個方塊的掛載點。

Script


第 20~22 行建立點按 (click) 事件的監聽和處理。
第 23~25 行建立雙點按 (double click) 事件的監聽和處理。
第 27 行的 clickDelay 是點按和點按之間的逾時值,也就是說,在這個時間內,如個碰到兩個點按,則視為雙點按; 如果二個點按之間的間隔時間,長於 clickDelay 的值,則視為兩次的點按。
第 28 行設定一個 clickTimer 變數,在逾時值滿足後,呼叫處理函式。
第 29~38 行為點按的處理函式。
第 39~47 行為雙點按的處理函式。

2015年10月30日 星期五

dojo/on

dojo/on

簡介

dojo/on 是 dojo 中用來連接事件 (event) 和事件監聽器 (event listener) 的模組。用法並不難,其中有幾個常用的函式,列示語法如下:

on(target, type, listener)
當 target 觸發 type 事件時,執行 listener 監聽函式。傳回一個 handler 物件。
on.once(target, type, listener)
當 target 觸發 type 事件時,執行 listener 監聽函式。但只有第一次觸發時,會執行監聽函式,隨後觸發的事件都即不再執行監聽函式。傳回一個 handler 物件。
on(target, type, listener)
在 target 元件觸發 type 事件時,執行 listener 函式,傳回值為事件的 handler。
on.emit(target, type, eventParam)
促使 target 觸發一個 type 型態的事件。eventParam 是一個 Javascript 的物件,內中包含所要傳給監聽函式的參數。傳回一個 handler 物件。
handler.remove()
移除監聽器。handler 為上面各函式所傳回的物件。

on.once() 和 on() 的用法完全一樣,唯一不同的地方是 on.once() 只會觸發一次事件,之後會自動移除事件的 handler,之後就不會再觸發相同型態的事件了。
on.emit() 函式執行時會引起 target 觸發 type 的事件,第三個參數 eventParam 是一個物件,物件中可以定義事件的屬性,這些屬性會被融入 (mixin) 觸發的事件物件中,可以藉此傳遞參數給事件監聽器。由 on.emit() 所觸發的事件物件是 Event,和由圖形介面元件所觸發的 MouseEvent 不太一樣,最大的差異在兩者具備屬性的個數。

範例

在範例中建立了兩個方塊圖形元件,點按左邊的淡紫色方塊會在主控台中,將事件物件印出來,按幾次印幾個。只要一按右邊的淡綠色方塊,就會讓淡紫色的方塊再觸發一次事件,隨後移除事件的 handler,之後再按淡紫色的方塊,就再也不會觸發任何事件了。

CSS

<style>
html {
    width:100%;
    height:100%;
}
body {
    margin: 0 auto;
    width:1000px;
    height:100%;
    padding-top:20px;
}
.box {
    box-sizing:border-sizing;
    margin:10px;
    width:200px;
    height:200px;
    border:3px solid gray;
    background-color: #EEEEEE;
}
.box:hover {
    cursor:pointer;
}
.violet {
    background-color:#EE82EE;
    float: left;
}
.lightGreen{
    background-color:#98FB98;
    float:left;
}
</style>

CSS 中,.box 定義了兩個方塊元件的共通樣式,.box:hover 定義了游標在移動到方塊上方時,改變游標的樣式。.violet 及 .lightGreen 則定義各自的背景顏色及位置。

HTML

<body class="claro"<
    
</body>

HTML 中就定義兩個 <div< 用來顯示兩個方塊。

Script


第 21~23 行把由淡紫色方塊觸發的事件和處理函式串起來。
第 25~27 行是事件處理函式,單純只是把事件物件在主控台印出來。
第 30~33 行把由淡綠色方塊觸發的事件和處理函式串起來。在處理函式中,再讓淡紫色方塊觸發一次 click 事件。這事件只會觸發一次。
第 35 行把淡紫色方塊的事件處理器移除。

2015年10月1日 星期四

dojo/request (AJAX)

dojo/request

簡介

dojo/request 是 dojo toolkit 的 AJAX 模組,用來傳送符合 AJAX 規範的 request 給後端伺服器,要求伺服器傳送資料給流覽器。

這篇先介紹如何使用 get 和 post 兩種,接收的檔案是標準的文字檔。因為沒有真的伺服器在後端,所以就放一個檔案在目錄裡,直接去讀這個檔案。但是 Chrome 的預設會阻擋流覽器讀取本地 (local) 的檔案,所以得先把 Chrome 關掉,在 OS X 的主控台下"open /Applications/Browser/Google\ Chrome.app --args --allow-file-access-from-files" 指令,在 windows 的主控台下 "Chrome.exe --allow-file-access-from-files",記得在下指令前,一定要把所有的開啟的 Chrome 流覽器都關掉,不然指令會不起作用。

範例

範例中建立兩個按鈕,一個按下後會送出 get 的 request,另一個會送出 post 的 request,但接收的檔案都是同一個;把資料檔和網頁放在同一個目錄下就可以了。資料檔的檔名為 lyrics.txt。記得開啟「開發者工具」中的「主控台」看結果。如果真的送資料到伺服器, url 的值就要填提供服務的 servlet 或 CGI (Common Gatway Interface) 程式的名稱了。

CSS

<style>
input, textarea {
    font-family:monospace;
}
</style>

在 CSS 中改變 input 及 textarea 兩毎標記內容所使用的字型,改用定寬字。

HTML

<body class="claro">
    Different Requests
    
    
</body>

Script


第 18 行和第 42 行指派給變數 query 的值,就當成由輸入欄位取得,透過 dojos/form/Manager 的 gatherFormValues() 所傳回的 Javascipt 物件,當成送到伺服器的查詢資料。

變數 opts 的值也是個 Javascript 的物作,其中的屬性用來設定 request 的選項。

method 指定 request 所使用的方法,其實共有八種如下:

  1. OPTIONS
  2. GET
  3. HEAD
  4. POST
  5. PUT
  6. DELETE
  7. TRACE
  8. CONNECT
這裡只介紹 GET 和 POST 兩種,其它六種各有不同的用途。

GET 和 POST 選項不同的地方在 GET 用 query 鍵傳送資料給伺服器,query 的值會被轉成 query string 的格式,附加在 url 的後面,傳給伺服器。POST 則用 data 鍵,傳送資料給伺服器, url 的後面不會加任何東西。

async:true 是預設值,指 AJAX request 會以非同步的方式傳送,如果程式一定要等到收到伺服器傳回的資料後才能開始做其它事,就要把它設定為 false,改為同步作業。

preventCache:true, 告訴流覽器不要使用快取 (cache) 中的資料,每次都要向伺服器要資料。如果後端資料變更的頻率很高時,最後設定為 true,避免使用 cache 中的資料,如果資料很少在變動,設定為 false 可以節省頻寬,而且反應會比較快。

timeout 設定逾時值,單為為 milliseconds。設這個值和網路的頻寬有關,最好實地實驗,測一下。

handlAs 指定傳回的資料要以何種格式進行處理。支援的格式有下列幾種:

  1. text
  2. json
  3. javascript
  4. xml

設定為 text 時,直接傳回純文字。

設定為 json 時,若收到的資料確實為 JSON 格式時,會轉成 Javascrpt 的物件後傳回。

設定為 javascript 時,若收到正確的 Javascript,則下載後會立刻執行該段 Javascript 程式碼。但這很有可能造成安全上的漏洞,要小心使用。

設定為 xml 時,則傳回一份 XML 文件,以供處理。

request 的回呼函式有三個傳入的參數都不同。第一個回呼函式是成功時呼叫,參數是伺服器傳回的資料。第二個是發生錯誤時呼叫,傳入的參數是含有錯誤訊息的物件。第三個函式在每一次傳回回應 (response)時呼叫一次;有時一個 request 會有一個以上的 response,可以物件裡的資料來顯示傳輸進度。