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 建立前的狀態。

沒有留言:
張貼留言