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.