iT邦幫忙

DAY 29
3

且戰且走HTML5系列 第 29

且戰且走HTML5(29) 逐步完成整合應用

視訊會議功能可行,就先開始嘗試怎樣進行應用整合。
應用整合的重點有幾個部分。

之前所有的應用,都是獨立分散的,要整合的話,會需要花一些心思,另外也需要把操作介面做一個整理。

為了可以讓各種功能不會混雜在一起,比較重要的事情是先做好模組化。在伺服器環境中,以node.js為例,他就使用了CommonJS規範的模組與套件。但是這樣同步載入的模組,並不適合用在瀏覽器環境中。為了在瀏覽器中應用,有人提出了AMD,也就是非同步模組定義的規格。模組可以透過define這個函數來定義。然後透過require來載入。

(function(window, undefined) {
	var modules = {};
	var document = window.document;
	var define = window.define = function(name, deps, fn) {
		if(arguments.length===3) {
			if(typeof modules[name] === 'undefined') {
				modules[name] = {deps: deps, fn: fn};
			}
		}
	};
	var require = window.require = function(deps, fn) {
		var filename = '';
		var next = new recurser(
			function() {
				var keys = [];
				for(var i in modules) {
					keys.push(i);
				}
				var tocompare = keys.join('|');
				var ret = true;
				keys.forEach(function(key) {
					modules[key]['deps'].forEach(function(n) {
						if(tocompare.indexOf(n)<0) {
							ret = false;
						}
					});
				});
				return ret;
			}, 
			function() {
				var retarg = [];
				deps.forEach(function(name1) {
					retarg.push(multiComposer(modules[name1]['fn'], modules[name1]['deps']));
				});
				fn.apply(window, retarg);
				console.log(modules);
			}
		).next;
		deps.forEach(function(name) {
			loadModule(name, next);
		});
	};
	function loadModule(name, cb) {
		if(typeof modules[name] !== 'undefined') {
			//already loaded
			if(typeof cb !== 'undefined' && typeof cb === 'function') {
				cb();
			}
			return;
		}
		//not yet loaded
		if(name.indexOf>-1) {
			filename = name;
		} else {
			filename = name + '.js';
		}
		var s = document.createElement('script');
		s.src = filename;
		var h = document.getElementsByTagName('head')[0];
		s.onload = function() {
			if(modules[name]['deps'].length>0) {
				modules[name]['deps'].forEach(function(name1) {
					loadModule(name1, cb);
				});
			}
			if(typeof cb !== 'undefined' && typeof cb === 'function') {
				cb();
			}
			cb = null;
		}
		h.appendChild(s);
	}
	function recurser(stop, cb) {
		this.next = function() {
			if(stop()) {
				cb();
			}
		}
	}
	function multiComposer(fn, deps) {
		var fnArgs = [];
		deps.forEach(function(name) {
			fnArgs.push(multiComposer(modules[name]['fn'], modules[name]['deps']));
		});
		return fn.apply(window, fnArgs);
	}	
})(window);

只要利用define定義好模組名稱、相依性、以及模組程式,回傳值(模組執行結果),然後就可以利用require,載入相依的模組,傳給callback做為參數來執行。例如:

<script src='amd.js'></script>




<script>
require(['test845a'], function(cls) {
	cls.show(cls.data.all);
});
</script>

他會載入test845a.js:

define('test845a', ['test845b', 'test845c'], function(util, not) {
	return {
		data: {all:'hello'},
		show: util.show
	};
});

而test845a.js定義了他會依賴於test845b.js以及test845c.js這兩個模組:

(test845b.js)

define('test845b', [], function() {
	return {
		show: function(msg) {alert(msg);}
	};
});

(test845c.js)

define('test845c', ['test845b', 'test845d'], function(a, b) {
	return {};
});

test845b沒有依賴其他模組,但是test845c又依賴test845b與test845d。test845b前面已經看過,test845d則是:

(test845d.js)

define('test845d', [], function() {
	return {};
});

把模組載入到記憶體後,接下來就會依照呼叫順序執行,把一個函數執行結果傳給要使用他的函數做為參數,最後整合到html裡面呼叫require的callback函數中,然後跑出執行結果。(alert訊息:hello)

用這個方式,可以把之前做過的chat、塗鴉白板、資源分享、視訊會議等,放在不同的模組,在要使用時把他們require到程式中來,用這個方式,程式才會簡潔有組織。

在操作介面上,則利用twitter的bootstrap來快速建立。目前的構想,是需要最頂端有一個header,裡面放登入的輸入欄。底下的空間,則利用bootstrap的tab功能,整理到不同的tab中。

包含多方視訊的整合,就一起在明天嘗試一下。


上一篇
且戰且走HTML5(28) 建立視訊會議
下一篇
且戰且走HTML5(30) 利用Bootstrap逐步整合出UI
系列文
且戰且走HTML530

尚未有邦友留言

立即登入留言