Tuesday, March 08, 2011 at 12:00 PM.
system.verbs.builtins.radio.prefs.browser
on browser (adroutline, pagename="Preferences", flAddSubmitButton=true, nextLinkText="Next", prevLinkText="Previous", submitButtonText="Submit", adrToolsPrefs=nil, flShowNavigation=true) {
<<Changes
<<3/8/11; 10:59:23 AM by DW
<<New optional param, flShowNavigation, if false we don't show the navigation part of the display. This is for the prefs of a Tool that all fits on one page. There's no need for navigation, and it's a major distraction away from the functionality of the product.
<<8/8/08; 11:41:52 AM by DW
<<Added optional param adrToolsPrefs, if not nil, points to a table of addresses of prefs outlines that are included with this outline.
<<8/3/08; 10:49:44 AM by DW
<<Added support for a new "title" argument, if present use that to determine the navigation path. Now links into the prefs don't break if they get reorganized. Nice.
<<Example: http://127.0.0.1:5337/opmlEditor/prefs?title=automatic%20updates
<<12/3/07; 2:31:09 PM by DW
<<Add a space before and after the slash in Next/Prev links.
<<10/12/02; 1:44:56 AM by JES
<<Three new parameters to facilitate localization: nextLinkText, prevLinkText and submitButtonText. These parameters specify the text for the next and previous links, and the text for the submit button.
<<9/24/02; 12:51:38 AM by JES
<<Decode ampersand entities in category and topic names. Needed for localization.
<<6/26/02; 11:51:52 PM by JES
<<Before adding the Submit button, check to see if pta^.flAddSubmitButton is defined. If defined and false, don't add the button. This allows macros in a prefs outline to suppress the Submit button, and add their own button(s) if desired.
<<2/5/02; 11:26:46 AM by PBS
<<Conditionalized to work in Frontier.
<<1/9/02; 5:03:56 PM by JES
<<Call radio.prefs.compileIfDirty, instead of compiling the xml and caching home page text, next-prev links, and page titles here.
<<12/10/01; 10:21:06 PM by JES
<<Include the full path in the link to sub-pages, since Opera doesn't know how to link to the same page, adding just the searchArgs. Fixes a bug where none of the Prefs or Help sub-pages could be reached in Opera.
<<11/24/01; 5:18:15 PM by JES
<<Set pta^.headTitle, which is used for the <%title%> in the header of the page (when rendered in the context of an #flUseHomeTitle true directive).
<<See radio.webserver.setTemplate for the code that handles the #flUseHomeTitle directive.
<<New optional parameter, flAddSubmitButton. If true, then the Submit button will be added at the bottom of the page. If false, there's no submit button. Default is true. This is needed in order to remove the Submit button from the bottom of the help pages.
<<11/23/01; 9:17:39 PM by DW
<<Put the address of the prefs outline into pta^.radioResponder.adrPrefsOutline.
<<It's picked up in radio.prefs.seeAlso, to determine which element of the cache it should use.
<<11/23/01; 9:06:49 PM by DW
<<Add a second parameter which is the name of the home page of the sub-site.
<<11/18/01; 5:48:45 PM by DW
<<Not content with my most recent one, now I'm swingin for the fences.
<<This browser runs off a single outline. It's not XML. It's just an outline.
<<Where it requires user input -- a checkbox or a number-entry box, it calls macros.
<<We do a directory-like browser for prefs, breaking it down to sections.
<<The key thing about this approach is that the writer gets to use a writing tool, not an XML editor, and not a bunch of scattered strings. This makes it possible for docs and settings to be mixed in a single presentation. This is how docs were supposed to work.
local (pta = html.getpagetableaddress ());
<<scratchpad.pt = pta^; scratchpad.adroutline = adroutline //debugging
if system.environment.isRadio { //PBS 02/05/02: conditionalized for Frontier
pta^.radioResponder.adrPrefsOutline = adroutline}
else {
pta^.adrPrefsOutline = adroutline};
pta^.title = " ";
local (titleBarColor = "#" + gainsboro, titleBarTextColor = "#" + black);
titleBarColor = "#859EC9"; titleBarTextColor = "#" + white; //matches the coffee-cup background color
titleBarcolor = "#C5CEDE";
titleBarcolor = "#" + whitesmoke;
<<scratchpad.params = pta^
<<1/9/02; 7:08:11 PM by JES: call radio.prefs.compileIfDirty to set home page cache, build next/prev's and get page titles
<<This prevents a crash on Help pages which link to related Prefs pages, when the Prefs have not been viewed since Radio was launched.
<<bundle //original code
<<local (adrcache)
<<bundle //find the cache for this outline
<<local (adr = @system.temp.radio.prefsCache)
<<if not defined (adr^)
<<new (tabletype, adr)
<<adr = @adr^.[string (adroutline)]
<<if not defined (adr^)
<<new (tabletype, adr)
<<adrcache = adr
<<
<<local (flcompile, adrxstruct = @adrcache^.xstruct)
<<bundle //compile the outline if it changed
<<flcompile = true
<<if defined (adrxstruct^)
<<if timemodified (adroutline) <= timemodified (adrxstruct)
<<flcompile = false
<<if flcompile
<<xml.compile (op.outlinetoxml (adroutline), adrxstruct)
<<
<<local (adropml = xml.getAddress (adrxstruct, "opml"))
<<local (adrbody = xml.getAddress (adropml, "body"))
<<
<<local (adrhomepagehtml = @adrcache^.homePageHtml, adrnextprevlist = @adrcache^.nextPrevList, adrpagetitles = @adrcache^.pagetitles)
<<if flcompile //cache the text for the home page, create next-prevs list and cache it, and the page-titles table
<<adrnextprevlist^ = {}
<<new (tabletype, adrpagetitles)
<<local (htmltext = "", indentlevel = 0)
<<on add (s)
<<htmltext = htmltext + string.filledstring ("\t", indentlevel) + s + "\r\n"
<<local (adrcat, catnum = 1)
<<for adrcat in adrbody
<<if not (nameof (adrcat^) beginswith "/")
<<local (catname = xml.getattributevalue (adrcat, "text"), adrtopic, topicnum = 1)
<<add ("<h4>" + catname + "</h4>")
<<add ("<ul>"); indentlevel++
<<for adrtopic in adrcat
<<if not (nameof (adrtopic^) beginswith "/")
<<local (dottedid = catnum + "." + topicnum)
<<adrnextprevlist^ = adrnextprevlist^ + {dottedid}
<<local (url = pta^.URI + "?page=" + dottedid)
<<local (pagetitle = xml.getattributevalue (adrtopic, "text"))
<<adrpagetitles^.[pagetitle] = dottedid
<<add ("<li><a href=\"" + url + "\">" + pagetitle + "</a></li>")
<<topicnum++
<<add ("</ul>"); indentlevel--
<<catnum++
<<adrhomepagehtml^ = htmltext
local (adrcache = radio.prefs.compileIfDirty (adroutline, adrToolsPrefs)); //8/8/08 by DW -- added adrToolsPrefs param
local (adrxstruct = @adrcache^.xstruct);
local (adropml = xml.getAddress (adrxstruct, "opml"));
local (adrbody = xml.getAddress (adropml, "body"));
local (adrhomepagehtml = @adrcache^.homePageHtml, adrnextprevlist = @adrcache^.nextPrevList);
local (navigationpath = "");
if system.environment.isRadio { //PBS 02/05/02: conditionalized for Frontier
if defined (pta^.radioresponder.getargs.page) {
navigationpath = pta^.radioresponder.getargs.page}}
else {
if defined (pta^.searchArgTable.page) {
navigationpath = pta^.searchArgTable.page}};
bundle { //8/3/08 by DW -- look for "title" arg
local (title = "");
if system.environment.isRadio {
if defined (pta^.radioresponder.getargs.title) {
title = string.urldecode (pta^.radioresponder.getargs.title)}}
else {
if defined (pta^.searchArgTable.title) {
title = string.urldecode (pta^.searchArgTable.title)}};
if title != "" { //got one!
if defined (adrcache^.pagetitles.[title]) {
navigationpath = adrcache^.pagetitles.[title]}}};
local (adrframe, fltoplevel);
bundle { //set adrframe, fltoplevel
local (ctfields = string.countfields (navigationpath, "."));
if ctfields >= 2 {
local (i, ix, nomad = adrbody);
for i = 1 to ctfields {
ix = number (string.nthfield (navigationpath, ".", i));
if defined (nomad^.["/atts"]) { //skip over /atts
ix++};
nomad = @nomad^ [ix]};
adrframe = nomad;
fltoplevel = false}
else {
adrframe = adrbody;
fltoplevel = true}};
local (htmltext = "", indentlevel = 0);
on add (s) {
htmltext = htmltext + string.filledstring ("\t", indentlevel) + s + "\r\n"};
bundle { //display the frame
if fltoplevel { //adrframe points to the first category
add (adrhomepagehtml^);
pta^.headTitle = pagename}
<<bundle //discarded method -- displays the topics in an array
<<Too bad the topic names are too long for this to look reasonable.
<<local (adrcat, catnames = {}, tableofcontents)
<<new (tabletype, @tableofcontents)
<<
<<for adrcat in adrframe //loop over the top-level
<<if not (nameof (adrcat^) beginswith "/")
<<local (catname = xml.getattributevalue (adrcat, "text"))
<<catnames = catnames + {catname}
<<
<<local (adrtopic, topics)
<<new (tabletype, @topics)
<<for adrtopic in adrcat
<<if not (nameof (adrtopic^) beginswith "/")
<<topics.[string.padwithzeros (sizeof (topics), 3)] = xml.getattributevalue (adrtopic, "text")
<<tableofcontents.[catname] = topics
<<scratchpad.tableofcontents = tableofcontents
<<
<<add ("<table border=\"0\" cellspacing=\"0\" cellpadding=\"4\">"); indentlevel++
<<bundle //add top row of the table, the category names
<<local (catname, width)
<<width = 33
<<add ("<tr>"); indentlevel++
<<for catname in catnames
<<add ("<td width=\"" + width + "%\"><b>" + catname + "</b></td>")
<<add ("</tr>"); indentlevel--
<<bundle //add rows of topics
<<local (rownum = 1, catname)
<<loop //do a row
<<local (rowtext = "<tr>", flallblank = true)
<<for catname in catnames
<<msg (sizeof (tableofcontents.[catname]) + " " + rownum); clock.waitseconds (1)
<<if sizeof (tableofcontents.[catname]) >= rownum
<<s = tableofcontents.[catname] [rownum]
<<flallblank = false
<<else
<<s = " "
<<rowtext = rowtext + "<td>" + s + "</td>"
<<rowtext = rowtext + "</tr>"
<<if flallblank
<<break
<<add (rowtext)
<<rownum++
<<add ("</table>"); indentlevel--
else {
local (category);
bundle { //set category
local (categoryname = xml.getattributevalue (parentof (adrframe^), "text"));
categoryname = string.replaceAll (categoryname, "&", "&");
category = categoryname};
local (nextprev);
bundle { //set nextprev
local (ixmyself, i);
for i = 1 to sizeof (adrnextprevlist^) {
if adrnextprevlist^ [i] == navigationpath {
ixmyself = i;
break}};
local (next, prev);
if ixmyself == sizeof (adrnextprevlist^) {
next = nextLinkText}
else {
next = "<a href=\"?page=" + adrnextprevlist^ [ixmyself + 1] + "\">" + nextLinkText + "</a>"};
if ixmyself == 1 {
prev = prevLinkText}
else {
prev = "<a href=\"?page=" + adrnextprevlist^ [ixmyself - 1] + "\">" + prevLinkText + "</a>"};
nextprev = prev + " / " + next};
on blankLine () {
return ("<tr height=\"15\"><td colspan=\"2\"> </td></tr>")};
on titleBar (s) {
return ("<tr bgcolor=\"" + titleBarColor + "\"><td colspan=\"2\"><b><font color=\"" + titlebartextcolor + "\">" + s + "</font></b></td></tr>")};
if flShowNavigation { //3/8/11 by DW
add ("<table border=\"0\" width=\"100%\" cellpadding=\"0\" cellspacing=\"0\"><tr><td><a href=\"?page=1\">" + pagename + "</a> > " + category + "</td><td align=\"right\">" + nextprev + "</td></tr></table>")};
add ("<h3>" + string.replaceAll (adrframe^.["/atts"].text, "&", "&") + "</h3>");
add ("<form method=\"POST\">"); indentlevel++;
pta^.headTitle = category + ": " + adrframe^.["/atts"].text;
add ("<table border=\"0\" cellspacing=\"0\" cellpadding=\"4\" width=\"100%\">"); indentlevel++;
bundle { //add the sub-elements
local (adr);
for adr in adrframe {
if not (nameof (adr^) beginswith "/") {
local (s = xml.entitydecode (adr^.["/atts"].text, true));
if s beginswith "<%" {
add (html.processmacros (s, adrPageTable:pta))}
else {
add ("<tr><td colspan=\"2\">" + html.processmacros (s, adrPageTable:pta) + "</td></tr>")}}}};
if defined (pta^.flAddSubmitButton) { //JES 6/26/02: allow macros to suppress the Submit button
flAddSubmitButton = pta^.flAddSubmitButton};
if flAddSubmitButton { //add the Submit button
add (blankline () + "<tr><td colspan=\"2\"><input type=\"submit\" value=\"" + submitButtonText + "\"></td></tr>")};
add ("</table>"); indentlevel--;
add ("</form>"); indentlevel--}};
return (htmltext)}
<<bundle //test code
<<html.setpagetableaddress (@scratchpad.pt)
<<radio.prefs.browser (@opmlEditor.data.outlines.prefs, adrToolsPrefs:@user.opmlEditor.prefs.toolsWithPrefs)
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.