|
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Strict//EN" >
<html onscroll="menubar.style.top = window.document.documentElement.scrollTop + 'px'">
<head>
<!--
TinyRss.htm
A small rss reader for Internet Explorer using the Search panel.
Copyright by Matthias Hertel, http://www.mathertel.de
This work is licensed under a Creative Commons Attribution 2.0 Germany License.
See http://creativecommons.org/licenses/by/2.0/de/
Instructions and documentation is available at http://www.codeproject.com/jscript/tinyrss.asp
16.02.2005 first release on http://www.codeproject.com/jscript/TinyRSS.asp
27.04.2005 working with http://purl.org/atom feeds
20.06.2005 more functionality, add & settings in main window
22.06.2005 bugfix
22.11.2005 bugfix: url encoding
22.11.2005 better error handling
25.05.2006 sidebar version
03.08.2006 Forced refresh added (ctrl+click on "RSS" in title)
05.08.2006 RSS2.0 syntax added, better layout
-->
<style type="text/css">
html {border:0px;overflow-x:hidden}
BODY,input,button {FONT-FAMILY: Arial,Verdana; FONT-SIZE: 8pt; COLOR: black; margin:0px;overflow-x:hidden;background-color:#eeeeee}
#header { padding-top:18px;}
#menubar {display:block;background-color:orange;margin:0px;position:absolute;top:0px;left:0px;height:18px}
#menubar #TITLE {FONT-SIZE: 12pt; font-weight:bold;color: white;text-decoration:none;width:40px}
#menubar span { width:80px;float:right; text-align:right;padding-top:2px}
#menubar a { margin:2px;font-size:8pt;padding:0px}
.feed { background-color:white; margin-left:2px; margin-top:2px;}
.feed h2 {font-size:10pt;color:black;margin:6px 0px 0px 0px;height:16px;xbackground-color:#DDDDDD}
.feed a.link, span.link {display:block;height:13px}
.feed a.nolink, span.nolink {display:none}
.feed h2, .feed a.link, .feed span.link {padding-left:1px;white-space:pre;width:100%;overflow:hidden;text-overflow:ellipsis}
input,label {vertical-align:middle}
form {margin:0px}
.dlg { display:none;width:490px;background-color:white; margin:8px 4px 4px 4px; border:1px solid #aaaaaa; padding:2px;}
.dlg h2 { margin:0px;background-color:#acc1e4;}
#rssList, #newrss { background-color:#cad6ee;padding:4px}
#rssList a { display:inline-block;background-color:white;padding-right:1px;padding-left:1px}
#rssList * { margin-bottom:1px;vertical-align:bottom}
.func {background-color:#acc1e4;border-top:solid 1px black;padding:4px;text-align:right }
</style>
<title>TinyRss Reader</title>
</head>
<body>
<span id="feeds" style="display: none; behavior: url(#default#userdata)"></span>
<span id="data" style="display: none; behavior: url(#default#userdata)"></span>
<div id="header">
<div id="menubar">
<span><a href="TinyRss.htm?mode=admin" target="_main" title="Open settings dialog.">
Settings</a> </span><a id="TITLE" href="TinyRss.htm?mode=list" target="_self" title="click here to refresh the page. Press <ctrl> to reload all RSS feeds.">
RSS</a>
</div>
</div>
<xml id="rssLoad"></xml>
<div id="startblock" style="display: none; padding: 4px;">
<h1>Welcome</h1>
<p>Tiny RSS for MS Internet Explorer.</p>
<p></p>
<hr>
<p></p>
</div>
<div id="adminblock1" class="dlg" style="display: none; width: 490px">
<h2>Add a New RSS Feed</h2>
<form action="TinyRss.htm">
<input type="hidden" name="mode" value="add" />
<div id="newrss">
<label for="newUrl">Enter a new RSS Url:</label><br>
<input autocomplete="on" name="newUrl" style="width: 430px" /><br />
<input type="checkbox" checked="checked" name="openUrl" id="Checkbox1" />
<label for="openUrl">open on load</label>
</div>
<div class="func">
<input type="button" value="Cancel" style="width: 60px" onclick="window.location.replace('?')" />
<input type="submit" style="width: 60px" value="OK" />
</div>
</form>
</div>
<div id="adminblock2" class="dlg" style="display: none; width: 490px">
<h2>Change RSS Feeds</h2>
<div id="rssList">
</div>
<div class="func">
<input type="button" value="OK" style="width: 60px" onclick="window.location.replace('?')" />
<input type="button" value="Delete all Bookmarks" style="width: 120px" onclick="window.location.replace('?mode=resetall')" />
</div>
</div>
<script type="text/javascript">
var RssUrls, RssFlags;
var RssUrl, RssName;
var LinkClass = "link";
var ForceRefresh = false;
window.onload = window_onload;
document.onclick = doc_onclick;
rssLoad.onreadystatechange = rssLoad_onreadystatechange;
function doc_onclick() {
if (event.srcElement.tagName == "H2") {
var l = event.srcElement.nextSibling;
while ((l != null) && ((l.tagName == "A") || (l.tagName == "SPAN"))) {
l.className = (l.className == "link" ? "nolink" : "link");
l = l.nextSibling;
} // while
} // if
} // doc_onclick
/// Check the given parameter and display the corresponding part of this page.
/// The mode parameter specifies what content should be displayed:
function window_onload() {
var feedStore = document.getElementById("feeds");
feedStore.load("RssStore");
var xDoc = feedStore.XMLDocument;
var n, s, p;
ForceRefresh = event.ctrlKey;
// get url-parameters
s = window.location.search.substr(1).split("&");
var par = new Object();
for (n = 0; n < s.length; n++) {
p = s[n].split("=");
if (p.length > 1)
par[p[0]] = decodeURIComponent(p[1]);
} // for
if ((window.location.search == "") || (window.location.search == "?")) {
// display rssNews inside the search panel
startblock.style.display = "";
window.open("?mode=list", "_search"); // Sidebar-version: window.open("?mode=list", "_self");
// To the MS IE team: the features parameter is ignored: "width=280,toolbar=no". That would be great.
// Better: a _sidebar target without any headers.
} else if (par["mode"] == "list") {
// display rssNews inside the search panel
xNodes = xDoc.selectNodes("//feedUrl");
RssUrls = new Array(xNodes.length);
RssFlags = new Array(xNodes.length);
for (n = 0; n < xNodes.length; n++) {
RssUrls[n] = xNodes[n].text;
RssFlags[n] = xNodes[n].getAttribute("open");
}
rssLoadNext();
} else if (par["mode"] == "resetall") {
if (confirm("Do you want to delete all registered bookmarks ?")) {
var xDoc = feedStore.XMLDocument;
xDoc.loadXML("<ROOTSTUB />");
feedStore.save("RssStore");
} // if
window.location.replace("?");
} else if (par["mode"] == "reset") {
var xDoc = feedStore.XMLDocument;
var xNode = xDoc.selectSingleNode("//feedUrl[.='" + par["url"] + "']");
if ((xNode != null) && (confirm("Do you want to delete bookmark " + par["url"] + "?"))) {
xNode.parentNode.removeChild(xNode);
feedStore.save("RssStore");
} // if
window.location.replace("?mode=admin");
} else if (par["mode"] == "up") {
var xDoc = feedStore.XMLDocument;
var xNode = xDoc.selectSingleNode("//feedUrl[.='" + par["url"] + "']");
if ((xNode != null) && (xNode.previousSibling != null)) {
xNode.parentNode.insertBefore(xNode, xNode.previousSibling);
feedStore.save("RssStore");
} // if
window.location.replace("?mode=admin");
} else if (par["mode"] == "down") {
var xDoc = feedStore.XMLDocument;
var xNode = xDoc.selectSingleNode("//feedUrl[.='" + par["url"] + "']");
if ((xNode != null) && (xNode.nextSibling != null)) {
xNode.parentNode.insertBefore(xNode, xNode.nextSibling.nextSibling);
feedStore.save("RssStore");
} // if
window.location.replace("?mode=admin");
} else if (par["mode"] == "open") {
var xDoc = feedStore.XMLDocument;
var xNode = xDoc.selectSingleNode("//feedUrl[.='" + par["url"] + "']");
if (xNode != null) {
f = xNode.getAttribute("open");
xNode.setAttribute("open", (f == "on" ? "off": "on"));
feedStore.save("RssStore");
} // if
window.location.replace("?mode=admin");
} else if (par["mode"] == "admin") {
adminblock1.style.display = "block";
adminblock2.style.display = "block";
var list = document.getElementById("rssList");
var xNodes = feedStore.XMLDocument.selectNodes("//feedUrl");
for (n = 0; n < xNodes.length; n++) {
// a + to the feed
a = document.createElement("a");
list.appendChild(a);
a.style.width="12px";
a.href = "?mode=open&url=" + xNodes[n].text;
if (xNodes[n].getAttribute("open") == "on") {
a.innerText = "[-]";
a.title = "Show closed";
} else {
a.innerText = "[+]";
a.title = "Show open";
}
// a link to the feed
a = document.createElement("a");
a.style.width="406px";
list.appendChild(a);
a.innerText = xNodes[n].text;
a.href = xNodes[n].text;
a.title = a.href;
// a link to delete the feed
a = document.createElement("a");
a.style.width="26px";
list.appendChild(a);
a.innerText = "[X]";
a.href = "?mode=reset&url=" + encodeURIComponent(xNodes[n].text);
a.title = "Delete this feed";
// a link to move the feed up
a = document.createElement("a");
a.style.width="12px";
list.appendChild(a);
a.innerText = "[^]";
a.href = "?mode=up&url=" + xNodes[n].text;
a.title = "Move this feed up";
// a link to move the feed down
a = document.createElement("a");
a.style.width="12px";
list.appendChild(a);
a.innerText = "[v]";
a.href = "?mode=down&url=" + xNodes[n].text;
a.title = "Move this feed down";
a = document.createElement("br");
list.appendChild(a);
} // for
} else if ((par["mode"] == "add") && (par["newUrl"] != null)) {
// add a new Url to the RssStore
var url = par["newUrl"];
var flag = ((par["openUrl"] != null) ? par["openUrl"] : "off");
if ((url != "") && ( (url.substr(0, 7) == "http://") || (url.substr(0, 8) == "https://"))) {
var xDoc = feedStore.XMLDocument;
var f = xDoc.createNode(1, "feedUrl", "");
f.text = url;
f.setAttribute("open", flag);
xDoc.documentElement.appendChild(f);
feedStore.save("RssStore");
} // if
window.location.replace("?");
} // if
} // window.onload
/// Load the next RSS Feed from the userData or from the net.
function rssLoadNext() {
var dataStore = document.getElementById("data");
if (RssUrls.length > 0) {
RssUrl = RssUrls[0];
RssName = RssUrl.replace(/\W/g, "");
RssUrls = RssUrls.slice(1);
LinkClass = ((RssFlags[0] == "on") ? "link" : "nolink");
RssFlags = RssFlags.slice(1);
if (! ForceRefresh) {
try {
dataStore.load(RssName);
ListItems(dataStore.XMLDocument);
window.setTimeout("rssLoadNext()", 10);
return;
} catch (ex) {}
} // if
status = "Getting feed " + RssUrl;
rssLoad.src = RssUrl;
} // if
} // rssLoadNext
/// The content of the xml tag has changed
function rssLoad_onreadystatechange() {
var dataStore = document.getElementById("data");
var state = rssLoad.readyState;
if ((state == "loaded") && (rssLoad.XMLDocument.parseError != 0)) {
ListItems(rssLoad.XMLDocument);
window.setTimeout("rssLoadNext()", 10);
} else if ((state == "interactive") && (rssLoad.XMLDocument.parseError != 0)) {
a = document.createElement("div");
document.body.appendChild(a);
a.style.backgroundColor = "#FFFF80";
a.style.marginTop = "4px";
a.innerText = rssLoad.XMLDocument.parseError.url + "-failed to load:\n" + rssLoad.XMLDocument.parseError.reason;
window.setTimeout("rssLoadNext()", 10);
} else if (state == "interactive") {
var xData = ListItems(rssLoad.XMLDocument);
// save data to local store for 30 minutes.
dataStore.XMLDocument.loadXML(xData);
var ex = new Date();
ex.setMinutes(ex.getMinutes() + 30);
dataStore.expires = ex.toUTCString();
dataStore.save(RssName);
window.setTimeout("rssLoadNext()", 10);
} // if
} // rssLoad_onreadystatechange
function ListItems(xmlDoc) {
var xNodes, tmpNode;
var i, title, link, a;
var d;
var xData;
if (xmlDoc.parseError.errorCode != 0) {
a = document.createElement("div");
document.body.appendChild(a);
a.innerText = xmlDoc.parseError.url + " failed to load:\n" + xmlDoc.parseError.reason;
return(null)
} // if
xNodes = xmlDoc.selectSingleNode("//channel/title|/feed/title|//c/t");
title = xNodes.text;
d = document.createElement("div");document.body.appendChild(d);
d.className = "feed";
a = document.createElement("h2");d.appendChild(a);
a.innerText = title;
a.title = "Click here to show or hide the feed items."
xData = "<rss>\n<channel><title>" + xCode(title) + "</title></channel>\n";
xNodes = xmlDoc.selectNodes("//item|//entry|//i");
for (n = 0; n < xNodes.length; n++) {
i = xNodes[n];
tmpNode = i.selectSingleNode("title|t");
title = (tmpNode ? tmpNode.text : null);
link = null;
tmpNode = i.selectSingleNode("link[@rel='alternate']");
if (tmpNode != null) {
link = (tmpNode ? tmpNode.getAttribute("href") : null);
}
if (link == null) {
tmpNode = i.selectSingleNode("link[@href]");
if (tmpNode != null)
link = (tmpNode ? tmpNode.getAttribute("href") : null);
}
if (link == null) {
tmpNode = i.selectSingleNode("link|l");
link = (tmpNode ? tmpNode.text : null);
}
if (link == null) {
tmpNode = i.selectSingleNode("guid[@isPermaLink]");
if (tmpNode != null)
link = (tmpNode ? tmpNode.text : null);
}
if (title != null) {
if ((link != null) && (link != "")) {
// append a link
a = document.createElement("a");
d.appendChild(a);
a.href = link;
a.target = "_main";
} else {
// append a text
a = document.createElement("span");
d.appendChild(a);
link = "";
} // if
a.className = LinkClass;
a.innerText = title;
a.title = title;
xData += "<i><t>" + xCode(title) + "</t><l>" + xCode(link) + "</l></i>\n";
} // if
} // for
xData += "</rss>";
return(xData);
} // ListItems
function xCode(s) {
if (s != null)
s = s.replace(/&/g, "&").replace(/</g, "<").replace(/>/g, ">");
return(s);
} // xCode
</script>
</body>
</html>
|
By viewing downloads associated with this article you agree to the Terms of Service and the article's licence.
If a file you wish to view isn't highlighted, and is a text file (not binary), please
let us know and we'll add colourisation support for it.