balance9235 的部落格

[Pre-class]XPath

"

XPath即為XML路徑語言(XML Path Language),它是一種用來確定XML文檔中某部分位置的語言。

XPath基於XML的樹狀結構,提供在資料結構樹中找尋節點的能力。起初 XPath 的提出的初衷是將其作為一個通用的、介於XPointer與XSL間的語法模型。但是 XPath 很快的被開發者採用來當作小型查詢語言。

最常見的XPath表達式是路徑表達式(XPath這一名稱的另一來源)。路徑表達式是從一個XML節點(當前的上下文節點)到另一個節點、或一組節點的書面步驟順序。這些步驟以「/」字元分開,每一步有三個構成成分:

●軸描述 (用最直接的方式接近目標節點)
●節點測試(用於篩選節點位置和名稱)
●節點描述(用於篩選節點的屬性和子節點特徵)

軸描述元表示XML文件分支樹表達式的瀏覽方向。這些座標──以全名然後縮寫語法──列舉如下:

child (子節點:比自身節點深度大的一層的節點,且包含在自身之內)
預設,不需要縮寫語法聲明
attribute (屬性)
@
descendant (子孫節點:比自身節點深度大的節點,且包含在自身之內)
縮寫語法不提供
descendant-or-self (自身引用及子孫節點)
//
parent (父節點:比自身節點深度小一層的節點,且需要包含自身的節點)
.. 例如:點點
ancestor (祖先節點:比自身節點深度小的節點,且需要包含自身的節點)
縮寫語法不提供
ancestor-or-self (自身引用及祖先節點)
縮寫語法不提供
following (下文節點:按縱軸視圖,在此節點後的所有完整節點,即不包含其祖先節點)
縮寫語法不提供
preceding (前文節點:按縱軸視圖,在此節點前的所有完整節點,即不包含其祖先節點)
縮寫語法不提供
following-sibling (下一個同級節點)
縮寫語法不提供
preceding-sibling (上一個同級節點)
縮寫語法不提供
self (自己)
. 例如:點
namespace (名稱空間)
縮寫語法不提供
關於使用attribute座標簡寫語法的一個範例, //a/@href 在文件樹裡任何地方的元素下選擇了一個叫href的屬性。self座標最通常與述語同用,以參考現行選定節點。例如,h3[.='See also']在現行上下文選取了叫h3的元素,該元素文字內容是See also。

參考網站:http://zh.wikipedia.org/wiki/XPath

"

[Pre class]排序演算法

"Mergesort是一種divide-and-conquer類型的演算法─把一個大問題切成幾個小一號的問題,個個擊破。如果這些小一號的問題,與原問題長得很像,就可以寫recursive程式來解。Quicksort 也是一種 divide-and-conquer 類型的演算法,也可以用遞迴來實作。
[@more@]

Mergesort

摘要:「把資料等分成兩堆,各自用 mergesort 排序好後再合併。」

如何合併?「兩手各指著 (已排好的) 左右兩堆的最小資料,取出兩者之中較小的一個後隨即將指向那一堆的手移至下一筆資料。」永遠不必翻下面的資料,只需要盯著最上面這兩張看。

Mergesort有兩種:top-down及bottom-up。

分析mergesort的time complexity:只考慮 n = 2^k 這種狀況,因為這種狀況比較容易算,更重要的是因為只考慮這種狀況就夠了。耗時T(n)=2*T(n/2)+n

一個排序演算法,若只需要用到 O(1) 的額外空間,則稱它具有 in-place 特性。例如 insertion sort、selection sort 都是 in-place。 但 merge sort 就不是 in-place,它在 merge 時耗費 O(n) 的空間。

Mergesort 可以是 stable。

Quicksort

摘要:「挑一個元素當做 pivot,把陣列內比它小元素的都放在同一側;把比它大的都放在另一側,然後對兩側使用 quicksort。」

如何分側?「從左右向中間掃描,每找到一對放錯側的元素,就把它們對調過來。對調後繼續向中間掃描,直到兩個指標交錯為止。」這個分側動作叫做 partition。注意:完成 partition 動作後,這個 pivot 元素自然也就落到它最終的正確位置。

簡單版的 quicksort 以陣列的第一個元素作為 pivot。

Time complexity:

best case: Theta(n lg n), 因為 T(n) = 2*T(n/2) + n
worst case: Theta(n^2), 因為 T(n) = T(n-1) + n
average case: Theta(n lg n)
Quicksort 不適合用於「幾乎已排好」或「幾乎正好排顛倒」的資料。

資料來源:http://apt.nc.hcc.edu.tw/pub/mirror/ckhung_wp/b/al/sort1.shtml

"

[Pre-Class]What's Backtracking

"

Backtracking is a type of algorithm that is a refinement of brute force search. In backtracking, multiple solutions can be eliminated without being explicitly examined, by using specific properties of the problem. It can be a strategy for finding solutions to constraint satisfaction problems. The term "backtrack" was coined by American mathematician D. H. Lehmer in 1950s.

[@more@]

Constraint satisfaction problems are problems with a complete solution, where the order of elements does not matter. The problems consist of a set of variables each of which must be assigned a value, subject to the particular constraints of the problem. Backtracking attempts to try all the combinations in order to obtain a solution. Its strength is that many implementations avoid trying many partial combinations, thus speeding up the running-time.

Backtracking is closely related to combinatorial search.

資料來源:http://en.wikipedia.org/wiki/Backtracking

"

[Pre-Class]SAX 的基本概要

"SAX和DOM一樣也是一個存取XML文件的介面。SAX是Simple API for XML的縮寫。它不像DOM那樣是W3C的認可標準。它是由XML-DEV信件清單的成員開發維護,由David Megginson領導(david@megginson.com)的一個Public Domain軟體。SAX是一個徹底的自由軟體,它的作者放棄了對它的所有權利,它也被許可用於任何目的。

到現在為止SAX的版本已經發展到2.0。在這個最新版本中增加了對命名空間(Namespaces)的支援,而且可以透過對features以及properties的設定來對剖析器做全面的配置,這其中包括設定剖析器是否對文件進行有效性驗證,以及怎樣來處理帶有命名空間的元素名稱等。SAX1中的介面已經不再使用了,這裡只會討論有關SAX2的開發。在本文中提到SAX只是指SAX 2。另外,本文的所有例子都是用java編寫,SAX剖析器也使用的是JAVA版本。

像DOM一樣,SAX並不是一個可以實際使用的XML文件剖析器,而是其它相容SAX的剖析器所要實作的介面和幫助性類別的集合。如果你想使用SAX的話,你必須滿足下面的要求︰

  1. 系統中包括Java 1.1 或者更高版本。
  2. 在Java classpath中匯入你的SAX類別庫。
  3. 在Java classpath中匯入相容SAX的XML剖析器類別庫。

有很多實作SAX的剖析器,比如Apache的Xerces,Oracle的XML Parser等等。在本文中的例子使用的是Xerces剖析器,你可以從 http://xml.apache.org 取得。下載xerces.jar檔案然後加入到classpath中,這樣就建立好環境(在xerces.jar中已經包括了SAX介面,所以不必特意再去尋找SAX類別庫)。

在SAX API中有兩個套件,org.xml.sax和org.xml.sax.helper。其中org.xml.sax主要定義了SAX的一些基礎介面,如XMLReader、ContentHandler、ErrorHandler、DTDHandler、EntityResolver等。而在org.xml.sax.helper中則是一些方便工作人員使用的幫助性類別,如預設實作所有處理器介面的幫助性類別DefaultHandler、方便工作人員建立XMLReader的XMLReaderFactory類別等等。        文章來源:http://www.javaworld.com.tw/confluence/pages/viewpage.action?pageId=492

"

[pre-class]什麼是 DOM?

"

文件物件模型(Document Object Model,DOM)是給 HTML 與 XML 文件使用的一組 API。它提供了文件的結構表述,讓你可以更動其中的內容及可見物。其本質是建立網頁與 Script 或程式語言溝通的橋樑。

所有網頁設計師可操作及建立文件的屬性、方法及事件都以[物件]來展現(例如,document 就代表「文件本身」這個物件,table 物件則代表 HTML 的表格物件等等)。這些物件可以由當今大多數的瀏覽器以 Script 來取用。

DOM 最常被用以[與 JavaScript 溝通],也就是說雖然程式以 JavaScript? 寫成,但使用 DOM 來存取頁面及其元素。無論如何,DOM 本身是設計為一種獨立的程式語言,以一致的 API 存取文件的結構表述;是以雖然本站的焦點放在 JavaScript? 上,但 DOM 其實可以與[任何程式語言]共同運作。

[全球資訊網協會](World Wide Web Consortium,W3C)建立了 [DOM] 的標準,稱之為「W3C DOM」。在當今主要瀏覽器都已正確實作的情況下,W3C DOM 使強大、跨瀏覽器的應用程式成真。這是眾網頁設計師在 Netscape 4 與 MSIE 多不相容的時代從未夢想過的事情。

"

Server Side Paging using SQL Server 2005

"A common activity in applications is to page results or record sets from a database. This is usually done on the client using the client's paging functionality or on the server through a variety of methods. In SQL Server 2000 those server side methods typically used dynamic SQL or nested TOP clauses and weren't very efficient. Using Common Table Expressions in SQL Server 2005 we have a better way to page record sets on the server. [@more@]

The Members Page on SQLTeam.com lists the first 20 members sorted by number of posts. In order to generate this it selects the entire set of members, returns it to the client and then displays the first 20 rows using ADO's paging functionality. The SELECT statement it runs looks something like this:
SELECT      M_NAME, M_POSTS, M_LASTPOSTDATE, M_LASTHEREDATE, M_DATE, M_COUNTRYFROM  dbo.FORUM_MEMBERSORDER BY M_POSTS DESC;

It has a cost of 3.2 and does approximately 1,999 logical page reads to return the 25,000 registered members in our forum. It does have the benefit of being very simple to write.Converting this query to a Common Table Expression (CTE) is straightforward and that looks like this:

WITH PagedMembers  AS(      SELECT      M_NAME, M_POSTS, M_LASTPOSTDATE, M_LASTHEREDATE,                   M_DATE, M_COUNTRY      FROM  dbo.FORUM_MEMBERS)SELECT      M_NAME, M_POSTS, M_LASTPOSTDATE, M_LASTHEREDATE,             M_DATE, M_COUNTRYFROM  PagedMembersORDER BY M_POSTS DESC;

This query has the exact same execution plan, query cost and logical reads when you run it. At this point all the CTE has give us is a named wrapper around a simple query. The WITH clause defines the name of the CTE as "PagedMembers" In fact, it acts an awful lot like a derived table.SQL Server 2005 adds a number of functions that are useful with common table expressions. One of these is ROW_NUMBER. If we include this in our CTE our new query looks like this:

WITH Members  AS(      SELECT      M_NAME, M_POSTS, M_LASTPOSTDATE, M_LASTHEREDATE, M_DATE, M_COUNTRY,                  ROW_NUMBER() OVER (ORDER BY M_POSTS DESC) AS RowNumber      FROM  dbo.FORUM_MEMBERS)SELECT      RowNumber, M_NAME, M_POSTS, M_LASTPOSTDATE, M_LASTHEREDATE, M_DATE, M_COUNTRYFROM  MembersWHERE RowNumber BETWEEN 1 AND 20ORDER BY RowNumber ASC;

The ROW_NUMBER function needs an OVER clause. In our example the OVER clause contains an ORDER BY clause. This just tells the ROW_NUMBER function in what order to generate the row numbers. It's possible to have multiple ROW_NUMBER functions in a single SELECT statement each with their own ordering. You can see we aliased the ROW_NUMBER function and then referenced that column in the WHERE clause of the outer SELECT statement. This only selects the first twenty members from those with the most posts.This query has a cost of 0.3 and does 71 logical reads. It runs faster because it's able to use an index on M_POSTS that the other queries weren't able to take advantage of. If that index weren't there it would have the performance as the other query but return much less data to the client. As you increase the number of rows returned or how far down into the results you go the logical reads will increase. On my query the breakeven was around 500 rows. If I'm looking for a page that starts at row 500 or earlier this method is faster -- or at least has fewer logical reads. If I'm looking for a page that starts after row 500 then the table scan was faster. I'm most cases people aren't paging past the first few pages of results.You can also use the ROW_NUMBER function in a straight SELECT statement like this:

SELECT      M_NAME, M_POSTS, M_LASTPOSTDATE, M_LASTHEREDATE, M_DATE, M_COUNTRY,      ROW_NUMBER() OVER (ORDER BY M_POSTS DESC) AS RowNumberFROM  dbo.FORUM_MEMBERSORDER BY M_POSTS DESC;

This will return a column for the row number but you won't be able to use it in the WHERE clause. You'll have to write it in a CTE or a derived table for that to work. Common table expressions also expect to be the first statement in a batch or they expect the statement preceding them to be terminated with a semicolon.You can easily use variables to determine which rows to SELECT by passing in parameters for the page size and which page to return:

DECLARE     @PageSize INT,            @PageNumber INT,            @FirstRow INT,            @LastRow INT SELECT      @PageSize = 20,            @PageNumber = 3 SELECT      @FirstRow = ( @PageNumber - 1) * @PageSize + 1,            @LastRow = @PageSize + (@PageNumber - 1) * @PageSize; WITH Members  AS(      SELECT      M_NAME, M_POSTS, M_LASTPOSTDATE, M_LASTHEREDATE, M_DATE, M_COUNTRY,                  ROW_NUMBER() OVER (ORDER BY M_POSTS DESC) AS RowNumber,                  ROW_NUMBER() OVER (ORDER BY M_NAME DESC) AS RowNumber2      FROM  dbo.FORUM_MEMBERS)SELECT      RowNumber, M_NAME, M_POSTS, M_LASTPOSTDATE, M_LASTHEREDATE, M_DATE, M_COUNTRYFROM  MembersWHERE RowNumber BETWEEN @FirstRow AND @LastRowORDER BY RowNumber ASC;

Common table expressions and the ROW_NUMBER function are a handy way to server side paging on a query result. 

 

"

SOAP 會不會泡沫化?

"XML 的相關科技中,相信許多人對 SOAP(Simple Object Access Protocol;簡單物件連結協定)這個名詞已不陌生。在業者的強力炒作、推波助瀾之下,SOAP 在資訊軟體界儼然已凝聚了一股態勢,成為當下網路軟體逐步邁向 web-services 境界時,一個重要的業界既成標準 (de-facto standard)。現在已經有愈來愈多的軟體開始對 SOAP 提供支援,而像 RosettaNet 這樣著名的電子商務標準,也考慮在未來利用 SOAP 的機制。[@more@]

SOAP 的概念起源於 Userland Software 創辦人 Dave Winer 的 XML/RPC。SOAP 的名稱則是當 DevelopMentor 的 Don Box 應微軟之邀,開始研發一個彌補 MTS/COM 不足的標準時產生的。當初研發的動機,根據 Don Box 的現身說法,是著眼於 MTS/COM 的機制對系統資源索求過重、不夠輕巧,難以應付未來需求。在 SOAP 制定初期,微軟扮演了主要的推手,同時也是最 早宣佈全力支援這個標準的大型業者。去年年初開始,隨著 IBM 及其他業者加入標準的制定,SOAP 1.1 已較趨完備,同時並加入了以 W3C Schema 標準來定義資料類型的重要功能。類似於過去 Web 上許多既成標準,SOAP 1.1 是以 Note 的身分被呈遞給 W3C 標準會作參考 (http://www.w3.org/TR/SOAP)。Notes 在 W3C 形同於備忘錄,並不代表已具業界共識, 標準會亦不給予正式推薦。

關於 SOAP 的說帖,相信大家多少都聽過一些,但許多人可能還是要問:它到底是做什麼用的? 事實上, SOAP 可用三、四字以蔽之--“RPC/messaging through XML”;RPC (Romote Procedure Call) 是遠端程式呼叫,也就是說, SOAP 以 XML 作為媒介,為分散式環境下的程式和系統之間,提供了一套簡單的訊息傳呼協定。 我們知道,RPC 早已不是什麼新鮮話題。在企業軟體日趨網路化、分散化的環境下,不論是企業內或跨企業的資訊整合,以及新一代整合工程所偏好的多層式 (n-tier) 運算架構(較知名的包括了微軟的 DNA 及昇陽的 J2EE),server 對 server、程式對程式間的互動均大量增加;而此類互動的特性是必須跨越 processes (行程)、甚至 server 軟、硬體,及企業的疆界。過去幾年內,最為知名的 RPC 機制包括了 CORBA、Java RMI,及 COM。 Java RMI 是 J2EE 及其主角 EJB (Enterprise Java Beans) 框架的重要基礎科技; COM/DCOM/COM+ 則是 Windows DNA 賴以維繫的命脈。這些機制對平台或程式語言一致性,都有一定的要求:RMI 綁的是 Java 語言,COM 綁的是 Windows 作業系統,CORBA 則需要適當的運行環境和平台來支援。這些遠端傳呼的機制在今日、乃至可預見的未來, 仍會在 IT 領域中扮演著重要的角色。在過去,企業為達到內部資源整合 (EAI) ,或許 AP 統一採用 DCOM、CORBA,再搭配某種 message broker 的傳訊機制,並透過該 broker 作傳遞樞紐即可達成。然而,網路所帶來的資訊革命及電子商務,加上企業併購風潮的盛行,促使企業對系統整合的需求日殷,異質性系統間的互動亦隨著大量增加,CORBA、Java RMI,COM 等 RPC 機制,開始顯得僵硬、彈性不足,而這正是 XML 和 SOAP 誕生、並開始大放異彩的時代背景: SOAP 利用 XML 純文字的特性,提供一套機制,以 XML 來包裝方程式呼叫和訊息。由於採用了 XML,SOAP 順理成章地繼承了許多 XML 的優點,可輕易透過 HTTP、SMTP 等網路上最常使用、 極為耐操的通信管道來來挾帶,更能穿越企業的 firewalls,還可透過 SSL、S/MIME 等機制加密,安全性高。透過 XML 來傳訊,還有一項更大的優點,是 CORBA、Java RMI,及 DCOM 這些以專屬 binary 格式傳送資料所不及之處,那就是對程式語言、作業平台的獨立性--由於是純文字 XML 格式, SOAP 訊息可由任何一種程式語言所產生,被任何程式語言、甚至肉眼所解讀。這個 late-binding 的特性, 正是 Web-services 時代所迫切需要的。

SOAP 不是萬靈丹。顧名思義,它是個簡單的標準。SOAP 的設計者在設計時刻意迴避了一些分散式運算環境中較為複雜的的課題,包括分散式垃圾收集技巧 (distributed garbage collection) 等相關課題。 SOAP 的設計者認為,標準儘量保持簡單,往往能提供使用者更大的彈性空間。

SOAP 引起業界對 XML 傳訊協定的注意,W3C 也因而成立了一個工作小組,從事 XML Protocol 的 標準研發(W3C 對標準研發相當審慎,要成為推薦標準,得先成立 Working Group,接著訂定 Requirements, 再來得歷經數個標準草案 [Working Drafts]、候選人標準 [Candidate Recommendation]、 建議標準 [Proposed Recommendation]等艱苦階段,最後才能成為正式標準 [Recommendation])。 許多人擔心 SOAP 的前途,深恐 XML Protocol Working Group 在未來會制定出一套取代 SOAP 的正式標準。 但目前根據來自 W3C 內部的消息指出,未來 XML Protocol 的研發方向,將是制定出一套和 SOAP 能追溯相容的標準。對 SOAP 的支持者來說,無疑是劑強心針。

"

CSS實務排版技巧、秘訣與技術

"

自從網頁標準計劃 (The Web Standards Project) 提出瀏覽器升級方案 (Browser Upgrade Initiative) 後,無數的網站設計師開始採用較為符合標準的網站設計方式:他們用 CSS 來設計版面,以取代傳統使用的表格。

[@more@]

"表格已死......"

有些設計師在 Jeffrey Zeldman 的指導下,用撰寫教學文件的方式幫助我們解決第一道難題 – 不使用表格,網頁會缺乏設計感。起初他們的重心放在撰寫幾篇以 CSS 的定位能力取代表格的專欄:如此一來,網站設計師就能把網頁的架構與內容完整地分離。在 Eric Costello 的 glish 網站及 Rob Chandanais 的 Blue Robot 網站都有許多相關的技術文件。

許多人也一起參與,包括製作 Box lesson 的 Owen Briggs,以及撰寫相關討論的 Eric CostelloTantek ÇelikDotfile、Web Nouveau (譯註:已經無法連結) 列舉了數百個利用 CSS 設計版面的網站。

"......表格長存"

當大家可以利用這些資源,只靠著 CSS 的定位能力來設計一般性版面時,我們這些設計師卻發現有某些實作上的問題,可以用表格輕易解決,而使用 CSS 時則會遇到一些麻煩。像這樣的問題都會以 "Tables are dead ... long live tables." 這個標題發表在 Webdesign-L 網站上。

問題

假設你要將一堆縮圖連結到較大尺寸的版本 – 這種網頁相當常見。除此之外,你希望每張縮圖的正下方都有個簡短的標題。接著,為了有效利用瀏覽器視窗的空間,你希望讓縮圖跟標題成對地排成一列,並會隨瀏覽器視窗寬度自動分行 (wrap,即流動式設計)。隨著最後一個要求,我們放棄表格,進入了 CSS 的王國。

一步步來

讓我們一步步來。第一個要求是縮圖的正下方要有個標題。作法相當直接了當:在你的 HTML 裡放上圖片,接著一個斷行 (BR),再把標題放在一個段落 (P) 裡並且置中 (利用 CSS)。

接著我們要讓這些縮圖跟標題成對地排列在瀏覽器視窗裡。使用表格排版時,這一對對的縮圖跟標題會被分別放置在 TD 裡。在使用 CSS 排版時,我們要把它們分別放置在 DIV 裡。為了讓它們能水平排列在視窗上,我們用 CSS 讓這些 DIV 往左浮動 (FLOAT)。

這時候 CSS 看起來應該像這樣:

div.float { float: left; } div.float p { text-align: center; } 

而 HTML:

<div class="float"> <img src="image1.gif" width="100" height="100" alt="圖 1" /><br /> <p>標題 1</p> </div> <div class="float"> <img src="image2.gif" width="100" height="100" alt="圖 2" /><br /> <p>標題 2</p> </div> <div class="float"> <img src="image3.gif" width="100" height="100" alt="圖 3" /><br /> <p>標題 3</p> </div> 

而在瀏覽器裡應該會看到:

標題 1

標題 2

標題 3

下一個要求得靠 CSS 解決。我們要讓圖片跟標題成對地自動換行,以配合瀏覽視窗的寬度。讓 DIV 往左浮動 (FLOAT) 已經解決了這個問題。只要我們多放幾張縮圖,它們就會在瀏覽視窗裡自動換行 (只要改變瀏覽視窗的寬度,你就可以看到流動式設計的作用):

標題 1

標題 2

標題 3

標題 1

標題 2

標題 3


現在假設你希望同時在網頁上顯示好幾類的縮圖,並利用背景顏色或邊界等外觀條件幫它們分組。這時候只要用一個容器 (container) DIV 把它們包在一起就好:

div.container { border: 2px dashed #333; background-color: #ffe; } 

但這時候麻煩來了。當你在 CSS 裡將一個元件浮動 (FLOAT) 以後,它就不再佔據任何 "空間",因此背景及邊界都會在圖片的正下方出現,而不是繞著圖片。所以我們必須在容器 DIV 裡多放點東西,比方說一個間隔 (spacer) DIV:

div.spacer { clear: both; } 

其次是 HTML (注意在容器 DIV 的上下方都有個間隔 DIV):

<div class="container"> <div class="spacer"> &nbsp; </div> <div class="float"> <img src="image1.gif" width="100" height="100" alt="圖 1" /><br /> <p>標題 1</p> </div> <div class="float"> <img src="image2.gif" width="100" height="100" alt="圖 2" /><br /> <p>標題 2</p> </div> <div class="float"> <img src="image3.gif" width="100" height="100" alt="圖 3" /><br /> <p>標題 3</p> </div> <div class="spacer"> &nbsp; </div> </div> 

結果如下:

標題 1

標題 2

標題 3

根據 sam marshall 的原始碼製作。

巢狀 DIV 與巢狀 TABLE 有什麼不一樣?

好吧,我們有了一堆的巢狀 (nested) DIV,這比巢狀表格好在哪裡?答案是在於這些標籤的設計觀點上。DIV 暗示著一種邏輯或結構上的分組,即使它們以巢狀表示,仍然具有標記的結構性。在我們的例子裡,我們把縮圖跟它們的標題分成一組 (第一層),再將這些成對的縮圖跟標題依照相似性分組 (第二層)。這些都是利用 DIV 標籤把結構上的分組處理得相當好的範例。

然而表格暗示的是一種行與列的標頭 (header) 跟每個欄位資料的關係。當我們利用表格設計版面時,我們就喪失了表格結構的意義。讓我們回過頭來用 HTML 設計版面,巢狀表格只會讓問題複雜化。

表單功能

另一個常見的表格排版應用是排列表單 (FORM) 裡的元件與描述。關於這是不是表格的合適應用尚有很多爭論,而就像我們即將看到的,CSS 技術對類似的排版需求也很有用。

一個典型的表單版面裡,在左方的是描述,緊靠著右邊界,在右方的是元件,緊靠著左邊界。一切事物都在中央交會:

姓名:
年齡:
鞋子尺寸:
附註:

根據 Eric Meyer 的原始碼設計概念製作。

上面這個表單沒有使用到表格。我們又再度使用到浮動 (FLOAT) 來達成定位的工作。戲法是這樣的:我們用一個 DIV 模仿表格的列。然後我們創造兩個 SPAN,一個給描述、另一個給元件。把描述的 SPAN 往左浮動,元件的 SPAN 往右浮動。讓描述 SPAN 裡的文字往右靠,讓元件 SPAN 裡的文字往左靠。

所以 CSS 應該長這樣:

div.row { clear: both; padding-top: 10px; } div.row span.label { float: left; width: 100px; text-align: right; } div.row span.formw { float: right; width: 235px; text-align: left; } 

上面的 CSS 也設了 SPAN 的寬度。寬度可以像是範例裡的絕對值,或者也可以用百分比表示。百分比最多是到 100% 或少一點點,依照你設的留白跟邊界而定 (還有你設計的容器)。在範例裡我用另一個 DIV 把表單包起來,以設定邊界與背景。

範例 HTML:

<div style="width: 350px; background-color: #cc9; border: 1px dotted #333; padding: 5px; margin: 0px auto";> <form> <div class="row"> <span class="label">姓名:</span><span class="formw"><input type="text" size="25" /></span> </div> <div class="row"> <span class="label">年齡:</span><span class="formw"><input type="text" size="25" /></span> </div> <div class="row"> <span class="label">鞋子尺寸:</span><span class="formw"><input type="text" size="25" /></span> </div> <div class="row"> <span class="label">附註:</span><span class="formw"> <textarea cols="25" rows="8"> 快! 來寫點東西...... </textarea> </span> </div> <div class="spacer"> &nbsp; </div> </form> </div> 

追求卓越

你也許會注意到,上面容器 DIV 的 STYLE 裡有一個屬性:margin: 0px auto;。在符合標準的瀏覽器裡,它會讓 DIV 往中間對齊。一些瀏覽器 (如 Windows 底下的 IE5.x) 會忽略這一點,卻會錯誤地讓有 text-align: center 的 DIV 往中間對齊。想讓 DIV 在這些瀏覽器往中間對齊的話,你可以用有 text-align: center 的 DIV 把另一個有 margin: 0px auto; 的 DIV 包起來 (裡面的 TEXT-ALIGN 是 left,所以文字會正常排列)。詳見 Rob Chandanais 在 Layout Reservoir 網站撰寫的置中對齊技術(1, 2)。

分隔差異

在處理本質上相對的事物時,也常會用到與前面類似的表格排版設計。這次你不是讓它們在中央交會,而是讓兩個元件擺在瀏覽器視窗的兩側。這也許是一個你想讓商標放在頁面右上角,而讓導覽元件放在頁面左上角的案例:

首頁 > 產品[商標]

在這裡我們使用跟表單範例裡一樣的 DIV.ROW,但這次會使用不同的 SPAN。左邊的 SPAN 往左浮動,而且文字往左靠。右邊的 SPAN 往右浮動,而且文字往右靠。

CSS:

div.row span.left { float: left; text-align: left; font-weight: bold; color: #fff; width: 49%; } div.row span.right { float: right; text-align: right; font-weight: bold; color: #fff; width: 49%; } 

HTML:

<div style= "width: 90%; background-color: #666; border: 1px solid #333; padding: 0px; margin: 0px auto;"> <div class="spacer"></div> <div class="row"><span class="left"> 首頁 > 產品</span> <span class="right"> [商標]</span></div> <div class="spacer"></div> </div> 

CSS 求助

ACRONYM 與 ABBR 標籤雖然只在少數情況派上用場,卻有不錯的實用價值,可以配合著 TITLE 屬性來解釋頭字語或縮寫。但即使網頁有提供文字來協助網站參觀者瞭解縮寫或頭字語的意義,現在大部分的瀏覽器不會為這個標籤作出任何的警示。所以讓我們從 CSS 來著手。

你可以在樣式表裡為這些標籤加上底線,讓它們能引起注意。透過瀏覽器的支援,你也可以用 CSS 把游標換成 "求助" 符號 (通常用問號表示)。當然你也可以不用被 HTML 標籤限制。創造一個叫 .help 的類別,再用 SPAN 來為那些容易讓讀者混淆的字詞添加資訊。

CSS 範例:

abbr, acronym, .help { border-bottom: 1px dotted #333; cursor: help; } 

這個 CSS 配合縮寫或頭字語標籤的 TITLE 屬性使用,可以產生跟超連結不一樣的底線效果。把游標改成 "求助" 暗示著這些文字是不能按的,而 TITLE 屬性則會解釋縮寫或頭字語。我最早是在 Sander Tekelenburg 的網站上看到這種做法。

請三思而後行......

我最先是在 Bos 跟 Lie 的 Cascading Style Sheets 讀到關於將串列 (LIST) 改成行內 (inline) 顯示的文章。後來我在 Christopher Schmitt 的 BabbleList 網站率先看到了這個技巧的實際應用。這個戲法讓串列水平地顯示在一行裡;也就是說從:

  • 項目一
  • 項目二
  • 項目三

轉換成:

  • 項目一
  • 項目二
  • 項目三

如果加上些留白跟邊界的效果:

  • 項目一
  • 項目二
  • 項目三

CSS:

li.inline { display: inline; padding-left: 3px; padding-right: 7px; border-right: 1px dotted #066; } li.last { display: inline; padding-left: 3px; padding-right: 3px; border-right: 0px; } 

HTML:

<ul> <li class="inline">項目一</li> <li class="inline">項目二</li> <li class="last">項目三</li> </ul> 

"

更準確、更有效率的Web2.0行銷

"

還記得前一陣子懷孕的藝人小S嗎?透過小S懷孕前的超人氣和知名化妝品公司的結合。在去年十月以《小S性感 媽咪日記》為名開站的部落格在短短兩個月內就衝破百萬人次的瀏灠。而具德國血統的奧迪(Audi)汽車也在去年利用部落格為其新發表的車款作宣傳,三個月內在全球共創造出七千萬人次的討論。諸如此類的例子還有很多,雖然表面上這些案例中間沒有直接的相關,但其實他們背後都有一個共通的特點,也就是以Web 2.0為基礎的行銷概念。

[@more@]

早期的網路行銷不外乎是透過電子郵件發送、彈出式視窗、橫幅式廣告等幾種手法。最常見的例子就是入口網站將其網頁上的廣告空間待價而沽,等到廣告商上門之後,入口網站再依點選率或是擺放時間的長短來收取費用。這樣的缺點是,廣告商永遠無法知道你所擺放的廣告是不是真的接觸到你的目標客戶,還是只是在茫茫的網海中找尋一兩個真正有需求的消費者。就像是Tim O'Reilly所說的一樣,如果Web 1.0的代表者是Netscape,那Web 2.0的代表就是Google。Google一改以往廣告商尋找消費者的思考模式,而改以消費者自行查詢廣告的思維模式來經營。Google將首頁保持乾淨,但在關鍵字搜尋的時候提供你想要查找資訊的相關廣告,不但確保每一個點選進網站的瀏灠者都是對該資訊有興趣的潛在消費者,也一併解決了消費者對廣告視窗擾人的困擾。而前一陣子Google推出的Google Page也有異曲同工之妙,利用免費提供部落格服務的形式,從中蒐集更多消費者的習性,其中的用意就是要為消費者量身訂做一個個人化的Google。

Web 2.0還有一個重要的概念就是去中心化。以前的網路媒體是由廣告商透過媒體宣傳商品,訊息流動的方向就像一張單程車票一樣,不但方向固定且訊息回流困難,廣告商與消費者之間的界線也畫分的很清楚,消費者一看就知道這是廣告。但在Web 2.0的概念中,廣告商所要做的不是花大把的金錢作廣告,而是創造一個話題來吸引你的潛在消費者,一但你真的碰觸到他的需求並滿足他,他自然就成了你的最佳代言人,利用它自身的經驗將你的商品資訊分享給和他擁有相同特質的人。他不但是你的消費者,同時也是你的代言人。試想,同一種商品,你會相信網站上的官方說法還是你同部門長官同事的親身體驗,我想答案很明顯會是後者。

但話題行銷也不是沒有風險。在這個資訊流動量龐大的年代,如果你的話題不夠出色且爆紅的速度不夠快,恐怕很快就會和其他的部落格一樣被淹沒在茫茫的網海之中。不過不論網路行銷的樣貌如何演變,個人化及高互動性的中心精神卻是永不會變的。

"

頁面