GrazrScript Tutorial

Creating outline nodes

Outline Object

We have now seen outline.writeText() and outline.writeFeed() used to create OPML nodes. There are additional commands we can use for the other node types, but first let's take a closer look at the concepts and terminology involved with these commands. Outline in this context is called an object, which is a combination of data and programming commands. The commands associated with objects, such as outline.writeText(), are called methods. You can think of the outline object as a copy of the OPML that will be produced from a GrazrScript application. As the application runs, OPML nodes that are in the template are added to the outline object. When the application is done, the contents of the outline object are placed in the results. In effect, the outline object is a buffer, which accumulates the results before they are presented in the Grazr widget. Outline methods, such as outline.writeText(), are used to add additional nodes to the buffer.

Outline Methods

There are outline methods for all of the OPML node types. If you are unfamiliar with the details of OPML syntax, you can read our primer. Here is a template for each method, and a schematic example of what it produces:

MethodOutput
outline.openFolder( "text" )<outline text="text">
outline.closeFolder()</outline>
outline.writeFeed( "text", "URL" )<outline type="rss" text="text" xmlUrl="URL" />
outline.writeInclude( "text", "URL" )<outline type="include" text="text" url="URL" />
outline.writeLink( "text", URL" )<outline type="link" text="text" htmlUrl="URL" />
outline.writeText( "text" )<outline text="text" />

Substitution Within Outline Arguments

All of the outline methods allow you to use substitution variables within arguments. This means that variables from forms and script blocks can be placed directly in the text and URL arguments using the standard %variable% format. This is a feature of the outline methods, and does not work within any other JavaScript methods in a script block. For example, in the Baseball4.xml application below, the value of the team variable is substituted in the outline.writeFeed() method:

outline.writeFeed( "%team% news", "http://news.google.com?q=baseball+%team%&output=rss");

Writing Raw OPML

You can see that these methods hide the syntactic complexity of OPML, but sometimes you may want to have complete control over the OPML that is created. The outline.write() method is used in this situation. The argument for outline.write() is plain OPML. Whatever appears in the method will be output to the result. It is up to you to make sure this is valid OPML. For example, creating a text node would be done with: outline.write('<outline text="text" />').

One important detail is the use of quotes. The argument to outline.write() must be in quotes, and within that argument are attribute values, such as text, that must also be in quotes. The solution is to use one type of quotes on the outside, and another on the inside. Either order is allowed. Here we have used a single quote around the argument and double quotes around the values.

Here is a new version of the baseball program that demonstrates both ways of generating outline nodes. One feature in this example that we haven't seen before is the use of comments. A comment line is added to a script block with a leading double slash. This means that the text on that line can be read by humans, but will be ignored by GrazrScript.

http://docs.grazr.com/script/tutorial/baseball4.xml
<?xml version="1.0" encoding="UTF-8"?>
<opml version="2.0" xmlns:grazr="http://docs.grazr.com/script/spec/1.0">
<head>
<title>Baseball Search #4</title>
</head>
<body>
<grazr:form name="teamform">
<strong>Baseball Search</strong>
<input type="submit" value="Ok" /><br />
Favorite team: <select name="team">
<option value="Red Sox">Red Sox</option>
<option value="Yankees">Yankees</option>
</select>
Choose another team: <input type="text" name="other" />
</grazr:form>

<grazr:formtemplate name="teamform">
<grazr:script><!--
if (other != "") {
var team=other;
}
if (team.toLowerCase()=="red sox") {
//Create a folder of Red Sox info
outline.openFolder("Red Sox information");
outline.writeFeed( "Red Sox news", "http://news.google.com?q=baseball+%team%&amp;output=rss");
outline.writeLink("Red Sox home page", "http://boston.redsox.mlb.com/index.jsp?c_id=bos");
outline.writeInclude("Red Sox reading list", "http://www.toptensources.com/topten/Boston-Red-Sox/?display=.opml");
outline.closeFolder();
} else if (team.toLowerCase()=="yankees") {
//Create a folder for the Yankees
outline.write('<outline text="Yankees information">');
outline.write('<outline text="Yankees news" type="rss" xmlUrl="http://news.google.com?q=baseball+Yankees&amp;output=rss" />');
outline.write('<outline text="Yankees home page" type="link" htmlUrl="http://newyork.yankees.mlb.com/index.jsp?c_id=nyy" />');
outline.write('<outline text="Yankees reading list" type="include" url="http://www.toptensources.com/topten/New-York-Yankees/?display=.opml" />');
outline.write('</outline>');
} else {
//All other teams get a single news feed
outline.writeFeed( "%team% news", "http://news.google.com?q=baseball+%team%&amp;output=rss");
}
--></grazr:script>
</grazr:formtemplate>

<grazr:formresult text="Search results:" name="teamform" />
</body>
</opml>


Multiple Line Output

Creating OPML with outline.write() can be tedious if you have to create one node at a time, as in the program above. A shortcut when you need to create a large block of OPML is to use a multiple line argument. You can start the method on one line, and then have as many lines of OPML as you want. This type of multiple line argument is only available within the outline.write() method. Using it with any other outline method will cause an error.

outline.write('<outline text="Yankees information">
<outline text="Yankees news" type="rss"
xmlUrl="http://news.google.com?q=baseball+Yankees&output=rss" />
<outline text="Yankees home page" type="link"
htmlUrl="http://newyork.yankees.mlb.com/index.jsp?c_id=nyy" />
<outline text="Yankees reading list" type="include"
url="http://www.toptensources.com/topten/New-York-Yankees/?display=.opml" />
</outline>');

http://docs.grazr.com/script/tutorial/baseball5.xml
<?xml version="1.0" encoding="UTF-8"?>
<opml version="2.0" xmlns:grazr="http://docs.grazr.com/script/spec/1.0">
<head>
<title>Baseball Search #5</title>
</head>
<body>
<grazr:form name="teamform">
<strong>Baseball Search</strong>
<input type="submit" value="Ok" /><br />
Favorite team: <select name="team">
<option value="Red Sox">Red Sox</option>
<option value="Yankees">Yankees</option>
</select>
Choose another team: <input type="text" name="other" />
</grazr:form>

<grazr:formtemplate name="teamform">
<grazr:script><!--
if (other != "") {
var team=other;
}
if (team.toLowerCase()=="red sox") {
//Create a folder of Red Sox info
outline.openFolder("Red Sox information");
outline.writeFeed( "Red Sox news", "http://news.google.com?q=baseball+%team%&amp;output=rss");
outline.writeLink("Red Sox home page", "http://boston.redsox.mlb.com/index.jsp?c_id=bos");
outline.writeInclude("Red Sox reading list", "http://www.toptensources.com/topten/Boston-Red-Sox/?display=.opml");
outline.closeFolder();
} else if (team.toLowerCase()=="yankees") {
//Create a folder for the Yankees
outline.write('<outline text="Yankees information">
<outline text="Yankees news" type="rss"
xmlUrl="http://news.google.com?q=baseball+Yankees&amp;output=rss" />
<outline text="Yankees home page" type="link"
htmlUrl="http://newyork.yankees.mlb.com/index.jsp?c_id=nyy" />
<outline text="Yankees reading list" type="include"
url="http://www.toptensources.com/topten/New-York-Yankees/?display=.opml" />
</outline>');
} else {
//All other teams get a single news feed
outline.writeFeed( "%team% news", "http://news.google.com?q=baseball+%team%&amp;output=rss");
}
--></grazr:script>
</grazr:formtemplate>

<grazr:formresult text="Search results:" name="teamform" />
</body>
</opml>


Catching script errorsHow much of JavaScript is available?