視訊會議功能可行,就先開始嘗試怎樣進行應用整合。
應用整合的重點有幾個部分。
之前所有的應用,都是獨立分散的,要整合的話,會需要花一些心思,另外也需要把操作介面做一個整理。
為了可以讓各種功能不會混雜在一起,比較重要的事情是先做好模組化。在伺服器環境中,以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中。
包含多方視訊的整合,就一起在明天嘗試一下。