iT邦幫忙

DAY 19
5

Javascript面面觀系列 第 19

Javascript面面觀:網頁篇《jQuery inside - plugin》

之前的文章裡,我稍微追蹤了jQuery的程式碼,來理解jQuery的架構及運作。其實除了前文中比較複雜的selector以及events,jQuery接下來還包裝了traverse、css、positioning、animate...等種類的函數,這部份比較沒有那麼複雜,都是用數個函數來包裝相關的功能,並在內部解決瀏覽器不相容的問題。大體來說,jQuery其實是一個大facade,透過他的定義好的操作方法,就可以簡單地操作DOM,並且可以透過一些方式延伸及擴充功能。(但不是繼承,你要嘛就是用他的功能,要嘛就是擴充他,不過很難繼承)

解下來實作一下plugin,就可以了解到底有多簡單。
我好幾年前寫過一個簡單的date picker函數,在需要使用的頁面上new一個instance之後,在要使用的node上,或要觸發但是把結果寫入另一個node的button上面使用getCalendar()就可以叫出來使用:

<meta http-equiv="Content-Type" content="text/html; charset=utf-8">


<script src="http://www.fillano.idv.tw/calendar/calendar2.js"></script>
<table border="1">
<tr><td>test: <td><input type=text id=date1><input id="date2" type="button" value="date" onclick="iCalendar.getCalendar('date2','date1')">
<tr><td>test1: <td><input type=text id=date3><input id="date4" type="button" value="date" onclick="iCalendar.getCalendar('date4','date3')">
</table>


<script>
	var iCalendar = new calendar();
	iCalendar.init();
</script>

(source可以參考連結中的calendar2.js,程式有點長,我不想放進來。)

原來的程式結構大概長這樣:

function calendar () {
	......
	this.getCalendar = function (sLauncher, sReceiver) {
		_now = new Date();
		_render();
		var launcher = document.getElementById(sLauncher);
		_receiver = document.getElementById(sReceiver);
		var realY = realPosY(launcher);
		var realX = realPosX(launcher);
		_container.style.top = realY + "px";
		_container.style.left = realX + "px";
		_visible();
	}
	this.init = function () {
		document.body.appendChild(_container);
		_render();
	}
	......
}
function realPosX (oTarget) {
	......
}
function realPosY (oTarget) {
	......
}

改成jQuery plugin時,只要稍微改幾行然後用jQuery.fn.extend加入包裝使用方法的函數就可以運行了:

(function(){
function calendar () {
	......
	this.getCalendar = function (sLauncher, sReceiver) {
		_now = new Date();
		_render();
		if (typeof sLauncher == 'string') {
			var launcher = document.getElementById(sLauncher);
		} else {
			var launcher = sLauncher;
		}
		if (typeof sReceiver == 'string') {
			_receiver = document.getElementById(sReceiver);
		} else {
			_receiver = sReceiver;
		}
		var realY = realPosY(launcher);
		var realX = realPosX(launcher);
		_container.style.top = realY + "px";
		_container.style.left = realX + "px";
		_visible();
	}
	this.init = function () {
		document.body.appendChild(_container);
		_render();
	}
	......
	this.inited = false;
}
function realPosX (oTarget) {
	......
}
function realPosY (oTarget) {
	......
}
var iCalendar = new calendar();
jQuery.fn.extend(
	{SimpleDatePicker: function() {
		if(!iCalendar.inited) iCalendar.init();
		jQuery.each(this, function(i, n) {
			$(n).click(function(){
				iCalendar.getCalendar(this,this);
			});
		});
		return this;
	}
});
})(jQuery);

然後在網頁中使用:

<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<script src="../js/jquery-1.3.2.js"></script>
<script src="http://www.fillano.idv.tw/calendar/calendar3.js"></script>
<script>
$(document).ready(function(){
	$('#date1').SimpleDatePicker();
	$('#date3').SimpleDatePicker();
});
</script>


<table border="1">
<tr><td>test: <td><input type=text id=date1>
<tr><td>test1: <td><input type=text id=date3>
</table>

想要實際執行看看,可以連到http://www.fillano.idv.tw/calendar/index2.html

不過我這只是做概念驗證,並不適合當作正式的datepicker來用喔。這個兩三年前寫的東西,架構可以調整的更好,而且可以把一些configuration相關的變數移到程式外,到呼叫時再用物件傳入,這樣程式會更有彈性。另外,在date picker panel上,我完全沒使用css,這樣會在使用css的網頁中出問題,這些都是要進一步調整的地方。另外,就是有許多方法可以改用jQuery的方法,例如偵測node的位置等等。


上一篇
Javascript面面觀:網頁篇《jQuery inside - events》
下一篇
Javascript面面觀:網頁篇《Frameworks/Libraries》
系列文
Javascript面面觀30

尚未有邦友留言

立即登入留言