網頁模板文件在加載完畢時,通過調用“ Fusion.initialize(); ”來啟動 Fusion 框架的初始化過程。但是,在執行這行代碼執行之前, Fusion 就已經執行了一些啟動代碼( bootstrap )。這些代碼主要涉及確定瀏覽器語言、加載其余 Fusion 腳本代碼和加載商業地圖腳本等等。這些工作的代碼位于“ <FusionRoot>\lib\fusion.js ”文件中,從 1064 行至文件尾。當網頁加載到 fusion.js 時候,這些代碼就會被執行。
讓我們先看看加載其余 Fusion 腳本代碼做了什么。前文我們提到了,三種加載 Fusion 框架方式是等效的。其中獨立壓縮方式和獨立文件方式是等效的是很容易理解的,這是因為獨立壓縮方式僅僅是去掉了無用的空格、換行符號和注釋。那么,分散加載方式加載的 fusion.js 僅僅是獨立文件方式加載的 fusionSF.js 里面代碼的一部分,它們兩者之間又是如何保證等效的呢?原來,當 Fusion 中有一個要加載腳本文件的列表( fusion.js 的 1080-1091 行),這個列表的文件和 fusion.js 放在一起,跟 fusionSF.js 文件是完全等效的。在啟動代碼中, Fusion 如果發現當前采用的是分散加載方式( Fusion._singleFile 值為 false ),那么就會通過向網頁中添加 script 標簽的形式來增加新文件。
除了加載其余 Fusion 腳本代碼之外,啟動代碼所做的一個不得不提的工作就是加載商業地圖腳本。這個是 2.1.0 新增的一個功能。如果用戶需要在地圖中加入雅虎、谷歌或者必應地圖,那么在啟動代碼中, Fusion 會檢查網頁布局文件中是否有 GoogleScript 、 YahooScript 或者 VitualEarthScript 標簽,并訪問標簽里面包含的腳本地址來加載對應的腳本。
當瀏覽器調用 Fusion.initialize() 腳本的時候, Fusion 便開始了加載的過程。 Fusion 加載的過程分為兩步。第一步是將服務器端的網頁布局文件變成一個瀏覽器中包含的信息對象;第二步是根據這個信息對象逐步初始化各個部分。
下面,我們將分別介紹這兩個步驟。
從服務器到瀏覽器——加載應用程序定義
在 Fusion 框架中,網頁布局文件又稱為應用程序定義( ApplicationDefinition )文件。在本章其余部分,這兩個詞可能會交替使用,但兩者意思完全相同。
Fusion 是通過地圖代理( MapAgent )來獲取應用程序定義的。但在此之前, Fusion 先需要知道地圖代理的位置。雖然在默認狀態下, FusionRoot 是直接放置于“ <WebRoot>\fusion ”文件夾中。但 Fusion 本身相對獨立一些,支持將 Fusion 放置在其他文件夾中。這時就需要有一個地方能夠告訴 Fusion 地圖代理的位置,這個地方就位于 Fusion 的 configuration 屬性中, Fusion 通過 Fusion.configuration.mapguide.webTierUrl 屬性值找到 MapGuide 的位置(該屬性值的形式應當類似“ http://localhost/mapguide ”)。如果您使用的是獨立文件加載方式或獨立壓縮加載方式的話,這個屬性是已經被設置好了的 (fusionSF.js 的 63201-62346 行 ) 。而對于分散加載方式,這個屬性在初始狀態下是為定義的,這時 Fusion 會去訪問并加載服務器的“ <FusionRoot>\config.json ”做為 Fusion.configuration 的值。也就是說,如果您采用的是分散加載的方式,而且 Fusion 并沒有采用默認的文件夾部署,那么,您可以修改這個文件來指示 Fusion 去哪兒尋找地圖代理。
找到地圖代理的位置后, Fusion 就會初始化一個 Fusion.Lib.ApplicationDefinition 對象( fusion.js 的 482 行,這個對象的定義位于 “ <FusionRoot>\lib\ApplicationDefinition.js ”中)。該對象會在初始化的過程中,通過地圖代理請求應用程序定義的內容,并把該定義轉化成一個瀏覽器可以處理的 Javascript 對象。
為了獲得一個瀏覽器可以處理的 Javascript 對象,需要先把應用程序定義文件轉成一個 Javascript 對象。這個工作是“ <FusionRoot>\common\php\Xml2JSON.php ”頁面完成的。 Fusion 把獲得的應用程序定義 XML 發送到該頁面,該頁面就會返回轉換后的 JSON 對象。但是這個轉換過程僅僅是一個形式上的轉換,要想讓這個 JSON 對象最終可以被 Fusion 框架處理,還需要進一步把它的各個部分解析成 Fusion 庫中相應的實例,這個過程由 ApplicationDefinition 的 parseAppDef 函數來完成。
我們知道,應用程序定義中各個部分是采用了一個層次化的結構最終放置在一個 ApplicationDefinition 根節點下。同樣地,轉換后的 Javascript 對象也是采用類似的結構放置在一個 Fusion.Lib.ApplicationDefinition 對象中。 XML 標簽與瀏覽器對象的轉換關系如表 3-1 所示(限于空間,這里應用程序定義的瀏覽器對象類別省略掉前綴“ Fusion.Lib ”,其余的瀏覽器對象省略掉前綴“ Fusion.Lib.ApplicationDefinition ”)。
要注意的是,這個過程僅僅是一個把 XML 標簽轉化成對應的瀏覽器對象,并沒有開始對這些對象的初始化。還有一個有意思的地方是,當構造 Widget 對象的時候,構造代碼會通過檢查是否定義了類“ Fusion.Widget.< 小工具類型 > ”來檢查瀏覽器中是否已經加載了相應的小工具腳本。如果沒有,構造代碼會調用 Fusion.require 函數來將腳本代碼放置到 Fusion 的一個待加載腳本列表中。這個列表將在下一步進行加載。
當 parseAppDef 將整個應用程序定義文件轉換成瀏覽器對象后, Fusion 就會調用 loadQueuedScripts 函數來加載上一步中發現的沒有加載的小工具腳本代碼。當所有代碼加載完畢之后, Fusion 就會開始整個小工具的初始化工作。
小工具的初始化
當所有代碼加載完畢之后, Fusion 會調用 ApplicationDefinition 對象的 create 函數,該函數最終會調用 WidgetSet 的 create 函數,這時,小工具便一個接一個的開始初始化了。
小工具的初始化工作無外乎兩個方面:構造一個小工具對象、將其放置到界面中。構造小工具對象的過程相對簡單,只要調用“ Fusion.Widget.< 小工具類型 > ”類的構造函數即可。而將小工具放置在界面中的過程,則相對復雜一些。
小工具界面的初始化,有點像一個“填空”過程。
首先, create 函數會檢查小工具的 uiClass 屬性,并用該屬性值作為類名初始化一個界面類。比如,“關于”小工具的 uiClass 屬性的值是 Jx.Button ,那么, create 函數會初始化一個 Jx.Button 對象,做為“關于”的界面。在這個初始化過程中,小工具信息中的 label 、 imageUrl 、 imageClass 、 isExclusive 等屬性會被作為參數傳遞到初始化過程中,用來提供初始化的信息。
初始化界面元素之后, create 函數會調用小工具腳本代碼的 setUiObject 函數,來允許小工具執行一些定制化的內容。 Fusion.Widget 已經為我們實現了一些常用的代碼,比如設置提示、將按鈕的按下和彈起事件與小工具的 activate 和 deactivate 函數進行關聯等等。如果您需要對于小工具界面提供的空間進行“填空”,一般也會在這個函數內完成。
當 setUiObject 函數執行完畢后,小工具的界面就初始化完畢了。接下來,需要將小工具的界面添加到頁面中。這時候有以下兩種情況:
1.?????? 如果小工具不屬于任何容器,那么 Fusion 框架就會認為這個小工具的界面是一個獨立的頁面元素。因此, Fusion 框架去尋找頁面中以小工具名稱作為標識的 div ,并把小工具的界面“填空”到這個 div 中。舉個例子,概覽地圖( OverviewMap )小工具的名稱( name )為 OverviewMap 。那么, Fusion 框架就會通過去尋找網頁中標識為 OverviewMap 的 div ,并將小工具的界面利用其 addTo 函數添加到這個 div 中。
2.?????? 如果小工具屬于某一容器,那么 Fusion 框架會先尋找相應的容器界面(此前 Fusion 會像添加小工具界面到頁面中那樣,把容器界面“填空”到相應的 div 中),然后將小工具通過 addTo 函數添加到這個 div 中。
這里我們可以看出,其實在小工具初始化之前,其位于網頁中的位置就已經在網頁模板中,根據其對應的名稱或者容器名稱決定下來了。如果您想修改小工具在網頁中的位置,您完全不需要改變應用程序定義的內容,而只需要改變網頁模板就可以了。
當小工具的界面都被初始化完畢之后,界面就完全加載完畢了。用戶就可以通過與界面的交互來使用小工具提供的功能了。
有一點要說明的是,雖然地圖小工具也稱為小工具,也放置在 Fusion.Widget 命名空間中。但是, Fusion 對于地圖小工具的處理是完全不同于其他小工具的。地圖小工具在應用程序定義中使用其專用的 MapWidget 標簽。 WidgetSet 類也有一個專門的位置來放置地圖小工具( mapWidget 屬性)。 Fusion.Widget.Map 也并不是繼承自 Fusion.Widget 的,甚至其 create 函數的參數列表也不同于普通的小工具。地圖小工具與其他小工具的唯一一點相似是,在“填空”的時候,地圖小工具也會添加到以其名稱為標識的 div 中。
從中我們不難看出,地圖小工具的地位是其他小工具無法比擬的。這是因為,地圖是網頁地理信息系統最核心的部分。大部分用戶交互都是通過地圖完成的。所以,我們有必要了解一下地圖小工具。
?