楼主: lastwinner

[参考文档] Ajax RSS 阅读器

[复制链接]
论坛徽章:
484
ITPUB北京香山2007年会纪念徽章
日期:2007-01-24 14:35:02ITPUB北京九华山庄2008年会纪念徽章
日期:2008-01-21 16:50:24ITPUB北京2009年会纪念徽章
日期:2009-02-09 11:42:452010新春纪念徽章
日期:2010-03-01 11:04:552010数据库技术大会纪念徽章
日期:2010-05-13 10:04:272010系统架构师大会纪念
日期:2010-09-04 13:35:54ITPUB9周年纪念徽章
日期:2010-10-08 09:28:512011新春纪念徽章
日期:2011-02-18 11:43:32ITPUB十周年纪念徽章
日期:2011-11-01 16:19:412012新春纪念徽章
日期:2012-01-04 11:49:54
11#
 楼主| 发表于 2006-7-11 23:27 | 只看该作者
这在形式上与 list.php 页面极其类似。我使用 Feed 类来获取文章列表。随后使用 XML DOM 对象来创建 XML 并进行输出。在 Firefox 中浏览此页面时,输出如 图 2 所示。
图 2. read.php 页面的 XML

至此,我们已完成了这一综合体的服务器端。现在需要将一个利用 Ajax 来使用这些 PHP 页面的 DHTML(Dynamic Hyper Text Markup Language)页面加入进来。

使用道具 举报

回复
论坛徽章:
484
ITPUB北京香山2007年会纪念徽章
日期:2007-01-24 14:35:02ITPUB北京九华山庄2008年会纪念徽章
日期:2008-01-21 16:50:24ITPUB北京2009年会纪念徽章
日期:2009-02-09 11:42:452010新春纪念徽章
日期:2010-03-01 11:04:552010数据库技术大会纪念徽章
日期:2010-05-13 10:04:272010系统架构师大会纪念
日期:2010-09-04 13:35:54ITPUB9周年纪念徽章
日期:2010-10-08 09:28:512011新春纪念徽章
日期:2011-02-18 11:43:32ITPUB十周年纪念徽章
日期:2011-11-01 16:19:412012新春纪念徽章
日期:2012-01-04 11:49:54
12#
 楼主| 发表于 2006-7-11 23:28 | 只看该作者
构建客户机
接下来要完成的任务就是构建一个使用 PHP 页面的客户机。为使您能循序渐进地理解,我将分三个阶段完成构建。第一个版本如 清单 8 所示,展示了一个显示提要列表的控件。
清单 8. index2.html
[php]
<html> <head> <title>Ajax RSS Reader</title>
<style>
body { font-family: arial, verdana, sans-serif; }
</style>
<script>
var g_homeDirectory = 'http://localhost/rss/';

var req = null;
function processReqChange( handler ) {
  if (req.readyState == 4 && req.status == 200 && req.responseXML ) {
    handler( req.responseXML ); }
}

function loadXMLDoc( url, handler ) {
  if(window.XMLHttpRequest) {
    try { req = new XMLHttpRequest(); } catch(e) { req = false; }
  }
  else if(window.ActiveXObject)
  {
    try { req = new ActiveXObject("Msxml2.XMLHTTP"; } catch(e) {
    try { req = new ActiveXObject("Microsoft.XMLHTTP"; } catch(e) { req = false; } }
  }

  if(req) {
    req.onreadystatechange = function() { processReqChange( handler ); };
    req.open("GET", url, true);
    req.send("";
  }
}

function parseFeedList( dom ) {
  var elfl = document.getElementById( 'elFeedList' );
  elfl.innerHTML = '';

  var nl = req.responseXML.getElementsByTagName( 'feed' );
  for( var i = 0; i < nl.length; i++ ) {
    var nli = nl.item( i );
    var id = nli.getAttribute( 'id' );
    var link = nli.getAttribute( 'link' );
    var name = nli.getAttribute( 'name' );

    var elOption = document.createElement( 'option' );
    elOption.value = id;
    elOption.innerHTML = name;
    elfl.appendChild( elOption );
  }
}

function getFeedList()
{
  loadXMLDoc( g_homeDirectory+'list.php', parseFeedList );
}
</script> </head> <body>
<select id="elFeedList"> </select>
<script> getFeedList(); </script>
</body> </html>

.........
[/php]

此页面上有一个控件 —— <select> 控件。此控件由向服务器请求 ist.php 页面的 getFeedList 函数填充。载入页面时,parseFeedList 函数向 <select> 控件添加项目。

使用道具 举报

回复
论坛徽章:
484
ITPUB北京香山2007年会纪念徽章
日期:2007-01-24 14:35:02ITPUB北京九华山庄2008年会纪念徽章
日期:2008-01-21 16:50:24ITPUB北京2009年会纪念徽章
日期:2009-02-09 11:42:452010新春纪念徽章
日期:2010-03-01 11:04:552010数据库技术大会纪念徽章
日期:2010-05-13 10:04:272010系统架构师大会纪念
日期:2010-09-04 13:35:54ITPUB9周年纪念徽章
日期:2010-10-08 09:28:512011新春纪念徽章
日期:2011-02-18 11:43:32ITPUB十周年纪念徽章
日期:2011-11-01 16:19:412012新春纪念徽章
日期:2012-01-04 11:49:54
13#
 楼主| 发表于 2006-7-11 23:29 | 只看该作者
在 Firefox 中浏览此页面时,输出如 图 3 所示。
图 3. RSS 阅读器的第一个版本

为将最初这些提要添加到系统中,我使用 MySQL 接口来手动添加这些提要。

使用道具 举报

回复
论坛徽章:
484
ITPUB北京香山2007年会纪念徽章
日期:2007-01-24 14:35:02ITPUB北京九华山庄2008年会纪念徽章
日期:2008-01-21 16:50:24ITPUB北京2009年会纪念徽章
日期:2009-02-09 11:42:452010新春纪念徽章
日期:2010-03-01 11:04:552010数据库技术大会纪念徽章
日期:2010-05-13 10:04:272010系统架构师大会纪念
日期:2010-09-04 13:35:54ITPUB9周年纪念徽章
日期:2010-10-08 09:28:512011新春纪念徽章
日期:2011-02-18 11:43:32ITPUB十周年纪念徽章
日期:2011-11-01 16:19:412012新春纪念徽章
日期:2012-01-04 11:49:54
14#
 楼主| 发表于 2006-7-11 23:29 | 只看该作者
下一步是显示所选提要的内容。清单 9 展示了升级后的代码。
清单 9. index3.html
[php]
<html> <head> <title>Ajax RSS Reader</title>
<style>
body { font-family: arial, verdana, sans-serif; }
.title { font-size: 14pt; border-bottom: 1px solid black; }
.title a { text-decoration: none; }
.title a:hover { text-decoration: none; }
.title a:visited { text-decoration: none; }
.title a:active { text-decoration: none; }
.title a:link { text-decoration: none; }
.description { font-size: 9pt; margin-left: 20px; }
</style>
<script>
var g_homeDirectory = 'http://localhost/rss/';

var req = null;
function processReqChange( handler ) { ...  }

function loadXMLDoc( url, handler ) { ...  }

function parseFeed( dom ) {
  var ela = document.getElementById( 'elArticles' );
  ela.innerHTML = '';

  var elTable = document.createElement( 'table' );
  var elTBody = document.createElement( 'tbody' );
  elTable.appendChild( elTBody );

  var nl = req.responseXML.getElementsByTagName( 'article' );
  for( var i = 0; i < nl.length; i++ ) {
    var nli = nl.item( i );
    var title = nli.getAttribute( 'title' );
    var link = nli.getAttribute( 'link' );
    var description = nli.firstChild.nodeValue;

    var elTR = document.createElement( 'tr' );
    elTBody.appendChild( elTR );

    var elTD = document.createElement( 'td' );
    elTR.appendChild( elTD );

    var elTitle = document.createElement( 'h1' );
    elTitle.className = 'title';
    elTD.appendChild( elTitle );

    var elTitleLink = document.createElement( 'a' );
    elTitleLink.href = link;
    elTitleLink.innerHTML = title;
    elTitleLink.target = '_blank';
    elTitle.appendChild( elTitleLink );

    var elDescription = document.createElement( 'p' );
    elDescription.className = 'description';
    elDescription.innerHTML = description;
    elTD.appendChild( elDescription );
  }

  ela.appendChild( elTable );
}

function parseFeedList( dom ) {
  var elfl = document.getElementById( 'elFeedList' );
  elfl.innerHTML = '';

  var nl = req.responseXML.getElementsByTagName( 'feed' );
  var firstId = null;
  for( var i = 0; i < nl.length; i++ ) {
    var nli = nl.item( i );
    var id = nli.getAttribute( 'id' );
    var link = nli.getAttribute( 'link' );
    var name = nli.getAttribute( 'name' );

    var elOption = document.createElement( 'option' );
    elOption.value = id;
    elOption.innerHTML = name;
    elfl.appendChild( elOption );

    if ( firstId == null ) firstId = id;
  }
  loadFeed( firstId );
}

function loadFeed( id ) { loadXMLDoc( g_homeDirectory+'read.php?id='+id, parseFeed ); }

function getFeedList() { loadXMLDoc( g_homeDirectory+'list.php', parseFeedList ); }
</script> </head> <body> <div style="width:600px;">
<select id="elFeedList"
  onchange="loadFeed( this.options[this.selectedIndex].value )"> </select>
<div id="elArticles"> </div>
<script> getFeedList(); </script>
</div> </body> </html>


.......
[/php]
我省略了 processReqChange 和 loadXMLDoc 函数,因为它们与之前的代码完全相同。新代码在 loadFeed 和 parseFeed 函数中,这些函数用于从 read.php 页面请求数据、解析数据,随后将其添加到页面中。

使用道具 举报

回复
论坛徽章:
484
ITPUB北京香山2007年会纪念徽章
日期:2007-01-24 14:35:02ITPUB北京九华山庄2008年会纪念徽章
日期:2008-01-21 16:50:24ITPUB北京2009年会纪念徽章
日期:2009-02-09 11:42:452010新春纪念徽章
日期:2010-03-01 11:04:552010数据库技术大会纪念徽章
日期:2010-05-13 10:04:272010系统架构师大会纪念
日期:2010-09-04 13:35:54ITPUB9周年纪念徽章
日期:2010-10-08 09:28:512011新春纪念徽章
日期:2011-02-18 11:43:32ITPUB十周年纪念徽章
日期:2011-11-01 16:19:412012新春纪念徽章
日期:2012-01-04 11:49:54
15#
 楼主| 发表于 2006-7-11 23:29 | 只看该作者
图 4 展示了在 Firefox 中浏览此页面的输出。
图 4. 显示文章列表的升级页面

使用道具 举报

回复
论坛徽章:
484
ITPUB北京香山2007年会纪念徽章
日期:2007-01-24 14:35:02ITPUB北京九华山庄2008年会纪念徽章
日期:2008-01-21 16:50:24ITPUB北京2009年会纪念徽章
日期:2009-02-09 11:42:452010新春纪念徽章
日期:2010-03-01 11:04:552010数据库技术大会纪念徽章
日期:2010-05-13 10:04:272010系统架构师大会纪念
日期:2010-09-04 13:35:54ITPUB9周年纪念徽章
日期:2010-10-08 09:28:512011新春纪念徽章
日期:2011-02-18 11:43:32ITPUB十周年纪念徽章
日期:2011-11-01 16:19:412012新春纪念徽章
日期:2012-01-04 11:49:54
16#
 楼主| 发表于 2006-7-11 23:30 | 只看该作者
下一步是加入通过 add.php 页面向列表添加提要的能力,以完成页面。页面的最终代码如 清单 10 所示。
清单 10. index.html
[php]
<html> <head> <title>Ajax RSS Reader</title>
<style>
...
</style>
<script>
var g_homeDirectory = 'http://localhost/rss/';

// The same transfer functions as before

function addFeed()
{
  var url = prompt( "Url" );
  loadXMLDoc( g_homeDirectory+'add.php?url='+escape( url ), parseAddReturn );
  window.setTimeout( getFeedList, 1000 );
}

function loadFeed( id ) { loadXMLDoc( g_homeDirectory+'read.php?id='+id, parseFeed ); }

function getFeedList() { loadXMLDoc( g_homeDirectory+'list.php', parseFeedList ); }
</script> </head> <body> <div style="width:600px;">
<select id="elFeedList" onchange="loadFeed( this.options[this.selectedIndex].value )">
</select>
<input type="button" onclick="addFeed()" value="Add Feed..." />
<div id="elArticles"> </div>
<script> getFeedList(); </script>
</div> </body> </html>

.......
[/php]

这里的绝大多数代码都是相同的,但我插入了一个新的 Add Feed... 按钮,用于打开一个对话框,您可通过此对话框向提要列表插入一个新 URL。为简化我自己的工作,我让浏览器等了两秒钟,在添加好提要后,获取新提要列表。

使用道具 举报

回复
论坛徽章:
484
ITPUB北京香山2007年会纪念徽章
日期:2007-01-24 14:35:02ITPUB北京九华山庄2008年会纪念徽章
日期:2008-01-21 16:50:24ITPUB北京2009年会纪念徽章
日期:2009-02-09 11:42:452010新春纪念徽章
日期:2010-03-01 11:04:552010数据库技术大会纪念徽章
日期:2010-05-13 10:04:272010系统架构师大会纪念
日期:2010-09-04 13:35:54ITPUB9周年纪念徽章
日期:2010-10-08 09:28:512011新春纪念徽章
日期:2011-02-18 11:43:32ITPUB十周年纪念徽章
日期:2011-11-01 16:19:412012新春纪念徽章
日期:2012-01-04 11:49:54
17#
 楼主| 发表于 2006-7-11 23:30 | 只看该作者
图 5 展示了最终完成的页面。
图 5. 最终完成的页面

现在这看起来非常酷。但我还不够满意,因为 XMLHTTP 安全性使我无法从此页面中获取 JavaScript 代码,无法将其复制到其他人的博客上以使他人能够看到提要。为此,我需要重新设计服务,以使用  标记和 JavaScript Object Notation(JSON)语法。

使用道具 举报

回复
论坛徽章:
484
ITPUB北京香山2007年会纪念徽章
日期:2007-01-24 14:35:02ITPUB北京九华山庄2008年会纪念徽章
日期:2008-01-21 16:50:24ITPUB北京2009年会纪念徽章
日期:2009-02-09 11:42:452010新春纪念徽章
日期:2010-03-01 11:04:552010数据库技术大会纪念徽章
日期:2010-05-13 10:04:272010系统架构师大会纪念
日期:2010-09-04 13:35:54ITPUB9周年纪念徽章
日期:2010-10-08 09:28:512011新春纪念徽章
日期:2011-02-18 11:43:32ITPUB十周年纪念徽章
日期:2011-11-01 16:19:412012新春纪念徽章
日期:2012-01-04 11:49:54
18#
 楼主| 发表于 2006-7-11 23:31 | 只看该作者
从 XML 到 JSON
本文将仅允许通过脚本语法查看提要,但我确实会完整地使用脚本标记作为数据传输机制。为获得提要,首先需要将提要列表编码为 JavaScript 代码。因此我创建了一个 list_js.php 页面,如 清单 11 所示。
清单 11. list_js.php
[php]
<?php
require_once 'rss_db.php';

header( 'Content-type: text/javascript' );

$rows = FeedList::getAll();

$feeds = array();

foreach( $rows as $row )
{
  $feed = "{ id:".$row['rss_feed_id'];
  $feed .= ", link:'".$row['url']."'";
  $feed .= ", name:'".$row['name']."' }";
  $feeds []= $feed;
}
?>
setFeeds( [ <?php echo( join( ', ', $feeds ) ); ?> ] );
.........
[/php]

使用道具 举报

回复
论坛徽章:
484
ITPUB北京香山2007年会纪念徽章
日期:2007-01-24 14:35:02ITPUB北京九华山庄2008年会纪念徽章
日期:2008-01-21 16:50:24ITPUB北京2009年会纪念徽章
日期:2009-02-09 11:42:452010新春纪念徽章
日期:2010-03-01 11:04:552010数据库技术大会纪念徽章
日期:2010-05-13 10:04:272010系统架构师大会纪念
日期:2010-09-04 13:35:54ITPUB9周年纪念徽章
日期:2010-10-08 09:28:512011新春纪念徽章
日期:2011-02-18 11:43:32ITPUB十周年纪念徽章
日期:2011-11-01 16:19:412012新春纪念徽章
日期:2012-01-04 11:49:54
19#
 楼主| 发表于 2006-7-11 23:31 | 只看该作者
在命令行中运行此脚本时,输出如 清单 12 所示。
清单 12. list_js.php 的输出
[php]
setFeeds( [
{ id:1, link:'http://muttmansion.com/ds/index.xml', name:'Driving Sideways' },
{ id:2, link:'http://slashdot.org/slashdot.rdf', name:'Slashdot' },
{ id:3, link:'http://muttmansion.com/vl/index.xml', name:'Visible Light' },
{ id:4, link:'http://muttmansion.com/sor/index.xml', name:'Socks on a Rooster' },
{ id:5, link:'http://muttmansion.com/dd/index.xml', name:'Doxie Digest' },
{ id:6, link:'http://rss.cnn.com/rss/cnn_topstories.rss', name:'CNN.com' },
{ id:7, link:'http://rss.cnn.com/rss/cnn_world.rss', name:'CNN.com - World' },
{ id:8, link:'http://rss.cnn.com/rss/cnn_us.rss', name:'CNN.com - U.S.' } ] );
......
[/php]

这对于 <script> 标记而言很有用。浏览器加载此输出时,将通过提要列表调用 setFeeds 函数。然后依次设置 <select> 控件,加载第一个提要。

使用道具 举报

回复
论坛徽章:
484
ITPUB北京香山2007年会纪念徽章
日期:2007-01-24 14:35:02ITPUB北京九华山庄2008年会纪念徽章
日期:2008-01-21 16:50:24ITPUB北京2009年会纪念徽章
日期:2009-02-09 11:42:452010新春纪念徽章
日期:2010-03-01 11:04:552010数据库技术大会纪念徽章
日期:2010-05-13 10:04:272010系统架构师大会纪念
日期:2010-09-04 13:35:54ITPUB9周年纪念徽章
日期:2010-10-08 09:28:512011新春纪念徽章
日期:2011-02-18 11:43:32ITPUB十周年纪念徽章
日期:2011-11-01 16:19:412012新春纪念徽章
日期:2012-01-04 11:49:54
20#
 楼主| 发表于 2006-7-11 23:33 | 只看该作者
还需要与 read.php 功能等同的页面,不过是使用 JavaScript 代码而不是 XML 来返回文章数据。清单 13 展示了 read_js.php 页面。
清单 13. read_js.php
[php]
<?php
require_once 'rss_db.php';

function js_clean( $str )
{
  $str = preg_replace( "/\'/", "", $str );
  return $str;
}

FeedList::update();

$id = array_key_exists( 'id', $_GET ) ? $_GET['id'] : 1;

$rows = Feed::get( $id );

$items = array();

foreach( $rows as $row )
{
  $js = "{ title:'".js_clean($row['title'])."'";
  $js .= ", link:'".js_clean($row['link'])."'";
  $js .= ", description:'".js_clean($row['description'])."' }";
  $items []= $js;
}
?>
addFeed( <?php echo( $id ); ?>,
[ <?php echo( join( ', ', $items ) ); ?> ] );
....
[/php]

使用道具 举报

回复

您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

TOP技术积分榜 社区积分榜 徽章 团队 统计 知识索引树 积分竞拍 文本模式 帮助
  ITPUB首页 | ITPUB论坛 | 数据库技术 | 企业信息化 | 开发技术 | 微软技术 | 软件工程与项目管理 | IBM技术园地 | 行业纵向讨论 | IT招聘 | IT文档
  ChinaUnix | ChinaUnix博客 | ChinaUnix论坛
CopyRight 1999-2011 itpub.net All Right Reserved. 北京盛拓优讯信息技术有限公司版权所有 联系我们 未成年人举报专区 
京ICP备16024965号-8  北京市公安局海淀分局网监中心备案编号:11010802021510 广播电视节目制作经营许可证:编号(京)字第1149号
  
快速回复 返回顶部 返回列表