Note: this section is intended for folks comfortable editing HTML files.
Last updated 4/19/04.
IRML is HTML with IRScript statements contained within SGML processing tags (<? ?>). Anything outside the tags is considered HTML and passed along to the resulting HTML file. Anything inside the SGML tags is parsed and interpreted as IRScript statements. The echo statement causes a string expression to be evaluated inserted into the HTML at the point where the echo statement appeared. This is more or less the same as server-side scripting systems such as PHP, JSP and ASP. Note, however, that IRScript doesnt run on the web server - it runs when you build the web site in Image Rodeo.
You can include anything thats legal in a HTML file, and even stuff thats not legal, with the exception of anything that also uses the <? ?> tags (such as PHP). Image Rodeo doesnt interpret the HTML at all - except to look for the SGML processing tags.
Unlike JavaScript, IRScript statements consist of all the text inside the SGML processing tags, no matter where they appear in the HTML. This means that IRScript can appear (and often does appear) inside quoted HTML strings. Consider this IRML fragment:
<img src="thumb/<?echo uid;?>.jpg" width="<?echo tw;?>" height="<?echo th;?>">
The echo statement is used to write a string into the HTML stream at the point where it was found. When the web site is built, and the IRScript statements are executed, the fragment above could generate the following HTML:
<img src="thumb/1.jpg" width="100" height="75">
Of course, the exact HTML generated depends on the values of the uid, tw and th variables.
IRScript syntax is loosely based on JavaScript syntax, which itself is loosely based on "C" syntax. This is strictly to avoid defining a new syntax - youll find that many key features of JavaScript (such as functions) are missing. Heres a quick sample:
<? /* This is a comment. Note that // is not supported! * / ?>
<? echo "hello, world"; ?>
Normally it makes sense to look at an IRML file as HTML with embedded IRScript tags, but its possible to turn that inside-out: you can consider an IRML file as IRScript with embedded HTML. In other words, instead of <?IRScript?> you have ?>HTML<?. (Of course, youd have to start the ball rolling with a <? tag at the beginning of the file.)
Consider this fragment:
<?for (i = 0; i < pages; i = i + 1) {?><a href="<?echo pages[i].uid;?>.html"><?echo pages[i].title;?></a> <?}?>
This rather complicated fragment can be indented to highlight the nested characteristics of both IRScript and HTML:
<?for (i = 0; i < pages; i = i + 1) {?>
<a href="<?echo pages[i].uid;?>.html">
<?echo pages[i].title;?>
</a>
<?}?>
This is fairly readable, but it has the side effect of generating more white space - which the browser will remove, but which wastes a little space and bandwidth. If we wanted to avoid the white space, but maintain the indentation, we could turn the fragment inside-out. We also add comments:
<? for (i = 0; i < pages; i = i + 1) {
?><a href="<? /* Start the <a> tag. */
echo pages[i].uid; /* Write the unique id. */
?>.html"><? /* End the <a> tag. */
echo pages[i].title; /* Write the title. */
?></a> <? /* Now the </a> tag. */
}
?>
Believe it or not, this version generates HTML identical to the first version.
As a further refinement we could substitute echo statements for the inside out >?HTML<? tags. Heres the same fragment one more time:
<? for (i = 0; i < pages; i = i + 1) {
echo '<a href="'; /* Start the <a> tag. */
echo pages[i].uid; /* Write the unique id. */
echo '.html">'; /* End the <a> tag. */
echo pages[i].title; /* Write the title. */
echo '</a> '; /* Now the </a> tag. */
}
?>
Which style you use depends on your personal preferences.
IRScript consists of a sequence of statements separated by semi-colors. You can combine statements in blocks using braces ({}). The braces dont affect variable scoping - its always global.
In this and subsequent sections the <? ?> tags are omitted for clarity.
Like many languages, IRScript assignment is a hybrid between a statement and an expression. In the simple form it looks like this:
foo = 1;
bar = foo + 1;
However, it also evaluates to an expression, so you can use forms such as:
foo = bar = 2;
The echo statement is the workhorse of IRScript. It writes strings into the HTML stream being generated. Two examples:
echo "Hello, world."; /* Writes a string into the HTML stream. */
echo foo; /* Writes the contents of a variable into the HTML stream. */
If-else statements work just like "C" and JavaScript. The expression inside the ( ) is coerced to an integer if necessary. 0 means false; anything other integer means true. See type conversion.
if (foo == 1)
echo "Foo is 1"; /* Note that whitespace is not signficant. */
if (foo == 1) {
echo "Foo is 1";
} else if (foo == 2) {
echo "Foo is 2";
} else {
echo "I'm not sure what foo is.";
}
For loops are similar to "C" or JavaScript. Theres an initializer expression, a test expression, and an increment expression. The test expression is coerced to an integer if necessary. 0 means false (stop looping), any other integer value means true (keep looping). Note that an empty expression evaluates to 0 (false) - unlike "C". Also note that theres no break statement.
for (i = 0; i < count; i = i + 1) {
echo "Iteration #";
echo i;
echo "<p>";
}
IRScript supports two simple types with fairly typical semantics: integer and string. The real power, though, lies in the access to Image Rodeos internal objects, which can be considered types. These object types are restricted, in the sense that you cant create or modify objects from within an IRML file. We consider each type in turn.
Theres no boolean type, but IRScript applies boolean semantics to integers. Boolean expressions (if statements, etc.) consider 0 to be false, and any other integer to be true. Boolean expressions always return integers: 0 for false and 1 for true.
Integer literals have the usual forms: 0, -1, 122334, etc.
You can use the standard math operators on integers. See Operators.
Strings consist of sequences of Latin-1 characters (ISO 8859-1).
String literals may be surrounded by foot (') or inch (") marks, depending on the situation. (OK, I realize that everybody else calls them single and double quotes, but years of work with typographers have addled my brain.) Note that string literals can contain anything - including SGML processing tags (<? ?>)!
There are only two operators that work with strings: == (equality) and != (inequality). See Operators.
Arrays are ordered collections of objects. IRScript does not allow you to create new arrays, so the only way to get an array is to reference an object property that returns an array. Also, you cant modify an array, so youll never see the subscript operator used on the left-hand-side of the assignment (=) operator.
Once you have an array you can get at any element of the array using the subscript ([]) operator. The expression inside the brackets is converted to an integer if required. Arrays start at 0, not 1.
echo myArray[0]; /* Note that arrays start with 0 - like "C" and JavaScript. */
There are no array literals.
An object is a bundle of properties. IRScript does not allow you to define new object types, but you do have access to four built-in Image Rodeo internal object types. Each object type has various properties that you can access using the dot (.) operator. Note that you can combine dot operators to drill down an object hierarchy, or even combine dot and subscript operators to create complex expressions. A few examples:
firstPage = pages[0];
titleOfFirstPage = firstPage.title;
titleOfSecondPage = pages[1].title;
titleOfTheTopLevelPage = document.indexPage.title;
The four built-in object types are as follows:
In addition, theres one abstract object type: the page. A page may be either an index page or a photo page. (O-O Programmers will note that photo page and index page subclass from page.)
There are no object literals.
A property that returns an object may return nothing at all - its as if you referenced an unassigned variable. (See Variables.) You can test for this by taking advantage of a quirk in type conversion: when converting to an integer, an object that exists will convert to 1 (true), while an object that doesnt exist will convert to 0 (false). Consider the following fragment:
if (previous) { echo '<a href="'; echo previous.uid; echo '.html">Previous</a>'; }
In this case the variable previous may or may not contain an object. If it does, it converts to 1, and the if expression evaluates to true, and the block is executed. If it doesnt, it converts to 0, and the if expression evaluates to false.
AppleScript tip: the IRScript object types are identical to the AppleScript object types.
All of the types may be converted to an integer or a string, although the conversion isnt always meaningful. Conversion is based on context; theres no explicit conversion operator. String conversions are sometimes used for debugging scripts: try <?echo pages;?>.
The following table summarzes the possible conversions:
| From: | Integer | String | Array | Other objects |
| To: Integer | - | Interpreted as a number, then converted to an integer if required. | The length of the array. | 1 if theres an object, 0 if there isnt. |
| To: String | A string, perhaps with a leading minus sign. | - | A long-ish description of the array contents. | A short description of the object, typically with the title. |
The page object an abstract type, so youll never actually see a page object. Instead, youll see a photo page object or index page object. In standard object-oriented fashion we use the term page object to mean a photo page object or index page object.
If you have a page object and you want to find out what sort of object it is (photo or index), test the isIndex property like so:
if (page.isindex) {
echo "This is an index page.";
} else {
echo "This is a photo page.";
}
As a convenience, the current page object is referred to as this.
All page objects have the following properties:
| Page Properties | AppleScript | IRML | Type |
| Unique identifier - unique within a document. This is used to generate file names, e.g., 1.jpg or 2.html. The top-level index page always has a uid of 0. | uid | uid | Integer |
| Is this an index page? 1 for yes, 0 for no. | is index | isIndex | Integer |
| The page title. Always starts out as the file name. | title | title | String |
| The page caption. May be nil. | caption | caption | String |
| The parent page for this page, i.e., the index page that contains a reference to this page. Nil if this is the top-level index page. | n/a | parent | Index Page |
| The array of acestor pages, starting with this page's parent, and ending with the top-level index page. Might be empty. Since 1.2, but undocumented until 11/14/02. | ancestors | ancestors | Array of Pages |
| The document object that contains this page. | n/a | document | Document |
| The application. | n/a | application | Application |
The most important property is the uid property - this provides the linkage between the various files. All JPEG files generated for an object are named x.jpg where x is the uid of that object. HTML file names are actually pulled from the plist file for that template, but all should include the uid embedded somewhere in the name. By referencing the current objects uid you can write HTML that references the other files in the web site.
Note that the only way to get to the document and application object is by referencing the appropriate property of a page object.
All photo page objects have these properties in addition to the page properties outlined above:
| Photo Page Properties | AppleScript | IRML | Type |
| The Unix path to the source file. | source | source | String |
| The rotation angle. Only 4 numbers are valid: 0, 90, 180 and 270. | rotation | rotation | Integer |
| Did we find the source file when we opened the document? 1 for yes and 0 for no. | found | found | Integer |
| The original width of source image. All widths and heights are in pixels. | ow | ow | Integer |
| The original height. | oh | oh | Integer |
| The width of scaled thumbnail. | tw | tw | Integer |
| The height of scaled thumbnail. | th | th | Integer |
| The width of scaled photo page image (aka display image). | dw | dw | Integer |
| The height of scaled photo page image. | dh | dh | Integer |
| The width of printable image. | pw | pw | Integer |
| The height of printable image. | ph | ph | Integer |
| The previous photo page. Nil if this is the first photo on the parent page. | n/a | previous | Photo Page |
| The next photo page. Nil if this is the last photo on the parent page. | n/a | next | Photo Page |
All photo page objects have these properties in addition to the page properties outlined above:
| Index Page Properties | AppleScript | IRML | Type |
| The array of pages that this page contains. The order of the array is set by the user; index and page children pages may be intermingled. | pages | pages | Array of Pages |
| Just like the pages array, but missing all the photo pages. | n/a | indexPages | Array of Index Pages |
| Just like the pages array, but missing all the index pages. | n/a | photoPages | Array of Photo Pages |
| A count of all photo pages accessable from this page, including all the photos accessable by contained index pages, etc. | n/a | totalPhotos | Integer |
| A count of all index pages accessable from this page, including all the index pages accessable by contained index pages, etc. Does not include this object - i.e., it's possible for this property to return 0. New for 1.2.9. | n/a | totalIndices | Integer |
| The first photo accessable from this page. If this page doesn't have any contained photo pages, then the index pages are checked. Nil if there are no photos at all - in which case totalphotos will be 0. | n/a | firstPhoto | Photo Page |
The document object has the following properties:
| Document Properties | AppleScript | IRML | Type |
| The top-level index page for this document. | index page | indexPage | Index Page |
| The number of thumbnail columns. | columns | columns | Integer |
| The global thumbnail size. Global sizes are maximums in both width and height. | thumbnail size | thumbnailSize | Integer |
| The global photo size. | photo size | photoSize | Integer |
| The global print size. | print size | printSize | Integer |
| Should we generated printable images? 1 for yes, 0 for no. | printable | printable | Integer |
| Desired dpi for printable images. Dropped in version 1.2.3. | print dpi | printDpi | Integer |
| Should we show titles on index pages? 1 for yes, 0 for no. | show thumbnail titles | showThumbnailTitles | Integer |
| Should we show titles on photo pages? 1 for yes, 0 for no. | show photo titles | showPhotoTitles | Integer |
| Unix path for the destination folder. | build path | buildPath | String |
| The name of the template being used. | template name | templateName | String |
| Unix path for the file containing this document. | n/a | fileName | String |
| Just the file name of the file containing this document. | n/a | justFileName | String |
The application object has the following properties:
| Application Properties | AppleScript | IRML | Type |
| Image Rodeo version, in X.Y format. | version | version | String |
| Unix path for the user-installed Templates.plist file. | user template path | userTemplatePath | String |
IRScript supports the usual collection of integer operators, and a few odd ones for good measure. The usual collection of boolean operators is also supported, but note that there is no boolean type, so they operate on integers. There are no bit-wise operators. There are two string operators: == (equal) and != (not equal). (These operators are new for 1.2.8.) These string form of the operator is used if both operands are strings, otherwise the operands are coerced to integers and the integer operator is used.
The following table summarizes the list of operators:
|
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||
Maximum and minimum are equivalent to max() and min(), respectively. Ceiling division is a shortcut for this expression:
(lhs / (rhs + lhs - 1)/
Variables in IRScript are typeless, and do not have to be declared before being used. To create a variable simply assign something to it. It will hold that value until all the IRScript statements in an IRML file have been executed, then it will cease to exist. Theres no way to save values across IRML files.
All variables have global scope.
Access to the built-in objects is provided by adding all the properties for the active page to the global scope. IRScript runs in the context of an IRML file, and each file corresponds to a page object (either index or photo - this is set up in the plist file), so theres always one and only one active page. All other objects are accessable from that active page.
When searching for variables, any user-defined variables are searched first. Watch out! Its possible to lose access to the built-in objects by assigning values to user-defined variables of the same name.
Heres an example:
if (isIndex) {
/* Must be an index page; dump the pages array. */
echo pages;
} else {
/* Must be a photo page; dump the source path. */
echo source;
}
/* We always have access to the document object, so now dump the pages array of the top-level index page. */
echo document.indexpage.pages;
/* Now assign something to pages. */
pages = 1;
/* We just lost access to the pages array! The next statement will inject the number 1 into the HTML stream. */
echo pages;
Its OK to reference a variable before its been assigned anything - it will simply return nothing. This nothing value will be converted to 0 (integer) or the empty string ("") if necessary. Note that an array subscript on nothing returns nothing, and a property reference on nothing also returns nothing.