The comet plugins support creating and updating cross references in documents and books. Cross references can show page numbers and names, document names and paths, and other information, down to the X/Y-coordinates of the referenced object.
This documnet shows you how to define cross references and keep them up to date.
Cross references consist of a definition and any number of references to that definition. Definitions and references do not have to be in the same document, though they have to be in the same book.
Reference definitions are created with the help of InDesign® hyper links.
Cross references are a special type of comet placeholder. In these placeholders' loadscripts you can search the book's or document's reference definitions and insert the contained elements into the document.
By keeping the names as clear as possible, you ensure that references find the correct reference definitions. Of course, that is not always easy, which is why we help you with that : In addition to the name, you can supply a comet ID (consisting of up to three numbers and some text) to identify a reference. These IDs are used in product research, for example. When searching for references, you can usually omit the name altogether and search only by comet ID.
In the document, reference definitions are inserted as hyperlinks. You can view all hyperlinks in a documnet in the Hyperlinks panel, which is included with InDesign®, and can be opened from the menu Window:Interactive:Hyperlinks. It is, however, not needed when creating cross references.
In the hyperlink panel you can see the names of cross references and - when hovering over an entry with your mouse pointer for a while - their comet IDs.
Even with comet IDs, the possibility of multiple reference definitions conflicting cannot be ruled out. InDesign® therefore renames definitions with the same name with a counter, e.g. Paul, Paul 1, Paul 2 usw.. When searching for references, these counters are ignored.
There are several ways to create new reference definition :
In any case, bear in mind that InDesign® does not support nested hyperlinks. This means that you cannot nest reference definitions, either. When inserting a new reference definition, all hyperlinks touching the new definition's area are removed from the documnent.
To prevent errors, reference definitions can only be placed entirely inside or entirely outside of comet placeholders, meaning they cannot overlap.
Reference definitions can be highlighted. InDesign® offers multiple frames around the text. These will not be printed! Comet cross references are highlighted with a dashed orange frame by default :
InDesign® may delete the ending highlight of a reference (here: after the l in "...ziel") without deleting the opening highlight. When that happens, InDesign® will crash soon, damaging your document file. To prevent that, only define references to a single glyph:
This first example is a script that will insert a reference definition into the document. The reference will be layered on top of the current selection and gets its name from that text. The creation of a cross reference is handled by the textmodel::insert_crossref function.
int main () { ItemRef frame = item::alloc(); String str = string::alloc (); Table t = table::alloc (); List prod = list::alloc (3,2,1); List prod2 = list::alloc (3,2,2); List prod3 = list::alloc (3,2,3); StringList prodsid = stringlist::alloc (3, 2); int start, len, col, row; int res; // Validate procuct selection if (list::length (prod) == 0) { showmessage ("No product selected"); return 0; } // Fetch document selection textmodel::selection (&start, &len, frame, 0, t, &col, &row); if (len > 0) textmodel::gettext (str, start, len); // Insert reference definition res = textmodel::insert_crossref ( start, len, string::get (str), 3, list::get (prod, 0), list::get (prod2, 0), list::get (prod3, 0), stringlist::get (prodsid, 0), 1, // Visible 3, // 1-3 frame width 3, // 1 Invert, 2 Inset, 3 Outline 1, // 0 Solid, 2 Dashed 100.0, 0.0, 0.0, -1.0 0); return 0; }
The next example is for a valid w2cross tag :
<w2cross:
''
3
14 1 2008 'Paul'
0
1
1
Outline
Dashed
100.0 50.0 0.0 -1.0
1 >
Cross references are implemented as regular placeholders of the "crossref" type. The following table shows which placeholder attribute you need to set to get a cross reference placeholder.
Attribute | Value | Environment |
type | crossref | XML and SOAP |
RelatedToID | 9 | ODBC and Oracle |
Cross references have their own icon () in the placeholder panel.
A similar icon is also used to highlight references in the document. :
The definition of a cross reference placeholder in XML looks like this:
<placeholder>
<id>123470</id>
<name>Cross-Reference</name>
<description></description>
<type>crossref</type>
<domain>Tutorial</domain>
<domainid>2000</domainid>
<class>3</class>
<load>2027</load>
<sync></sync>
<store>0</store>
<lov>0</lov>
<color name="">
<id>6</id>
</color>
<style></style>
<styleid>0</styleid>
<syncstateinvisible>0</syncstateinvisible>
<loadconstraint>0</loadconstraint>
<active>1</active>
</placeholder>
There are three color variations of the icon, signifying different states:
Color | Meaning | Automation |
Green | Okay / 0 | set after successful load |
Yellow | Ambiguous / 2 Changed / -1 |
set after link with an object |
Red | Other | none |
The state is only automatically set in the specific situations explained in the table. In particular, the state is not automatically set to yellow when the document or a document in the book is changed.
Naturally, you can set the state in the load and sync scripts. Please bear in mind, though, that the state is still only set to yellow if the placeholder is modified - it may still be green, despite the document or book changing, which may also affect the reference, undermining the meaning of the green state.
Cross referencs are updated as a consequence of the following actions. In those situations only cross references are reloaded. Other placeholders are ignored.
Please note that cross references are not updated automatically.
Most of the work in cross references is actually done in their loadscripts. You can determine whether the script should execute normally or update cross references by checking the global variable gRepagination: If gRepagination equals 0, you're in a normal load call. Here you can set a (default) set for a reference. If gRepagination equals 1, cross references should be updated and you can search the document / book for the reference definition and store the result in the placeholder.
We considered running cross reference scripts in regular load mode. We went with this option because it allows users to load cross referencses individually, set their state or whatever else may please them.
In the placeholders' loadscript, use the script functions hyperlink::find1 or hyperlink::find to search for the desired reference definition (or a lost of those reference definitions), and insert the desired text into the document (e.g. with textmodel::replace). Usually, the function find1 will suffice, because it fetches exactly one piece of information about a reference definition as a string and inserts it directly.
If you want to insert multiple pieces of information (from the same reference, too), it is better to use the find function instead. Find1 would have to search the entire book once for each piece, in this scenario.
This example searches for the first definition of the current placeholder object and inserts its page number and document name into the document. Attentive readers will notice that the script has at least three weaknesses:
1. It is executed during normal loads.
2. It does not define any behaviour for the case when no definition is found.
3. find1 is called twice.
Before using this script, please have a look at the following example.
int main () { char pg [512]; wlog ("", "Cross refed called, placeholder %d (%d)\n", gPlaceholderID, gRepagination); strcpy (pg, "Page "); strcat (pg, hyperlink::find1 ( 0, // (unused) return variable "Page", // Value name 0, // First reference definition 0, // Current document or its book "", // Do not test reference name 3, // object class "Product" gRecordID, gRecordID2, gRecordID3, gRecordStringID, 1)); // Search the entire book strcat (pg, " (<CharStyle:Italic>"); strcat (pg, hyperlink::find1 ( 0, "DocName", 0, 0, "", 3, gRecordID, gRecordID2, gRecordID3, gRecordStringID, 1, 1, 1, 1, 1)); strcat (pg, "<CharStyle:>)"); textmodel::replace (pg); return 0; }
The following example is more clever. It also fetches the values from the first reference definition. But then the document text from the definition's location is also fetched and copied into the reference. Bear in mind that text is fetched from one character after the definition's location. There's an InDesign® hyperlink symbol at the actual location.
Furthermore, this script also takes its execution context into account; in normal load mode, it will set the placeholder's state to 'changed'. If the cross reference fails to be resolved, the state is set to 'error' instead.
int find_word (String str, char * result) { char * abbrev = 0; *result = 0; if (!str || !string::length (str)) return 1; abbrev = string::get (str); if (strtokencount (abbrev, ' ') < 2) { strcpy (result, abbrev); } else { strcat (result, strword (abbrev, 0)); strcat (result, strword (abbrev, 1)); strcat (result, strword (abbrev, 2)); } return 0; } int main () { LinkList lks = 0; int res = 0; Link lk = 0; char txt [2000]; String str = 0; wlog ("", "Cross refed called, placeholder %d (%d)\n", gPlaceholderID, gRepagination); // Regular load call if (!gRepagination) { // Set state to "changed" placeholder::set_sync (-1); *gSyncChanged = 1; return 0; } // Find the reference definition lks = linklist::alloc (); res = hyperlink::find ( lks, // Result list 0, // Current document "", // Ignore the reference name 3, // object class "Product" gRecordID, gRecordID2, gRecordID3, gRecordStringID, 1, // Search the entire book 1, 1, 1, 1, // page name formatting 1); // Calculate XY-coordinates of the cross reference if (res != 0) { // Set the state to "error" wlog ("", "# Error %d while searching cross references\n", res); linklist::release (lks); placeholder::set_sync (-4); *gSyncChanged = 1; return 0; } // Text of the cross reference if (linklist::length (lks) == 0) { sprintf (txt, "Reference not found [%d, %d, %d, '%s']", gRecordID, gRecordID2, gRecordID3, gRecordStringID); } else { lk = linklist::first (lks); // Fetch text after the definition location str = string::alloc (); frame::gettext ( link::crossref::frame (lk), str, link::crossref::pos (lk)+1, 200); sprintf (txt, "Seite %d [%fx%f]", link::crossref::page (lk, 0), link::crossref::x (lk), link::crossref::y (lk)); if (string::length (str)) { char word[2000]; find_word (str, word); strcat (txt, " ("); strcat (txt, word); strcat (txt, ")"); string::release (str); } } // Insert text textmodel::replace (txt); linklist::release (lks); return 0; }
The following script functions may help you create the reference text :
Function | Summary |
hyperlink::find | Find all definitions by name and/or ID within the document or entire book |
hyperlink::find1 | Find the value of a definition attribute by the name and/or ID of the reference |
link::crossref::document | Document name, folder and path of the reference definition |
link::crossref::page | Page number of the reference definition |
link::crossref::pagename | Page name of the reference definition |
link::crossref::name | Name of the reference definition |
link::crossref::destination | ID of the reference definition |
link::crossref::x | XZ coordinate of the reference definition within text |
link::crossref::y | |
link::crossref::left | frame coordinates of the reference definition |
link::crossref::top | |
link::crossref::right | |
link::crossref::bottom | |
link::crossref::pos | Textposition of the reference definition |
link::crossref::frame | Frame of the reference definition |