Monday, April 04, 2011 at 1:06 AM.
river2Suite.viewSubs
on viewSubs () {
<<Changes
<<4/1/11; 8:08:48 PM by DW
<<Changed "reading lists" to "OPML subscription lists" to make terminology consistent. Display the feeds each subscription list contains.
<<3/24/11; 12:41:32 PM by DW
<<Pass adruser to subscribeFeed so it can properly handle list subscriptions.
<<3/23/11; 8:14:47 AM by DW
<<Call the afterSubscribe callbacks. They're called whenever the user's subscription list changed, so we call them after a subscription is deleted as well. The idea is that the guy we call will clear cached stuff.
<<4/24/10; 4:36:32 PM by DW
<<Pass the user param to the bookmarklet page.
<<4/24/10; 2:08:46 PM by DW
<<Add a "user" param to the viewOpml link, if we're viewing the feeds of a user.
<<12/27/09; 10:13:55 AM by DW
<<Set adrdata^.stats.cloudPipeClient.flFeedsDirty true on unsub.
<<12/25/09; 6:30:53 PM by DW
<<Add link at the bottom of the page to view the OPML for the feed list.
<<12/21/09; 11:51:07 AM by DW
<<Announcement of the one-click-subscribe bookmarklet.
<<12/2/09; 11:06:12 AM by DW
<<Only show the feeds subscribed to by the user, if pta^.adruser is non-nil.
<<Handle multi-user subscriptions.
<<Handle multi-user unsubs.
<<9/17/09; 7:14:00 AM by DW
<<If there's a link available for the reading list, hot-up the name with the link.
<<9/16/09; 10:44:08 AM by DW
<<Get the name of the feed from subscribeFeed instead of trying to figure it out after the fact.
<<9/16/09; 10:05:34 AM by DW
<<Include a title line for reading lists.
<<9/15/09; 9:00:42 PM by DW
<<If there's a "url" parameter pre-populate the "subscribe" box with it.
<<9/10/09; 12:42:34 PM by DW
<<The feeds are now sorted in alphabetic order of the feed name, not the feed URL.
<<9/10/09; 11:59:31 AM by DW
<<There is now confirmation that a subscribe was successful.
<<9/5/09; 5:57:43 PM by DW
<<Include a link to view the feed contents after the feed name.
<<9/3/09; 4:15:04 AM by DW
<<Include reading lists on the Feeds page.
<<6/20/09; 8:17:20 PM by DW
<<Created.
local (pta = html.getpagetableaddress (), adrdata = river2suite.init (), htmltext = "", indentlevel = 0);
local (imgNew = string (river2Suite.data.html.new));
local (errorstring = "", statusstring = "", url = "http://", ix=1, class, adruser = pta^.adruser);
scratchpad.subsparams = pta^;
on spaceout (s) {
local (s2 = "", i);
for i = 1 to sizeof (s) {
s2 = s2 + s [i] + " "};
return (string.replaceall (string.upper (string.trimwhitespace (s2)), " ", " "))};
if pta^.method == "POST" {
local (args, adr, i, flchanged = false);
new (tabletype, @args);
webserver.parseargs (pta^.requestbody, @args);
<<scratchpad.args = args; edit (@scratchpad.args)
if defined (args.subscribeButton) {
try {
if adruser == nil {
local (namefeed);
river2Suite.subscribeFeed (args.url, @namefeed);
statusstring = "Successfully subscribed to \"" + namefeed + ".\"";
flchanged = true}
else {
local (adrfeed = @adrdata^.feeds.[args.url]);
if defined (adrfeed^) { //someone else is subscribed
local (adruserfeed = @adruser^.feeds.[args.url]);
if defined (adruserfeed^) {
scripterror ("Good show old chap. You're already subscribed to that feed.")};
new (tabletype, adruserfeed);
statusstring = "Successfully subscribed to \"" + adrfeed^.feedinfo.title + ".\"";
flchanged = true}
else {
local (namefeed);
river2Suite.subscribeFeed (args.url, @namefeed, adruser); //3/24/11 by DW
new (tabletype, @adruser^.feeds.[args.url]);
statusstring = "Successfully subscribed to \"" + namefeed + ".\"";
flchanged = true}}}
else {
url = args.url;
errorstring = tryerror}};
if defined (args.deleteButton) {
try {
for i = sizeof (args) downto 1 {
local (adrarg = @args [i], name = nameof (adrarg^));
if name beginswith "checkbox" {
local (ix = number (string.delete (name, 1, sizeof ("checkbox"))));
local (adrfeed = @adrdata^.feeds [ix]);
if adruser != nil {
try {delete (@adruser^.feeds.[nameof (adrfeed^)])}}
else {
<<dialog.alert (nameof (adrfeed^))
adrdata^.trash.[nameof (adrfeed^)] = adrfeed^;
delete (adrfeed)}}
else {
if name beginswith "listcheckbox" {
local (ix = number (string.delete (name, 1, sizeof ("listcheckbox"))));
local (adrlist = @adrdata^.lists [ix]);
if adruser != nil {
try {delete (@adruser^.feeds.[nameof (adrlist^)])}}
else {
<<dialog.alert (nameof (adrlist^))
adrdata^.trash.[nameof (adrlist^)] = adrlist^;
delete (adrlist)}}};
adrdata^.stats.cloudPipeClient.flFeedsDirty = true; //12/27/09 by DW
flchanged = true}}
else {
errorstring = tryerror}};
bundle { //call callbacks if changed, 3/23/11 by DW
if flchanged {
local (adrscript);
for adrscript in @adrdata^.callbacks.afterSubscribe {
while typeof (adrscript^) == addresstype {
adrscript = adrscript^};
try {adrscript^ (adruser)}}}}}
else {
local (args); //if there's a "url" parameter put it in the "subscribe" box, 9/15/09 by DW
new (tabletype, @args);
webserver.parseargs (pta^.searchargs, @args);
if defined (args.url) {
url = args.url}};
local (imgXml = river2Suite.loadImage ("linkToFeed.gif", pta), now = clock.now (), adrfeed, adrsorted, adrlist);
on getWhenString (when) {
if date.sameday (now, when) {
when = "Today"}
else {
if date.sameday (date.yesterday (now), when) {
when = "Yesterday"}
else {
if when == date (0) {
when = " "}
else {
when = date.shortstring (when)}}}};
on add (s) {
htmltext = htmltext + string.filledstring ("\t", indentlevel) + s + "\r"};
add ("<form method=\"POST\">"); indentlevel++;
bundle { //add the url-entry box
local (t, s = string (river2Suite.data.urlEntryBox));
new (tabletype, @t);
t.error = errorstring;
t.status = statusstring; //9/10/09 by DW
t.url = url;
s = string.multiplereplaceall (s, @t, false, "<%", "%>");
add (s)};
add ("<table id=\"rivertable\" cellspacing=\"0\" cellpadding=\"0\" border=\"0\" summary=\"" + adrdata^.prefs.tableSummary + "\">"); indentlevel++;
bundle { //add announcement of bookmarklet, 12/21/09 by DW
local (link = river2Suite.addUserLink ("bookmarklet")); //4/24/10 by DW
add ("<caption>" + imgNew + " One-click subscribe with the River2 <a href=\"" + link + "\">bookmarklet</a>. Get it now!</caption>")};
on addfeed (adrfeed, flcheckbox=true) {
local (feedurl = nameof (adrfeed^));
<<if adruser != nil //don't list the feed if the user isn't subscribed to it
<<if not defined (adruser^.feeds.[feedurl])
<<continue
river2Suite.initFeed (feedurl);
add ("<tr>"); indentlevel++;
bundle { //set class
<<if (ix % 2) == 0
<<class = "subscription"
<<else
<<class = "subscriptionAlt"
class = "subscription"};
bundle { //add checkbox
if flcheckbox {
add ("<td class=\"" + class + "\" valign=\"top\"><center><input type=\"checkbox\" name=\"checkbox" + string.padwithzeros (ixfeed, 6) + "\" value=xxx ></center></td>")}
else {
add ("<td class=\"" + class + "\" valign=\"top\"> </td>")}};
add ("<td class=\"" + class + "\"><a href=\"" + adrfeed^.feedinfo.link + "\">" + adrfeed^.feedinfo.title + "</a> " + river2Suite.linkToFeedContents (feedurl) + "</td>");
add ("<td class=\"" + class + "\" align=\"right\">" + getWhenString (adrfeed^.stats.whenSubscribed) + "</td>");
<<add ("<td class=\"" + class + "\" align=\"right\">" + getWhenString (adrfeed^.stats.whenLastNewItem) + "</td>")
bundle { //add ctReads
add ("<td class=\"" + class + "\" align=\"right\">" + adrfeed^.stats.ctreads + "</td>")};
bundle { //add ctItems
add ("<td class=\"" + class + "\" align=\"right\">" + adrfeed^.stats.ctitems + "</td>")};
add ("<td class=\"" + class + "\"><center><a href=\"" + feedurl + "\">" + imgXml + "</a></center></td>");
add ("</tr>"); indentlevel--};
local (sortedtable);
bundle { //fill sortedtable
local (adrfeed);
new (tabletype, @sortedtable);
for adrfeed in @adrdata^.feeds {
sortedtable.[string.padwithzeros (ix++, 6)] = string.lower (adrfeed^.feedinfo.title)};
local (oldtarget = target.set (@sortedtable));
table.sortby ("Value");
target.set (oldtarget)};
<<scratchpad.sortedtable = sortedtable
for adrsorted in @sortedtable { //adrfeed in @adrdata^.feeds
local (ixfeed = number (nameof (adrsorted^)));
local (adrfeed = @adrdata^.feeds [ixfeed]);
if adruser != nil {
if defined (adruser^.feeds.[nameof (adrfeed^)]) {
addfeed (adrfeed)}}
else {
addfeed (adrfeed)}};
<<ix++
bundle { //add reading lists
local (flshowlists);
if adruser != nil {
local (flusersublist = false);
for adrlist in @adrdata^.lists {
if defined (adruser^.feeds.[nameof (adrlist^)]) { //user is subscribed to at least one list
flusersublist = true;
break}};
flshowlists = flusersublist}
else {
flshowlists = sizeof (adrdata^.lists) > 0};
ix = 1; //start the counter over
if flshowlists {
add ("<tr><td colspan=\"6\"><br><center><b>" + spaceout ("OPML subscription lists") + "</b></center><br></td></tr>");
for adrlist in @adrdata^.lists {
if adruser != nil {
if not defined (adruser^.feeds.[nameof (adrlist^)]) { //user is not subscribed to this list
continue}};
river2Suite.initList (nameof (adrlist^));
add ("<tr>"); indentlevel++;
bundle { //set class
class = "subscription"};
bundle { //add checkbox
add ("<td class=\"" + class + "\" valign=\"top\"><center><input type=\"checkbox\" name=\"listcheckbox" + string.padwithzeros (ix, 6) + "\" value=xxx ></center></td>")};
bundle { //add title
local (title = adrlist^.listinfo.title);
if sizeof (adrlist^.listinfo.link) > 0 {
title = "<a href=\"" + adrlist^.listinfo.link + "\">" + title + "</a>"};
add ("<td class=\"" + class + "\"><b>" + title + "</b></a></td>")};
add ("<td class=\"" + class + "\" align=\"right\">" + getWhenString (adrlist^.stats.whenSubscribed) + "</td>");
bundle { //add ctReads
add ("<td class=\"" + class + "\" align=\"right\">" + adrlist^.stats.ctreads + "</td>")};
bundle { //add ctItems
add ("<td class=\"" + class + "\" align=\"right\"> </td>")};
add ("<td class=\"" + class + "\"><center><a href=\"" + nameof (adrlist^) + "\">" + imgXml + "</a></center></td>");
add ("</tr>"); indentlevel--;
ix++;
bundle { //add the feeds that are contained within the list
local (adrlistfeed);
for adrlistfeed in @adrlist^.feeds {
addfeed (@adrdata^.feeds.[nameof (adrlistfeed^)], flcheckbox:false)}}}}};
add ("</table>"); indentlevel--;
add ("<br /><br /><input id=\"submit\" type=\"submit\" name=\"deleteButton\" class=\"submitButton\" value=\"Delete\" />");
add ("</form>"); indentlevel--;
bundle { //add view OPML link
local (link = "viewOpml");
if pta^.adruser != nil { //4/24/10 by DW
link = link + "?user=" + nameof (pta^.adruser^)};
add ("<br /><p><a href=\"" + link + "\">View</a> the OPML subscription list. " + imgNew + "</p>")};
return (htmltext)};
bundle { //test code
html.setpagetableaddress (@scratchpad.subsparams);
viewSubs ()}
This listing is for code that runs in the OPML Editor environment. I created these listings because I wanted the search engines to index it, so that when I want to look up something in my codebase I don't have to use the much slower search functionality in my object database. Dave Winer.