jQuery 學習筆記 (7) — 擴充 jQuery

簡單介紹一下怎麼寫一個新的「以 jQuery 為基礎的函式」。

jQuery 雖然已經提供了很多函式可以使用,但也許你還想設計出 jQuery 尚未提供的功能(或是寫一個 jQuery plugin),那就要瞭解怎麼擴充 jQuery,這篇文章將會介紹一個簡單例子來說明如何擴充 jQuery,這個例子是會把指定的網頁元件顯示出 Google Maps 以及對它的操作。

(其實已經有個叫 jmaps 的 jQuery plugin 有很完整的實作這個功能了)

先寫出整個網頁 HTML 的原始碼:

















簡單說明一下這個 HTML 的結構,必要的 jQuery JS 檔案是一定要引入的;而要使用到 Google Maps API 的話,要去官網註冊一個 API Key,然後參考它的說明加入 Google Maps API 所需要的 JS 檔案;然後,我們把擴充的內容寫在 jqmap.js 檔案裡,mymap.js 檔案裡則是這一頁主要執行的 JS 原始碼。而 HTML 的 body 裡只有一個 div,等一下要讓 Google Maps 顯示在這裡。

如同 jQuery 其它的函式,我希望等一下能用 $('#gmap').gmaps(); 來完成顯示的動作,所以我在 mymap.js 裡先寫成這樣:


/* 相當於 body onload 之後呼叫 */
$(function(){
// 先設定 div 的大小
$('#gmap').css({
width: '500px',
height: '375px'
});

// 產生並顯示 Google Maps
var gmap = $('#gmap').gmaps();

...
});

當然,現在還不會有什麼效果,還是要去 jqmap.js 裡實作出 $().gmaps() 這個函式,所以我們先在 jqmap.js 裡的檔案先完成這件事:


(function($){

$.fn.extend({

gmaps: function(options) {
var o = jQuery.extend({
center: [25.02359, 121.52808],
zoom: 15
}, options);

$(document).unload(function(){GUnload();});

return this.each(function(){
this.gMap = new GMap2(this);
this.gMap.setCenter(new GLatLng(o.center[0], o.center[1]), o.zoom);
});
},

});

})(jQuery);

首先,(function(){ ... })(); 把所有的 code 包起來,這樣的作法是確保你裡面寫的 code 不會成為全域變數,而在此例中我加入寫成 (function($){ .... })(jQuery); 表示我將 $ 定義成 jQuery 物件,好讓這個 function 中可以直接使用 $ 不造成混淆,很多 jQuery plugin 都會用這個方式包裝起來。

接著,$.fn.extend({ ... }) 是為了擴充 jQuery.fn 這個物件,為了讓我們之後定義的函式會跟原本 jQuery 提供的函式有相同的結構,所以擴充的內容會寫在 $.fn.extend({ ... }) 之中。

很快地,就來到定義 gmaps() 的部份,我們定義 gmaps 是一個函式,並且可以傳入一個參數當作 options,而下面用到 jQuery.extend( ... ) 的部份則是設定 options 的預設值,簡單地說,如果使用時有傳入 options 則用傳入的,否則就使用預設值。

接下來,就是直接使用 Google Maps API 了,而我把建立好的 GMap2 物件存放在 this.gMap 裡面。(會用 this.each 是因為 jQuery selector 可能會一次 select 很多個網頁元件,雖然實務上可能不會一次用很多 Google Maps,不過寫法上還是按照慣用(?)的模式來)

另外就是遵照 Google Maps API 的建議,在 unload 的時候呼叫 GUnload 以避免瀏覽器 memory leak。

如此一來,你應該可以看到頁面上出現一個 500x375 大小的 Google Maps 了(預設的座標是台北市中正區一帶)

如果要再寫一個可以在這地圖上加入指標的函式,那在 jqmap.js 裡可以寫成:


(function($){
$.fn.extend({
gmaps: function(options) { ... },

addGMarker: function(lat, lng) {
this.marker = new GMarker(new GLatLng(lat, lng));
return this[0].gMap.addOverlay(this.marker);
}
});
})(jQuery);

很簡單地加上一個 addGMarker 函式,並且帶入經緯度座標值為參數,好在剛才產生的 maps 上加入一個 marker 的 overlay。

如此一來,便能夠在 mymap.js 裡使用 $('#gmap').addGMarker(xxxx, xxxx) 來加入 marker 了。

看吧,擴充 jQuery 也是很簡單的。

  • laudieh

    太棒了! 把 Google 與 jQuery 結合!
    謝謝大大!!

  • KINK

    ericsk大可以麻煩您說明這2點嗎?
    1.jQuery.extend….請問他的用途是,看不懂耶;有去官方看了說明,依然不了解用途在於?
    2.這裡的”this”是指document本身,還是哪各物件呢?

    請您受教….謝謝

  • AXIS

    版主請問一個問題,研究了3天了,還是無解 , 如以下程式碼

    function room_change(k){

    var tmp = eval(“man_zone_”+k);

    //eval(‘var tmp = man_zone_’+k);

    $(tmp).html(k);
    }
    ?>

    也就是,外面有用迴圈製造出來的div , id分別是
    man_zone_1, man_zone_2…..動態的
    取得k=1後, 就在man_zone_1顯示1
    取得k=2後, 就在man_zone_2顯示2…依此類推
    使用eval這個技巧是當容器的id不固定的時候

    這種方式只能在ie做用, 在FireFox上是無效的

    我不曉得對付這樣的動態變數有沒有其它更好的方式, 能在FF上也能正常運作呢?

  • AXIS

    找到原因了, 在某個網站找到的

    IE下,,可以使用eval(“idName”)或getElementById(“idName”)來取得id為idName的HTML對像;Firefox下只能使用getElementById(“idName”)來取得id為idName的HTML對像.
    解決方法:統一用getElementById(“idName”)來取得id為idName的HTML對像.

    難到eval不是js的標準嗎?

  • ghost

    板大
    想請問一下return this[0]
    的this[0]為什麼要這樣用呢!?

    我改成
    return this.each(function(){
    this.gMap.addOverlay(this.marker);
    });
    就不能用了..

    但是用var maker
    return this.each(function(){
    this.gMap.addOverlay(marker);
    });
    就可以了…

    感覺搞不太懂this[0]

  • Pingback: JQuery | 寂光()

  • 謝謝大大…講的很清楚唷…
    本來不是很懂得怎麼用…一直有想要把它學起來…
    現在懂囉…^^