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 建立前的狀態。
沒有留言:
張貼留言