冲动了~~一夜没睡~~手写ajax rss2.0 reader
最近比较容易冲动,这不昨天一冲动,研究了半天,晚上没睡觉,用js写了ajax的rss2的未化妆版的阅读器。本来是因为想找一个合适的yahoo widget用来read rss的,但是在网上找了很久都不如意,nnd,于是算了自己做一个吧。
关键还是使用ajax的过程吧,后来才发现yahoo widget他有他自己实现fetch的过程,所以最后写出来的代码,还必须好好改造一下才能用在yahoo widget上面。
正当发愁之际,想看看人家的yahoo widget是怎么写的,然后打开默认的my widget文件夹,找找自己感兴趣的widget研究一下,没想到竟然被我看到了rss reader。我的天啊!我怎么一开始没看到呢。适用了一下虽然只能订阅一个rss,但是还是挺漂亮的。于是放弃了把ajax迁移过来的想法。
总结一下用ajax写rss reader
下面就是样图,很朴素吧,呵呵 , 非常之土了,但是功能到了,如果一天以前的就会显示为以前的源,一天之内的会显示多少分钟之前的,自己可以设定多长时间重新获取。下面写的临时更新是我让他更新的时候打印出来给我看的,没有什么实际意义。
先是html页面
<!DOCTYPE HTML PUBLIC “-//W3C//DTD HTML 4.01 Transitional//EN”>
<html>
<head>
<title>ajax测试</title>
<link href=”a.css” rel=”stylesheet” type=”text/css”/>
<script type=”text/javascript” src=”js/ajax.js”></script>
<script type=”text/javascript” src=”js/rss2reader.js”></script>
<script type=”text/javascript” src=”js/rssClass.js”></script>
<script type=”text/javascript” src=”js/display.js”></script>
<script type=”text/javascript”>
var requestUrl = “http://dongpingyuwen.blog.sohu.com/rss”
function iniPage(){
display.iniHolder(”holder”);
display.setTime(”time”);
if(initXMLHTTPRequest()!==null){
sendRequest(requestUrl,’1′,’GET’);
}
}
</script>
<meta http-equiv=”keywords” content=”keyword1,keyword2,keyword3″>
<meta http-equiv=”description” content=”this is my page”>
<meta http-equiv=”content-type” content=”text/html; charset=UTF-8″>
</head>
<body onload=”iniPage()”>
<div id=”time”></div>
<br/>
<div id=”holder”></div>
<br/>
<input type=”hidden” name=”hd” id=”hd”/>
</body>
</html>
//然后是负责异步的ajax核心代码,一般都是大同小异
var req = null;
var console = null;
var ie = false;
var READY_STATE_UNINITIALIZED = 0;
var READY_STATE_LOADING = 1;
var READY_STATE_LOADED = 2;
var READY_STATE_INTERACTIVE = 3;
var READY_STATE_COMPLETE = 4;
function sendRequest(url,params,HttpMethod){
if(!HttpMethod){
HttpMethod = “GET”
}
req = initXMLHTTPRequest();
if(req){
req.onreadystatechange = onReadyState;
try{
req.open(HttpMethod,url,true);
}catch(error){
alert(error);
}
req.setRequestHeader(”Content-Type”,”application/x-www-form-urlencoded”);
req.send(null);
}
}
function initXMLHTTPRequest(){
var xRequest = null;
try {
ie=true;
xRequest = new ActiveXObject(”Msxml2.XMLHTTP”);
return xRequest;
} catch (othermicrosoft) {
try {
xRequest = new ActiveXObject(”Microsoft.XMLHTTP”);
return xRequest;
} catch (failed) {
ie = false;
try{
xRequest = new XMLHttpRequest();
return xRequest;
}catch(error){
alert(error);
}
}
}
}
function onReadyState(){
var ready = req.readyState;
var xml = null;
if(ready==READY_STATE_COMPLETE){
var result = document.getElementById(’result’);
if(req.status==200){
xml = req.responseXML;
rss2Reader.fetchRss(xml,10000,true);
}
else{
result.value = req.status;
}
}
else{
data = “loading…[”+ready+”]”
}
}
//下面是自定义的保存rss节点信息的一些“类”和处理方法var rssClass = {};
rssClass.getChannelInfoInstance = function(channel){
var info = new Object();
var titleNodes = channel.getElementsByTagName(”title”);
var linkNodes = channel.getElementsByTagName(”link”);
var descriptionNodes = channel.getElementsByTagName(”description”);
var pubDateNodes = channel.getElementsByTagName(”pubDate”);
var generatorNodes = channel.getElementsByTagName(”generator”);
try{
if(titleNodes.length>0){
info.title = channel.getElementsByTagName(”title”)[0].firstChild.nodeValue;
}
if(linkNodes.length>0){
info.link = channel.getElementsByTagName(”link”)[0].firstChild.nodeValue;
}
if(descriptionNodes.length>0){
info.description = channel.getElementsByTagName(”description”)[0].firstChild.nodeValue;
}
if(pubDateNodes.length>0){
info.pubDate = channel.getElementsByTagName(”pubDate”)[0].firstChild.nodeValue;
}
if(generatorNodes.length>0){
info.generator = channel.getElementsByTagName(”generator”)[0].firstChild.nodeValue;
}
return info;
}catch(error){
alert(error);
return null;
}
};
rssClass.getItemInfoInstance=function(item){
var info = new Object();
var titleNodes = item.getElementsByTagName(”title”);
var linkNodes = item.getElementsByTagName(”link”);
var descriptionNodes = item.getElementsByTagName(”description”);
var pubDateNodes = item.getElementsByTagName(”pubDate”);
var commentsNodes = item.getElementsByTagName(”comments”);
var creatorNodes = item.getElementsByTagName(”dc:creator”);
var guidNodes = item.getElementsByTagName(”guid”);
try{
if(titleNodes.length>0){
info.title = item.getElementsByTagName(”title”)[0].firstChild.nodeValue;
}
if(linkNodes.length>0){
info.link = item.getElementsByTagName(”link”)[0].firstChild.nodeValue;
}
if(descriptionNodes.length>0){
info.description = item.getElementsByTagName(”description”)[0].firstChild.nodeValue;
}
if(pubDateNodes.length>0){
info.pubDate = item.getElementsByTagName(”pubDate”)[0].firstChild.nodeValue;
}
if(commentsNodes.length>0){
info.comments = item.getElementsByTagName(”comments”)[0].firstChild.nodeValue;
}
if(pubDateNodes.length>0){
info.creator = item.getElementsByTagName(”dc:creator”)[0].firstChild.nodeValue;
}
if(commentsNodes.length>0){
info.guid = item.getElementsByTagName(”guid”)[0].firstChild.nodeValue;
}
return info;
}catch(error){
alert(error);
return null;
}
};
rssClass.getTimeInstance = function(time){
var date = new Date(time);
var instance = new Object();
if(!ie){
instance.year = date.getYear()+1900;
}
else{
instance.year = date.getYear();
}
instance.month = date.getMonth()+1;
instance.date = date.getDate();
instance.day = date.getDay();
instance.hour = date.getHours();
instance.minute = date.getMinutes();
instance.second = date.getSeconds();
instance.zone = date.getTimezoneOffset();
return instance;
};
rssClass.getOffsetMinuteDescription = function(time){
var offset = rssClass.getMinutesByNow(time);
switch(offset){
case -1:return “无效时间:”break;
case -2:return “以前的:”break;
case 0:return “最新的:”break;
default:return offset+”分钟之前:”break;
}
}
rssClass.getCustomDate = function(time){
var t = rssClass.getTimeInstance(time);
return t.year+”年”+t.month+”月”+t.date+”日”+” “+t.hour+”时”+t.minute+”分”
}
rssClass.getMinutesByNow = function(time){
var date = new Date(time);
var current = new Date();
var result = 0;
var deltaYear = current.getYear() - date.getYear();
var deltaMonth = current.getMonth() - date.getMonth();
var deltaDay = current.getDate() - date.getDate();
var deltaHour = current.getHours() - date.getHours();
var deltaMinute = current.getMinutes() - date.getMinutes();
if(deltaYear < 0){
return -1;
}
else if(deltaYear==0){
if(deltaMonth<0){
return -1
}
else if(deltaMonth==0){
if(deltaDay<0){
return -1
}
else if(deltaDay==0){
if(deltaHour<0){
return -1;
}
else if(deltaHour==0){
if(deltaMinute <0){
return -1;
}
else{
result = deltaMinute + result;
}
}
else{
result = deltaHour*60+result;
}
}
else{
return -2;
}
}
else{
return -2;
}
}
else{
return -2;
}
return result;
}
//下面是负责解析rss的代码
var channels;
var first=true;
var rss2Reader={};
rss2Reader.fetchRss = function (xmlDoc,delay,timeEnabled){
if(delay>0){
if(timeEnabled){
display.setTime(”time”,”default”);
}
var root = xmlDoc.getElementsByTagName(”rss”)[0];
channels = root.getElementsByTagName(”channel”);
var oldItemDate = document.getElementById(”hd”).value;
var newItemDate = rss2Reader.getLatestItemDate(channels[0]);
if(oldItemDate!==newItemDate){
display.removeAll();
for(var i=0;i<channels.length;i++){
rss2Reader.decode(channels[i]);
}
}
else{
var div = display.appendDiv(”default”);
display.appendTextNode(div,”没有更新”,”default”);
}
window.setTimeout(”sendRequest(’”+requestUrl+”‘,’1′,’GET’)”,delay);
}
else{
var root = xmlDoc.getElementsByTagName(”rss”)[0];
channels = root.getElementsByTagName(”channel”);
for(var i=0;i<channels.length;i++){
rss2Reader.decode(channels[i]);
}
}
};
rss2Reader.getLatestItemDate = function(channel){
var channelInfo = rssClass.getChannelInfoInstance(channel);
if(channelInfo!==null){
return channelInfo.pubDate;
}
return null;
};
rss2Reader.decode = function(channel){
var channelInfo = rssClass.getChannelInfoInstance(channel);
if(channelInfo!==null){
display.setHiddenValue(channelInfo.pubDate);
var items = channel.getElementsByTagName(”item”);
for(var i = 0 ; i< items.length ; i++){
itemInfo = rssClass.getItemInfoInstance(items[i]);
if(itemInfo!==null){
var div = display.appendDiv(”defaultdiv”);
display.appendTextNode(div,rssClass.getOffsetMinuteDescription(itemInfo.pubDate),”default”);
display.appendLink(div,itemInfo.title,itemInfo.link,”default”);
}
}
}
};
//下面是用来显示在页面上的方法
var holder;
var display={};
display.iniHolder = function (holderid){
holder = document.getElementById(holderid);
if(holder===null){
alert(holderid);
window.alert(”Error while getting the holder!”);
}
};
display.removeAll = function(node,style){
var length = holder.childNodes.length;
for(var i = 0; i<length;i++){
holder.removeChild(holder.firstChild);
}
};
display.appendDiv = function (style){
if(holder===null){
window.alert(”Must you first initialize the holder!”);
}
var newDiv = document.createElement(”div”);
newDiv.className = style;
holder.appendChild(newDiv);
return newDiv;
};
display.appendTextNode = function (parentNode , text , style){
var newTextNode = document.createTextNode(text);
parentNode.appendChild(newTextNode);
return newTextNode;
};
display.appendLink = function (parentNode , text , link , style){
var newlink = document.createElement(”a”);
newlink.setAttribute(”href”,link);
newlink.setAttribute(”class”,style);
var newTextNode = document.createTextNode(text);
newlink.appendChild(newTextNode);
parentNode.appendChild(newlink);
return newlink;
};
display.setTime = function(holderid,style){
var holder = document.getElementById(holderid);
if(holder===null){
window.alert(”Error while getting the holder!”);
}
else{
if(holder.hasChildNodes()){
holder.removeChild(holder.firstChild);
}
var time = document.createTextNode(rssClass.getCustomDate(new Date))
holder.appendChild(time);
holder.setAttribute(”class”,style);
}
};
display.setHiddenValue = function(value){
var hd = document.getElementById(”hd”);
hd.value = value;
};
基本的逻辑是
1 在html里调用ajax的异步获取
2 将异步获取到的xml交给rssreader解析
3 rssreader将具体的每一个item以及channel信息,用具体的“类”rssClass来解析,并保存
4 rssreader将获得的数据调用display中的方法显示到页面上
由于是兴起而至,所以没有加注释 呵呵 敬请原谅
目前有一点碰到的问题
ajax有着很严格的安全性,是不能跨域的,比如说我在自己本机的tomcat里面架了一个网站,我的html是这个网站的一部分,我用localhost去访问时,如果这个时候xml源也是tomcat里面的另一个网站里的xml,那么没问题一切正常,但是如果我fetch的是internet上的源就不行了,无论是ie还是firefox都没有权限。
如果我们只是通过本地访问html文件,而不是通过网站访问,那么ie是可以的,但是firefox不可以。
这是很郁闷的一件事情不是吗?
网上提供了一个解决方法,就是在internet自己的站点上架一个servlet,然后去掉,自己对自己域内的有访问权限,然后由internet上的servlet对信息做中转,访问internet其他的信息源。
这种解决方案实在是哎 ~~ 欺负我们这种穷人啊。
自己写着玩的,首先健壮性肯定很弱的,呵呵,欢迎提出一些意见建议