| 2006 年 9 月 07 日 2006 年最時(shí)髦的詞莫過(guò)于 Web 2.0。Web 2.0 究竟意味著(zhù)什么,這是一個(gè)熱門(mén)的爭論話(huà)題,但它似乎與一種很酷的動(dòng)態(tài) Web 應用程序有關(guān)。那些 Web 應用程序 —— 通常以 PHP 開(kāi)發(fā) —— 使用動(dòng)態(tài) HTML(DHTML)創(chuàng )建頁(yè)面,移動(dòng)及更改此頁(yè)面時(shí)無(wú)需返回服務(wù)器進(jìn)行更新。Jack Herrington 在 “使用 PHP 和 DHTML 設計 Web 2.0 應用程序” 系列文章中教您開(kāi)始使用這項技術(shù)。 DHTML 是包含 JavaScript 代碼的 HTML,這些代碼可更改瀏覽器中的頁(yè)面布局,而無(wú)需返回服務(wù)器。在您編寫(xiě) HTML 頁(yè)面時(shí),您實(shí)際上是在編寫(xiě)一個(gè)對象樹(shù)。所有標記 —— 小小的 <table> 和 <p> —— 都成為 JavaScript 空間中的對象。使用 JavaScript,您可以更改其內容、層疊樣式表(Cascading Style Sheets,CSS)的式樣以及位置 —— 均無(wú)需再返回服務(wù)器。DHTML 是 HTML、CSS 和 JavaScript 的交集。 自瀏覽器中添加了 JavaScript 代碼后,使用 DHTML 的技術(shù)就已出現,但對此技術(shù)的支持一直參差不齊。早期,Microsoft? Internet Explorer 在這方面做得非常出色,但同一時(shí)期的 Netscape V4 缺乏支持。近來(lái),Mozilla 和 Firefox 漸漸提供了可靠的 DHTML 支持。有些人認為形勢已經(jīng)與過(guò)去完全不同,Internet Explorer 現已在這方面落后。 DHTML 的優(yōu)缺點(diǎn) 在您的頁(yè)面中結合 JavaScript 將使頁(yè)面具有動(dòng)態(tài)性,并且能夠帶來(lái)更出色的用戶(hù)體驗。用戶(hù)可更快地獲得更多數據、從不同角度查看信息、無(wú)縫地在站點(diǎn)中導航 —— 而站點(diǎn)不必返回服務(wù)器處獲得大量頁(yè)面。 然而,也存在避免使用 JavaScript 的理由:瀏覽器兼容性。早期僅使用平面 HTML 時(shí),Internet Explorer 呈現頁(yè)面的方式與 Netscape 不同。那些問(wèn)題已得到解決。但隨著(zhù) CSS 支持的添加,出現了新的兼容性問(wèn)題。如今,多半 CSS 問(wèn)題已被解決,但又出現了 JavaScript 兼容性問(wèn)題。 這些兼容性問(wèn)題沒(méi)有簡(jiǎn)單的解決方案。您需要根據需要測試和支持的瀏覽器的數量來(lái)衡量 JavaScript 的收益。 這里我們給出幾條建議: - 使 JavaScript 盡可能地簡(jiǎn)單。
- 發(fā)現兼容性問(wèn)題時(shí),首先上網(wǎng)查找最佳解決方法。您往往會(huì )找到經(jīng)過(guò)精心研究的答案。
- 擁有一個(gè)平面 HTML 代用系統,以應對您不支持的那些瀏覽器。
- 保留一份支持的瀏覽器列表(及其版本號)。
- 在 Mac 和 Microsoft Windows? 中查看 Internet Explorer。
本文的示例盡可能保持簡(jiǎn)單清楚。但僅在 Firefox 上進(jìn)行了測試,所以會(huì )出現一些兼容性問(wèn)題。本文將在出現兼容性問(wèn)題的地方提醒您,以便您獲得更多的實(shí)踐經(jīng)驗。 實(shí)現 DHTML 最簡(jiǎn)便的方法就是首先在平面 HTML 頁(yè)面中編寫(xiě),不使用 PHP 或任何服務(wù)器端語(yǔ)言,隨后以該代碼作為 PHP 代碼模板來(lái)生成 DHTML。通過(guò)這種方式,您可檢查解決方案的基礎,并將服務(wù)器的問(wèn)題與客戶(hù)機的問(wèn)題區分開(kāi)來(lái)。在本文中,每個(gè)示例都首先給出 HTML,隨后再給出相應的 PHP 代碼。
廣告框 第一個(gè)示例簡(jiǎn)單且兼容:浮動(dòng)廣告框。圖 1 展示了一個(gè)帶有 Close 按鈕的對話(huà)框,浮動(dòng)于頁(yè)面之上。 圖 1. 浮動(dòng)廣告框
用戶(hù)可單擊 Close 按鈕關(guān)閉廣告框,如圖 2 所示。 圖 2. 關(guān)閉廣告框后的頁(yè)面效果
清單 1 為頁(yè)面代碼。 清單 1. 廣告框代碼 <html> <head> <title>Ad box demonstration</title> <style> body { width: 800px; } .ad-box { background: #eee; border: 1px solid black; padding: 5px; position: absolute; left: 50px; top: 50px; width: 600px; } .ad-box-title { background: #ccc; padding: 5px; font-weight: bold; font-size: large; text-align: center; text-transform: uppercase; letter-spacing: 0.2em; } </style> <script> function closead() { var obj = document.getElementById( "ad" ); obj.style.visibility = "hidden"; } </script> </head> <body> <div class="ad-box" id="ad"> <div class="ad-box-title"> Special offer </div> <p> You have been selected for our special offer. Can you imagine? What are the odds? Just buy five hundred or more of our product and we will give you a 1% discount on additional orders. Only the Department of Defense gets deals like that! </p> <p style="text-align: right;"> <a href="javascript:closead();">close</a> </p> </div> <p>This is our home page. Welcome to it. Here we talk about all of our great products.</p> <h1>Products</h1> <p>This is a list of our products:</p> <ul> <li>The amazing all in one toothpix holder and axe grinder.</li> <li>The complete Jean Claude Van Damme DVD collection.</li> </ul> </body> </html> | 本例的大部分工作是使用 CSS 完成的。使用 position CSS 屬性,使廣告框浮在頁(yè)面文本之上。left 和 top 屬性根據元素與頁(yè)面左上角的相對位置定位元素。 為使廣告框消失,您為 close 錨定標記編寫(xiě)了一些 JavaScript 代碼。這里并未使用 http 協(xié)議,而是使用 javascript 協(xié)議,并調用了 closead 函數。closead JavaScript 函數獲取 ad <div> 的對象引用,并改變 CSS 樣式 visibility,從 visible 設置為 hidden,這樣廣告框就消失了。 本例展示了一些 DHTML 基本原理。首先是 id 屬性的用法。為動(dòng)態(tài)引用一個(gè)項目,通過(guò) id 屬性給予其一個(gè)惟一的 ID。在本例中,您為廣告框設置的 ID 為 ad。隨后使用 document.getElementById 方法獲取廣告框的 <div> 對象。 本例還示范了可在錨定標記中使用的 javascript 偽 URL。使用它,您可以在放置鏈接的任意位置調用 JavaScript。 這些技術(shù)兼容其他瀏覽器。所有現代瀏覽器均支持 JavaScript、CSS、絕對定位和在運行時(shí)對 visibility 屬性這樣的動(dòng)態(tài)元素進(jìn)行設置。
PHP 中的廣告框 現在已經(jīng)有了廣告框的 DHTML 代碼,接下來(lái)讓我們看看如何在 PHP 中實(shí)現它(參見(jiàn)清單 2)。該廣告框的惟一可選項就是顯示與否。PHP 代碼通過(guò)一個(gè)函數調用寫(xiě)出了廣告框,根據環(huán)境決定是否調用頁(yè)面。 清單 2. 廣告框的 PHP 代碼 <?php function place_ad( $title ) { ?> <div class="ad-box" id="ad"> <div class="ad-box-title"> <?php echo( $title ); ?> </div> <p> You have been selected for our special offer. Can you imagine? What are the odds? Just buy five hundred or more of our product and we will give you a 1% discount on additional orders. Only the Dept. of Defense gets deals like that! </p> <p style="text-align: right;"> <a href="javascript:closead();">close</a> </p> </div> <?php } ?> <html> <head> <title>Ad box demonstration</title> <style> body { width: 800px; } .ad-box { background: #eee; border: 1px solid black; padding: 5px; position: absolute; left: 50px; top: 50px; width: 600px; } .ad-box-title { background: #ccc; padding: 5px; font-weight: bold; font-size: large; text-align: center; text-transform: uppercase; letter-spacing: 0.2em; } </style> <script> function closead() { var obj = document.getElementById( "ad" ); obj.style.visibility = "hidden"; } </script> </head> <body> <?php place_ad( "Today‘s Special Offer!" ); ?> <p>This is our home page. Welcome to it. Here we talk about all of our great products.</p> <h1>Products</h1> <p>This is a list of our products:</p> <ul> <li>The amazing all in one toothpix holder and axe grinder.</li> <li>The complete Jean Claude Van Damme DVD collection.</li> </ul> </body> </html> | 全新的 place_ad PHP 函數通過(guò)靈活的 title 字符串將廣告置于頁(yè)面之上。為獲得在多個(gè)頁(yè)面上發(fā)布廣告的能力,您可將此函數提取出來(lái),放在一個(gè)單獨的文件中,這樣,每次需要在頁(yè)面上插入廣告時(shí),只需包含此獨立文件即可。
彈出框 浮動(dòng)對話(huà)框主題的另一變種就是彈出框。您可使用彈出框提供用戶(hù)請求的附加信息??紤]圖 3 所示文本。 圖 3. 關(guān)于動(dòng)物的純文本頁(yè)面
如果用戶(hù)能看到關(guān)于長(cháng)頸鹿的更多信息,豈不是更好嗎?文本包含一個(gè)便捷的鏈接,如果您單擊此鏈接,將看到圖 4 所示的彈出框。 圖 4. 關(guān)于長(cháng)頸鹿的更多信息
本例中,您應請求提供了一個(gè)對話(huà)框,并依據文檔中的文本定位此對話(huà)框。代碼如清單 3 所示。 清單 3. 彈出框的 HTML 代碼 <html> <head> <title>Pop up Example</title> <style type="text/css"> body { font-family: arial, verdana, sans serif; } #popup { position: absolute; padding: 5px; border: 1px solid black; background: #eee; left: 0px; top: 0px; visibility: hidden; } </style> <script> function popup( id ) { var obj = document.getElementById( id ); var popup = document.getElementById( ‘popup‘ ); if ( popup.style.visibility == ‘visible‘ ) { popup.style.visibility = ‘hidden‘; } else { popup.style.left = obj.offsetLeft + "px"; popup.style.top = ( obj.offsetTop + 20 ) + "px"; popup.style.visibility = ‘visible‘; } } </script> </head> <body> <div id="popup"> An animal with a very long neck. </div> <h2>Animals</h2> A <a href="javascript:popup(‘word‘)" id="word">giraffe</a> is a very interesting animal. </body> </html> | 本例中,包含彈出信息的 popup <div> 最初定義為 hidden,絕對位置為頁(yè)面左上角。隨后 giraffe 文字旁的錨定標記將調用 JavaScript 來(lái)顯示彈出框。 popup JavaScript 方法使用 word ID 查找 giraffe 文本。隨后使用 offsetLeft 和 offsetTop 值使彈出框恰好位于文本之下。若彈出框已為可見(jiàn)狀態(tài),則隱藏它。 您可在顯示彈出框之前設置其內容,只需設置 popup <div> 對象的 innerHTML 成員即可。 此代碼的兼容性相當好。但依然可能會(huì )出現問(wèn)題,這是因為每個(gè)瀏覽器的 offsetLeft 和 offsetTop 值可能有所不同,對于帶有復雜嵌套內容的頁(yè)面而言更是如此。為在復雜頁(yè)面中獲得更準確的位置讀數,您可能需要遞歸增加 offsetLeft 和 offsetTop 值,為此,使用 offsetParent 對象在您沿 HTML 對象樹(shù)移動(dòng)時(shí)獲取各對象的父對象。
彈出框的 PHP 代碼 有了 DHTML 代碼后,即可更輕松地在 PHP 應用程序中使用彈出框。清單 4 給出了 PHP 代碼。 清單 4. 彈出框的 PHP 代碼 <?php function popup_header() { ?> <style type="text/css"> body { font-family: arial, verdana, sans serif; } #popup { position: absolute; padding: 5px; border: 1px solid black; background: #eee; left: 0px; top: 0px; visibility: hidden; } </style> <script> function popup( id, info ) { var obj = document.getElementById( id ); var popup = document.getElementById( ‘popup‘ ); if ( popup.style.visibility == ‘visible‘ ) { popup.style.visibility = ‘hidden‘; } else { popup.innerHTML = info; popup.style.left = obj.offsetLeft + "px"; popup.style.top = ( obj.offsetTop + 20 ) + "px"; popup.style.visibility = ‘visible‘; } } </script> <?php } function popup( $id, $text, $info ) { ?> <a href="javascript:popup(‘<?php echo($id) ?>‘,‘<?php echo($info) ?>‘)" id="<?php echo($id) ?>"><?php echo($text) ?></a> <?php } ?> <html> <head> <title>Pop up Example</title> <?php popup_header(); ?> </head> <body> <div id="popup"> </div> <h2>Animals</h2> A <?php popup( ‘word‘, ‘giraffe‘, ‘An animal with a very long neck.‘ ) ?> is a very interesting animal. </body> </html> ?tml> | 在本例中,您將標題的生成與各彈出框的放置相分離。頁(yè)面必須調用 head 標記中的 popup_header,然后添加 id 值為 popup 的 <div> 標記。隨后,只要需要彈出框,頁(yè)面就會(huì )調用 PHP 函數 popup。 PHP 函數 popup 接受 3 個(gè)參數:彈出框的 ID、純文本版本以及單擊項目時(shí)彈出的文本。函數隨后會(huì )呈現一個(gè)錨定標記,其外觀(guān)幾乎與原 DHTML 中的版本完全相同。 由于一個(gè)頁(yè)面上可能會(huì )顯示多個(gè)彈出框,所以添加了第三個(gè)參數以提供彈出框中顯示的文本。為實(shí)現這一功能,為 JavaScript 函數 popup 再添加一個(gè)參數。<div> 標記的 innerHTML 隨后會(huì )設置為這個(gè)新參數的內容。
微調控制項 在頁(yè)面中隱藏和顯示數據的另一選擇就是微調控制項(spinner)。在此模型中,頁(yè)面劃分為幾部分,各部分可使用微調控制項獨立隱藏或顯示。圖 5 展示了帶有兩部分微調控制項的頁(yè)面,各部分最初都是關(guān)閉的。 圖 5. 各微調控制項部分均關(guān)閉的頁(yè)面
單擊 Level One 部分中的 Open 鏈接將顯示此部分的內容,如圖 6 所示。 圖 6. 展開(kāi)了第一個(gè)微調控制項部分的頁(yè)面
您可以使用圖形來(lái)取代文字 open 和 closed。按照慣例,通常使用向右的三角形取代 closed,向下的三角形取代 open;也可使用加減號,加號表示 closed,減號表示 open。(對于哪種方式更好的評價(jià)涉及到 Mac 與 Windows 對比的爭論。這兩個(gè)平臺上的微調控制項正與這兩種不同的方式分別對應。) 清單 5 中的代碼展示了這些微調控制項的工作原理: 清單 5. 微調控制項的 HTML 代碼 <html> <head> <title>Spinner Example</title> <style type="text/css"> body { font-family: arial, verdana, sans serif; width: 800px; } .item-header a { font-size: small; } .item-header { font-weight: bold; border-bottom: 1px solid black; font-size: x-large; } .item-body { margin: 0px; font-size: small; visibility: hidden; height: 0px; } </style> <script> function spin( obj ) { var spinner = document.getElementById( obj ); var spinner_content = document.getElementById( obj+"_body" ); if ( spinner_content.style.visibility == ‘visible‘ ) { spinner.innerHTML = ‘open‘; spinner_content.style.visibility = ‘hidden‘; spinner_content.style.height = ‘0px‘; spinner_content.style.margin = ‘0px‘; } else { spinner.innerHTML = ‘close‘; spinner_content.style.visibility = ‘visible‘; spinner_content.style.height = ‘a(chǎn)uto‘; spinner_content.style.margin = ‘20px 0px 20px 50px‘; } } </script> </head> <body> <div class="item-header"> <a href="javascript:spin(‘lev1‘)" id="lev1">open</a> Level One </div> <div class="item-body" id="lev1_body"> This is the content of level one. </div> <div class="item-header"> <a href="javascript:spin(‘lev2‘)" id="lev2">open</a> Level Two </div> <div class="item-body" id="lev2_body"> This is the content of level two. </div> </body> </html> | 兩組 <div> 定義了各部分及其內容。按照慣例,為標題賦予 ID lev 加上一個(gè)數字(例如,lev2),正文使用相同的 ID 加后綴 _body。lev2 是微調控制項的鏈接,lev2_body 是該項目的正文。 微調控制項的智能部分是在 spin 函數中實(shí)現的,它查看微調控制項正文部分的可見(jiàn)性,并加以轉換,將可見(jiàn)轉變?yōu)殡[藏、隱藏轉變?yōu)榭梢?jiàn)。 在項目不可見(jiàn)時(shí),將 height 屬性設置為 0px,而在項目可見(jiàn)時(shí)將此屬性設置為 auto。對于 Internet Explorer,項目不可見(jiàn)時(shí),其空間也會(huì )隨之折疊。但對于 Firefox,內容不可見(jiàn)時(shí),其空間依然作為占位符存在。您需要將 height 設置為 0px,才能使空間正確地折疊起來(lái)。 為使用圖形取代文本來(lái)表示展開(kāi)和關(guān)閉狀態(tài),更改代碼,改變微調控制項對象的 innerHTML 值,使其指定一個(gè)圖像標記而非文本。
微調控制項的 PHP 代碼 為在 PHP 中實(shí)現微調控制項,采用服務(wù)器端創(chuàng )建 DHTML 代碼的標準模式即可,在 start 和 end 函數中劃分 HTML 的各部分。PHP 代碼如清單 6 所示。 清單 6. 微調控制項的 PHP 代碼 <?php function start_spinner( $id, $title ) { ?> <div class="item-header"> <a href="javascript:spin(‘<?php echo( $id ); ?>‘)" id="<?php echo( $id ); ?>">open</a> <?php echo( $title ); ?> </div> <div class="item-body" id="<?php echo( $id ); ?>_body"> <?php } function end_spinner() { ?> </div> <?php } ?> <html> <head> <title>Spinner Example</title> <style type="text/css"> body { font-family: arial, verdana, sans serif; width: 800px; } .item-header a { font-size: small; } .item-header { font-weight: bold; border-bottom: 1px solid black; font-size: x-large; } .item-body { margin: 0px; font-size: small; visibility: hidden; height: 0px; } </style> <script> function spin( obj ) { var spinner = document.getElementById( obj ); var spinner_content = document.getElementById( obj+"_body" ); if ( spinner_content.style.visibility == ‘visible‘ ) { spinner.innerHTML = ‘open‘; spinner_content.style.visibility = ‘hidden‘; spinner_content.style.height = ‘0px‘; spinner_content.style.margin = ‘0px‘; } else { spinner.innerHTML = ‘close‘; spinner_content.style.visibility = ‘visible‘; spinner_content.style.height = ‘a(chǎn)uto‘; spinner_content.style.margin = ‘20px 0px 20px 50px‘; } } </script> </head> <body> <?php start_spinner( ‘lev1‘, "Level One" ); ?> This is the content of level one. <?php end_spinner( ); ?> <?php start_spinner( ‘lev2‘, "Level Two" ); ?> This is the content of level two. <?php end_spinner( ); ?> </body> </html> | 通過(guò)調用 start_spinner 和 end_spinner 劃分內容的各部分。start_spinner 函數接受兩個(gè)參數:微調控制項的 ID 及其標題。end_spinner 調用結束 start_spinner 中打開(kāi)的 <div> 標記,以容納微調控制項的內容。 您可將微調控制項的內容作為第三個(gè)參數引入。但在一般情況下,這些內容部分形式復雜,若您以這種方式編寫(xiě)代碼,界面使用起來(lái)將非常困難。在 start 和 end 函數中劃分動(dòng)態(tài)部分的模式意味著(zhù)您可以隨意選擇其中 PHP 的復雜度。
選項卡 選項卡是查看內容不同部分的另一種常見(jiàn)方法。在 MetaCritic 站點(diǎn)上可以看到選項卡的輕量級版本(參見(jiàn) 參考資料),該站點(diǎn)使用選項卡切換游戲列表的查看方式 —— 按名稱(chēng)查看或按評價(jià)分數查看,而且不必返回服務(wù)器。圖 7 展示了此游戲列表的簡(jiǎn)化示例。 圖 7. 按名稱(chēng)排列的游戲
若要查看按評價(jià)分數排列的游戲,單擊 By Score 鏈接。列表會(huì )發(fā)生變化,如圖 8 所示。 圖 8. 按分數排列的游戲
MetaCritic 站點(diǎn)沒(méi)有在客戶(hù)端進(jìn)行復雜的排序,而是使用了相當于 flash 卡的一種方式:一個(gè)選項卡上的列表按名稱(chēng)排列,另外一個(gè)選項卡按分數排列。單擊鏈接時(shí),則隱藏一個(gè)選項卡,顯示另外一個(gè)選項卡。代碼如清單 7 所示。 清單 7. 選項卡的 HTML 代碼 <html> <head> <title>Tabs Example</title> <style type="text/css"> body { font-family: arial,verdana,sans serif; } .button-on, .button-off { padding: 3px; border: 1px solid black; } .button-on { background: #333; color: white; font-weight: bold; } .game-list { position: absolute; top: 0px; left: 0px; } .container { padding: 5px; border: 1px solid black; margin: 5px; position: relative; height: 400px; width: 200px; } </style> <script> function show( divid ) { var tos = [ "names", "score" ]; for( var t in tos ) { var to = document.getElementById( tos[t] ); to.style.visibility = "hidden"; to.style.height = "0px"; var bo = document.getElementById( tos[t]+"-button" ); bo.className = "button-off" } var to = document.getElementById( divid ); to.style.visibility = "visible"; to.style.height = "auto"; var bo = document.getElementById( divid + "-button" ); bo.className = "button-on"; } </script> </head> <body onload="show(‘names‘)"> Sort by: <a href="javascript:show(‘names‘)" id="names-button" class="button-on">By Name</a> <a href="javascript:show(‘score‘)" id="score-button" class="button-off">By Score</a><br/> <div class="container"> <div id="names" class="game-list"> <table width="100%"> <tr><td>Crank Shaft</td><td>22</td></tr> <tr><td>Driver</td><td>42</td></tr> <tr><td>Football 2006</td><td>72</td></tr> <tr><td>Soccer 2006</td><td>99</td></tr> <tr><td>Xevious</td><td>32</td></tr> </table> </div> <div id="score" class="game-list"> <table width="100%"> <tr><td>Crank Shaft</td><td>22</td></tr> <tr><td>Xevious</td><td>32</td></tr> <tr><td>Driver</td><td>42</td></tr> <tr><td>Football 2006</td><td>72</td></tr> <tr><td>Soccer 2006</td><td>99</td></tr> </table> </div> </div> </body> </html> | 兩個(gè)列表分別位于兩個(gè) <div> 標記中:names 和 score。names <div> 擁有按名稱(chēng)排序的游戲列表,score 擁有按分數排序的列表。show 函數連接到 By Name 和 By Score 鏈接,首先使所有列表均不可見(jiàn),隨后使所選列表可見(jiàn)。 還有其他一些有趣的東西。首先,您使用 className 屬性動(dòng)態(tài)地更改了鏈接的 CSS 類(lèi)。這也就是所選按鈕從白色變?yōu)楹谏脑颉?/p> 其次,觀(guān)察 names 和 score 的 CSS。兩個(gè) <div> 均按絕對位置定位于左上部,但不在頁(yè)面的左上角。這是因為它們位于 ID 值為 container 的 <div> 中,而 container 的位置設置為 relative。container <div> 有效地重置了包含于其中的項目的原點(diǎn)。表格是相對于容器而不是頁(yè)面來(lái)定位的。 這種 DHTML 不但復雜度合理、有趣,而且幾乎與所有現代瀏覽器兼容。
選項卡的 PHP 代碼 在 PHP 中開(kāi)發(fā) DHTML 的另外一種工具就是輸出緩存區 的使用。輸出緩存區存儲頁(yè)面中的文本、選項卡和重復素材,并將其作為字符串返回,供以后使用。為實(shí)現選項卡,將使用輸出緩存區,在把選項卡內容呈現到頁(yè)面中之前將其作為字符串存儲(參見(jiàn)清單 8)。 清單 8. 選項卡的 PHP 代碼 <?php $tabs = array(); $current_tab = null; function start_tab( $id, $title ) { global $tabs, $current_tab; ob_start(); $current_tab = $id; $tabs[ $id ] = array( ‘title‘ => $title, ‘html‘ => "" ); } function end_tab() { global $tabs, $current_tab; $tabs[ $current_tab ][ ‘html‘ ] = ob_get_contents(); ob_end_clean(); } function get_tab_ids() { global $tabs; $ids = array(); foreach( $tabs as $tabid => $tab ) { $ids []= "‘".$tabid."‘"; } return $ids; } function get_first_tab() { $tabs = get_tab_ids(); return $tabs[0]; } function place_tab_buttons() { global $tabs; foreach( $tabs as $tabid => $tab ) { ?> <a href="javascript:show(‘<?php echo($tabid); ?>‘)" id="<?php echo($tabid); ?>-button" class="button-off"><?php echo( $tab[‘title‘] ); ?></a> <?php } } function place_tab_content() { global $tabs; foreach( $tabs as $tabid => $tab ) { ?> <div id="<?php echo($tabid); ?>" class="game-list"> <?php echo( $tab[‘html‘] ); ?> </div> <?php } } ?> <?php start_tab( ‘names‘, "By Name" ); ?> <table width="100%"> <tr><td>Crank Shaft</td><td>22</td></tr> <tr><td>Driver</td><td>42</td></tr> <tr><td>Football 2006</td><td>72</td></tr> <tr><td>Soccer 2006</td><td>99</td></tr> <tr><td>Xevious</td><td>32</td></tr> </table> <?php end_tab( ); ?> <?php start_tab( ‘scores‘, "By Score" ); ?> <table width="100%"> <tr><td>Crank Shaft</td><td>22</td></tr> <tr><td>Xevious</td><td>32</td></tr> <tr><td>Driver</td><td>42</td></tr> <tr><td>Football 2006</td><td>72</td></tr> <tr><td>Soccer 2006</td><td>99</td></tr> </table> <?php end_tab( ); ?> <html> <head> <title>Tabs Example</title> <style type="text/css"> body { font-family: arial,verdana,sans serif; } .button-on, .button-off { padding: 3px; border: 1px solid black; } .button-on { background: #333; color: white; font-weight: bold; } .game-list { position: absolute; top: 0px; left: 0px; } .container { padding: 5px; border: 1px solid black; margin: 5px; position: relative; height: 400px; width: 200px; } </style> <script> function show( divid ) { var tos = [ <?php echo( join( ",", get_tab_ids() ) ); ?> ]; for( var t in tos ) { var to = document.getElementById( tos[t] ); to.style.visibility = "hidden"; to.style.height = "0px"; var bo = document.getElementById( tos[t]+"-button" ); bo.className = "button-off" } var to = document.getElementById( divid ); to.style.visibility = "visible"; to.style.height = "auto"; var bo = document.getElementById( divid + "-button" ); bo.className = "button-on"; } </script> </head> <body onload="show(<?php echo( get_first_tab() ); ?>)"> Sort by: <?php place_tab_buttons() ?> <div class="container"> <?php place_tab_content() ?> </div> </body> </html> | PHP 代碼首先定義了兩個(gè)變量:tabs 和 current_tab。tabs 數組保存各選項卡的 id、title 和 html 值。current_tab 指向 start_tab 和 end_tab 調用間創(chuàng )建的選項卡。start_tab 函數接受兩個(gè)參數:選項卡的 id 值和 title 值。它隨后會(huì )啟動(dòng)輸出緩存。 end_tab 函數終止輸出緩存,并將作為結果的 HTML 存儲在 tabs 數組的 current_tab 的 html 值中。 再往下看,可以看到 start_tab 和 end_tab 調用中包含要在選項卡中呈現的選項卡內容。 將選項卡呈現在頁(yè)面上的重要函數就是 place_tab_buttons 和 place_tab_content。place_tab_buttons 函數創(chuàng )建有著(zhù)選項卡名稱(chēng)的錨定標記,單擊錨定標記時(shí),將切換選項卡。place_tab_content 函數創(chuàng )建具有輸出緩存區存儲的各選項卡內容的 <div> 標記。 get_tab_ids 和 get_first_tab 是創(chuàng )建 JavaScript 的輔助函數。它們分別返回選項卡 ID 的完整列表和第一個(gè)選項卡的 ID。
下期預告 “使用 PHP 和 DHTML 設計 Web 2.0 應用程序” 系列的下一篇文章將介紹通過(guò) JavaScript 生成動(dòng)態(tài)圖片的內容。下篇文章將教您如何動(dòng)態(tài)創(chuàng )建新的 HTML 元素,并在 PHP 應用程序所顯示的頁(yè)面中定位這些元素。
參考資料 學(xué)習 獲得產(chǎn)品和技術(shù) - 使用 IBM 試用軟件 革新您的下一個(gè)開(kāi)放源碼開(kāi)發(fā)項目,可通過(guò)下載獲得,也可通過(guò) DVD 獲得。
討論
關(guān)于作者 | | | | Jack D. Herrington 是一名高級軟件工程師,有著(zhù)二十余年的經(jīng)驗。他撰寫(xiě)了三本圖書(shū):Code Generation in Action、Podcasting Hacks 和即將出版的 PHP Hacks。他的作品還包括三十多篇文章。 |
|