聰明的Web導航
Domino在很多方面做的很好,但是也有許多做的不好的地方。自從Notes 數據庫 可以用瀏覽器來打開之時,Domino 服務器 就在一些很簡單的任務方面做的一團糟。很多時候我們要改進Domino服務器產生的代碼,甚至是重寫。 本文將關注Domino產生的視圖/文檔導航代碼
Domino在很多方面做的很好,但是也有許多做的不好的地方。自從Notes
數據庫可以用瀏覽器來打開之時,Domino
服務器就在一些很簡單的任務方面做的一團糟。很多時候我們要改進Domino
服務器產生的代碼,甚至是重寫。
本文將關注Domino產生的視圖/文檔導航代碼。當你打開一個Domino視圖的時候幾乎很難看到所有的文檔,這就需要需要指向下一頁的鏈接,類似的情 況是當你轉到下一頁的時候就需要一個“上一頁”鏈接。當你打開一個文檔時如果有上一文檔和下一文檔的鏈接也是個不錯的想法--否則就要回到視圖去單擊當前 文檔上面/下面的文檔鏈接。Domino可以很容易的生成所有的這些鏈接,但是運行的效果不是很理想,我們來動手解決它。
問題在哪兒?
Domino很多時候就是在元素上面加上雙向的箭頭,這在實際操作的時候很簡單,生成的代碼能正常運行,就是有些難看。要在視圖的多個頁面之間導航的時候,最簡單的方法就是在$$ViewTemplate上創建兩個操作熱點,公式很簡單:
@DbCommand( "Domino"; "ViewPreviousPage")
下一頁的公式也同樣簡單,下面的圖形是我們在Domino Designer里面的表單:

如我前面所說的,這些代碼能正確運行,那么問題出在哪兒呢?讓我們來看看公式所生成的HTML代碼:
<< Previous它就是執行一個名為_doClick()的
JavaScript函數,這個函數只是簡單的重新載入頁面,但是傳給服務器一個字符串,用它來告訴服務器在頁面上按下了什么“按鈕”,服務器可以通過這個函數來決定返回什么頁面,為什么這么復雜呢?
這種代碼有兩個問題,第一個問題是它依賴于啟用
JavaScript的瀏覽器,第二個問題是Internet搜索引擎不能抓取這個視圖下面的任何鏈接,也 就不會去索引這些文檔,搜索引擎只喜歡那些使用href屬性的鏈接,而現在這種情況是沒有指向任何東西,搜索引擎不會去跟蹤onClick時間所調用的任 何代碼。
現在局域網里面絕大多數的Domino
數據庫都不會被搜索引擎抓取,而且我們幾乎可以保證絕大多數的瀏覽器(或者用戶)沒有禁用任何東西。
但是在Internet上就是另外一回事了,根本就沒有所有用戶共享的一個通用環境,不止這些,而且搜索引擎是占有統治地位的,這就要求你要讓站點盡可能的容易訪問,不論是用戶還是搜索引擎。
在文檔級別也存在類似的問題,我們可以創建類似的上一文檔和下一文檔的鏈接,只需使用如@Command([NavigateNext])的公式即可,這種情況下生成的代碼并不是很壞,但是依然存在問題,它生成的URL和下面的比較類似:
/db.nsf/ViewID/DocID?Navigate&To=Next
當你單擊這個鏈接的時候,服務器返回給瀏覽器一個狀態為302的HTTP回應,它告訴瀏覽器定位要找的文檔并傳給它正確的URL,這種情況下返回的就是下一個文檔的URL。
現在還不能確認,但是可以假想搜索引擎(比如Google)不會喜歡這種鏈接。
可訪問性先放在一邊,還有一個較小的問題值得一提,它不僅是邏輯的問題,因為它并不象你所期望的那樣運行。當你第一次打開一個視圖或者打開視圖里第一個文 檔的時候,你回經??吹健吧弦豁摗辨溄?,這種情況下單擊鏈接就是重復的載入當前頁面,當在文檔中單擊的時候,就會回到打開它的視圖,在視圖的最后一頁或者 視圖里面最后一個文檔中也有類似的問題。還有一個比較奇怪的問題就是在視圖的上一頁和下一頁之間跳轉的時候,下一頁里面的第一個文檔就是上一頁里面的最后 一個文檔。
你可能會說這是吹毛求疵,但是現在這些都是用戶/客戶對網站的基本要求了。
解決這個問題不要失望,這個問題可以解決,但是需要我們自己編寫一些代碼。
所說的兩種情況中都要用到一個
WebQueryOpen代理,一種情況是$$ViewTemplate,另外一種情況是文檔(譯者注:其實是生成文檔的表單)。如果你確實不喜歡這個想法,那就不要繼續看下去了。這種情況下的
性能可能有些損失,但是好處也是顯而易見的。
使用代理的話我們就可以得到視圖的句柄并且計算出它里面有多少文檔,使用這些信息我們就可以在表單上面使用一些簡單的@函數來創建所需的鏈接,我們還可以告訴用戶他們所處的頁數以及共有多少頁。
在文檔級別中,代理在視圖中定位當前entry并且搜索它上面和下面的entry,在這些信息的基礎上,就可以知道是否顯示上一個文檔和下一個文檔鏈接,其實并不只能做到這些,還可以提供一些文檔的高級信息,比如標題。
為視圖編碼代理只是簡單的告訴我們在視圖里面一共有多少文檔,我們下面的工作可以使用@函數來在實際的表單上進行。
開始的時候我在得到總數的時候使用了下面的代碼:
Set nav = view.CreateViewNav()
Call doc.ReplaceItemValue( "Total", nav.Count)
代碼返回了我想要的結果,但是當向視圖里面加入上千條文檔之后,
性能問題就凸顯出來了,使用NotesViewEntryCollection也存在這個問題,經過一些
測試和重寫,發現最快的函數是視圖的EntryCount屬性。
Call doc.ReplaceItemValue( "Total", view.EntryCount)
然而這是R6的新特性并且不能用在分類視圖中,有時候我們依然需要使用數據庫的Search()函數,傳給它和視圖一樣的搜索公式,如下所示:
Set col = db.Search("Form='article'", Nothing, 0)
Call doc.ReplaceItemValue( "Total", col.Count)
如果你的視圖是分類視圖,你就可以用復雜的公式來迎合你的需要,總體看來這是得到總數的最好的方法,下面的結果是一些不很科學的
測試所得到的結果。
Approach/Documents | 5,000 | 10,000 | 15,000 | 25,000 | 90,000 |
NotesViewNavigator.count | 2s | 7s | 9s | - | - |
NotesViewEntryCollection.count | - | - | 3s | - | - |
db.AllDocuments.count | - | - | 0s | 0s | - |
db.Search.count | - | - | 0s | 1s | 3s |
view.EntryCount | - | - | - | - | 0s |
現在$$ViewTemplate表單上的Total域中就是所有文檔的總數了,下面我們就來更正Domino產生的鏈接。
為了計算出是否顯示鏈接和鏈接的指向,我們需要另外幾個域。第一個是一個名為“Start”的數值類型的域,這個域檢驗URL中的&start= X,如果有那個參數(&start=X),它的值就會派上用場,如果沒有那個參數,它就使用它的默認值1。我們還需要另外一個數值類型的域: ShowPerPage,它用來告訴我們視圖每頁上面顯示的文檔數目,如果URL使用了Count參數,并且域里面有值的話就會用這個域值,否則我們要硬 性指定一個數值(同樣也是視圖每頁顯示的行數)。本例中我選擇了5并且在嵌入視圖的“顯示行數”屬性中指定了相同的數值,如下圖所示:

現在我們可以計算出要顯示哪個鏈接和它的指向了,首先是“上一頁”鏈接,這是一個包含下面公式的計算文本:
@If(Start<=1; @Return(" "); "");
newstart:=@If(Start-ShowPerPage<=1; 1; Start-ShowPerPage);
"
+ "">« Previous"
我們首先做的是檢查當前頁面是不是第一頁,如果是的話,計算文本就什么都不顯示(一種隱藏鏈接的簡單方法),就象沒有生成它一樣。
如果有一頁的要顯示的話,就會計算出它是不是開始的那個頁面并生成指向它的鏈接。
下一頁的代碼和上面的很相似,不再贅述,另外一件要做的事情是顯示頁面的位置,代碼如下:
@If(Total=0 | Total<=ShowPerPage ;
@Return("Page 1 of 1"); "");
div:=Total/ShowPerPage;
dif:=div-@Integer(div);
pages:=@Integer(div)+@If(dif=0;0;1);
"Page " + @Text(@Integer(Start/ShowPerPage)+1)
+ " of " + @Text(pages)
邏輯非常簡單:用每頁顯示的文檔數目去除總數,如果有余數,不管有多小,我們都要把值加上1,這就是頁數。
為表單編碼為表單編碼的過程和對視圖的操作過程類似,只是所有的工作都是在WebQueryOpen代理中完成的,我們要做的只是得到當前文檔的句柄并在視圖里面進行定位。
通過文檔對象的信息,我們可以計算出它是不是視圖中的第一個或者最后一個文檔,這樣我們就可以決定我們是否需要創建鏈接并生成指向的具體文檔的鏈接了。
盡管在視圖里面我們由于性能原因不使用NotesViewNavigator對象,但是視圖的大小好像并不影響計算當前文檔信息所需的時間。
在我們開始計算之前,還需要在表單上面創建一些保存鏈接的域。因為沒有必要保存它們,所以它可以是“顯示時計算”類型的域,而且名字可以隨意,我用的名字是PrevDocLink和NextDocLink,表單上面有了保存鏈接的域之后我們就可以開始編寫代碼了。
代碼里面首先要做的是創建一個NotesViewNavigator對象并找到其中的當前文檔,不要擔心我們如何定義對象,代碼其實就是很簡單的兩行:
Set nav = view.CreateViewNav()
Set ThisEntry = nav.GetEntry(doc)
有了這個信息我們就很容易知道它是不是視圖里面第一個或者最后一個entry,我們還需要創建另外兩個NotesViewEntry對象來達到我們的目 的,一個叫FirstEntry,另外一個叫LastEntry,接下來我們就可以測試當前文檔是否是它們中的一個,下面的代碼判計算它是不是第一個 entry:
Set FirstEntry = nav.GetFirstDocument
If ThisEntry.UniversalID = FirstEntry.UniversalID Then
Call doc.ReplaceItemValue( "PrevDocLink", "None Found")
Else
Call doc.ReplaceItemValue( "PrevDocLink",
"
Open "+nav.GetPrev(ThisEntry).Document.GetItemValue("Title")(0)
+"")
End If
代碼確實不是那么復雜,首先判斷當前文檔是不是和第一個文檔有相同的ID,如果相同,說明是第一條文檔,那么就給“link”域賦上一個說明情況的值,或 者就是讓它什么都不顯示;如果不同,說明當前文檔上面還有文檔,我們就把指向它的鏈接賦到域中,為了讓它看起來更具體一些,我們將鏈接的文檔的真實標題顯 示了出來。
生成下一條文檔鏈接的代碼和上面的很相似,你可以在附件中進行查看。
本文原文地址:
Sensible Web Navigation[From:CodeStore]
原文轉自:http://www.kjueaiud.com
老湿亚洲永久精品ww47香蕉图片_日韩欧美中文字幕北美法律_国产AV永久无码天堂影院_久久婷婷综合色丁香五月
|