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

沒有留言:

張貼留言